source: trunk/include/dblayer/functions_pgsql.inc.php @ 5267

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

Fix warning for postgresql installation
Remove unused function

File size: 13.0 KB
RevLine 
[4410]1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based picture gallery                                  |
4// +-----------------------------------------------------------------------+
[5196]5// | Copyright(C) 2008-2010 Piwigo Team                  http://piwigo.org |
[4410]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_PGSQL_VERSION', '8.0');
25define('DB_ENGINE', 'PostgreSQL');
26
27define('DB_REGEX_OPERATOR', '~');
28define('DB_RANDOM_FUNCTION', 'RANDOM');
29
30/**
31 *
32 * simple functions
33 *
34 */
35
[5236]36function pwg_db_connect($host, $user, $password, $database)
[4410]37{
38  $connection_string = '';
39  if (strpos($host,':') !== false) 
40  {
41    list($host, $port) = explode(':', $host);
42  }
43  $connection_string = sprintf('host=%s', $host);
44  if (!empty($port))
45  {
46    $connection_string .= sprintf(' port=%d', $port);
47  }
48  $connection_string .= sprintf(' user=%s password=%s dbname=%s', 
49                                $user, 
50                                $password,
51                                $database);
[5267]52  $link = @pg_connect($connection_string);
[5236]53  if (!$link)
54  {
55    throw new Exception("Can't connect to server");
56  }
57  else
58  {
59    return $link;
60  }
[4410]61}
62
63function pwg_db_check_charset() 
64{
65  return true;
66}
67
68function pwg_get_db_version() 
69{
70  list($pg_version) = pwg_db_fetch_row(pwg_query('SHOW SERVER_VERSION;'));
71 
72  return $pg_version;
73}
74
75function pwg_query($query)
76{
77  global $conf,$page,$debug,$t2;
78
[4886]79  $replace_pattern = '`REPLACE INTO\s(\S*)\s*([^)]*\))\s*VALUES\(([^,]*),(.*)\)\s*`mi'; 
80
[4410]81  $start = get_moment();
82
[4886]83  if (preg_match($replace_pattern, $query, $matches)
84      && $matches[1]==SESSIONS_TABLE)
85  {
86    $select_query = '
87SELECT id FROM '.$matches[1].'
88  WHERE id='.$matches[3];
89    ( $result = pg_query($select_query)) or die($query."\n<br>".pg_last_error());
90    if (pwg_db_num_rows($result)==1)
91    {
92      $query = '
93UPDATE '.$matches[1].'
94  SET expiration=now()
95  WHERE id='.$matches[3];
96    }
97    else
98    {
99      $query = '
100INSERT INTO '.$matches[1].'
101  '.$matches[2].' VALUES('.$matches[3].','.$matches[4].')';
102    }
103    ( $result = pg_query($query)) or die($query."\n<br>".pg_last_error());     
104  }
105  else 
106  {
107    ($result = pg_query($query)) or die($query."\n<br>".pg_last_error());
108  }
109
[4410]110  $time = get_moment() - $start;
111
112  if (!isset($page['count_queries']))
113  {
114    $page['count_queries'] = 0;
115    $page['queries_time'] = 0;
116  }
117
118  $page['count_queries']++;
119  $page['queries_time']+= $time;
120
121  if ($conf['show_queries'])
122  {
123    $output = '';
124    $output.= '<pre>['.$page['count_queries'].'] ';
125    $output.= "\n".$query;
126    $output.= "\n".'(this query time : ';
127    $output.= '<b>'.number_format($time, 3, '.', ' ').' s)</b>';
128    $output.= "\n".'(total SQL time  : ';
129    $output.= number_format($page['queries_time'], 3, '.', ' ').' s)';
130    $output.= "\n".'(total time      : ';
131    $output.= number_format( ($time+$start-$t2), 3, '.', ' ').' s)';
132    if ( $result!=null and preg_match('/\s*SELECT\s+/i',$query) )
133    {
134      $output.= "\n".'(num rows        : ';
135      $output.= pwg_db_num_rows($result).' )';
136    }
137    elseif ( $result!=null
138      and preg_match('/\s*INSERT|UPDATE|REPLACE|DELETE\s+/i',$query) )
139    {
140      $output.= "\n".'(affected rows   : ';
141      $output.= pwg_db_changes($result).' )';
142    }
143    $output.= "</pre>\n";
144
145    $debug .= $output;
146  }
147
148  return $result;
149}
150
151function pwg_db_nextval($column, $table)
152{
153  $query = '
154SELECT nextval(\''.$table.'_'.$column.'_seq\')';
155  list($next) = pwg_db_fetch_row(pwg_query($query));
156
157  return $next;
158}
159
160/**
161 *
162 * complex functions
163 *
164 */
165
166function pwg_db_changes($result) 
167{
168  return pg_affected_rows($result);
169}
170
171function pwg_db_num_rows($result) 
172{
173  return pg_num_rows($result);
174}
175
176function pwg_db_fetch_assoc($result)
177{
178  return pg_fetch_assoc($result);
179}
180
181function pwg_db_fetch_row($result)
182{
183  return pg_fetch_row($result);
184}
185
186function pwg_db_fetch_object($result)
187{
188  return pg_fetch_object($result);
189}
190
191function pwg_db_free_result($result) 
192{
193  return pg_free_result($result);
194}
195
196function pwg_db_real_escape_string($s)
197{
198  return pg_escape_string($s);
199}
200
[4892]201function pwg_db_insert_id($table=null, $column='id')
[4410]202{
[4892]203  $sequence = sprintf('%s_%s_seq', strtolower($table), $column);
204  $query = '
205SELECT CURRVAL(\''.$sequence.'\');';
206
207  list($id) = pwg_db_fetch_row(pwg_query($query));
208
209  return $id;
[4410]210}
211
212/**
213 *
214 * complex functions
215 *
216 */
217
218/**
219 * creates an array based on a query, this function is a very common pattern
220 * used here
221 *
222 * @param string $query
223 * @param string $fieldname
224 * @return array
225 */
226function array_from_query($query, $fieldname)
227{
228  $array = array();
229
230  $result = pwg_query($query);
231  while ($row = pg_fetch_assoc($result))
232  {
233    array_push($array, $row[$fieldname]);
234  }
235
236  return $array;
237}
238
239define('MASS_UPDATES_SKIP_EMPTY', 1);
240/**
241 * updates multiple lines in a table
242 *
243 * @param string table_name
244 * @param array dbfields
245 * @param array datas
246 * @param int flags - if MASS_UPDATES_SKIP_EMPTY - empty values do not overwrite existing ones
247 * @return void
248 */
249function mass_updates($tablename, $dbfields, $datas, $flags=0)
250{
251  if (count($datas) == 0)
252    return;
[4781]253
[4410]254  if (count($datas) < 10)
[4781]255  {
[4410]256    foreach ($datas as $data)
257    {
258      $query = '
259UPDATE '.$tablename.'
260  SET ';
261      $is_first = true;
262      foreach ($dbfields['update'] as $key)
263      {
264        $separator = $is_first ? '' : ",\n    ";
265
266        if (isset($data[$key]) and $data[$key] != '')
267        {
268          $query.= $separator.$key.' = \''.$data[$key].'\'';
269        }
270        else
271        {
272          if ($flags & MASS_UPDATES_SKIP_EMPTY )
273            continue; // next field
274          $query.= "$separator$key = NULL";
275        }
276        $is_first = false;
277      }
278      if (!$is_first)
279      {// only if one field at least updated
280        $query.= '
281  WHERE ';
282        $is_first = true;
283        foreach ($dbfields['primary'] as $key)
284        {
285          if (!$is_first)
286          {
287            $query.= ' AND ';
288          }
289          if ( isset($data[$key]) )
290          {
291            $query.= $key.' = \''.$data[$key].'\'';
292          }
293          else
294          {
295            $query.= $key.' IS NULL';
296          }
297          $is_first = false;
298        }
299        pwg_query($query);
300      }
301    } // foreach update
302  } // if mysql_ver or count<X
303  else
304  {
305    $all_fields = array_merge($dbfields['primary'], $dbfields['update']);
306    $temporary_tablename = $tablename.'_'.micro_seconds();
307    $query = '
308CREATE TABLE '.$temporary_tablename.'
309  AS SELECT * FROM '.$tablename.' WHERE 1=2';
310
311    pwg_query($query);
312    mass_inserts($temporary_tablename, $all_fields, $datas);
313    if ( $flags & MASS_UPDATES_SKIP_EMPTY )
314      $func_set = create_function('$s, $t', 'return "$s = IFNULL(t2.$s, '.$tablename.'.$s)";');
315    else
316      $func_set = create_function('$s', 'return "$s = t2.$s";');
317
318    // update of images table by joining with temporary table
319    $query = '
320UPDATE '.$tablename.'
321  SET '.
322      implode(
323        "\n    , ",
324        array_map($func_set, $dbfields['update'])
325        ).'
326FROM '.$temporary_tablename.' AS t2
327  WHERE '.
328      implode(
329        "\n    AND ",
330        array_map(
331          create_function('$s, $t', 'return "'.$tablename.'.$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 */
351
352function mass_inserts($table_name, $dbfields, $datas)
353{
354  if (count($datas) != 0)
355  {
356    $first = true;
357
358    $packet_size = 16777216;
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
[4781]419  $query = 'SELECT tablename FROM pg_tables
420WHERE tablename like \''.$prefixeTable.'%\'';
[4410]421
[4781]422  $all_tables = array_from_query($query, 'tablename');
[4410]423
424  // Optimize all tables
[4781]425  foreach ($all_tables as $table)
[4410]426  {
[4781]427    $query = 'VACUUM FULL '.$table;
428    pwg_query($query);
[4410]429  }
[4781]430  array_push($page['infos'],
[5036]431             l10n('All optimizations have been successfully completed.')
[4781]432             );
[4410]433}
434
[4833]435function pwg_db_concat($array)
436{
437  $string = implode($array, ',');
438  return 'ARRAY_TO_STRING(ARRAY['.$string.'])';
439}
440
[4781]441function pwg_db_concat_ws($array, $separator)
[4410]442{
[4781]443  $string = implode($array, ',');
444  return 'ARRAY_TO_STRING(ARRAY['.$string.'],\''.$separator.'\')';
[4410]445}
446
447function pwg_db_cast_to_text($string)
448{
449  return 'CAST('.$string.' AS TEXT)';
450}
451
452/**
453 * returns an array containing the possible values of an enum field
454 *
455 * @param string tablename
456 * @param string fieldname
457 */
458function get_enums($table, $field)
459{
460  $typname = preg_replace('/'.$GLOBALS['prefixeTable'].'/', '', $table); 
461  $typname .= '_' . $field;
462
463  $query = 'SELECT
464enumlabel FROM pg_enum JOIN pg_type
465  ON pg_enum.enumtypid=pg_type.oid
466  WHERE typname=\''.$typname.'\'
467';
468  $result = pwg_query($query);
469  while ($row = pwg_db_fetch_assoc($result))
470  {
471    $options[] = $row['enumlabel'];
472  }
473
474  return $options;
475}
476
477// get_boolean transforms a string to a boolean value. If the string is
478// "false" (case insensitive), then the boolean value false is returned. In
479// any other case, true is returned.
480function get_boolean( $string )
481{
482  $boolean = true;
483  if ('f' == $string || 'false' == $string)
484  {
485    $boolean = false;
486  }
487  return $boolean;
488}
489
490/**
491 * returns boolean string 'true' or 'false' if the given var is boolean
492 *
493 * @param mixed $var
494 * @return mixed
495 */
496function boolean_to_string($var)
497{
498  if (!empty($var) && ($var == 't'))
499  {
500    return 'true';
501  }
502  else
503  {
504    return 'false';
505  }
506}
507
508/**
509 *
510 * interval and date functions
511 *
512 */
513
514function pwg_db_get_recent_period_expression($period, $date='CURRENT_DATE')
515{
516  if ($date!='CURRENT_DATE')
517  {
518    $date = '\''.$date.'\'::date';
519  }
520
521  return '('.$date.' - \''.$period.' DAY\'::interval)::date';
522}
523
524function pwg_db_get_recent_period($period, $date='CURRENT_DATE')
525{
526  $query = 'select '.pwg_db_get_recent_period_expression($period, $date);
527  list($d) = pwg_db_fetch_row(pwg_query($query));
528
529  return $d;
530}
531
532function pwg_db_get_date_YYYYMM($date)
533{
534  return 'TO_CHAR('.$date.', \'YYYYMM\')';
535}
536
537function pwg_db_get_date_MMDD($date)
538{
539  return 'TO_CHAR('.$date.', \'MMDD\')';
540}
541
542function pwg_db_get_year($date)
543{
544  return 'EXTRACT(YEAR FROM '.$date.')';
545}
546
547function pwg_db_get_month($date)
548{
549  return 'EXTRACT(MONTH FROM '.$date.')';
550}
551
552function pwg_db_get_week($date, $mode=null)
553{
554  return 'EXTRACT(WEEK FROM '.$date.')';
555}
556
557function pwg_db_get_dayofmonth($date)
558{
559  return 'EXTRACT(DAY FROM '.$date.')';
560}
561
562function pwg_db_get_dayofweek($date)
563{
564  return 'EXTRACT(DOW FROM '.$date.')::INTEGER - 1';
565}
566
567function pwg_db_get_weekday($date)
568{
569  return 'EXTRACT(ISODOW FROM '.$date.')::INTEGER - 1';
570}
571
572// my_error returns (or send to standard output) the message concerning the
573// error occured for the last mysql query.
574function my_error($header, $die)
575{
576  $error = '[pgsql error]'.pg_last_error()."\n";
577  $error .= $header;
578
579  if ($die)
580  {
581    fatal_error($error);
582  }
583  echo("<pre>");
584  trigger_error($error, E_USER_WARNING);
585  echo("</pre>");
586}
587
588
589?>
Note: See TracBrowser for help on using the repository browser.