source: trunk/include/dblayer/functions_sqlite.inc.php @ 12922

Last change on this file since 12922 was 12922, checked in by mistic100, 12 years ago

update Piwigo headers to 2012, last change before the expected (or not) apocalypse

File size: 15.5 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2012 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24define('REQUIRED_SQLITE_VERSION', '3.0.0');
25define('DB_ENGINE', 'SQLite');
26
27define('DB_REGEX_OPERATOR', 'REGEXP');
28define('DB_RANDOM_FUNCTION', 'RANDOM');
29
30/**
31 *
32 * simple functions
33 *
34 */
35
36function pwg_db_connect($host, $user, $password, $database)
37{
38  global $conf;
39
40  $db_file = sprintf('%s/%s.db', PHPWG_ROOT_PATH.$conf['data_location'], $database);
41
42  if (script_basename()=='install') 
43  {
44    $sqlite_open_mode = SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE;
45  }
46  else 
47  {
48    $sqlite_open_mode = SQLITE3_OPEN_READWRITE;
49  }
50 
51  $link = new SQLite3($db_file, $sqlite_open_mode);
52  if (!$link)
53  {
54    throw new  Exception('Connection to server succeed, but it was impossible to connect to database');
55  }
56
57  $link->createFunction('now', 'pwg_now', 0);
58  $link->createFunction('unix_timestamp', 'pwg_unix_timestamp', 1);
59  $link->createFunction('md5', 'md5', 1);
60  $link->createFunction('if', 'pwg_if', 3);
61
62  $link->createFunction('regexp', 'pwg_regexp', 2);
63
64  return $link;
65}
66
67function pwg_db_check_version()
68{
69  $current_version = pwg_get_db_version();
70  if (version_compare($current_version, REQUIRED_SQLITE_VERSION, '<'))
71  {
72    fatal_error(
73      sprintf(
74        'your database version is too old, you have "%s" and you need at least "%s"',
75        $current_version,
76        REQUIRED_SQLITE_VERSION
77        )
78      );
79  }
80}
81
82function pwg_db_check_charset() 
83{
84  return true;
85}
86
87function pwg_get_db_version() 
88{
89  global $pwg_db_link;
90
91  $versionInfos = $pwg_db_link->version();
92  return $versionInfos['versionString'];
93}
94
95function pwg_query($query)
96{
97  global $conf,$page,$debug,$t2,$pwg_db_link;
98
99  $start = get_moment();
100
101  $truncate_pattern = '`truncate(.*)`i';
102  $insert_pattern = '`(INSERT INTO [^)]*\)\s*VALUES)(\([^)]*\))\s*,\s*(.*)`mi'; 
103
104  if (preg_match($truncate_pattern, $query, $matches))
105  {
106    $query = str_replace('TRUNCATE TABLE', 'DELETE FROM', $query);
107    $truncate_query = true;
108    ($result = $pwg_db_link->exec($query)) or die($query."\n<br>".$pwg_db_link->lastErrorMsg());
109  }
110  elseif (preg_match($insert_pattern, $query, $matches))
111  {
112    $base_query = substr($query, 0, strlen($matches[1])+1);
113    $values_pattern = '`\)\s*,\s*\(`';
114    $values = preg_split($values_pattern, substr($query, strlen($matches[1])+1));
115    $values[0] = substr($values[0], 1);
116    $values[count($values)-1] = substr($values[count($values)-1], 
117                                     0, 
118                                     strlen($values[count($values)-1])-1
119                                     );
120    for ($n=0;$n<count($values);$n++)
121    {
122      $query = $base_query . '('. $values[$n] . ")\n;";
123      ($result = $pwg_db_link->query($query)) 
124        or die($query."\n<br>".$pwg_db_link->lastErrorMsg());
125    }
126  }
127  else 
128  {
129    ($result = $pwg_db_link->query($query)) 
130      or die($query."\n<br>".$pwg_db_link->lastErrorMsg());
131  }
132
133  $time = get_moment() - $start;
134
135  if (!isset($page['count_queries']))
136  {
137    $page['count_queries'] = 0;
138    $page['queries_time'] = 0;
139  }
140
141  $page['count_queries']++;
142  $page['queries_time']+= $time;
143
144  if ($conf['show_queries'])
145  {
146    $output = '';
147    $output.= '<pre>['.$page['count_queries'].'] ';
148    $output.= "\n".$query;
149    $output.= "\n".'(this query time : ';
150    $output.= '<b>'.number_format($time, 3, '.', ' ').' s)</b>';
151    $output.= "\n".'(total SQL time  : ';
152    $output.= number_format($page['queries_time'], 3, '.', ' ').' s)';
153    $output.= "\n".'(total time      : ';
154    $output.= number_format( ($time+$start-$t2), 3, '.', ' ').' s)';
155    if ( $result!=null and preg_match('/\s*SELECT\s+/i',$query) )
156    {
157      $output.= "\n".'(num rows        : ';
158      $output.= pwg_db_num_rows($result).' )';
159    }
160    elseif ( $result!=null
161      and preg_match('/\s*INSERT|UPDATE|REPLACE|DELETE\s+/i',$query) 
162      and !isset($truncate_query))
163    {
164      $output.= "\n".'(affected rows   : ';
165      $output.= pwg_db_changes($result).' )';
166    }
167    $output.= "</pre>\n";
168
169    $debug .= $output;
170  }
171
172  return $result;
173}
174
175function pwg_db_nextval($column, $table)
176{
177  $query = '
178SELECT MAX('.$column.')+1
179  FROM '.$table;
180  list($next) = pwg_db_fetch_row(pwg_query($query));
181  if (is_null($next))
182  {
183    $next = 1;
184  }
185  return $next;
186}
187
188/**
189 *
190 * complex functions
191 *
192 */
193
194function pwg_db_changes(SQLite3Result $result=null) 
195{
196  global $pwg_db_link;
197
198  return $pwg_db_link->changes();
199}
200
201function pwg_db_num_rows($result) 
202{ 
203  return $result->numColumns();
204}
205
206function pwg_db_fetch_assoc($result)
207{
208  return $result->fetchArray(SQLITE3_ASSOC);
209}
210
211function pwg_db_fetch_row($result)
212{
213  return $result->fetchArray(SQLITE3_NUM);
214}
215
216function pwg_db_fetch_object($result)
217{
218  return $result;
219}
220
221function pwg_db_free_result($result) 
222{
223}
224
225function pwg_db_real_escape_string($s)
226{
227  global $pwg_db_link;
228
229  return $pwg_db_link->escapeString($s);
230}
231
232function pwg_db_insert_id($table=null, $column='id')
233{
234  global $pwg_db_link;
235
236  return $pwg_db_link->lastInsertRowID();
237}
238
239/**
240 *
241 * complex functions
242 *
243 */
244
245/**
246 * creates an array based on a query, this function is a very common pattern
247 * used here
248 *
249 * @param string $query
250 * @param string $fieldname
251 * @return array
252 */
253function array_from_query($query, $fieldname)
254{
255  $array = array();
256
257  $result = pwg_query($query);
258  while ($row = pwg_db_fetch_assoc($result))
259  {
260    array_push($array, $row[$fieldname]);
261  }
262
263  return $array;
264}
265
266define('MASS_UPDATES_SKIP_EMPTY', 1);
267/**
268 * updates multiple lines in a table
269 *
270 * @param string table_name
271 * @param array dbfields
272 * @param array datas
273 * @param int flags - if MASS_UPDATES_SKIP_EMPTY - empty values do not overwrite existing ones
274 * @return void
275 */
276function mass_updates($tablename, $dbfields, $datas, $flags=0)
277{
278  if (count($datas) == 0)
279    return;
280
281  foreach ($datas as $data)
282  {
283    $query = '
284UPDATE '.$tablename.'
285  SET ';
286    $is_first = true;
287    foreach ($dbfields['update'] as $key)
288    {
289      $separator = $is_first ? '' : ",\n    ";
290     
291      if (isset($data[$key]) and $data[$key] != '')
292      {
293        $query.= $separator.$key.' = \''.$data[$key].'\'';
294      }
295      else
296      {
297        if ( $flags & MASS_UPDATES_SKIP_EMPTY )
298          continue; // next field
299        $query.= "$separator$key = NULL";
300      }
301      $is_first = false;
302    }
303    if (!$is_first)
304    {// only if one field at least updated
305      $query.= '
306  WHERE ';
307      $is_first = true;
308      foreach ($dbfields['primary'] as $key)
309      {
310        if (!$is_first)
311        {
312          $query.= ' AND ';
313        }
314        if ( isset($data[$key]) )
315        {
316          $query.= $key.' = \''.$data[$key].'\'';
317        }
318        else
319        {
320          $query.= $key.' IS NULL';
321        }
322        $is_first = false;
323      }
324      pwg_query($query);
325    }
326  }
327}
328
329/**
330 * updates one line in a table
331 *
332 * @param string table_name
333 * @param array set_fields
334 * @param array where_fields
335 * @param int flags - if MASS_UPDATES_SKIP_EMPTY - empty values do not overwrite existing ones
336 * @return void
337 */
338function single_update($tablename, $set_fields, $where_fields, $flags=0)
339{
340  if (count($set_fields) == 0)
341  {
342    return;
343  }
344
345  $query = '
346UPDATE '.$tablename.'
347  SET ';
348  $is_first = true;
349  foreach ($set_fields as $key => $value)
350  {
351    $separator = $is_first ? '' : ",\n    ";
352
353    if (isset($value) and $value != '')
354    {
355      $query.= $separator.$key.' = \''.$value.'\'';
356    }
357    else
358    {
359      if ( $flags & MASS_UPDATES_SKIP_EMPTY )
360        continue; // next field
361      $query.= "$separator$key = NULL";
362    }
363    $is_first = false;
364  }
365  if (!$is_first)
366  {// only if one field at least updated
367    $query.= '
368  WHERE ';
369    $is_first = true;
370    foreach ($where_fields as $key => $value)
371    {
372      if (!$is_first)
373      {
374        $query.= ' AND ';
375      }
376      if ( isset($value) )
377      {
378        $query.= $key.' = \''.$value.'\'';
379      }
380      else
381      {
382        $query.= $key.' IS NULL';
383      }
384      $is_first = false;
385    }
386    pwg_query($query);
387  }
388}
389
390/**
391 * inserts multiple lines in a table
392 *
393 * @param string table_name
394 * @param array dbfields
395 * @param array inserts
396 * @return void
397 */
398function mass_inserts($table_name, $dbfields, $datas)
399{
400  if (count($datas) != 0)
401  {
402    $first = true;
403
404    $packet_size = 16777216;
405    $packet_size = $packet_size - 2000; // The last list of values MUST not exceed 2000 character*/
406    $query = '';
407
408    foreach ($datas as $insert)
409    {
410      if (strlen($query) >= $packet_size)
411      {
412        pwg_query($query);
413        $first = true;
414      }
415
416      if ($first)
417      {
418        $query = '
419INSERT INTO '.$table_name.'
420  ('.implode(',', $dbfields).')
421  VALUES';
422        $first = false;
423      }
424      else
425      {
426        $query .= '
427  , ';
428      }
429
430      $query .= '(';
431      foreach ($dbfields as $field_id => $dbfield)
432      {
433        if ($field_id > 0)
434        {
435          $query .= ',';
436        }
437
438        if (!isset($insert[$dbfield]) or $insert[$dbfield] === '')
439        {
440          $query .= 'NULL';
441        }
442        else
443        {
444          $query .= "'".$insert[$dbfield]."'";
445        }
446      }
447      $query .= ')';
448    }
449    pwg_query($query);
450  }
451}
452
453/**
454 * inserts one line in a table
455 *
456 * @param string table_name
457 * @param array dbfields
458 * @param array insert
459 * @return void
460 */
461function single_insert($table_name, $data)
462{
463  if (count($data) != 0)
464  {
465    $query = '
466INSERT INTO '.$table_name.'
467  ('.implode(',', array_keys($data)).')
468  VALUES';
469
470    $query .= '(';
471    $is_first = true;
472    foreach ($data as $key => $value)
473    {
474      if (!$is_first)
475      {
476        $query .= ',';
477      }
478      else
479      {
480        $is_first = false;
481      }
482     
483      if ($value === '')
484      {
485        $query .= 'NULL';
486      }
487      else
488      {
489        $query .= "'".$value."'";
490      }
491    }
492    $query .= ')';
493   
494    pwg_query($query);
495  }
496}
497
498/**
499 * Do maintenance on all PWG tables
500 *
501 * @return none
502 */
503function do_maintenance_all_tables()
504{
505  global $prefixeTable, $page;
506
507  $all_tables = array();
508
509  // List all tables
510  $query = 'SELECT name FROM SQLITE_MASTER
511WHERE name LIKE \''.$prefixeTable.'%\'';
512
513  $all_tables = array_from_query($query, 'name');
514  foreach ($all_tables as $table_name)
515  {
516    $query = 'VACUUM '.$table_name.';';
517    $result = pwg_query($query);
518  }
519 
520  array_push($page['infos'],
521             l10n('All optimizations have been successfully completed.')
522             );
523}
524
525function pwg_db_concat($array)
526{
527  return implode($array, ' || ');
528}
529
530function pwg_db_concat_ws($array, $separator)
531{
532  return implode($array, ' || \''.$separator.'\' || ');
533}
534
535function pwg_db_cast_to_text($string)
536{
537  return $string;
538}
539
540/**
541 * returns an array containing the possible values of an enum field
542 *
543 * @param string tablename
544 * @param string fieldname
545 */
546function get_enums($table, $field)
547{
548  $Enums['categories']['status'] = array('public', 'private');
549  $Enums['history']['section'] = array('categories','tags','search','list','favorites','most_visited','best_rated','recent_pics','recent_cats');
550  $Enums['user_infos']['status'] = array('webmaster','admin','normal','generic','guest');
551  $Enums['image']['type'] = array('picture','high','other');
552  $Enums['plugins']['state'] = array('active', 'inactive');
553  $Enums['user_cache_image']['access_type'] = array('NOT IN','IN');
554
555  $table = str_replace($GLOBALS['prefixeTable'], '', $table);
556  if (isset($Enums[$table][$field])) {
557    return $Enums[$table][$field];
558  } else {
559    return array();
560  }
561}
562
563// get_boolean transforms a string to a boolean value. If the string is
564// "false" (case insensitive), then the boolean value false is returned. In
565// any other case, true is returned.
566function get_boolean( $string )
567{
568  $boolean = true;
569  if ('f' === $string || 'false' === $string)
570  {
571    $boolean = false;
572  }
573  return $boolean;
574}
575
576/**
577 * returns boolean string 'true' or 'false' if the given var is boolean
578 *
579 * @param mixed $var
580 * @return mixed
581 */
582function boolean_to_string($var)
583{
584  if (is_bool($var))
585  {
586    return $var ? 'true' : 'false';
587  }
588  else
589  {
590    return $var;
591  }
592}
593
594/**
595 *
596 * interval and date functions
597 *
598 */
599
600function pwg_db_get_recent_period_expression($period, $date='CURRENT_DATE')
601{
602  if ($date!='CURRENT_DATE')
603  {
604    $date = '\''.$date.'\'';
605  }
606
607  return 'date('.$date.',\''.-$period.' DAY\')';
608}
609
610function pwg_db_get_recent_period($period, $date='CURRENT_DATE')
611{
612  $query = 'select '.pwg_db_get_recent_period_expression($period, $date);
613  list($d) = pwg_db_fetch_row(pwg_query($query));
614
615  return $d;
616}
617
618function pwg_db_get_flood_period_expression($seconds)
619{
620  return 'datetime(\'now\', \'localtime\', \''.-$seconds.' seconds\')';
621}
622
623function pwg_db_get_hour($date)
624{
625  return 'strftime(\'%H\', '.$date.')';
626}
627
628function pwg_db_get_date_YYYYMM($date)
629{
630  return 'strftime(\'%Y%m\','.$date.')';
631}
632
633function pwg_db_get_date_MMDD($date)
634{
635  return 'strftime(\'%m%d\','.$date.')';
636}
637
638function pwg_db_get_year($date)
639{
640  return 'strftime(\'%Y\','.$date.')';
641}
642
643function pwg_db_get_month($date)
644{
645  return 'strftime(\'%m\','.$date.')';
646}
647
648function pwg_db_get_week($date, $mode=null)
649{
650  return 'strftime(\'%W\','.$date.')';
651}
652
653function pwg_db_get_dayofmonth($date)
654{
655  return 'strftime(\'%d\','.$date.')';
656}
657
658function pwg_db_get_dayofweek($date)
659{
660  return 'strftime(\'%w\','.$date.')';
661}
662
663function pwg_db_get_weekday($date)
664{
665  return 'strftime(\'%w\',date('.$date.',\'-1 DAY\'))';
666}
667
668function pwg_db_date_to_ts($date) 
669{
670  return 'UNIX_TIMESTAMP('.$date.')';
671}
672
673// my_error returns (or send to standard output) the message concerning the
674// error occured for the last mysql query.
675function my_error($header, $die)
676{
677  global $pwg_db_link;
678
679  $error = '';
680  if (isset($pwg_db_link)) 
681  {
682    $error .= '[sqlite error]'.$pwg_db_link->lastErrorMsg()."\n";
683  }
684
685  $error .= $header;
686
687  if ($die)
688  {
689    fatal_error($error);
690  }
691  echo("<pre>");
692  trigger_error($error, E_USER_WARNING);
693  echo("</pre>");
694}
695
696// sqlite create functions
697function pwg_now()
698{
699  return date('Y-m-d H:i:s');
700}
701
702function pwg_unix_timestamp()
703{
704  return strtotime($strDate);
705}
706
707function pwg_if($expression, $value1, $value2) 
708{
709  if ($expression)
710  {
711    return $value1;
712  }
713  else
714  {
715    return $value2;
716  }
717} 
718
719function pwg_regexp($pattern, $string)
720{
721  $pattern = sprintf('`%s`', $pattern);
722  return preg_match($pattern, $string);
723}
724?>
Note: See TracBrowser for help on using the repository browser.