dolibarr  7.0.0-beta
pgsql.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001 Fabien Seisen <seisen@linuxfr.org>
3  * Copyright (C) 2002-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
4  * Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
5  * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
6  * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
7  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
8  * Copyright (C) 2012 Yann Droneaud <yann@droneaud.fr>
9  * Copyright (C) 2012 Florian Henry <florian.henry@open-concept.pro>
10  * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
31 require_once DOL_DOCUMENT_ROOT .'/core/db/DoliDB.class.php';
32 
36 class DoliDBPgsql extends DoliDB
37 {
39  public $type='pgsql'; // Name of manager
41  const LABEL='PostgreSQL'; // Label of manager
43  var $forcecharset='UTF8'; // Can't be static as it may be forced with a dynamic value
45  var $forcecollate=''; // Can't be static as it may be forced with a dynamic value
47  const VERSIONMIN='9.0.0'; // Version min database
49  private $_results;
50 
51  public $unescapeslashquot;
52  public $standard_conforming_strings;
53 
65  function __construct($type, $host, $user, $pass, $name='', $port=0)
66  {
67  global $conf,$langs;
68 
69  // Note that having "static" property for "$forcecharset" and "$forcecollate" will make error here in strict mode, so they are not static
70  if (! empty($conf->db->character_set)) $this->forcecharset=$conf->db->character_set;
71  if (! empty($conf->db->dolibarr_main_db_collation)) $this->forcecollate=$conf->db->dolibarr_main_db_collation;
72 
73  $this->database_user=$user;
74  $this->database_host=$host;
75  $this->database_port=$port;
76 
77  $this->transaction_opened=0;
78 
79  //print "Name DB: $host,$user,$pass,$name<br>";
80 
81  if (! function_exists("pg_connect"))
82  {
83  $this->connected = false;
84  $this->ok = false;
85  $this->error="Pgsql PHP functions are not available in this version of PHP";
86  dol_syslog(get_class($this)."::DoliDBPgsql : Pgsql PHP functions are not available in this version of PHP",LOG_ERR);
87  return $this->ok;
88  }
89 
90  if (! $host)
91  {
92  $this->connected = false;
93  $this->ok = false;
94  $this->error=$langs->trans("ErrorWrongHostParameter");
95  dol_syslog(get_class($this)."::DoliDBPgsql : Erreur Connect, wrong host parameters",LOG_ERR);
96  return $this->ok;
97  }
98 
99  // Essai connexion serveur
100  //print "$host, $user, $pass, $name, $port";
101  $this->db = $this->connect($host, $user, $pass, $name, $port);
102 
103  if ($this->db)
104  {
105  $this->connected = true;
106  $this->ok = true;
107  }
108  else
109  {
110  // host, login ou password incorrect
111  $this->connected = false;
112  $this->ok = false;
113  $this->error='Host, login or password incorrect';
114  dol_syslog(get_class($this)."::DoliDBPgsql : Erreur Connect ".$this->error,LOG_ERR);
115  }
116 
117  // Si connexion serveur ok et si connexion base demandee, on essaie connexion base
118  if ($this->connected && $name)
119  {
120  if ($this->select_db($name))
121  {
122  $this->database_selected = true;
123  $this->database_name = $name;
124  $this->ok = true;
125  }
126  else
127  {
128  $this->database_selected = false;
129  $this->database_name = '';
130  $this->ok = false;
131  $this->error=$this->error();
132  dol_syslog(get_class($this)."::DoliDBPgsql : Erreur Select_db ".$this->error,LOG_ERR);
133  }
134  }
135  else
136  {
137  // Pas de selection de base demandee, ok ou ko
138  $this->database_selected = false;
139  }
140 
141  return $this->ok;
142  }
143 
144 
153  static function convertSQLFromMysql($line,$type='auto',$unescapeslashquot=false)
154  {
155  // Removed empty line if this is a comment line for SVN tagging
156  if (preg_match('/^--\s\$Id/i',$line)) {
157  return '';
158  }
159  // Return line if this is a comment
160  if (preg_match('/^#/i',$line) || preg_match('/^$/i',$line) || preg_match('/^--/i',$line))
161  {
162  return $line;
163  }
164  if ($line != "")
165  {
166  // group_concat support (PgSQL >= 9.0)
167  // Replace group_concat(x) or group_concat(x SEPARATOR ',') with string_agg(x, ',')
168  $line = preg_replace('/GROUP_CONCAT/i', 'STRING_AGG', $line);
169  $line = preg_replace('/ SEPARATOR/i', ',', $line);
170  $line = preg_replace('/STRING_AGG\(([^,\)]+)\)/i', 'STRING_AGG(\\1, \',\')', $line);
171  //print $line."\n";
172 
173  if ($type == 'auto')
174  {
175  if (preg_match('/ALTER TABLE/i',$line)) $type='dml';
176  else if (preg_match('/CREATE TABLE/i',$line)) $type='dml';
177  else if (preg_match('/DROP TABLE/i',$line)) $type='dml';
178  }
179 
180  $line=preg_replace('/ as signed\)/i',' as integer)',$line);
181 
182  if ($type == 'dml')
183  {
184  $line=preg_replace('/\s/',' ',$line); // Replace tabulation with space
185 
186  // we are inside create table statement so lets process datatypes
187  if (preg_match('/(ISAM|innodb)/i',$line)) { // end of create table sequence
188  $line=preg_replace('/\)[\s\t]*type[\s\t]*=[\s\t]*(MyISAM|innodb).*;/i',');',$line);
189  $line=preg_replace('/\)[\s\t]*engine[\s\t]*=[\s\t]*(MyISAM|innodb).*;/i',');',$line);
190  $line=preg_replace('/,$/','',$line);
191  }
192 
193  // Process case: "CREATE TABLE llx_mytable(rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,code..."
194  if (preg_match('/[\s\t\(]*(\w*)[\s\t]+int.*auto_increment/i',$line,$reg)) {
195  $newline=preg_replace('/([\s\t\(]*)([a-zA-Z_0-9]*)[\s\t]+int.*auto_increment[^,]*/i','\\1 \\2 SERIAL PRIMARY KEY',$line);
196  //$line = "-- ".$line." replaced by --\n".$newline;
197  $line=$newline;
198  }
199 
200  // tinyint type conversion
201  $line=preg_replace('/tinyint\(?[0-9]*\)?/','smallint',$line);
202  $line=preg_replace('/tinyint/i','smallint',$line);
203 
204  // nuke unsigned
205  $line=preg_replace('/(int\w+|smallint)\s+unsigned/i','\\1',$line);
206 
207  // blob -> text
208  $line=preg_replace('/\w*blob/i','text',$line);
209 
210  // tinytext/mediumtext -> text
211  $line=preg_replace('/tinytext/i','text',$line);
212  $line=preg_replace('/mediumtext/i','text',$line);
213  $line=preg_replace('/longtext/i','text',$line);
214 
215  $line=preg_replace('/text\([0-9]+\)/i','text',$line);
216 
217  // change not null datetime field to null valid ones
218  // (to support remapping of "zero time" to null
219  $line=preg_replace('/datetime not null/i','datetime',$line);
220  $line=preg_replace('/datetime/i','timestamp',$line);
221 
222  // double -> numeric
223  $line=preg_replace('/^double/i','numeric',$line);
224  $line=preg_replace('/(\s*)double/i','\\1numeric',$line);
225  // float -> numeric
226  $line=preg_replace('/^float/i','numeric',$line);
227  $line=preg_replace('/(\s*)float/i','\\1numeric',$line);
228 
229  //Check tms timestamp field case (in Mysql this field is defautled to now and
230  // on update defaulted by now
231  $line=preg_replace('/(\s*)tms(\s*)timestamp/i','\\1tms timestamp without time zone DEFAULT now() NOT NULL',$line);
232 
233  // nuke ON UPDATE CURRENT_TIMESTAMP
234  $line=preg_replace('/(\s*)on(\s*)update(\s*)CURRENT_TIMESTAMP/i','\\1',$line);
235 
236  // unique index(field1,field2)
237  if (preg_match('/unique index\s*\((\w+\s*,\s*\w+)\)/i',$line))
238  {
239  $line=preg_replace('/unique index\s*\((\w+\s*,\s*\w+)\)/i','UNIQUE\(\\1\)',$line);
240  }
241 
242  // We remove end of requests "AFTER fieldxxx"
243  $line=preg_replace('/\sAFTER [a-z0-9_]+/i','',$line);
244 
245  // We remove start of requests "ALTER TABLE tablexxx" if this is a DROP INDEX
246  $line=preg_replace('/ALTER TABLE [a-z0-9_]+\s+DROP INDEX/i','DROP INDEX',$line);
247 
248  // Translate order to rename fields
249  if (preg_match('/ALTER TABLE ([a-z0-9_]+)\s+CHANGE(?: COLUMN)? ([a-z0-9_]+) ([a-z0-9_]+)(.*)$/i',$line,$reg))
250  {
251  $line = "-- ".$line." replaced by --\n";
252  $line.= "ALTER TABLE ".$reg[1]." RENAME COLUMN ".$reg[2]." TO ".$reg[3];
253  }
254 
255  // Translate order to modify field format
256  if (preg_match('/ALTER TABLE ([a-z0-9_]+)\s+MODIFY(?: COLUMN)? ([a-z0-9_]+) (.*)$/i',$line,$reg))
257  {
258  $line = "-- ".$line." replaced by --\n";
259  $newreg3=$reg[3];
260  $newreg3=preg_replace('/ DEFAULT NULL/i','',$newreg3);
261  $newreg3=preg_replace('/ NOT NULL/i','',$newreg3);
262  $newreg3=preg_replace('/ NULL/i','',$newreg3);
263  $newreg3=preg_replace('/ DEFAULT 0/i','',$newreg3);
264  $newreg3=preg_replace('/ DEFAULT \'?[0-9a-zA-Z_@]*\'?/i','',$newreg3);
265  $line.= "ALTER TABLE ".$reg[1]." ALTER COLUMN ".$reg[2]." TYPE ".$newreg3;
266  // TODO Add alter to set default value or null/not null if there is this in $reg[3]
267  }
268 
269  // alter table add primary key (field1, field2 ...) -> We remove the primary key name not accepted by PostGreSQL
270  // ALTER TABLE llx_dolibarr_modules ADD PRIMARY KEY pk_dolibarr_modules (numero, entity)
271  if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+PRIMARY\s+KEY\s*(.*)\s*\((.*)$/i',$line,$reg))
272  {
273  $line = "-- ".$line." replaced by --\n";
274  $line.= "ALTER TABLE ".$reg[1]." ADD PRIMARY KEY (".$reg[3];
275  }
276 
277  // Translate order to drop primary keys
278  // ALTER TABLE llx_dolibarr_modules DROP PRIMARY KEY pk_xxx
279  if (preg_match('/ALTER\s+TABLE\s*(.*)\s*DROP\s+PRIMARY\s+KEY\s*([^;]+)$/i',$line,$reg))
280  {
281  $line = "-- ".$line." replaced by --\n";
282  $line.= "ALTER TABLE ".$reg[1]." DROP CONSTRAINT ".$reg[2];
283  }
284 
285  // Translate order to drop foreign keys
286  // ALTER TABLE llx_dolibarr_modules DROP FOREIGN KEY fk_xxx
287  if (preg_match('/ALTER\s+TABLE\s*(.*)\s*DROP\s+FOREIGN\s+KEY\s*(.*)$/i',$line,$reg))
288  {
289  $line = "-- ".$line." replaced by --\n";
290  $line.= "ALTER TABLE ".$reg[1]." DROP CONSTRAINT ".$reg[2];
291  }
292 
293  // Translate order to add foreign keys
294  // ALTER TABLE llx_tablechild ADD CONSTRAINT fk_tablechild_fk_fieldparent FOREIGN KEY (fk_fieldparent) REFERENCES llx_tableparent (rowid)
295  if (preg_match('/ALTER\s+TABLE\s+(.*)\s*ADD CONSTRAINT\s+(.*)\s*FOREIGN\s+KEY\s*(.*)$/i',$line,$reg))
296  {
297  $line=preg_replace('/;$/','',$line);
298  $line.=" DEFERRABLE INITIALLY IMMEDIATE;";
299  }
300 
301  // alter table add [unique] [index] (field1, field2 ...)
302  // ALTER TABLE llx_accountingaccount ADD INDEX idx_accountingaccount_fk_pcg_version (fk_pcg_version)
303  if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+(UNIQUE INDEX|INDEX|UNIQUE)\s+(.*)\s*\(([\w,\s]+)\)/i',$line,$reg))
304  {
305  $fieldlist=$reg[4];
306  $idxname=$reg[3];
307  $tablename=$reg[1];
308  $line = "-- ".$line." replaced by --\n";
309  $line.= "CREATE ".(preg_match('/UNIQUE/',$reg[2])?'UNIQUE ':'')."INDEX ".$idxname." ON ".$tablename." (".$fieldlist.")";
310  }
311  }
312 
313  // To have postgresql case sensitive
314  $line=str_replace(' LIKE \'',' ILIKE \'',$line);
315  $line=str_replace(' LIKE BINARY \'',' LIKE \'',$line);
316 
317  // Replace INSERT IGNORE into INSERT
318  $line=preg_replace('/^INSERT IGNORE/','INSERT',$line);
319 
320  // Delete using criteria on other table must not declare twice the deleted table
321  // DELETE FROM tabletodelete USING tabletodelete, othertable -> DELETE FROM tabletodelete USING othertable
322  if (preg_match('/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i',$line,$reg))
323  {
324  if ($reg[1] == $reg[2]) // If same table, we remove second one
325  {
326  $line=preg_replace('/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i','DELETE FROM \\1 USING \\3', $line);
327  }
328  }
329 
330  // Remove () in the tables in FROM if 1 table
331  $line=preg_replace('/FROM\s*\((([a-z_]+)\s+as\s+([a-z_]+)\s*)\)/i','FROM \\1',$line);
332  //print $line."\n";
333 
334  // Remove () in the tables in FROM if 2 table
335  $line=preg_replace('/FROM\s*\(([a-z_]+\s+as\s+[a-z_]+)\s*,\s*([a-z_]+\s+as\s+[a-z_]+\s*)\)/i','FROM \\1, \\2',$line);
336  //print $line."\n";
337 
338  // Remove () in the tables in FROM if 3 table
339  $line=preg_replace('/FROM\s*\(([a-z_]+\s+as\s+[a-z_]+)\s*,\s*([a-z_]+\s+as\s+[a-z_]+\s*),\s*([a-z_]+\s+as\s+[a-z_]+\s*)\)/i','FROM \\1, \\2, \\3',$line);
340  //print $line."\n";
341 
342  // Remove () in the tables in FROM if 4 table
343  $line=preg_replace('/FROM\s*\(([a-z_]+\s+as\s+[a-z_]+)\s*,\s*([a-z_]+\s+as\s+[a-z_]+\s*),\s*([a-z_]+\s+as\s+[a-z_]+\s*),\s*([a-z_]+\s+as\s+[a-z_]+\s*)\)/i','FROM \\1, \\2, \\3, \\4',$line);
344  //print $line."\n";
345 
346  // Remove () in the tables in FROM if 5 table
347  $line=preg_replace('/FROM\s*\(([a-z_]+\s+as\s+[a-z_]+)\s*,\s*([a-z_]+\s+as\s+[a-z_]+\s*),\s*([a-z_]+\s+as\s+[a-z_]+\s*),\s*([a-z_]+\s+as\s+[a-z_]+\s*),\s*([a-z_]+\s+as\s+[a-z_]+\s*)\)/i','FROM \\1, \\2, \\3, \\4, \\5',$line);
348  //print $line."\n";
349 
350  // Replace espacing \' by ''.
351  // By default we do not (should be already done by db->escape function if required
352  // except for sql insert in data file that are mysql escaped so we removed them to
353  // be compatible with standard_conforming_strings=on that considers \ as ordinary character).
354  if ($unescapeslashquot) $line=preg_replace("/\\\'/","''",$line);
355 
356  //print "type=".$type." newline=".$line."<br>\n";
357  }
358 
359  return $line;
360  }
361 
370  function select_db($database)
371  {
372  if ($database == $this->database_name) return true;
373  else return false;
374  }
375 
387  function connect($host, $login, $passwd, $name, $port=0)
388  {
389  // use pg_pconnect() instead of pg_connect() if you want to use persistent connection costing 1ms, instead of 30ms for non persistent
390 
391  $this->db = false;
392 
393  // connections parameters must be protected (only \ and ' according to pg_connect() manual)
394  $host = str_replace(array("\\", "'"), array("\\\\", "\\'"), $host);
395  $login = str_replace(array("\\", "'"), array("\\\\", "\\'"), $login);
396  $passwd = str_replace(array("\\", "'"), array("\\\\", "\\'"), $passwd);
397  $name = str_replace(array("\\", "'"), array("\\\\", "\\'"), $name);
398  $port = str_replace(array("\\", "'"), array("\\\\", "\\'"), $port);
399 
400  if (! $name) $name="postgres"; // When try to connect using admin user
401 
402  // try first Unix domain socket (local)
403  if ((! empty($host) && $host == "socket") && ! defined('NOLOCALSOCKETPGCONNECT'))
404  {
405  $con_string = "dbname='".$name."' user='".$login."' password='".$passwd."'"; // $name may be empty
406  $this->db = @pg_connect($con_string);
407  }
408 
409  // if local connection failed or not requested, use TCP/IP
410  if (! $this->db)
411  {
412  if (! $host) $host = "localhost";
413  if (! $port) $port = 5432;
414 
415  $con_string = "host='".$host."' port='".$port."' dbname='".$name."' user='".$login."' password='".$passwd."'";
416  $this->db = @pg_connect($con_string);
417  }
418 
419  // now we test if at least one connect method was a success
420  if ($this->db)
421  {
422  $this->database_name = $name;
423  pg_set_error_verbosity($this->db, PGSQL_ERRORS_VERBOSE); // Set verbosity to max
424  pg_query($this->db, "set datestyle = 'ISO, YMD';");
425  }
426 
427  return $this->db;
428  }
429 
435  function getVersion()
436  {
437  $resql=$this->query('SHOW server_version');
438  if ($resql)
439  {
440  $liste=$this->fetch_array($resql);
441  return $liste['server_version'];
442  }
443  return '';
444  }
445 
451  function getDriverInfo()
452  {
453  return 'pgsql php driver';
454  }
455 
462  function close()
463  {
464  if ($this->db)
465  {
466  if ($this->transaction_opened > 0) dol_syslog(get_class($this)."::close Closing a connection with an opened transaction depth=".$this->transaction_opened,LOG_ERR);
467  $this->connected=false;
468  return pg_close($this->db);
469  }
470  return false;
471  }
472 
481  function query($query,$usesavepoint=0,$type='auto')
482  {
483  global $conf;
484 
485  $query = trim($query);
486 
487  // Convert MySQL syntax to PostgresSQL syntax
488  $query=$this->convertSQLFromMysql($query,$type,($this->unescapeslashquot && $this->standard_conforming_strings));
489  //print "After convertSQLFromMysql:\n".$query."<br>\n";
490 
491  if (! empty($conf->global->MAIN_DB_AUTOFIX_BAD_SQL_REQUEST))
492  {
493  // Fix bad formed requests. If request contains a date without quotes, we fix this but this should not occurs.
494  $loop=true;
495  while ($loop)
496  {
497  if (preg_match('/([^\'])([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9])/',$query))
498  {
499  $query=preg_replace('/([^\'])([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9])/','\\1\'\\2\'',$query);
500  dol_syslog("Warning: Bad formed request converted into ".$query,LOG_WARNING);
501  }
502  else $loop=false;
503  }
504  }
505 
506  if ($usesavepoint && $this->transaction_opened)
507  {
508  @pg_query($this->db, 'SAVEPOINT mysavepoint');
509  }
510 
511  if (! in_array($query,array('BEGIN','COMMIT','ROLLBACK'))) dol_syslog('sql='.$query, LOG_DEBUG);
512 
513  $ret = @pg_query($this->db, $query);
514 
515  //print $query;
516  if (! preg_match("/^COMMIT/i",$query) && ! preg_match("/^ROLLBACK/i",$query)) // Si requete utilisateur, on la sauvegarde ainsi que son resultset
517  {
518  if (! $ret)
519  {
520  if ($this->errno() != 'DB_ERROR_25P02') // Do not overwrite errors if this is a consecutive error
521  {
522  $this->lastqueryerror = $query;
523  $this->lasterror = $this->error();
524  $this->lasterrno = $this->errno();
525 
526  if ($conf->global->SYSLOG_LEVEL < LOG_DEBUG) dol_syslog(get_class($this)."::query SQL Error query: ".$query, LOG_ERR); // Log of request was not yet done previously
527  dol_syslog(get_class($this)."::query SQL Error message: ".$this->lasterror." (".$this->lasterrno.")", LOG_ERR);
528  dol_syslog(get_class($this)."::query SQL Error usesavepoint = ".$usesavepoint, LOG_ERR);
529  }
530 
531  if ($usesavepoint && $this->transaction_opened) // Warning, after that errno will be erased
532  {
533  @pg_query($this->db, 'ROLLBACK TO SAVEPOINT mysavepoint');
534  }
535  }
536  $this->lastquery=$query;
537  $this->_results = $ret;
538  }
539 
540  return $ret;
541  }
542 
549  function fetch_object($resultset)
550  {
551  // If resultset not provided, we take the last used by connexion
552  if (! is_resource($resultset)) { $resultset=$this->_results; }
553  return pg_fetch_object($resultset);
554  }
555 
562  function fetch_array($resultset)
563  {
564  // If resultset not provided, we take the last used by connexion
565  if (! is_resource($resultset)) { $resultset=$this->_results; }
566  return pg_fetch_array($resultset);
567  }
568 
575  function fetch_row($resultset)
576  {
577  // Si le resultset n'est pas fourni, on prend le dernier utilise sur cette connexion
578  if (! is_resource($resultset)) { $resultset=$this->_results; }
579  return pg_fetch_row($resultset);
580  }
581 
589  function num_rows($resultset)
590  {
591  // If resultset not provided, we take the last used by connexion
592  if (! is_resource($resultset)) { $resultset=$this->_results; }
593  return pg_num_rows($resultset);
594  }
595 
603  function affected_rows($resultset)
604  {
605  // If resultset not provided, we take the last used by connexion
606  if (! is_resource($resultset)) { $resultset=$this->_results; }
607  // pgsql necessite un resultset pour cette fonction contrairement
608  // a mysql qui prend un link de base
609  return pg_affected_rows($resultset);
610  }
611 
612 
619  function free($resultset=null)
620  {
621  // If resultset not provided, we take the last used by connexion
622  if (! is_resource($resultset)) { $resultset=$this->_results; }
623  // Si resultset en est un, on libere la memoire
624  if (is_resource($resultset)) pg_free_result($resultset);
625  }
626 
627 
635  function plimit($limit=0,$offset=0)
636  {
637  global $conf;
638  if (empty($limit)) return "";
639  if ($limit < 0) $limit=$conf->liste_limit;
640  if ($offset > 0) return " LIMIT ".$limit." OFFSET ".$offset." ";
641  else return " LIMIT $limit ";
642  }
643 
644 
651  function escape($stringtoencode)
652  {
653  return pg_escape_string($stringtoencode);
654  }
655 
663  function idate($param)
664  {
665  return dol_print_date($param,"%Y-%m-%d %H:%M:%S");
666  }
667 
676  function ifsql($test,$resok,$resko)
677  {
678  return '(CASE WHEN '.$test.' THEN '.$resok.' ELSE '.$resko.' END)';
679  }
680 
686  function errno()
687  {
688  if (! $this->connected) {
689  // Si il y a eu echec de connexion, $this->db n'est pas valide.
690  return 'DB_ERROR_FAILED_TO_CONNECT';
691  }
692  else {
693  // Constants to convert error code to a generic Dolibarr error code
694  $errorcode_map = array(
695  1004 => 'DB_ERROR_CANNOT_CREATE',
696  1005 => 'DB_ERROR_CANNOT_CREATE',
697  1006 => 'DB_ERROR_CANNOT_CREATE',
698  1007 => 'DB_ERROR_ALREADY_EXISTS',
699  1008 => 'DB_ERROR_CANNOT_DROP',
700  1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
701  1044 => 'DB_ERROR_ACCESSDENIED',
702  1046 => 'DB_ERROR_NODBSELECTED',
703  1048 => 'DB_ERROR_CONSTRAINT',
704  '42P07' => 'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS',
705  '42703' => 'DB_ERROR_NOSUCHFIELD',
706  1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
707  42701=> 'DB_ERROR_COLUMN_ALREADY_EXISTS',
708  '42710' => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
709  '23505' => 'DB_ERROR_RECORD_ALREADY_EXISTS',
710  '42704' => 'DB_ERROR_NO_INDEX_TO_DROP', // May also be Type xxx does not exists
711  '42601' => 'DB_ERROR_SYNTAX',
712  '42P16' => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
713  1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
714  1091 => 'DB_ERROR_NOSUCHFIELD',
715  1100 => 'DB_ERROR_NOT_LOCKED',
716  1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
717  '42P01' => 'DB_ERROR_NOSUCHTABLE',
718  '23503' => 'DB_ERROR_NO_PARENT',
719  1217 => 'DB_ERROR_CHILD_EXISTS',
720  1451 => 'DB_ERROR_CHILD_EXISTS',
721  '42P04' => 'DB_DATABASE_ALREADY_EXISTS'
722  );
723 
724  $errorlabel=pg_last_error($this->db);
725  $errorcode='';
726  if (preg_match('/: *([0-9P]+):/',$errorlabel,$reg))
727  {
728  $errorcode=$reg[1];
729  if (isset($errorcode_map[$errorcode]))
730  {
731  return $errorcode_map[$errorcode];
732  }
733  }
734  $errno=$errorcode?$errorcode:$errorlabel;
735  return ($errno?'DB_ERROR_'.$errno:'0');
736  }
737  // '/(Table does not exist\.|Relation [\"\'].*[\"\'] does not exist|sequence does not exist|class ".+" not found)$/' => 'DB_ERROR_NOSUCHTABLE',
738  // '/table [\"\'].*[\"\'] does not exist/' => 'DB_ERROR_NOSUCHTABLE',
739  // '/Relation [\"\'].*[\"\'] already exists|Cannot insert a duplicate key into (a )?unique index.*/' => 'DB_ERROR_RECORD_ALREADY_EXISTS',
740  // '/divide by zero$/' => 'DB_ERROR_DIVZERO',
741  // '/pg_atoi: error in .*: can\'t parse /' => 'DB_ERROR_INVALID_NUMBER',
742  // '/ttribute [\"\'].*[\"\'] not found$|Relation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => 'DB_ERROR_NOSUCHFIELD',
743  // '/parser: parse error at or near \"/' => 'DB_ERROR_SYNTAX',
744  // '/referential integrity violation/' => 'DB_ERROR_CONSTRAINT'
745  }
746 
752  function error()
753  {
754  return pg_last_error($this->db);
755  }
756 
764  function last_insert_id($tab,$fieldid='rowid')
765  {
766  //$result = pg_query($this->db,"SELECT MAX(".$fieldid.") FROM ".$tab);
767  $result = pg_query($this->db,"SELECT currval('".$tab."_".$fieldid."_seq')");
768  if (! $result)
769  {
770  print pg_last_error($this->db);
771  exit;
772  }
773  //$nbre = pg_num_rows($result);
774  $row = pg_fetch_result($result,0,0);
775  return $row;
776  }
777 
786  function encrypt($fieldorvalue, $withQuotes=0)
787  {
788  global $conf;
789 
790  // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
791  $cryptType = ($conf->db->dolibarr_main_db_encryption?$conf->db->dolibarr_main_db_encryption:0);
792 
793  //Encryption key
794  $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey)?$conf->db->dolibarr_main_db_cryptkey:'');
795 
796  $return = $fieldorvalue;
797  return ($withQuotes?"'":"").$this->escape($return).($withQuotes?"'":"");
798  }
799 
800 
807  function decrypt($value)
808  {
809  global $conf;
810 
811  // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
812  $cryptType = ($conf->db->dolibarr_main_db_encryption?$conf->db->dolibarr_main_db_encryption:0);
813 
814  //Encryption key
815  $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey)?$conf->db->dolibarr_main_db_cryptkey:'');
816 
817  $return = $value;
818  return $return;
819  }
820 
821 
827  function DDLGetConnectId()
828  {
829  return '?';
830  }
831 
832 
833 
845  function DDLCreateDb($database,$charset='',$collation='',$owner='')
846  {
847  if (empty($charset)) $charset=$this->forcecharset;
848  if (empty($collation)) $collation=$this->forcecollate;
849 
850  // Test charset match LC_TYPE (pgsql error otherwise)
851  //print $charset.' '.setlocale(LC_CTYPE,'0'); exit;
852 
853  $sql='CREATE DATABASE "'.$database.'" OWNER "'.$owner.'" ENCODING \''.$charset.'\'';
854  dol_syslog($sql,LOG_DEBUG);
855  $ret=$this->query($sql);
856  return $ret;
857  }
858 
866  function DDLListTables($database, $table='')
867  {
868  $listtables=array();
869 
870  $like = '';
871  if ($table) $like = " AND table_name LIKE '".$table."'";
872  $result = pg_query($this->db, "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'".$like." ORDER BY table_name");
873  if ($result)
874  {
875  while($row = $this->fetch_row($result))
876  {
877  $listtables[] = $row[0];
878  }
879  }
880  return $listtables;
881  }
882 
890  function DDLInfoTable($table)
891  {
892  $infotables=array();
893 
894  $sql="SELECT ";
895  $sql.=" infcol.column_name as \"Column\",";
896  $sql.=" CASE WHEN infcol.character_maximum_length IS NOT NULL THEN infcol.udt_name || '('||infcol.character_maximum_length||')'";
897  $sql.=" ELSE infcol.udt_name";
898  $sql.=" END as \"Type\",";
899  $sql.=" infcol.collation_name as \"Collation\",";
900  $sql.=" infcol.is_nullable as \"Null\",";
901  $sql.=" '' as \"Key\",";
902  $sql.=" infcol.column_default as \"Default\",";
903  $sql.=" '' as \"Extra\",";
904  $sql.=" '' as \"Privileges\"";
905  $sql.=" FROM information_schema.columns infcol";
906  $sql.=" WHERE table_schema='public' ";
907  $sql.=" AND table_name='".$table."'";
908  $sql.=" ORDER BY ordinal_position;";
909 
910  dol_syslog($sql,LOG_DEBUG);
911  $result = $this->query($sql);
912  if ($result)
913  {
914  while($row = $this->fetch_row($result))
915  {
916  $infotables[] = $row;
917  }
918  }
919  return $infotables;
920  }
921 
922 
935  function DDLCreateTable($table,$fields,$primary_key,$type,$unique_keys=null,$fulltext_keys=null,$keys=null)
936  {
937  // FIXME: $fulltext_keys parameter is unused
938 
939  // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra
940  // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
941  $sql = "create table ".$table."(";
942  $i=0;
943  foreach($fields as $field_name => $field_desc)
944  {
945  $sqlfields[$i] = $field_name." ";
946  $sqlfields[$i] .= $field_desc['type'];
947  if( preg_match("/^[^\s]/i",$field_desc['value']))
948  $sqlfields[$i] .= "(".$field_desc['value'].")";
949  else if( preg_match("/^[^\s]/i",$field_desc['attribute']))
950  $sqlfields[$i] .= " ".$field_desc['attribute'];
951  else if( preg_match("/^[^\s]/i",$field_desc['default']))
952  {
953  if(preg_match("/null/i",$field_desc['default']))
954  $sqlfields[$i] .= " default ".$field_desc['default'];
955  else
956  $sqlfields[$i] .= " default '".$field_desc['default']."'";
957  }
958  else if( preg_match("/^[^\s]/i",$field_desc['null']))
959  $sqlfields[$i] .= " ".$field_desc['null'];
960 
961  else if( preg_match("/^[^\s]/i",$field_desc['extra']))
962  $sqlfields[$i] .= " ".$field_desc['extra'];
963  $i++;
964  }
965  if($primary_key != "")
966  $pk = "primary key(".$primary_key.")";
967 
968  if(is_array($unique_keys))
969  {
970  $i = 0;
971  foreach($unique_keys as $key => $value)
972  {
973  $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$value."')";
974  $i++;
975  }
976  }
977  if(is_array($keys))
978  {
979  $i = 0;
980  foreach($keys as $key => $value)
981  {
982  $sqlk[$i] = "KEY ".$key." (".$value.")";
983  $i++;
984  }
985  }
986  $sql .= implode(',',$sqlfields);
987  if($primary_key != "")
988  $sql .= ",".$pk;
989  if(is_array($unique_keys))
990  $sql .= ",".implode(',',$sqluq);
991  if(is_array($keys))
992  $sql .= ",".implode(',',$sqlk);
993  $sql .=") type=".$type;
994 
995  dol_syslog($sql,LOG_DEBUG);
996  if(! $this->query($sql))
997  return -1;
998  else
999  return 1;
1000  }
1001 
1008  function DDLDropTable($table)
1009  {
1010  $sql = "DROP TABLE ".$table;
1011 
1012  if (! $this->query($sql))
1013  return -1;
1014  else
1015  return 1;
1016  }
1017 
1027  function DDLCreateUser($dolibarr_main_db_host,$dolibarr_main_db_user,$dolibarr_main_db_pass,$dolibarr_main_db_name)
1028  {
1029  // Note: using ' on user does not works with pgsql
1030  $sql = "CREATE USER ".$this->escape($dolibarr_main_db_user)." with password '".$this->escape($dolibarr_main_db_pass)."'";
1031 
1032  dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1033  $resql=$this->query($sql);
1034  if (! $resql)
1035  {
1036  return -1;
1037  }
1038 
1039  return 1;
1040  }
1041 
1049  function DDLDescTable($table,$field="")
1050  {
1051  $sql ="SELECT attname FROM pg_attribute, pg_type WHERE typname = '".$table."' AND attrelid = typrelid";
1052  $sql.=" AND attname NOT IN ('cmin', 'cmax', 'ctid', 'oid', 'tableoid', 'xmin', 'xmax')";
1053  if ($field) $sql.= " AND attname = '".$field."'";
1054 
1055  dol_syslog($sql,LOG_DEBUG);
1056  $this->_results = $this->query($sql);
1057  return $this->_results;
1058  }
1059 
1069  function DDLAddField($table,$field_name,$field_desc,$field_position="")
1070  {
1071  // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra
1072  // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
1073  $sql= "ALTER TABLE ".$table." ADD ".$field_name." ";
1074  $sql .= $field_desc['type'];
1075  if(preg_match("/^[^\s]/i",$field_desc['value']))
1076  if (! in_array($field_desc['type'],array('int','date','datetime')))
1077  {
1078  $sql.= "(".$field_desc['value'].")";
1079  }
1080  if (preg_match("/^[^\s]/i",$field_desc['attribute']))
1081  $sql .= " ".$field_desc['attribute'];
1082  if (preg_match("/^[^\s]/i",$field_desc['null']))
1083  $sql .= " ".$field_desc['null'];
1084  if (preg_match("/^[^\s]/i",$field_desc['default']))
1085  if (preg_match("/null/i",$field_desc['default']))
1086  $sql .= " default ".$field_desc['default'];
1087  else
1088  $sql .= " default '".$field_desc['default']."'";
1089  if (preg_match("/^[^\s]/i",$field_desc['extra']))
1090  $sql .= " ".$field_desc['extra'];
1091  $sql .= " ".$field_position;
1092 
1093  dol_syslog($sql,LOG_DEBUG);
1094  if(! $this -> query($sql))
1095  return -1;
1096  return 1;
1097  }
1098 
1107  function DDLUpdateField($table,$field_name,$field_desc)
1108  {
1109  $sql = "ALTER TABLE ".$table;
1110  $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type'];
1111  if ($field_desc['type'] == 'double' || $field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int' || $field_desc['type'] == 'varchar') {
1112  $sql.="(".$field_desc['value'].")";
1113  }
1114 
1115  if ($field_desc['null'] == 'not null' || $field_desc['null'] == 'NOT NULL')
1116  {
1117  // We will try to change format of column to NOT NULL. To be sure the ALTER works, we try to update fields that are NULL
1118  if ($field_desc['type'] == 'varchar' || $field_desc['type'] == 'text')
1119  {
1120  $sqlbis="UPDATE ".$table." SET ".$field_name." = '".$this->escape($field_desc['default'] ? $field_desc['default'] : '')."' WHERE ".$field_name." IS NULL";
1121  $this->query($sqlbis);
1122  }
1123  elseif ($field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int')
1124  {
1125  $sqlbis="UPDATE ".$table." SET ".$field_name." = ".((int) $this->escape($field_desc['default'] ? $field_desc['default'] : 0))." WHERE ".$field_name." IS NULL";
1126  $this->query($sqlbis);
1127  }
1128  }
1129 
1130  if ($field_desc['default'] != '')
1131  {
1132  if ($field_desc['type'] == 'double' || $field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int') $sql.=" DEFAULT ".$this->escape($field_desc['default']);
1133  elseif ($field_desc['type'] == 'text') $sql.=" DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields
1134  }
1135 
1136  dol_syslog($sql,LOG_DEBUG);
1137  if (! $this->query($sql))
1138  return -1;
1139  return 1;
1140  }
1141 
1149  function DDLDropField($table,$field_name)
1150  {
1151  $sql= "ALTER TABLE ".$table." DROP COLUMN ".$field_name;
1152  dol_syslog($sql,LOG_DEBUG);
1153  if (! $this->query($sql))
1154  {
1155  $this->error=$this->lasterror();
1156  return -1;
1157  }
1158  return 1;
1159  }
1160 
1167  {
1168  $resql=$this->query('SHOW SERVER_ENCODING');
1169  if ($resql)
1170  {
1171  $liste=$this->fetch_array($resql);
1172  return $liste['server_encoding'];
1173  }
1174  else return '';
1175  }
1176 
1183  {
1184  $resql=$this->query('SHOW SERVER_ENCODING');
1185  $liste = array();
1186  if ($resql)
1187  {
1188  $i = 0;
1189  while ($obj = $this->fetch_object($resql))
1190  {
1191  $liste[$i]['charset'] = $obj->server_encoding;
1192  $liste[$i]['description'] = 'Default database charset';
1193  $i++;
1194  }
1195  $this->free($resql);
1196  } else {
1197  return null;
1198  }
1199  return $liste;
1200  }
1201 
1208  {
1209  $resql=$this->query('SHOW LC_COLLATE');
1210  if ($resql)
1211  {
1212  $liste=$this->fetch_array($resql);
1213  return $liste['lc_collate'];
1214  }
1215  else return '';
1216  }
1217 
1224  {
1225  $resql=$this->query('SHOW LC_COLLATE');
1226  $liste = array();
1227  if ($resql)
1228  {
1229  $i = 0;
1230  while ($obj = $this->fetch_object($resql) )
1231  {
1232  $liste[$i]['collation'] = $obj->lc_collate;
1233  $i++;
1234  }
1235  $this->free($resql);
1236  } else {
1237  return null;
1238  }
1239  return $liste;
1240  }
1241 
1247  function getPathOfDump()
1248  {
1249  $fullpathofdump='/pathtopgdump/pg_dump';
1250 
1251  if (file_exists('/usr/bin/pg_dump'))
1252  {
1253  $fullpathofdump='/usr/bin/pg_dump';
1254  }
1255  else
1256  {
1257  // TODO L'utilisateur de la base doit etre un superadmin pour lancer cette commande
1258  $resql=$this->query('SHOW data_directory');
1259  if ($resql)
1260  {
1261  $liste=$this->fetch_array($resql);
1262  $basedir=$liste['data_directory'];
1263  $fullpathofdump=preg_replace('/data$/','bin',$basedir).'/pg_dump';
1264  }
1265  }
1266 
1267  return $fullpathofdump;
1268  }
1269 
1275  function getPathOfRestore()
1276  {
1277  //$tool='pg_restore';
1278  $tool='psql';
1279 
1280  $fullpathofdump='/pathtopgrestore/'.$tool;
1281 
1282  if (file_exists('/usr/bin/'.$tool))
1283  {
1284  $fullpathofdump='/usr/bin/'.$tool;
1285  }
1286  else
1287  {
1288  // TODO L'utilisateur de la base doit etre un superadmin pour lancer cette commande
1289  $resql=$this->query('SHOW data_directory');
1290  if ($resql)
1291  {
1292  $liste=$this->fetch_array($resql);
1293  $basedir=$liste['data_directory'];
1294  $fullpathofdump=preg_replace('/data$/','bin',$basedir).'/'.$tool;
1295  }
1296  }
1297 
1298  return $fullpathofdump;
1299  }
1300 
1307  function getServerParametersValues($filter='')
1308  {
1309  $result=array();
1310 
1311  $resql='select name,setting from pg_settings';
1312  if ($filter) $resql.=" WHERE name = '".$this->escape($filter)."'";
1313  $resql=$this->query($resql);
1314  if ($resql)
1315  {
1316  while ($obj=$this->fetch_object($resql)) $result[$obj->name]=$obj->setting;
1317  }
1318 
1319  return $result;
1320  }
1321 
1328  function getServerStatusValues($filter='')
1329  {
1330  /* This is to return current running requests.
1331  $sql='SELECT datname,procpid,current_query FROM pg_stat_activity ORDER BY procpid';
1332  if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
1333  $resql=$this->query($sql);
1334  if ($resql)
1335  {
1336  $obj=$this->fetch_object($resql);
1337  $result[$obj->Variable_name]=$obj->Value;
1338  }
1339  */
1340 
1341  return array();
1342  }
1343 }
affected_rows($resultset)
Renvoie le nombre de lignes dans le resultat d'une requete INSERT, DELETE ou UPDATE.
lastqueryerror()
Return last query in error.
DDLUpdateField($table, $field_name, $field_desc)
Update format of a field into a table.
DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys=null, $fulltext_keys=null, $keys=null)
Create a table into database.
getServerStatusValues($filter='')
Return value of server status.
idate($param)
Convert (by PHP) a GM Timestamp date into a GM string date to insert into a date field.
getListOfCollation()
Return list of available collation that can be used for database.
DDLListTables($database, $table='')
List tables into a database.
decrypt($value)
Decrypt sensitive data in database.
lastquery()
Return last request executed with query()
getPathOfDump()
Return full path of dump program.
Class to manage Dolibarr database access.
DDLDropTable($table)
Drop a table into database.
select_db($database)
Select a database Ici postgresql n'a aucune fonction equivalente de mysql_select_db On compare juste ...
Class to drive a Postgresql database for Dolibarr.
Definition: pgsql.class.php:36
static convertSQLFromMysql($line, $type='auto', $unescapeslashquot=false)
Convert a SQL request in Mysql syntax to native syntax.
getVersion()
Return version of database server.
lasterror()
Return last error label.
$type
Database type.
Definition: pgsql.class.php:39
fetch_array($resultset)
Return datas as an array.
DDLInfoTable($table)
List information of columns into a table.
escape($stringtoencode)
Escape a string to insert data.
free($resultset=null)
Libere le dernier resultset utilise sur cette connexion.
fetch_row($resultset)
Return datas as an array.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
DDLDescTable($table, $field="")
Return a pointer of line with description of a table or field.
DDLAddField($table, $field_name, $field_desc, $field_position="")
Create a new field into table.
close()
Close database connexion.
fetch_object($resultset)
Renvoie la ligne courante (comme un objet) pour le curseur resultset.
DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
Create a user to connect to database.
getDriverInfo()
Return version of database client driver.
DDLDropField($table, $field_name)
Drop a field from table.
connect($host, $login, $passwd, $name, $port=0)
Connexion to server.
getServerParametersValues($filter='')
Return value of server parameters.
getDefaultCollationDatabase()
Return collation used in database.
error()
Renvoie le texte de l'erreur pgsql de l'operation precedente.
dol_print_date($time, $format='', $tzoutput='tzserver', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
print
Draft customers invoices.
Definition: index.php:91
DDLCreateDb($database, $charset='', $collation='', $owner='')
Create a new database Do not use function xxx_create_db (xxx=mysql, ...) as they are deprecated We fo...
getDefaultCharacterSetDatabase()
Return charset used to store data in database.
num_rows($resultset)
Return number of lines for result of a SELECT.
ifsql($test, $resok, $resko)
Format a SQL IF.
plimit($limit=0, $offset=0)
Define limits and offset of request.
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if(!empty($conf->fournisseur->enabled)&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->societe->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if(!empty($conf->fournisseur->enabled)&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1013
const VERSIONMIN
Version min database.
Definition: pgsql.class.php:47
query($query, $usesavepoint=0, $type='auto')
Convert request to PostgreSQL syntax, execute it and return the resultset.
__construct($type, $host, $user, $pass, $name='', $port=0)
Constructor.
Definition: pgsql.class.php:65
$forcecollate
Collate used to force collate when creating database.
Definition: pgsql.class.php:45
getListOfCharacterSet()
Return list of available charset that can be used to store data in database.
lasterrno()
Return last error code.
DDLGetConnectId()
Return connexion ID.
getPathOfRestore()
Return full path of restore program.
const LABEL
Database label.
Definition: pgsql.class.php:41
errno()
Renvoie le code erreur generique de l'operation precedente.
encrypt($fieldorvalue, $withQuotes=0)
Encrypt sensitive data in database Warning: This function includes the escape, so it must use direct ...
$forcecharset
Charset.
Definition: pgsql.class.php:43
last_insert_id($tab, $fieldid='rowid')
Get last ID after an insert INSERT.