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

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

Bug 1567 fixed : problem with old version of mysql
required version is now 5.0.0
move required version to functions database specific file like others engines

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