33require_once DOL_DOCUMENT_ROOT.
'/core/db/DoliDB.class.php';
58 public $unescapeslashquot =
false;
62 public $standard_conforming_strings =
false;
84 public function __construct(
$type, $host, $user, $pass, $name =
'', $port = 0, $forcenew =
false)
89 if (!empty(
$conf->db->character_set)) {
90 $this->forcecharset =
$conf->db->character_set;
92 if (!empty(
$conf->db->dolibarr_main_db_collation)) {
93 $this->forcecollate =
$conf->db->dolibarr_main_db_collation;
96 $this->database_user = $user;
97 $this->database_host = $host;
98 $this->database_port = $port;
100 $this->transaction_opened = 0;
104 if (!function_exists(
"pg_connect")) {
105 $this->connected =
false;
107 $this->
error =
"Pgsql PHP functions are not available in this version of PHP";
108 dol_syslog(get_class($this).
"::DoliDBPgsql : Pgsql PHP functions are not available in this version of PHP", LOG_ERR);
113 $this->connected =
false;
115 $this->
error = $langs->trans(
"ErrorWrongHostParameter");
116 dol_syslog(get_class($this).
"::DoliDBPgsql : Connection Error, wrong host parameters", LOG_ERR);
122 $this->db = $this->
connect($host, $user, $pass, $name, $port, $forcenew);
125 $this->connected =
true;
129 $this->connected =
false;
131 $this->
error =
'Host, login or password incorrect';
132 dol_syslog(get_class($this).
"::DoliDBPgsql : Connection Error ".$this->
error.
'. Failed to connect to host='.$host.
' port='.$port.
' user='.$user, LOG_ERR);
136 if ($this->connected && $name) {
138 $this->database_selected =
true;
139 $this->database_name = $name;
142 $this->database_selected =
false;
143 $this->database_name =
'';
146 dol_syslog(get_class($this).
"::DoliDBPgsql : Select_db Error ".$this->
error, LOG_ERR);
150 $this->database_selected =
false;
168 if (preg_match(
'/^--\s\$Id/i', $line)) {
172 if (preg_match(
'/^#/i', $line) || preg_match(
'/^$/i', $line) || preg_match(
'/^--/i', $line)) {
178 $line = preg_replace(
'/GROUP_CONCAT/i',
'STRING_AGG', $line);
179 $line = preg_replace(
'/ SEPARATOR/i',
',', $line);
180 $line = preg_replace(
'/STRING_AGG\(([^,\)]+)\)/i',
'STRING_AGG(\\1, \',\')', $line);
181 $line = preg_replace(
'/STRING_AGG\(([^,]+),([^\)]+)\)/i',
'STRING_AGG(\\1::TEXT,\\2::TEXT)', $line);
184 if (
$type ==
'auto') {
185 if (preg_match(
'/ALTER TABLE/i', $line)) {
187 } elseif (preg_match(
'/CREATE TABLE/i', $line)) {
189 } elseif (preg_match(
'/DROP TABLE/i', $line)) {
194 $line = preg_replace(
'/ as signed\)/i',
' as integer)', $line);
196 if (
$type ==
'dml') {
199 $line = preg_replace(
'/\s/',
' ', $line);
202 if (preg_match(
'/(ISAM|innodb)/i', $line)) {
203 $line = preg_replace(
'/\)[\s\t]*type[\s\t]*=[\s\t]*(MyISAM|innodb).*;/i',
');', $line);
204 $line = preg_replace(
'/\)[\s\t]*engine[\s\t]*=[\s\t]*(MyISAM|innodb).*;/i',
');', $line);
205 $line = preg_replace(
'/,$/',
'', $line);
209 if (preg_match(
'/[\s\t\(]*(\w*)[\s\t]+int.*auto_increment/i', $line, $reg)) {
210 $newline = preg_replace(
'/([\s\t\(]*)([a-zA-Z_0-9]*)[\s\t]+int.*auto_increment[^,]*/i',
'\\1 \\2 SERIAL PRIMARY KEY', $line);
215 if (preg_match(
'/[\s\t\(]*(\w*)[\s\t]+bigint.*auto_increment/i', $line, $reg)) {
216 $newline = preg_replace(
'/([\s\t\(]*)([a-zA-Z_0-9]*)[\s\t]+bigint.*auto_increment[^,]*/i',
'\\1 \\2 BIGSERIAL PRIMARY KEY', $line);
222 $line = preg_replace(
'/tinyint\(?[0-9]*\)?/',
'smallint', $line);
223 $line = preg_replace(
'/tinyint/i',
'smallint', $line);
226 $line = preg_replace(
'/(int\w+|smallint|bigint)\s+unsigned/i',
'\\1', $line);
229 $line = preg_replace(
'/\w*blob/i',
'text', $line);
232 $line = preg_replace(
'/tinytext/i',
'text', $line);
233 $line = preg_replace(
'/mediumtext/i',
'text', $line);
234 $line = preg_replace(
'/longtext/i',
'text', $line);
236 $line = preg_replace(
'/text\([0-9]+\)/i',
'text', $line);
240 $line = preg_replace(
'/datetime not null/i',
'datetime', $line);
241 $line = preg_replace(
'/datetime/i',
'timestamp', $line);
244 $line = preg_replace(
'/^double/i',
'numeric', $line);
245 $line = preg_replace(
'/(\s*)double/i',
'\\1numeric', $line);
247 $line = preg_replace(
'/^float/i',
'numeric', $line);
248 $line = preg_replace(
'/(\s*)float/i',
'\\1numeric', $line);
252 $line = preg_replace(
'/(\s*)tms(\s*)timestamp/i',
'\\1tms timestamp without time zone DEFAULT now() NOT NULL', $line);
255 $line = preg_replace(
'/(\s*)DEFAULT(\s*)CURRENT_TIMESTAMP/i',
'\\1', $line);
258 $line = preg_replace(
'/(\s*)ON(\s*)UPDATE(\s*)CURRENT_TIMESTAMP/i',
'\\1', $line);
261 if (preg_match(
'/unique index\s*\((\w+\s*,\s*\w+)\)/i', $line)) {
262 $line = preg_replace(
'/unique index\s*\((\w+\s*,\s*\w+)\)/i',
'UNIQUE\(\\1\)', $line);
266 $line = preg_replace(
'/\sAFTER [a-z0-9_]+/i',
'', $line);
269 $line = preg_replace(
'/ALTER TABLE [a-z0-9_]+\s+DROP INDEX/i',
'DROP INDEX', $line);
272 if (preg_match(
'/ALTER TABLE ([a-z0-9_]+)\s+CHANGE(?: COLUMN)? ([a-z0-9_]+) ([a-z0-9_]+)(.*)$/i', $line, $reg)) {
273 $line =
"-- ".$line.
" replaced by --\n";
274 $line .=
"ALTER TABLE ".$reg[1].
" RENAME COLUMN ".$reg[2].
" TO ".$reg[3];
278 if (preg_match(
'/ALTER TABLE ([a-z0-9_]+)\s+MODIFY(?: COLUMN)? ([a-z0-9_]+) (.*)$/i', $line, $reg)) {
279 $line =
"-- ".$line.
" replaced by --\n";
281 $newreg3 = preg_replace(
'/ DEFAULT NULL/i',
'', $newreg3);
282 $newreg3 = preg_replace(
'/ NOT NULL/i',
'', $newreg3);
283 $newreg3 = preg_replace(
'/ NULL/i',
'', $newreg3);
284 $newreg3 = preg_replace(
'/ DEFAULT 0/i',
'', $newreg3);
285 $newreg3 = preg_replace(
'/ DEFAULT \'?[0-9a-zA-Z_@]*\'?/i',
'', $newreg3);
286 $line .=
"ALTER TABLE ".$reg[1].
" ALTER COLUMN ".$reg[2].
" TYPE ".$newreg3;
292 if (preg_match(
'/ALTER\s+TABLE\s*(.*)\s*ADD\s+PRIMARY\s+KEY\s*(.*)\s*\((.*)$/i', $line, $reg)) {
293 $line =
"-- ".$line.
" replaced by --\n";
294 $line .=
"ALTER TABLE ".$reg[1].
" ADD PRIMARY KEY (".$reg[3];
299 if (preg_match(
'/ALTER\s+TABLE\s*(.*)\s*DROP\s+PRIMARY\s+KEY\s*([^;]+)$/i', $line, $reg)) {
300 $line =
"-- ".$line.
" replaced by --\n";
301 $line .=
"ALTER TABLE ".$reg[1].
" DROP CONSTRAINT ".$reg[2];
306 if (preg_match(
'/ALTER\s+TABLE\s*(.*)\s*DROP\s+FOREIGN\s+KEY\s*(.*)$/i', $line, $reg)) {
307 $line =
"-- ".$line.
" replaced by --\n";
308 $line .=
"ALTER TABLE ".$reg[1].
" DROP CONSTRAINT ".$reg[2];
313 if (preg_match(
'/ALTER\s+TABLE\s+(.*)\s*ADD CONSTRAINT\s+(.*)\s*FOREIGN\s+KEY\s*(.*)$/i', $line, $reg)) {
314 $line = preg_replace(
'/;$/',
'', $line);
315 $line .=
" DEFERRABLE INITIALLY IMMEDIATE;";
320 if (preg_match(
'/ALTER\s+TABLE\s*(.*)\s*ADD\s+(UNIQUE INDEX|INDEX|UNIQUE)\s+(.*)\s*\(([\w,\s]+)\)/i', $line, $reg)) {
321 $fieldlist = $reg[4];
323 $tablename = $reg[1];
324 $line =
"-- ".$line.
" replaced by --\n";
325 $line .=
"CREATE ".(preg_match(
'/UNIQUE/', $reg[2]) ?
'UNIQUE ' :
'').
"INDEX ".$idxname.
" ON ".$tablename.
" (".$fieldlist.
")";
331 $line = str_replace(
" LIKE '",
" ILIKE '", $line, $count_like);
334 $line = preg_replace(
'/\s+(\(+\s*)([a-zA-Z0-9\-\_\.]+) ILIKE /',
' \1unaccent(\2) ILIKE ', $line);
337 $line = str_replace(
" LIKE BINARY '",
" LIKE '", $line);
340 $line = preg_replace(
'/^INSERT IGNORE/',
'INSERT', $line);
344 if (preg_match(
'/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i', $line, $reg)) {
345 if ($reg[1] == $reg[2]) {
346 $line = preg_replace(
'/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i',
'DELETE FROM \\1 USING \\3', $line);
351 $line = preg_replace(
'/FROM\s*\((([a-z_]+)\s+as\s+([a-z_]+)\s*)\)/i',
'FROM \\1', $line);
355 $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);
359 $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);
363 $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);
367 $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);
374 if ($unescapeslashquot) {
375 $line = preg_replace(
"/\\\'/",
"''", $line);
396 if ($database == $this->database_name) {
420 public function connect($host, $login, $passwd, $name, $port = 0, $forcenew =
false)
427 $host = str_replace(array(
"\\",
"'"), array(
"\\\\",
"\\'"), $host);
428 $login = str_replace(array(
"\\",
"'"), array(
"\\\\",
"\\'"), $login);
429 $passwd = str_replace(array(
"\\",
"'"), array(
"\\\\",
"\\'"), $passwd);
430 $name = str_replace(array(
"\\",
"'"), array(
"\\\\",
"\\'"), $name);
431 $port = str_replace(array(
"\\",
"'"), array(
"\\\\",
"\\'"), (
string) $port);
437 $connectflags = $forcenew ? PGSQL_CONNECT_FORCE_NEW : 0;
440 if ((!empty($host) && $host ==
"socket") && !defined(
'NOLOCALSOCKETPGCONNECT')) {
441 $con_string =
"dbname='".$name.
"' user='".$login.
"' password='".$passwd.
"'";
446 $this->db = @pg_connect($con_string, $connectflags);
447 }
catch (Throwable $e) {
453 if (empty($this->db)) {
461 $con_string =
"host='".$host.
"' port='".$port.
"' dbname='".$name.
"' user='".$login.
"' password='".$passwd.
"'";
463 $this->db = @pg_connect($con_string, $connectflags);
464 }
catch (Throwable $e) {
465 print $e->getMessage();
471 $this->database_name = $name;
472 pg_set_error_verbosity($this->db, PGSQL_ERRORS_VERBOSE);
473 pg_query($this->db,
"set datestyle = 'ISO, YMD';");
486 $resql = $this->
query(
'SHOW server_version');
489 return $liste[
'server_version'];
501 return 'pgsql php driver';
513 if ($this->transaction_opened > 0) {
514 dol_syslog(get_class($this).
"::close Closing a connection with an opened transaction depth=".$this->transaction_opened, LOG_ERR);
516 $this->connected =
false;
517 return pg_close($this->db);
531 public function query($query, $usesavepoint = 0,
$type =
'auto', $result_mode = 0)
533 global $dolibarr_main_db_readonly;
535 $query = trim($query);
538 $query = $this->
convertSQLFromMysql($query,
$type, ($this->unescapeslashquot && $this->standard_conforming_strings));
545 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)) {
546 $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);
547 dol_syslog(
"Warning: Bad formed request converted into ".$query, LOG_WARNING);
554 if ($usesavepoint && $this->transaction_opened) {
555 @pg_query($this->db,
'SAVEPOINT mysavepoint');
558 if (!in_array($query, array(
'BEGIN',
'COMMIT',
'ROLLBACK'))) {
559 $SYSLOG_SQL_LIMIT = 10000;
560 dol_syslog(
'sql='.substr($query, 0, $SYSLOG_SQL_LIMIT), LOG_DEBUG);
566 if (!empty($dolibarr_main_db_readonly)) {
567 if (preg_match(
'/^(INSERT|UPDATE|REPLACE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) {
568 $this->
lasterror =
'Application in read-only mode';
575 $ret = @pg_query($this->db, $query);
578 if (!preg_match(
"/^COMMIT/i", $query) && !preg_match(
"/^ROLLBACK/i", $query)) {
580 if ($this->
errno() !=
'DB_ERROR_25P02') {
586 dol_syslog(get_class($this).
"::query SQL Error query: ".$query, LOG_ERR);
588 dol_syslog(get_class($this).
"::query SQL Error message: ".$this->
lasterror.
" (".$this->lasterrno.
")", LOG_ERR);
589 dol_syslog(get_class($this).
"::query SQL Error usesavepoint = ".$usesavepoint, LOG_ERR);
592 if ($usesavepoint && $this->transaction_opened) {
593 @pg_query($this->db,
'ROLLBACK TO SAVEPOINT mysavepoint');
597 $this->_results = $ret;
614 if (!is_resource($resultset) && !is_object($resultset)) {
615 $resultset = $this->_results;
617 return pg_fetch_object($resultset);
631 if (!is_resource($resultset) && !is_object($resultset)) {
632 $resultset = $this->_results;
634 return pg_fetch_array($resultset);
649 if (!is_resource($resultset) && !is_object($resultset)) {
650 $resultset = $this->_results;
652 if (is_bool($resultset)) {
655 return pg_fetch_row($resultset);
670 if (!is_resource($resultset) && !is_object($resultset)) {
671 $resultset = $this->_results;
675 return pg_num_rows($resultset);
693 if (!is_resource($resultset) && !is_object($resultset)) {
694 $resultset = $this->_results;
698 return pg_affected_rows($resultset);
708 public function free($resultset =
null)
711 if (!is_resource($resultset) && !is_object($resultset)) {
712 $resultset = $this->_results;
715 if (is_resource($resultset) || is_object($resultset)) {
716 pg_free_result($resultset);
728 public function plimit($limit = 0, $offset = 0)
735 $limit =
$conf->liste_limit;
738 return " LIMIT ".$limit.
" OFFSET ".$offset.
" ";
740 return " LIMIT $limit ";
753 return pg_escape_string($this->db, (
string) $stringtoencode);
764 return str_replace(array(
'\\',
'_',
'%'), array(
'\\\\',
'\_',
'\%'), (
string) $stringtoencode);
775 public function ifsql($test, $resok, $resko)
777 return '(CASE WHEN '.$test.
' THEN '.$resok.
' ELSE '.$resko.
' END)';
788 public function regexpsql($subject, $pattern, $sqlstring = 0)
791 return "(". $subject .
" ~ '" . $this->
escape($pattern) .
"')";
794 return "('". $this->
escape($subject) .
"' ~ '" . $this->
escape($pattern) .
"')";
805 if (!$this->connected) {
807 return 'DB_ERROR_FAILED_TO_CONNECT';
810 $errorcode_map = array(
811 1004 =>
'DB_ERROR_CANNOT_CREATE',
812 1005 =>
'DB_ERROR_CANNOT_CREATE',
813 1006 =>
'DB_ERROR_CANNOT_CREATE',
814 1007 =>
'DB_ERROR_ALREADY_EXISTS',
815 1008 =>
'DB_ERROR_CANNOT_DROP',
816 1025 =>
'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
817 1044 =>
'DB_ERROR_ACCESSDENIED',
818 1046 =>
'DB_ERROR_NODBSELECTED',
819 1048 =>
'DB_ERROR_CONSTRAINT',
820 '42P07' =>
'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS',
821 '42703' =>
'DB_ERROR_NOSUCHFIELD',
822 1060 =>
'DB_ERROR_COLUMN_ALREADY_EXISTS',
823 42701 =>
'DB_ERROR_COLUMN_ALREADY_EXISTS',
824 '42710' =>
'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
825 '23505' =>
'DB_ERROR_RECORD_ALREADY_EXISTS',
826 '42704' =>
'DB_ERROR_NO_INDEX_TO_DROP',
827 '42601' =>
'DB_ERROR_SYNTAX',
828 '42P16' =>
'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
829 1075 =>
'DB_ERROR_CANT_DROP_PRIMARY_KEY',
830 1091 =>
'DB_ERROR_NOSUCHFIELD',
831 1100 =>
'DB_ERROR_NOT_LOCKED',
832 1136 =>
'DB_ERROR_VALUE_COUNT_ON_ROW',
833 '42P01' =>
'DB_ERROR_NOSUCHTABLE',
834 '23503' =>
'DB_ERROR_NO_PARENT',
835 1217 =>
'DB_ERROR_CHILD_EXISTS',
836 1451 =>
'DB_ERROR_CHILD_EXISTS',
837 '42P04' =>
'DB_DATABASE_ALREADY_EXISTS'
840 $errorlabel = pg_last_error($this->db);
843 if (preg_match(
'/: *([0-9P]+):/', $errorlabel, $reg)) {
844 $errorcode = $reg[1];
845 if (isset($errorcode_map[$errorcode])) {
846 return $errorcode_map[$errorcode];
849 $errno = $errorcode ? $errorcode : $errorlabel;
850 return ($errno ?
'DB_ERROR_'.$errno :
'0');
869 return pg_last_error($this->db);
883 $sequencename = $table.
"_".$fieldid.
"_seq";
886 $result = pg_query($this->db,
"SELECT currval('".$sequencename.
"')");
888 print pg_last_error($this->db);
892 $row = pg_fetch_result($result, 0, 0);
904 public function encrypt($fieldorvalue, $withQuotes = 1)
914 $return = $fieldorvalue;
915 return ($withQuotes ?
"'" :
"").$this->
escape($return).($withQuotes ?
"'" :
"");
966 public function DDLCreateDb($database, $charset =
'', $collation =
'', $owner =
'')
969 if (empty($charset)) {
972 if (empty($collation)) {
980 $sql =
"CREATE DATABASE ".$this->sanitize($database).
" OWNER '".$this->
escape($owner).
"' ENCODING '".$this->
escape((
string) $charset).
"'";
983 $ret = $this->
query($sql);
999 $listtables = array();
1003 $tmptable = preg_replace(
'/[^a-z0-9\.\-\_%]/i',
'', $table);
1005 $escapedlike =
" AND table_name LIKE '".$this->escape($tmptable).
"'";
1007 $result = pg_query($this->db,
"SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'".$escapedlike.
" ORDER BY table_name");
1009 while ($row = $this->
fetch_row($result)) {
1010 $listtables[] = $row[0];
1027 $listtables = array();
1031 $tmptable = preg_replace(
'/[^a-z0-9\.\-\_%]/i',
'', $table);
1033 $escapedlike =
" AND table_name LIKE '".$this->escape($tmptable).
"'";
1035 $result = pg_query($this->db,
"SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = 'public'".$escapedlike.
" ORDER BY table_name");
1037 while ($row = $this->
fetch_row($result)) {
1038 $listtables[] = $row;
1054 $infotables = array();
1057 $sql .=
" infcol.column_name as \"Column\",";
1058 $sql .=
" CASE WHEN infcol.character_maximum_length IS NOT NULL THEN infcol.udt_name || '('||infcol.character_maximum_length||')'";
1059 $sql .=
" ELSE infcol.udt_name";
1060 $sql .=
" END as \"Type\",";
1061 $sql .=
" infcol.collation_name as \"Collation\",";
1062 $sql .=
" infcol.is_nullable as \"Null\",";
1063 $sql .=
" '' as \"Key\",";
1064 $sql .=
" infcol.column_default as \"Default\",";
1065 $sql .=
" '' as \"Extra\",";
1066 $sql .=
" '' as \"Privileges\"";
1067 $sql .=
" FROM information_schema.columns infcol";
1068 $sql .=
" WHERE table_schema = 'public' ";
1069 $sql .=
" AND table_name = '".$this->escape($table).
"'";
1070 $sql .=
" ORDER BY ordinal_position;";
1072 $result = $this->
query($sql);
1074 while ($row = $this->
fetch_row($result)) {
1075 $infotables[] = $row;
1095 public function DDLCreateTable($table, $fields, $primary_key,
$type, $unique_keys =
null, $fulltext_keys =
null, $keys =
null)
1110 $sql =
"CREATE TABLE ".$this->sanitize($table).
"(";
1112 $sqlfields = array();
1113 foreach ($fields as $field_name => $field_desc) {
1114 $sqlfields[$i] = $this->
sanitize($field_name).
" ";
1115 $sqlfields[$i] .= $this->
sanitize($field_desc[
'type']);
1116 if (isset($field_desc[
'value']) && $field_desc[
'value'] !==
'') {
1117 $sqlfields[$i] .=
"(".$this->sanitize($field_desc[
'value']).
")";
1119 if (isset($field_desc[
'attribute']) && $field_desc[
'attribute'] !==
'') {
1120 $sqlfields[$i] .=
" ".$this->sanitize($field_desc[
'attribute'], 0, 0, 1);
1122 if (isset($field_desc[
'default']) && $field_desc[
'default'] !==
'') {
1123 if (in_array($field_desc[
'type'], array(
'tinyint',
'smallint',
'int',
'double'))) {
1124 $sqlfields[$i] .=
" DEFAULT ".((float) $field_desc[
'default']);
1125 } elseif ($field_desc[
'default'] ==
'null' || $field_desc[
'default'] ==
'CURRENT_TIMESTAMP') {
1126 $sqlfields[$i] .=
" DEFAULT ".$this->sanitize($field_desc[
'default']);
1128 $sqlfields[$i] .=
" DEFAULT '".$this->escape($field_desc[
'default']).
"'";
1131 if (isset($field_desc[
'null']) && $field_desc[
'null'] !==
'') {
1132 $sqlfields[$i] .=
" ".$this->sanitize($field_desc[
'null'], 0, 0, 1);
1134 if (isset($field_desc[
'extra']) && $field_desc[
'extra'] !==
'') {
1135 $sqlfields[$i] .=
" ".$this->sanitize($field_desc[
'extra'], 0, 0, 1);
1137 if (!empty($primary_key) && $primary_key == $field_name) {
1138 $sqlfields[$i] .=
" AUTO_INCREMENT PRIMARY KEY";
1143 if (is_array($unique_keys)) {
1145 foreach ($unique_keys as $key => $value) {
1146 $sqluq[$i] =
"UNIQUE KEY '".$this->sanitize($key).
"' ('".$this->
escape($value).
"')";
1150 if (is_array($keys)) {
1152 foreach ($keys as $key => $value) {
1153 $sqlk[$i] =
"KEY ".$this->sanitize($key).
" (".$value.
")";
1157 $sql .= implode(
', ', $sqlfields);
1158 if (!is_array($unique_keys) && $unique_keys !=
"") {
1159 $sql .=
",".implode(
',', $sqluq);
1161 if (is_array($keys)) {
1162 $sql .=
",".implode(
',', $sqlk);
1167 if (!$this->
query($sql, 1)) {
1184 $tmptable = preg_replace(
'/[^a-z0-9\.\-\_]/i',
'', $table);
1186 $sql =
"DROP TABLE ".$this->sanitize($tmptable);
1188 if (!$this->
query($sql, 1)) {
1206 $sql =
"SELECT attname FROM pg_attribute, pg_type WHERE typname = '".$this->escape($table).
"' AND attrelid = typrelid";
1207 $sql .=
" AND attname NOT IN ('cmin', 'cmax', 'ctid', 'oid', 'tableoid', 'xmin', 'xmax')";
1209 $sql .=
" AND attname = '".$this->escape($field).
"'";
1213 $this->_results = $this->
query($sql);
1214 return $this->_results;
1227 public function DDLAddField($table, $field_name, $field_desc, $field_position =
"")
1232 $sql =
"ALTER TABLE ".$this->sanitize($table).
" ADD ".$this->
sanitize($field_name).
" ";
1234 if ($field_desc[
'type'] !==
'datetimegmt') {
1235 $sql .= $this->
sanitize($field_desc[
'type']);
1240 if (in_array($field_desc[
'type'], array(
'varchar')) && array_key_exists(
'value', $field_desc) && !empty($field_desc[
'value'])) {
1241 $sql .=
"(".$this->sanitize($field_desc[
'value']).
")";
1243 if (isset($field_desc[
'attribute']) && preg_match(
"/^[^\s]/i", $field_desc[
'attribute'])) {
1244 $sql .=
" ".$this->sanitize($field_desc[
'attribute']);
1246 if (isset($field_desc[
'null']) && preg_match(
"/^[^\s]/i", $field_desc[
'null'])) {
1247 if ($field_desc[
'null'] ==
'NOT NULL') {
1248 $sql .=
" ".$this->sanitize($field_desc[
'null'], 0, 0, 1);
1250 $sql .=
" ".$this->sanitize($field_desc[
'null']);
1253 if (isset($field_desc[
'default']) && preg_match(
"/^[^\s]/i", $field_desc[
'default'])) {
1254 if (in_array($field_desc[
'type'], array(
'tinyint',
'smallint',
'int',
'double'))) {
1255 $sql .=
" DEFAULT ".((float) $field_desc[
'default']);
1256 } elseif ($field_desc[
'default'] ==
'null' || $field_desc[
'default'] ==
'CURRENT_TIMESTAMP') {
1257 $sql .=
" DEFAULT ".$this->sanitize($field_desc[
'default']);
1259 $sql .=
" DEFAULT '".$this->escape($field_desc[
'default']).
"'";
1262 if (isset($field_desc[
'extra']) && preg_match(
"/^[^\s]/i", $field_desc[
'extra'])) {
1263 $sql .=
" ".$this->sanitize($field_desc[
'extra'], 0, 0, 1);
1265 $sql .=
" ".$this->sanitize($field_position, 0, 0, 1);
1267 dol_syslog(get_class($this).
"::DDLAddField ".$sql, LOG_DEBUG);
1268 if ($this->
query($sql)) {
1286 $sql =
"ALTER TABLE ".$this->sanitize($table);
1287 $sql .=
" ALTER COLUMN ".$this->sanitize($field_name).
" TYPE ";
1289 if ($field_desc[
'type'] !==
'datetimegmt') {
1290 $sql .= $this->
sanitize($field_desc[
'type']);
1295 if (in_array($field_desc[
'type'], array(
'varchar')) && array_key_exists(
'value', $field_desc) && !empty($field_desc[
'value'])) {
1296 $sql .=
"(".$this->sanitize($field_desc[
'value']).
")";
1299 if (isset($field_desc[
'null']) && ($field_desc[
'null'] ==
'not null' || $field_desc[
'null'] ==
'NOT NULL')) {
1301 if ($field_desc[
'type'] ==
'varchar' || $field_desc[
'type'] ==
'text') {
1302 $sqlbis =
"UPDATE ".$this->sanitize($table).
" SET ".$this->
sanitize($field_name).
" = '".$this->
escape(isset($field_desc[
'default']) ? $field_desc[
'default'] :
'').
"' WHERE ".$this->
sanitize($field_name).
" IS NULL";
1303 $this->
query($sqlbis);
1304 } elseif (in_array($field_desc[
'type'], array(
'tinyint',
'smallint',
'int',
'double'))) {
1305 $sqlbis =
"UPDATE ".$this->sanitize($table).
" SET ".$this->
sanitize($field_name).
" = ".((float) $this->
escape(isset($field_desc[
'default']) ? $field_desc[
'default'] : 0)).
" WHERE ".$this->
sanitize($field_name).
" IS NULL";
1306 $this->
query($sqlbis);
1310 if (isset($field_desc[
'default']) && $field_desc[
'default'] !=
'') {
1311 if (in_array($field_desc[
'type'], array(
'tinyint',
'smallint',
'int',
'double'))) {
1312 $sql .=
", ALTER COLUMN ".$this->sanitize($field_name).
" SET DEFAULT ".((float) $field_desc[
'default']);
1313 } elseif ($field_desc[
'type'] !=
'text') {
1314 $sql .=
", ALTER COLUMN ".$this->sanitize($field_name).
" SET DEFAULT '".$this->
escape($field_desc[
'default']).
"'";
1319 if (!$this->
query($sql)) {
1336 $tmp_field_name = preg_replace(
'/[^a-z0-9\.\-\_]/i',
'', $field_name);
1338 $sql =
"ALTER TABLE ".$this->sanitize($table).
" DROP COLUMN ".$this->
sanitize($tmp_field_name);
1339 if (!$this->
query($sql)) {
1356 public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
1360 $sql =
"CREATE USER ".$this->sanitize($dolibarr_main_db_user).
" with password '".$this->
escape($dolibarr_main_db_pass).
"'";
1362 dol_syslog(get_class($this).
"::DDLCreateUser", LOG_DEBUG);
1363 $resql = $this->
query($sql);
1378 $resql = $this->
query(
'SHOW SERVER_ENCODING');
1381 return $liste[
'server_encoding'];
1394 $resql = $this->
query(
'SHOW SERVER_ENCODING');
1399 $liste[$i][
'charset'] = $obj->server_encoding;
1400 $liste[$i][
'description'] =
'Default database charset';
1403 $this->
free($resql);
1417 $resql = $this->
query(
'SHOW LC_COLLATE');
1420 return $liste[
'lc_collate'];
1433 $resql = $this->
query(
'SHOW LC_COLLATE');
1438 $liste[$i][
'collation'] = $obj->lc_collate;
1441 $this->
free($resql);
1455 $fullpathofdump =
'/pathtopgdump/pg_dump';
1457 if (file_exists(
'/usr/bin/pg_dump')) {
1458 $fullpathofdump =
'/usr/bin/pg_dump';
1461 $resql = $this->
query(
'SHOW data_directory');
1464 $basedir = $liste[
'data_directory'];
1465 $fullpathofdump = preg_replace(
'/data$/',
'bin', $basedir).
'/pg_dump';
1469 return $fullpathofdump;
1482 $fullpathofdump =
'/pathtopgrestore/'.$tool;
1484 if (file_exists(
'/usr/bin/'.$tool)) {
1485 $fullpathofdump =
'/usr/bin/'.$tool;
1488 $resql = $this->
query(
'SHOW data_directory');
1491 $basedir = $liste[
'data_directory'];
1492 $fullpathofdump = preg_replace(
'/data$/',
'bin', $basedir).
'/'.$tool;
1496 return $fullpathofdump;
1509 $resql =
'select name,setting from pg_settings';
1511 $resql .=
" WHERE name = '".$this->escape($filter).
"'";
1513 $resql = $this->
query($resql);
1516 $result[$obj->name] = $obj->setting;
1569 dol_syslog(get_class($this).
"::prepare sql=".$sql, LOG_DEBUG);
1574 $len = strlen($sql);
1576 for ($i = 0; $i < $len; $i++) {
1579 if ($inquote && $i + 1 < $len && $sql[$i + 1] ===
"'") {
1581 $translated .=
"''";
1585 $inquote = !$inquote;
1589 if (
$c ===
'?' && !$inquote) {
1591 $translated .=
'$'.$num;
1597 $stmtname =
'dolipgstmt_' . bin2hex(random_bytes(8));
1599 $result = @pg_prepare($this->db, $stmtname, $translated);
1601 $this->
lasterror = pg_last_error($this->db);
1621 if (!is_string($stmt) || $stmt ===
'') {
1622 $this->
lasterror =
'execute() called with an invalid statement';
1631 foreach (array_values($params) as $v) {
1632 $values[] = is_bool($v) ? ($v ?
't' :
'f') : $v;
1635 dol_syslog(get_class($this).
"::execute ".$stmt.
" (".count($values).
" bound param(s))", LOG_DEBUG);
1637 $res = @pg_execute($this->db, $stmt, $values);
1638 if ($res ===
false) {
1639 $this->
lasterror = pg_last_error($this->db);
1644 $this->_results = $res;
1647 return (pg_num_fields($res) > 0) ? $res :
true;
Class to manage Dolibarr database access.
lastqueryerror()
Return last query in error.
lasterror()
Return last error label.
lasterrno()
Return last error code.
lastquery()
Return last request executed with query()
sanitize($stringtosanitize, $allowsimplequote=0, $allowsequals=0, $allowsspace=0, $allowschars=1)
Sanitize a string for SQL forging.
Class to drive a PostgreSQL database for Dolibarr.
errno()
Renvoie le code erreur generique de l'operation precedente.
DDLListTablesFull($database, $table='')
List tables into a database.
DDLGetConnectId()
Return connection ID.
num_rows($resultset)
Return number of lines for result of a SELECT.
const VERSIONMIN
Version min database.
DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
Create a user to connect to database.
DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys=null, $fulltext_keys=null, $keys=null)
Create a table into database.
getNextAutoIncrementId($table)
Get the last ID of an auto-increment field of a table.
DDLDropTable($table)
Drop a table into database.
DDLUpdateField($table, $field_name, $field_desc)
Update format of a field into a table.
getPathOfDump()
Return full path of dump program.
select_db($database)
Select a database PostgreSQL does not have an equivalent for mysql_select_db Only compare if the chos...
getServerStatusValues($filter='')
Return value of server status.
plimit($limit=0, $offset=0)
Define limits and offset of request.
decrypt($value)
Decrypt sensitive data in database.
error()
Renvoie le texte de l'erreur pgsql de l'operation precedente.
escape($stringtoencode)
Escape a string to insert data.
query($query, $usesavepoint=0, $type='auto', $result_mode=0)
Convert request to PostgreSQL syntax, execute it and return the resultset.
fetch_object($resultset)
Returns the current line (as an object) for the resultset cursor.
close()
Close database connection.
encrypt($fieldorvalue, $withQuotes=1)
Encrypt sensitive data in database Warning: This function includes the escape and add the SQL simple ...
getListOfCharacterSet()
Return list of available charset that can be used to store data in database.
fetch_array($resultset)
Return data as an array.
getPathOfRestore()
Return full path of restore program.
DDLAddField($table, $field_name, $field_desc, $field_position="")
Create a new field into table.
connect($host, $login, $passwd, $name, $port=0, $forcenew=false)
Connection to server.
DDLInfoTable($table)
List information of columns in a table.
__construct($type, $host, $user, $pass, $name='', $port=0, $forcenew=false)
Constructor.
getVersion()
Return version of database server.
escapeforlike($stringtoencode)
Escape a string to insert data into a like.
last_insert_id($table, $fieldid='rowid')
Get last ID after an insert INSERT.
affected_rows($resultset)
Return the number of rows in the result of a request INSERT, DELETE or UPDATE.
DDLDropField($table, $field_name)
Drop a field from table.
regexpsql($subject, $pattern, $sqlstring=0)
Format a SQL REGEXP.
DDLCreateDb($database, $charset='', $collation='', $owner='')
Create a new database Do not use function xxx_create_db (xxx=mysql, ...) as they are deprecated We fo...
const LABEL
Database label.
getListOfCollation()
Return list of available collation that can be used for database.
getDriverInfo()
Return version of database client driver.
free($resultset=null)
Free the last pointer resultset used by this connection.
DDLDescTable($table, $field="")
Return a pointer of line with description of a table or field.
ifsql($test, $resok, $resko)
Format a SQL IF.
getDefaultCollationDatabase()
Return collation used in database.
execute($stmt, $params=array())
Execute a statement previously created with prepare().
convertSQLFromMysql($line, $type='auto', $unescapeslashquot=false)
Convert a SQL request in Mysql syntax to native syntax.
getDefaultCharacterSetDatabase()
Return charset used to store data in database.
$forcecollate
Collation used to force collate when creating database.
fetch_row($resultset)
Return datas as an array.
getServerParametersValues($filter='')
Return value of server parameters.
prepare($sql)
Prepare a SQL statement for execution (PostgreSQL prepared statement).
DDLListTables($database, $table='')
List tables into a database.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.