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

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

Feature 1244 : bug fix
functions_mysql.inc.php must be loaded for install

File size: 11.3 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
24/**
25 *
26 * simple functions
27 *
28 */
29
30function pwg_db_connect($host, $user, $password, $database)
31{ 
32  $link = mysql_connect($host, $user, $password) or my_error('mysql_connect', true);
33  mysql_select_db($database, $link) or my_error('mysql_select_db', true);
34
35  return $link;
36}
37
38function pwg_db_check_charset() 
39{
40  defined('PWG_CHARSET') and defined('DB_CHARSET')
41    or fatal_error('PWG_CHARSET and/or DB_CHARSET is not defined');
42  if ( version_compare(mysql_get_server_info(), '4.1.0', '>=') )
43  {
44    if (DB_CHARSET!='')
45    {
46      pwg_query('SET NAMES "'.DB_CHARSET.'"');
47    }
48  }
49  elseif ( strtolower(PWG_CHARSET)!='iso-8859-1' )
50  {
51    fatal_error('PWG supports only iso-8859-1 charset on MySql version '.mysql_get_server_info());
52  }
53}
54
55function pwg_get_db_version() 
56{
57  list($mysql_version) = pwg_db_fetch_row(pwg_query('SELECT VERSION();'));
58 
59  return $mysql_version;
60}
61
62function pwg_query($query)
63{
64  global $conf,$page,$debug,$t2;
65
66  $start = get_moment();
67  ($result = mysql_query($query)) or my_error($query, $conf['die_on_sql_error']);
68
69  $time = get_moment() - $start;
70
71  if (!isset($page['count_queries']))
72  {
73    $page['count_queries'] = 0;
74    $page['queries_time'] = 0;
75  }
76
77  $page['count_queries']++;
78  $page['queries_time']+= $time;
79
80  if ($conf['show_queries'])
81  {
82    $output = '';
83    $output.= '<pre>['.$page['count_queries'].'] ';
84    $output.= "\n".$query;
85    $output.= "\n".'(this query time : ';
86    $output.= '<b>'.number_format($time, 3, '.', ' ').' s)</b>';
87    $output.= "\n".'(total SQL time  : ';
88    $output.= number_format($page['queries_time'], 3, '.', ' ').' s)';
89    $output.= "\n".'(total time      : ';
90    $output.= number_format( ($time+$start-$t2), 3, '.', ' ').' s)';
91    if ( $result!=null and preg_match('/\s*SELECT\s+/i',$query) )
92    {
93      $output.= "\n".'(num rows        : ';
94      $output.= mysql_num_rows($result).' )';
95    }
96    elseif ( $result!=null
97      and preg_match('/\s*INSERT|UPDATE|REPLACE|DELETE\s+/i',$query) )
98    {
99      $output.= "\n".'(affected rows   : ';
100      $output.= mysql_affected_rows().' )';
101    }
102    $output.= "</pre>\n";
103
104    $debug .= $output;
105  }
106
107  return $result;
108}
109
110function pwg_db_changes($result) 
111{
112  return mysql_affected_rows($result);
113}
114
115function pwg_db_num_rows($result) 
116{
117  return mysql_num_rows($result);
118}
119
120function pwg_db_fetch_assoc($result)
121{
122  return mysql_fetch_assoc($result);
123}
124
125function pwg_db_fetch_row($result)
126{
127  return mysql_fetch_row($result);
128}
129
130function pwg_db_fetch_object($result)
131{
132  return mysql_fetch_object($result);
133}
134
135function pwg_free_result($result) 
136{
137  return mysql_free_result($result);
138}
139
140function pwg_db_real_escape_string($s)
141{
142  return mysql_real_escape_string($s);
143}
144
145function pwg_db_insert_id()
146{
147  return mysql_insert_id();
148}
149
150/**
151 *
152 * complex functions
153 *
154 */
155
156/**
157 * creates an array based on a query, this function is a very common pattern
158 * used here
159 *
160 * @param string $query
161 * @param string $fieldname
162 * @return array
163 */
164function array_from_query($query, $fieldname)
165{
166  $array = array();
167
168  $result = pwg_query($query);
169  while ($row = mysql_fetch_assoc($result))
170  {
171    array_push($array, $row[$fieldname]);
172  }
173
174  return $array;
175}
176
177define('MASS_UPDATES_SKIP_EMPTY', 1);
178/**
179 * updates multiple lines in a table
180 *
181 * @param string table_name
182 * @param array dbfields
183 * @param array datas
184 * @param int flags - if MASS_UPDATES_SKIP_EMPTY - empty values do not overwrite existing ones
185 * @return void
186 */
187function mass_updates($tablename, $dbfields, $datas, $flags=0)
188{
189  if (count($datas) == 0)
190    return;
191  // depending on the MySQL version, we use the multi table update or N update queries
192  if (count($datas) < 10 or version_compare(mysql_get_server_info(), '4.0.4') < 0)
193  { // MySQL is prior to version 4.0.4, multi table update feature is not available
194    foreach ($datas as $data)
195    {
196      $query = '
197UPDATE '.$tablename.'
198  SET ';
199      $is_first = true;
200      foreach ($dbfields['update'] as $key)
201      {
202        $separator = $is_first ? '' : ",\n    ";
203
204        if (isset($data[$key]) and $data[$key] != '')
205        {
206          $query.= $separator.$key.' = \''.$data[$key].'\'';
207        }
208        else
209        {
210          if ($flags & MASS_UPDATES_SKIP_EMPTY )
211            continue; // next field
212          $query.= "$separator$key = NULL";
213        }
214        $is_first = false;
215      }
216      if (!$is_first)
217      {// only if one field at least updated
218        $query.= '
219  WHERE ';
220        $is_first = true;
221        foreach ($dbfields['primary'] as $key)
222        {
223          if (!$is_first)
224          {
225            $query.= ' AND ';
226          }
227          if ( isset($data[$key]) )
228          {
229            $query.= $key.' = \''.$data[$key].'\'';
230          }
231          else
232          {
233            $query.= $key.' IS NULL';
234          }
235          $is_first = false;
236        }
237        pwg_query($query);
238      }
239    } // foreach update
240  } // if mysql_ver or count<X
241  else
242  {
243    // creation of the temporary table
244    $query = '
245SHOW FULL COLUMNS FROM '.$tablename;
246    $result = pwg_query($query);
247    $columns = array();
248    $all_fields = array_merge($dbfields['primary'], $dbfields['update']);
249    while ($row = pwg_db_fetch_assoc($result))
250    {
251      if (in_array($row['Field'], $all_fields))
252      {
253        $column = $row['Field'];
254        $column.= ' '.$row['Type'];
255
256        $nullable = true;
257        if (!isset($row['Null']) or $row['Null'] == '' or $row['Null']=='NO')
258        {
259          $column.= ' NOT NULL';
260          $nullable = false;
261        }
262        if (isset($row['Default']))
263        {
264          $column.= " default '".$row['Default']."'";
265        }
266        elseif ($nullable)
267        {
268          $column.= " default NULL";
269        }
270        if (isset($row['Collation']) and $row['Collation'] != 'NULL')
271        {
272          $column.= " collate '".$row['Collation']."'";
273        }
274        array_push($columns, $column);
275      }
276    }
277
278    $temporary_tablename = $tablename.'_'.micro_seconds();
279
280    $query = '
281CREATE TABLE '.$temporary_tablename.'
282(
283  '.implode(",\n  ", $columns).',
284  UNIQUE KEY the_key ('.implode(',', $dbfields['primary']).')
285)';
286
287    pwg_query($query);
288    mass_inserts($temporary_tablename, $all_fields, $datas);
289    if ( $flags & MASS_UPDATES_SKIP_EMPTY )
290      $func_set = create_function('$s', 'return "t1.$s = IFNULL(t2.$s, t1.$s)";');
291    else
292      $func_set = create_function('$s', 'return "t1.$s = t2.$s";');
293
294    // update of images table by joining with temporary table
295    $query = '
296UPDATE '.$tablename.' AS t1, '.$temporary_tablename.' AS t2
297  SET '.
298      implode(
299        "\n    , ",
300        array_map($func_set,$dbfields['update'])
301        ).'
302  WHERE '.
303      implode(
304        "\n    AND ",
305        array_map(
306          create_function('$s', 'return "t1.$s = t2.$s";'),
307          $dbfields['primary']
308          )
309        );
310    pwg_query($query);
311    $query = '
312DROP TABLE '.$temporary_tablename;
313    pwg_query($query);
314  }
315}
316
317
318/**
319 * inserts multiple lines in a table
320 *
321 * @param string table_name
322 * @param array dbfields
323 * @param array inserts
324 * @return void
325 */
326function mass_inserts($table_name, $dbfields, $datas)
327{
328  if (count($datas) != 0)
329  {
330    $first = true;
331
332    $query = 'SHOW VARIABLES LIKE \'max_allowed_packet\'';
333    list(, $packet_size) = pwg_db_fetch_row(pwg_query($query));
334    $packet_size = $packet_size - 2000; // The last list of values MUST not exceed 2000 character*/
335    $query = '';
336
337    foreach ($datas as $insert)
338    {
339      if (strlen($query) >= $packet_size)
340      {
341        pwg_query($query);
342        $first = true;
343      }
344
345      if ($first)
346      {
347        $query = '
348INSERT INTO '.$table_name.'
349  ('.implode(',', $dbfields).')
350  VALUES';
351        $first = false;
352      }
353      else
354      {
355        $query .= '
356  , ';
357      }
358
359      $query .= '(';
360      foreach ($dbfields as $field_id => $dbfield)
361      {
362        if ($field_id > 0)
363        {
364          $query .= ',';
365        }
366
367        if (!isset($insert[$dbfield]) or $insert[$dbfield] === '')
368        {
369          $query .= 'NULL';
370        }
371        else
372        {
373          $query .= "'".$insert[$dbfield]."'";
374        }
375      }
376      $query .= ')';
377    }
378    pwg_query($query);
379  }
380}
381
382/**
383 * Do maintenance on all PWG tables
384 *
385 * @return none
386 */
387function do_maintenance_all_tables()
388{
389  global $prefixeTable, $page;
390
391  $all_tables = array();
392
393  // List all tables
394  $query = 'SHOW TABLES LIKE \''.$prefixeTable.'%\'';
395  $result = pwg_query($query);
396  while ($row = pwg_db_fetch_assoc($result))
397  {
398    array_push($all_tables, $row[0]);
399  }
400
401  // Repair all tables
402  $query = 'REPAIR TABLE '.implode(', ', $all_tables);
403  $mysql_rc = pwg_query($query);
404
405  // Re-Order all tables
406  foreach ($all_tables as $table_name)
407  {
408    $all_primary_key = array();
409
410    $query = 'DESC '.$table_name.';';
411    $result = pwg_query($query);
412    while ($row = pwg_db_fetch_assoc($result))
413    {
414      if ($row['Key'] == 'PRI')
415      {
416        array_push($all_primary_key, $row['Field']);
417      }
418    }
419
420    if (count($all_primary_key) != 0)
421    {
422      $query = 'ALTER TABLE '.$table_name.' ORDER BY '.implode(', ', $all_primary_key).';';
423      $mysql_rc = $mysql_rc && pwg_query($query);
424    }
425  }
426
427  // Optimize all tables
428  $query = 'OPTIMIZE TABLE '.implode(', ', $all_tables);
429  $mysql_rc = $mysql_rc && pwg_query($query);
430  if ($mysql_rc)
431  {
432    array_push(
433          $page['infos'],
434          l10n('Optimizations completed')
435          );
436  }
437  else
438  {
439    array_push(
440          $page['errors'],
441          l10n('Optimizations errors')
442          );
443  }
444}
445
446// my_error returns (or send to standard output) the message concerning the
447// error occured for the last mysql query.
448function my_error($header, $die)
449{
450  $error = "[mysql error ".mysql_errno().'] '.mysql_error()."\n";
451  $error .= $header;
452
453  if ($die)
454  {
455    fatal_error($error);
456  }
457  echo("<pre>");
458  trigger_error($error, E_USER_WARNING);
459  echo("</pre>");
460}
461
462?>
Note: See TracBrowser for help on using the repository browser.