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

Last change on this file since 5230 was 5230, checked in by patdenice, 14 years ago

feature 1255: add pwg_select_db function.

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