source: trunk/include/dblayer/functions_mysql.inc.php @ 4385

Last change on this file since 4385 was 4385, checked in by nikrou, 14 years ago

Feature_1255 :

  • single quotes in queries
  • start using $confdblayer
File size: 14.5 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based picture gallery                                  |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2009 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('DB_ENGINE', 'MySQL');
25
26define('DB_REGEX_OPERATOR', 'REGEXP');
27define('DB_RANDOM_FUNCTION', 'RAND');
28
29/**
30 *
31 * simple functions
32 *
33 */
34
35function pwg_db_connect($host, $user, $password, $database)
36{ 
37  $link = mysql_connect($host, $user, $password) or my_error('mysql_connect', true);
38  mysql_select_db($database, $link) or my_error('mysql_select_db', true);
39
40  return $link;
41}
42
43function pwg_db_check_charset() 
44{
45  defined('PWG_CHARSET') and defined('DB_CHARSET')
46    or fatal_error('PWG_CHARSET and/or DB_CHARSET is not defined');
47  if ( version_compare(mysql_get_server_info(), '4.1.0', '>=') )
48  {
49    if (DB_CHARSET!='')
50    {
51      pwg_query('SET NAMES "'.DB_CHARSET.'"');
52    }
53  }
54  elseif ( strtolower(PWG_CHARSET)!='iso-8859-1' )
55  {
56    fatal_error('PWG supports only iso-8859-1 charset on MySql version '.mysql_get_server_info());
57  }
58}
59
60function pwg_get_db_version() 
61{
62  list($mysql_version) = pwg_db_fetch_row(pwg_query('SELECT VERSION();'));
63 
64  return $mysql_version;
65}
66
67function pwg_query($query)
68{
69  global $conf,$page,$debug,$t2;
70
71  $start = get_moment();
72  ($result = mysql_query($query)) or my_error($query, $conf['die_on_sql_error']);
73
74  $time = get_moment() - $start;
75
76  if (!isset($page['count_queries']))
77  {
78    $page['count_queries'] = 0;
79    $page['queries_time'] = 0;
80  }
81
82  $page['count_queries']++;
83  $page['queries_time']+= $time;
84
85  if ($conf['show_queries'])
86  {
87    $output = '';
88    $output.= '<pre>['.$page['count_queries'].'] ';
89    $output.= "\n".$query;
90    $output.= "\n".'(this query time : ';
91    $output.= '<b>'.number_format($time, 3, '.', ' ').' s)</b>';
92    $output.= "\n".'(total SQL time  : ';
93    $output.= number_format($page['queries_time'], 3, '.', ' ').' s)';
94    $output.= "\n".'(total time      : ';
95    $output.= number_format( ($time+$start-$t2), 3, '.', ' ').' s)';
96    if ( $result!=null and preg_match('/\s*SELECT\s+/i',$query) )
97    {
98      $output.= "\n".'(num rows        : ';
99      $output.= mysql_num_rows($result).' )';
100    }
101    elseif ( $result!=null
102      and preg_match('/\s*INSERT|UPDATE|REPLACE|DELETE\s+/i',$query) )
103    {
104      $output.= "\n".'(affected rows   : ';
105      $output.= mysql_affected_rows().' )';
106    }
107    $output.= "</pre>\n";
108
109    $debug .= $output;
110  }
111
112  return $result;
113}
114
115function pwg_db_nextval($column, $table)
116{
117  $query = '
118SELECT IF(MAX('.$column.')+1 IS NULL, 1, MAX('.$column.')+1)
119  FROM '.$table;
120  list($next) = pwg_db_fetch_row(pwg_query($query));
121
122  return $next;
123}
124
125function pwg_db_changes($result) 
126{
127  return mysql_affected_rows($result);
128}
129
130function pwg_db_num_rows($result) 
131{
132  return mysql_num_rows($result);
133}
134
135function pwg_db_fetch_assoc($result)
136{
137  return mysql_fetch_assoc($result);
138}
139
140function pwg_db_fetch_row($result)
141{
142  return mysql_fetch_row($result);
143}
144
145function pwg_db_fetch_object($result)
146{
147  return mysql_fetch_object($result);
148}
149
150function pwg_db_free_result($result) 
151{
152  return mysql_free_result($result);
153}
154
155function pwg_db_real_escape_string($s)
156{
157  return mysql_real_escape_string($s);
158}
159
160function pwg_db_insert_id()
161{
162  return mysql_insert_id();
163}
164
165/**
166 *
167 * complex functions
168 *
169 */
170
171/**
172 * creates an array based on a query, this function is a very common pattern
173 * used here
174 *
175 * @param string $query
176 * @param string $fieldname
177 * @return array
178 */
179function array_from_query($query, $fieldname)
180{
181  $array = array();
182
183  $result = pwg_query($query);
184  while ($row = mysql_fetch_assoc($result))
185  {
186    array_push($array, $row[$fieldname]);
187  }
188
189  return $array;
190}
191
192define('MASS_UPDATES_SKIP_EMPTY', 1);
193/**
194 * updates multiple lines in a table
195 *
196 * @param string table_name
197 * @param array dbfields
198 * @param array datas
199 * @param int flags - if MASS_UPDATES_SKIP_EMPTY - empty values do not overwrite existing ones
200 * @return void
201 */
202function mass_updates($tablename, $dbfields, $datas, $flags=0)
203{
204  if (count($datas) == 0)
205    return;
206  // depending on the MySQL version, we use the multi table update or N update queries
207  if (count($datas) < 10 or version_compare(mysql_get_server_info(), '4.0.4') < 0)
208  { // MySQL is prior to version 4.0.4, multi table update feature is not available
209    foreach ($datas as $data)
210    {
211      $query = '
212UPDATE '.$tablename.'
213  SET ';
214      $is_first = true;
215      foreach ($dbfields['update'] as $key)
216      {
217        $separator = $is_first ? '' : ",\n    ";
218
219        if (isset($data[$key]) and $data[$key] != '')
220        {
221          $query.= $separator.$key.' = \''.$data[$key].'\'';
222        }
223        else
224        {
225          if ($flags & MASS_UPDATES_SKIP_EMPTY )
226            continue; // next field
227          $query.= "$separator$key = NULL";
228        }
229        $is_first = false;
230      }
231      if (!$is_first)
232      {// only if one field at least updated
233        $query.= '
234  WHERE ';
235        $is_first = true;
236        foreach ($dbfields['primary'] as $key)
237        {
238          if (!$is_first)
239          {
240            $query.= ' AND ';
241          }
242          if ( isset($data[$key]) )
243          {
244            $query.= $key.' = \''.$data[$key].'\'';
245          }
246          else
247          {
248            $query.= $key.' IS NULL';
249          }
250          $is_first = false;
251        }
252        pwg_query($query);
253      }
254    } // foreach update
255  } // if mysql_ver or count<X
256  else
257  {
258    // creation of the temporary table
259    $query = '
260SHOW FULL COLUMNS FROM '.$tablename;
261    $result = pwg_query($query);
262    $columns = array();
263    $all_fields = array_merge($dbfields['primary'], $dbfields['update']);
264    while ($row = pwg_db_fetch_assoc($result))
265    {
266      if (in_array($row['Field'], $all_fields))
267      {
268        $column = $row['Field'];
269        $column.= ' '.$row['Type'];
270
271        $nullable = true;
272        if (!isset($row['Null']) or $row['Null'] == '' or $row['Null']=='NO')
273        {
274          $column.= ' NOT NULL';
275          $nullable = false;
276        }
277        if (isset($row['Default']))
278        {
279          $column.= " default '".$row['Default']."'";
280        }
281        elseif ($nullable)
282        {
283          $column.= " default NULL";
284        }
285        if (isset($row['Collation']) and $row['Collation'] != 'NULL')
286        {
287          $column.= " collate '".$row['Collation']."'";
288        }
289        array_push($columns, $column);
290      }
291    }
292
293    $temporary_tablename = $tablename.'_'.micro_seconds();
294
295    $query = '
296CREATE TABLE '.$temporary_tablename.'
297(
298  '.implode(",\n  ", $columns).',
299  UNIQUE KEY the_key ('.implode(',', $dbfields['primary']).')
300)';
301
302    pwg_query($query);
303    mass_inserts($temporary_tablename, $all_fields, $datas);
304    if ( $flags & MASS_UPDATES_SKIP_EMPTY )
305      $func_set = create_function('$s', 'return "t1.$s = IFNULL(t2.$s, t1.$s)";');
306    else
307      $func_set = create_function('$s', 'return "t1.$s = t2.$s";');
308
309    // update of images table by joining with temporary table
310    $query = '
311UPDATE '.$tablename.' AS t1, '.$temporary_tablename.' AS t2
312  SET '.
313      implode(
314        "\n    , ",
315        array_map($func_set,$dbfields['update'])
316        ).'
317  WHERE '.
318      implode(
319        "\n    AND ",
320        array_map(
321          create_function('$s', 'return "t1.$s = t2.$s";'),
322          $dbfields['primary']
323          )
324        );
325    pwg_query($query);
326    $query = '
327DROP TABLE '.$temporary_tablename;
328    pwg_query($query);
329  }
330}
331
332
333/**
334 * inserts multiple lines in a table
335 *
336 * @param string table_name
337 * @param array dbfields
338 * @param array inserts
339 * @return void
340 */
341function mass_inserts($table_name, $dbfields, $datas)
342{
343  if (count($datas) != 0)
344  {
345    $first = true;
346
347    $query = 'SHOW VARIABLES LIKE \'max_allowed_packet\'';
348    list(, $packet_size) = pwg_db_fetch_row(pwg_query($query));
349    $packet_size = $packet_size - 2000; // The last list of values MUST not exceed 2000 character*/
350    $query = '';
351
352    foreach ($datas as $insert)
353    {
354      if (strlen($query) >= $packet_size)
355      {
356        pwg_query($query);
357        $first = true;
358      }
359
360      if ($first)
361      {
362        $query = '
363INSERT INTO '.$table_name.'
364  ('.implode(',', $dbfields).')
365  VALUES';
366        $first = false;
367      }
368      else
369      {
370        $query .= '
371  , ';
372      }
373
374      $query .= '(';
375      foreach ($dbfields as $field_id => $dbfield)
376      {
377        if ($field_id > 0)
378        {
379          $query .= ',';
380        }
381
382        if (!isset($insert[$dbfield]) or $insert[$dbfield] === '')
383        {
384          $query .= 'NULL';
385        }
386        else
387        {
388          $query .= "'".$insert[$dbfield]."'";
389        }
390      }
391      $query .= ')';
392    }
393    pwg_query($query);
394  }
395}
396
397/**
398 * Do maintenance on all PWG tables
399 *
400 * @return none
401 */
402function do_maintenance_all_tables()
403{
404  global $prefixeTable, $page;
405
406  $all_tables = array();
407
408  // List all tables
409  $query = 'SHOW TABLES LIKE \''.$prefixeTable.'%\'';
410  $result = pwg_query($query);
411  while ($row = pwg_db_fetch_row($result))
412  {
413    array_push($all_tables, $row[0]);
414  }
415
416  // Repair all tables
417  $query = 'REPAIR TABLE '.implode(', ', $all_tables);
418  $mysql_rc = pwg_query($query);
419
420  // Re-Order all tables
421  foreach ($all_tables as $table_name)
422  {
423    $all_primary_key = array();
424
425    $query = 'DESC '.$table_name.';';
426    $result = pwg_query($query);
427    while ($row = pwg_db_fetch_assoc($result))
428    {
429      if ($row['Key'] == 'PRI')
430      {
431        array_push($all_primary_key, $row['Field']);
432      }
433    }
434
435    if (count($all_primary_key) != 0)
436    {
437      $query = 'ALTER TABLE '.$table_name.' ORDER BY '.implode(', ', $all_primary_key).';';
438      $mysql_rc = $mysql_rc && pwg_query($query);
439    }
440  }
441
442  // Optimize all tables
443  $query = 'OPTIMIZE TABLE '.implode(', ', $all_tables);
444  $mysql_rc = $mysql_rc && pwg_query($query);
445  if ($mysql_rc)
446  {
447    array_push(
448          $page['infos'],
449          l10n('Optimizations completed')
450          );
451  }
452  else
453  {
454    array_push(
455          $page['errors'],
456          l10n('Optimizations errors')
457          );
458  }
459}
460
461function pwg_db_get_recent_period_expression($period, $date='CURRENT_DATE')
462{
463  if ($date!='CURRENT_DATE')
464  {
465    $date = '\''.$date.'\'';
466  }
467
468  return 'SUBDATE('.$date.',INTERVAL '.$period.' DAY)';
469}
470
471function pwg_db_get_recent_period($period, $date='CURRENT_DATE')
472{
473  $query = '
474SELECT '.pwg_db_get_recent_period_expression($period);
475  list($d) = pwg_db_fetch_row(pwg_query($query));
476
477  return $d;
478}
479
480/**
481 * returns an array containing the possible values of an enum field
482 *
483 * @param string tablename
484 * @param string fieldname
485 */
486function get_enums($table, $field)
487{
488  // retrieving the properties of the table. Each line represents a field :
489  // columns are 'Field', 'Type'
490  $result = pwg_query('desc '.$table);
491  while ($row = pwg_db_fetch_assoc($result))
492  {
493    // we are only interested in the the field given in parameter for the
494    // function
495    if ($row['Field'] == $field)
496    {
497      // retrieving possible values of the enum field
498      // enum('blue','green','black')
499      $options = explode(',', substr($row['Type'], 5, -1));
500      foreach ($options as $i => $option)
501      {
502        $options[$i] = str_replace("'", '',$option);
503      }
504    }
505  }
506  pwg_db_free_result($result);
507  return $options;
508}
509
510// get_boolean transforms a string to a boolean value. If the string is
511// "false" (case insensitive), then the boolean value false is returned. In
512// any other case, true is returned.
513function get_boolean( $string )
514{
515  $boolean = true;
516  if ( 'false' == strtolower($string) )
517  {
518    $boolean = false;
519  }
520  return $boolean;
521}
522
523/**
524 * returns boolean string 'true' or 'false' if the given var is boolean
525 *
526 * @param mixed $var
527 * @return mixed
528 */
529function boolean_to_string($var)
530{
531  if (is_bool($var))
532  {
533    return $var ? 'true' : 'false';
534  }
535  else
536  {
537    return $var;
538  }
539}
540
541/**
542 *
543 * interval and date functions
544 *
545 */
546
547
548function pwg_db_get_recent_period_expression($period, $date='CURRENT_DATE')
549{
550  if ($date!='CURRENT_DATE')
551  {
552    $date = '\''.$date.'\'';
553  }
554
555  return 'SUBDATE('.$date.',INTERVAL '.$period.' DAY)';
556}
557
558function pwg_db_get_recent_period($period, $date='CURRENT_DATE')
559{
560  $query = '
561SELECT '.pwg_db_get_recent_period_expression($period);
562  list($d) = pwg_db_fetch_row(pwg_query($query));
563
564  return $d;
565}
566
567function pwg_db_get_date_YYYYMM($date)
568{
569  return 'DATE_FORMAT('.$date.', \'%Y%m\')';
570}
571
572function pwg_db_get_date_MMDD($date)
573{
574  return 'DATE_FORMAT('.$date.', \'%m%d\')';
575}
576
577function pwg_db_get_year($date)
578{
579  return 'YEAR('.$date.')';
580}
581
582function pwg_db_get_month($date)
583{
584  return 'MONTH('.$date.')';
585}
586
587function pwg_db_get_week($date, $mode=null)
588{
589  if ($mode)
590  {
591    return 'WEEK('.$date.', '.$mode.')';
592  }
593  else
594  {
595    return 'WEEK('.$date.')';
596  }
597}
598
599function pwg_db_get_dayofmonth($date)
600{
601  return 'DAYOFMONTH('.$date.')';
602}
603
604function pwg_db_get_dayofweek($date)
605{
606  return 'DAYOFWEEK('.$date.')';
607}
608
609function pwg_db_get_weekday($date)
610{
611  return 'WEEKDAY('.$date.')';
612}
613
614// my_error returns (or send to standard output) the message concerning the
615// error occured for the last mysql query.
616function my_error($header, $die)
617{
618  $error = "[mysql error ".mysql_errno().'] '.mysql_error()."\n";
619  $error .= $header;
620
621  if ($die)
622  {
623    fatal_error($error);
624  }
625  echo("<pre>");
626  trigger_error($error, E_USER_WARNING);
627  echo("</pre>");
628}
629
630?>
Note: See TracBrowser for help on using the repository browser.