31require_once DOL_DOCUMENT_ROOT.
'/core/db/DoliDB.class.php';
44 const LABEL =
'MySQL or MariaDB';
63 public function __construct(
$type, $host, $user, $pass, $name =
'', $port = 0, $forcenew =
false)
68 if (!empty(
$conf->db->character_set)) {
69 $this->forcecharset =
$conf->db->character_set;
71 if (!empty(
$conf->db->dolibarr_main_db_collation)) {
72 $this->forcecollate =
$conf->db->dolibarr_main_db_collation;
75 $this->database_user = $user;
76 $this->database_host = $host;
77 $this->database_port = $port;
79 $this->transaction_opened = 0;
83 if (!class_exists(
'mysqli')) {
84 $this->connected =
false;
86 $this->
error =
"Mysqli PHP functions for using Mysqli driver are not available in this version of PHP. Try to use another driver.";
87 dol_syslog(get_class($this).
"::DoliDBMysqli : Mysqli PHP functions for using Mysqli driver are not available in this version of PHP. Try to use another driver.", LOG_ERR);
91 $this->connected =
false;
93 $this->
error = $langs->trans(
"ErrorWrongHostParameter");
94 dol_syslog(get_class($this).
"::DoliDBMysqli : Connect error, wrong host parameters", LOG_ERR);
99 $this->db = $this->
connect($host, $user, $pass,
'', $port);
101 if ($this->db && empty($this->db->connect_errno)) {
102 $this->connected =
true;
105 $this->connected =
false;
107 $this->
error = empty($this->db) ?
'Failed to connect' : $this->db->connect_error;
108 dol_syslog(get_class($this).
"::DoliDBMysqli Connect error: ".$this->
error, LOG_ERR);
111 $disableforcecharset = 0;
114 if ($this->connected && $name) {
116 $this->database_selected =
true;
117 $this->database_name = $name;
121 $clientmustbe = empty(
$conf->db->character_set) ?
'utf8' : (string)
$conf->db->character_set;
122 if (preg_match(
'/latin1/', $clientmustbe)) {
123 $clientmustbe =
'utf8';
126 if (empty($disableforcecharset) && $this->db->character_set_name() != $clientmustbe) {
128 dol_syslog(get_class($this).
"::DoliDBMysqli You should set the \$dolibarr_main_db_character_set and \$dolibarr_main_db_collation for the PHP to the same as the database default, so to ".$this->db->character_set_name().
" or upgrade database default to ".$clientmustbe.
".", LOG_WARNING);
135 $this->db->set_charset($clientmustbe);
136 }
catch (Throwable $e) {
137 print
'Failed to force character_set_client to '.$clientmustbe.
" (according to setup) to match the one of the server database.<br>\n";
138 print $e->getMessage();
140 if ($clientmustbe !=
'utf8') {
141 print
'Edit conf/conf.php file to set a charset "utf8"';
142 if ($clientmustbe !=
'utf8mb4') {
143 print
' or "utf8mb4"';
145 print
' instead of "'.$clientmustbe.
'".'.
"\n";
150 $collation = (empty(
$conf) ?
'utf8_unicode_ci' : (string)
$conf->db->dolibarr_main_db_collation);
151 if (preg_match(
'/latin1/', $collation)) {
152 $collation =
'utf8_unicode_ci';
155 if (!preg_match(
'/general/', $collation)) {
156 $this->db->query(
"SET collation_connection = ".$collation);
160 $this->database_selected =
false;
161 $this->database_name =
'';
164 dol_syslog(get_class($this).
"::DoliDBMysqli : Select_db error ".$this->
error, LOG_ERR);
168 $this->database_selected =
false;
170 if ($this->connected) {
172 $clientmustbe = empty(
$conf->db->character_set) ?
'utf8' : (string)
$conf->db->character_set;
173 if (preg_match(
'/latin1/', $clientmustbe)) {
174 $clientmustbe =
'utf8';
177 if (empty($disableforcecharset) && $this->db->character_set_name() != $clientmustbe) {
178 $this->db->set_charset($clientmustbe);
180 $collation = (string)
$conf->db->dolibarr_main_db_collation;
181 if (preg_match(
'/latin1/', $collation)) {
182 $collation =
'utf8_unicode_ci';
185 if (!preg_match(
'/general/', $collation)) {
186 $this->db->query(
"SET collation_connection = ".$collation);
203 return " ".($mode == 1 ?
'FORCE' :
'USE').
" INDEX(".preg_replace(
'/[^a-z0-9_]/',
'', $nameofindex).
")";
230 dol_syslog(get_class($this).
"::select_db database=".$database, LOG_DEBUG);
233 $result = $this->db->select_db($database);
234 }
catch (Throwable $e) {
253 public function connect($host, $login, $passwd, $name, $port = 0, $forcenew =
false)
255 dol_syslog(get_class($this).
"::connect host=$host, port=$port, login=$login, passwd=--hidden--, name=$name", LOG_DEBUG);
261 if (!class_exists(
'mysqli')) {
262 dol_print_error(
null,
'Driver mysqli for PHP not available');
265 if (strpos($host,
'ssl://') === 0) {
266 $tmp =
new mysqliDoli($host, $login, $passwd, $name, $port);
268 $tmp =
new mysqli($host, $login, $passwd, $name, $port);
270 }
catch (Throwable $e) {
271 dol_syslog(get_class($this).
"::connect failed", LOG_DEBUG);
283 return $this->db->server_info;
293 return $this->db->client_info;
306 if ($this->transaction_opened > 0) {
307 dol_syslog(get_class($this).
"::close Closing a connection with an opened transaction depth=".$this->transaction_opened, LOG_ERR);
309 $this->connected =
false;
310 return $this->db->close();
327 public function query($query, $usesavepoint = 0,
$type =
'auto', $result_mode = 0)
329 global $dolibarr_main_db_readonly;
331 $query = trim($query);
339 if (!in_array($query, array(
'BEGIN',
'COMMIT',
'ROLLBACK'))) {
340 $SYSLOG_SQL_LIMIT = 10000;
341 dol_syslog(
'sql='.substr($query, 0, $SYSLOG_SQL_LIMIT), LOG_DEBUG);
347 if (!empty($dolibarr_main_db_readonly)) {
348 if (preg_match(
'/^(INSERT|UPDATE|REPLACE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) {
349 $this->
lasterror =
'Application in read-only mode';
357 $ret = $this->db->query($query, $result_mode);
358 }
catch (Throwable $e) {
359 dol_syslog(get_class($this).
"::query Exception in query instead of returning an error: ".$e->getMessage(), LOG_ERR);
363 if (!preg_match(
"/^COMMIT/i", $query) && !preg_match(
"/^ROLLBACK/i", $query)) {
371 dol_syslog(get_class($this).
"::query SQL Error query: ".$query, LOG_ERR);
373 dol_syslog(get_class($this).
"::query SQL Error message: ".$this->
lasterrno.
" ".$this->lasterror.self::getCallerInfoString(), LOG_ERR);
383 $this->_results = $ret;
396 $backtrace = debug_backtrace();
398 if (count($backtrace) >= 1) {
399 $trace = $backtrace[1];
400 if (isset($trace[
'file'], $trace[
'line'])) {
401 $msg =
" From {$trace['file']}:{$trace['line']}.";
418 if (!is_object($resultset)) {
419 $resultset = $this->_results;
421 return $resultset->fetch_object();
436 if (!is_object($resultset)) {
437 $resultset = $this->_results;
439 return $resultset->fetch_array();
453 if (!is_bool($resultset)) {
454 if (!is_object($resultset)) {
455 $resultset = $this->_results;
457 return $resultset->fetch_row();
476 if (!is_object($resultset)) {
477 $resultset = $this->_results;
479 return isset($resultset->num_rows) ? $resultset->num_rows : 0;
494 if (!is_object($resultset)) {
495 $resultset = $this->_results;
498 return $this->db->affected_rows;
507 public function free($resultset =
null)
510 if (!is_object($resultset)) {
511 $resultset = $this->_results;
514 if (is_object($resultset)) {
515 $resultset->free_result();
527 return $this->db->real_escape_string((
string) $stringtoencode);
539 return str_replace(array(
'\\',
'_',
'%'), array(
'\\\\',
'\_',
'\%'), (
string) $stringtoencode);
549 if (!$this->connected) {
551 return 'DB_ERROR_FAILED_TO_CONNECT';
554 $errorcode_map = array(
555 1004 =>
'DB_ERROR_CANNOT_CREATE',
556 1005 =>
'DB_ERROR_CANNOT_CREATE',
557 1006 =>
'DB_ERROR_CANNOT_CREATE',
558 1007 =>
'DB_ERROR_ALREADY_EXISTS',
559 1008 =>
'DB_ERROR_CANNOT_DROP',
560 1022 =>
'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
561 1025 =>
'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
562 1044 =>
'DB_ERROR_ACCESSDENIED',
563 1046 =>
'DB_ERROR_NODBSELECTED',
564 1048 =>
'DB_ERROR_CONSTRAINT',
565 1050 =>
'DB_ERROR_TABLE_ALREADY_EXISTS',
566 1051 =>
'DB_ERROR_NOSUCHTABLE',
567 1054 =>
'DB_ERROR_NOSUCHFIELD',
568 1060 =>
'DB_ERROR_COLUMN_ALREADY_EXISTS',
569 1061 =>
'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
570 1062 =>
'DB_ERROR_RECORD_ALREADY_EXISTS',
571 1064 =>
'DB_ERROR_SYNTAX',
572 1068 =>
'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
573 1075 =>
'DB_ERROR_CANT_DROP_PRIMARY_KEY',
574 1091 =>
'DB_ERROR_NOSUCHFIELD',
575 1100 =>
'DB_ERROR_NOT_LOCKED',
576 1136 =>
'DB_ERROR_VALUE_COUNT_ON_ROW',
577 1146 =>
'DB_ERROR_NOSUCHTABLE',
578 1215 =>
'DB_ERROR_CANNOT_ADD_FOREIGN_KEY_CONSTRAINT',
579 1216 =>
'DB_ERROR_NO_PARENT',
580 1217 =>
'DB_ERROR_CHILD_EXISTS',
581 1396 =>
'DB_ERROR_USER_ALREADY_EXISTS',
582 1451 =>
'DB_ERROR_CHILD_EXISTS',
583 1824 =>
'DB_ERROR_CANNOT_CREATE',
584 1826 =>
'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
587 if (isset($errorcode_map[$this->db->errno])) {
588 return $errorcode_map[$this->db->errno];
590 $errno = $this->db->errno;
591 return ($errno ?
'DB_ERROR_'.$errno :
'0');
602 if (!$this->connected) {
604 return 'Not connected. Check setup parameters in conf/conf.php file and your mysql client and server versions';
606 return $this->db->error;
621 return $this->db->insert_id;
632 public function encrypt($fieldorvalue, $withQuotes = 1)
637 $cryptType = (!empty(
$conf->db->dolibarr_main_db_encryption) ?
$conf->db->dolibarr_main_db_encryption : 0);
640 $cryptKey = (!empty(
$conf->db->dolibarr_main_db_cryptkey) ?
$conf->db->dolibarr_main_db_cryptkey :
'');
642 $escapedstringwithquotes = ($withQuotes ?
"'" :
"").$this->
escape($fieldorvalue).($withQuotes ?
"'" :
"");
644 if ($cryptType && !empty($cryptKey)) {
645 if ($cryptType == 2) {
646 $escapedstringwithquotes =
"AES_ENCRYPT(".$escapedstringwithquotes.
", '".$this->
escape($cryptKey).
"')";
647 } elseif ($cryptType == 1) {
648 $escapedstringwithquotes =
"DES_ENCRYPT(".$escapedstringwithquotes.
", '".$this->
escape($cryptKey).
"')";
652 return $escapedstringwithquotes;
666 $cryptType = (!empty(
$conf->db->dolibarr_main_db_encryption) ?
$conf->db->dolibarr_main_db_encryption : 0);
669 $cryptKey = (!empty(
$conf->db->dolibarr_main_db_cryptkey) ?
$conf->db->dolibarr_main_db_cryptkey :
'');
673 if ($cryptType && !empty($cryptKey)) {
674 if ($cryptType == 2) {
675 $return =
'AES_DECRYPT('.$value.
',\''.$cryptKey.
'\')
';
676 } elseif ($cryptType == 1) {
677 $return = 'DES_DECRYPT(
'.$value.',\
''.$cryptKey.
'\')
';
685 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
691 public function DDLGetConnectId()
694 $resql = $this->query('SELECT CONNECTION_ID()
');
696 $row = $this->fetch_row($resql);
703 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
715 public function DDLCreateDb($database, $charset = '
', $collation = '', $owner = '')
718 if (empty($charset)) {
719 $charset = $this->forcecharset;
721 if (empty($collation)) {
722 $collation = $this->forcecollate;
725 // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci
726 $sql = "CREATE DATABASE `".$this->sanitize($database)."`";
727 $sql .= " DEFAULT CHARACTER SET `".$this->sanitize($charset)."` DEFAULT COLLATE `".$this->sanitize($collation)."`";
729 dol_syslog($sql, LOG_DEBUG);
730 $ret = $this->query($sql);
732 // We try again for compatibility with Mysql < 4.1.1
733 $sql = "CREATE DATABASE `".$this->sanitize($database)."`";
734 dol_syslog($sql, LOG_DEBUG);
735 $ret = $this->query($sql);
741 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
749 public function DDLListTables($database, $table = '
')
752 $listtables = array();
756 $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i
', '', $table);
758 $like = "LIKE '".$this->escape($tmptable)."'";
760 $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $database);
762 $sql = "SHOW TABLES FROM `".$tmpdatabase."` ".$like.";";
764 $result = $this->query($sql);
766 while ($row = $this->fetch_row($result)) {
767 $listtables[] = $row[0];
773 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
781 public function DDLListTablesFull($database, $table = '
')
784 $listtables = array();
788 $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i
', '', $table);
790 $like = "LIKE '".$this->escape($tmptable)."'";
792 $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $database);
794 $sql = "SHOW FULL TABLES FROM `".$tmpdatabase."` ".$like.";";
796 $result = $this->query($sql);
798 while ($row = $this->fetch_row($result)) {
799 $listtables[] = $row;
805 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
812 public function DDLInfoTable($table)
815 $infotables = array();
817 $sanitizedtmptable = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $table);
819 $sql = "SHOW FULL COLUMNS FROM ".$sanitizedtmptable.";";
821 dol_syslog($sql, LOG_DEBUG);
822 $result = $this->query($sql);
824 while ($row = $this->fetch_row($result)) {
825 $infotables[] = $row;
831 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
844 public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null)
847 // @TODO: $fulltext_keys parameter is unused
857 // Keys found into the array $fields: type,value,attribute,null,default,extra
858 // ex. : $fields['rowid
'] = array(
859 // 'type'=>'int' or 'integer
',
861 // 'null'=>'not
null',
862 // 'extra
'=> 'auto_increment
'
864 $sql = "CREATE TABLE ".$this->sanitize($table)."(";
866 $sqlfields = array();
867 foreach ($fields as $field_name => $field_desc) {
868 $sqlfields[$i] = $this->sanitize($field_name)." ";
869 $sqlfields[$i] .= $this->sanitize($field_desc['type']);
870 if (isset($field_desc['value
']) && $field_desc['value
'] !== '') {
871 $sqlfields[$i] .= "(".$this->sanitize($field_desc['value
']).")";
873 if (isset($field_desc['attribute
']) && $field_desc['attribute
'] !== '') {
874 $sqlfields[$i] .= " ".$this->sanitize($field_desc['attribute
'], 0, 0, 1); // Allow space to accept attributes like "ON UPDATE CURRENT_TIMESTAMP"
876 if (isset($field_desc['default']) && $field_desc['default'] !== '') {
877 if (in_array($field_desc['type'], array('tinyint
', 'smallint
', 'int', 'double'))) {
878 $sqlfields[$i] .= " DEFAULT ".((float) $field_desc['default']);
879 } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP
') {
880 $sqlfields[$i] .= " DEFAULT ".$this->sanitize($field_desc['default']);
882 $sqlfields[$i] .= " DEFAULT '".$this->escape($field_desc['default'])."'";
885 if (isset($field_desc['null']) && $field_desc['null'] !== '') {
886 $sqlfields[$i] .= " ".$this->sanitize($field_desc['null'], 0, 0, 1);
888 if (isset($field_desc['extra
']) && $field_desc['extra
'] !== '') {
889 $sqlfields[$i] .= " ".$this->sanitize($field_desc['extra
'], 0, 0, 1);
891 if (!empty($primary_key) && $primary_key == $field_name) {
892 $sqlfields[$i] .= " AUTO_INCREMENT PRIMARY KEY"; // mysql instruction that will be converted by driver late
897 if (is_array($unique_keys)) {
899 foreach ($unique_keys as $key => $value) {
900 $sqluq[$i] = "UNIQUE KEY '".$this->sanitize($key)."' ('".$this->escape($value)."')";
904 if (is_array($keys)) {
906 foreach ($keys as $key => $value) {
907 $sqlk[$i] = "KEY ".$this->sanitize($key)." (".$value.")";
911 $sql .= implode(',
', $sqlfields);
912 if (!is_array($unique_keys) && $unique_keys != "") {
913 $sql .= ",".implode(',
', $sqluq);
915 if (is_array($keys)) {
916 $sql .= ",".implode(',
', $sqlk);
919 $sql .= " engine=".$this->sanitize($type);
921 if (!$this->query($sql)) {
928 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
935 public function DDLDropTable($table)
938 $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $table);
940 $sql = "DROP TABLE ".$this->sanitize($tmptable);
942 if (!$this->query($sql)) {
949 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
957 public function DDLDescTable($table, $field = "")
960 $sql = "DESC ".$this->sanitize($table)." ".$this->sanitize($field);
962 dol_syslog(get_class($this)."::DDLDescTable ".$sql, LOG_DEBUG);
963 $this->_results = $this->query($sql);
964 return $this->_results;
967 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
977 public function DDLAddField($table, $field_name, $field_desc, $field_position = "")
980 // keys looked up in the descriptions array (field_desc): type,value,attribute,null,default,extra
981 // ex. : $field_desc = array('
type'=>'int','value
'=>'11
','null'=>'not
null','extra
'=> 'auto_increment
');
982 $sql = "ALTER TABLE ".$this->sanitize($table)." ADD ".$this->sanitize($field_name)." ";
984 if ($field_desc['type'] !== 'datetimegmt
') {
985 $sql .= $this->sanitize($field_desc['type']);
990 if (in_array($field_desc['type'], array('double', 'int', 'varchar
')) && array_key_exists('value
', $field_desc) && !empty($field_desc['value
'])) {
991 $sql .= "(".$this->sanitize($field_desc['value
']).")";
993 if (isset($field_desc['attribute
']) && preg_match("/^[^\s]/i", $field_desc['attribute
'])) {
994 $sql .= " ".$this->sanitize($field_desc['attribute
']);
996 if (isset($field_desc['null']) && preg_match("/^[^\s]/i", $field_desc['null'])) {
997 if ($field_desc['null'] == 'NOT NULL
') {
998 $sql .= " ".$this->sanitize($field_desc['null'], 0, 0, 1);
1000 $sql .= " ".$this->sanitize($field_desc['null']);
1003 if (isset($field_desc['default']) && preg_match("/^[^\s]/i", $field_desc['default'])) {
1004 if (in_array($field_desc['type'], array('tinyint
', 'smallint
', 'int', 'double'))) {
1005 $sql .= " DEFAULT ".((float) $field_desc['default']);
1006 } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP
') {
1007 $sql .= " DEFAULT ".$this->sanitize($field_desc['default']);
1009 $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'";
1012 if (isset($field_desc['extra
']) && preg_match("/^[^\s]/i", $field_desc['extra
'])) {
1013 $sql .= " ".$this->sanitize($field_desc['extra
'], 0, 0, 1);
1015 $sql .= " ".$this->sanitize($field_position, 0, 0, 1);
1017 dol_syslog(get_class($this)."::DDLAddField ".$sql, LOG_DEBUG);
1018 if ($this->query($sql)) {
1021 // A table where columns were added and dropped many times refuses any new one with "Row size too
1022 // large" (error 1118), because the space the dropped columns took in the physical record is only
1023 // given back by a table rebuild. Rebuilding needs privileges the database user of the application
1024 // may not have, so we only tell the administrator which command recovers the table.
1025 if ($this->lasterrno == 'DB_ERROR_1118
') {
1026 $hint = "Table ".$table." must be rebuilt by your database administrator with the command: ALTER TABLE ".$table." FORCE";
1027 dol_syslog(get_class($this)."::DDLAddField ".$hint, LOG_WARNING);
1028 $this->lasterror .= ' -
'.$hint;
1033 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1042 public function DDLUpdateField($table, $field_name, $field_desc)
1045 $sql = "ALTER TABLE ".$this->sanitize($table);
1046 $sql .= " MODIFY COLUMN ".$this->sanitize($field_name)." ";
1048 if ($field_desc['
type'] !== 'datetimegmt
') {
1049 $sql .= $this->sanitize($field_desc['type']);
1054 if (in_array($field_desc['type'], array('double', 'int', 'varchar
')) && array_key_exists('value
', $field_desc) && !empty($field_desc['value
'])) {
1055 $sql .= "(".$this->sanitize($field_desc['value
']).")";
1057 if (isset($field_desc['null']) && ($field_desc['null'] == 'not
null' || $field_desc['null'] == 'NOT NULL
')) {
1058 // 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
1059 if ($field_desc['type'] == 'varchar
' || $field_desc['type'] == 'text
') {
1060 $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";
1061 $this->query($sqlbis);
1062 } elseif (in_array($field_desc['type'], array('tinyint
', 'smallint
', 'int', 'double'))) {
1063 $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";
1064 $this->query($sqlbis);
1067 $sql .= " NOT NULL";
1070 if (isset($field_desc['default']) && $field_desc['default'] != '') {
1071 if (in_array($field_desc['type'], array('tinyint
', 'smallint
', 'int', 'double'))) {
1072 $sql .= " DEFAULT ".((float) $field_desc['default']);
1073 } elseif ($field_desc['type'] != 'text
') {
1074 $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields
1079 dol_syslog(get_class($this)."::DDLUpdateField ".$sql, LOG_DEBUG);
1080 if (!$this->query($sql)) {
1087 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1095 public function DDLDropField($table, $field_name)
1098 $tmp_field_name = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $field_name);
1100 $sql = "ALTER TABLE ".$this->sanitize($table)." DROP COLUMN `".$this->sanitize($tmp_field_name)."`";
1101 if ($this->query($sql)) {
1104 $this->error = $this->lasterror();
1109 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1119 public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
1122 $sql = "CREATE USER '
".$this->escape($dolibarr_main_db_user)."' IDENTIFIED BY '".$this->escape($dolibarr_main_db_pass)."'";
1123 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1124 $resql = $this->query($sql);
1126 if ($this->lasterrno != 'DB_ERROR_USER_ALREADY_EXISTS
') {
1129 // If user already exists, we continue to set permissions
1130 dol_syslog(get_class($this)."::DDLCreateUser sql=".$sql, LOG_WARNING);
1134 // Redo with localhost forced (sometimes user is created on %)
1135 $sql = "CREATE USER '".$this->escape($dolibarr_main_db_user)."'@'localhost
' IDENTIFIED BY '".$this->escape($dolibarr_main_db_pass)."'";
1136 $resql = $this->query($sql);
1138 $sql = "GRANT ALL PRIVILEGES ON `".$this->sanitize($dolibarr_main_db_name)."`.* TO '".$this->escape($dolibarr_main_db_user)."'@'".$this->escape($dolibarr_main_db_host)."'";
1139 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1140 $resql = $this->query($sql);
1142 $this->error = "Connected user not allowed to GRANT ALL PRIVILEGES ON ".$this->escape($dolibarr_main_db_name).".* TO '".$this->escape($dolibarr_main_db_user)."'@'".$this->escape($dolibarr_main_db_host)."'";
1146 $sql = "FLUSH Privileges";
1148 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
1149 $resql = $this->query($sql);
1164 public function getDefaultCharacterSetDatabase()
1166 $resql = $this->query("SHOW VARIABLES LIKE 'character_set_database
'");
1168 // version Mysql < 4.1.1
1169 return $this->forcecharset;
1171 $liste = $this->fetch_array($resql);
1172 $tmpval = $liste['Value
'];
1182 public function getListOfCharacterSet()
1184 $resql = $this->query('SHOW CHARSET
');
1188 while ($obj = $this->fetch_object($resql)) {
1189 $liste[$i]['charset
'] = $obj->Charset;
1193 $this->free($resql);
1195 // version Mysql < 4.1.1
1207 public function getDefaultCollationDatabase()
1209 $resql = $this->query("SHOW VARIABLES LIKE 'collation_database
'");
1211 // version Mysql < 4.1.1
1212 return $this->forcecollate;
1214 $liste = $this->fetch_array($resql);
1215 $tmpval = $liste['Value
'];
1225 public function getListOfCollation()
1227 $resql = $this->query('SHOW COLLATION
');
1231 while ($obj = $this->fetch_object($resql)) {
1232 $liste[$i]['collation
'] = $obj->Collation;
1235 $this->free($resql);
1237 // version Mysql < 4.1.1
1248 public function getPathOfDump()
1250 $fullpathofdump = '/pathtomysqldump/mysqldump
';
1252 $resql = $this->query("SHOW VARIABLES LIKE 'basedir
'");
1254 $liste = $this->fetch_array($resql);
1255 $basedir = $liste['Value
'];
1256 $fullpathofdump = $basedir.(preg_match('/\/$/
', $basedir) ? '' : '/
').'bin/mysqldump
';
1258 return $fullpathofdump;
1266 public function getPathOfRestore()
1268 $fullpathofimport = '/pathtomysql/mysql
';
1270 $resql = $this->query("SHOW VARIABLES LIKE 'basedir
'");
1272 $liste = $this->fetch_array($resql);
1273 $basedir = $liste['Value
'];
1274 $fullpathofimport = $basedir.(preg_match('/\/$/
', $basedir) ? '' : '/
').'bin/mysql
';
1276 return $fullpathofimport;
1285 public function getServerParametersValues($filter = '
')
1289 $sql = 'SHOW VARIABLES
';
1291 $sql .= " LIKE '".$this->escape($filter)."'";
1293 $resql = $this->query($sql);
1295 while ($obj = $this->fetch_object($resql)) {
1296 $result[$obj->Variable_name] = $obj->Value;
1309 public function getServerStatusValues($filter = '
')
1313 $sql = 'SHOW STATUS
';
1315 $sql .= " LIKE '".$this->escape($filter)."'";
1317 $resql = $this->query($sql);
1319 while ($obj = $this->fetch_object($resql)) {
1320 $result[$obj->Variable_name] = $obj->Value;
1333 public function getNextAutoIncrementId($table)
1335 // Request to get last status of table
1336 $sql = "SHOW TABLE STATUS LIKE '
".$this->escape($table)."'";
1337 $result = $this->query($sql);
1340 $obj = $this->fetch_object($result);
1341 if ($obj && isset($obj->Auto_increment)) {
1342 return (int) $obj->Auto_increment;
1356 public function prepare($sql)
1358 if (!$this->connected) {
1359 $this->lasterror = 'Not connected to database
';
1362 dol_syslog(get_class($this)."::prepare sql=".$sql, LOG_DEBUG);
1364 $stmt = $this->db->prepare($sql);
1365 } catch (Throwable $e) {
1366 // With MYSQLI_REPORT_STRICT, mysqli::prepare() throws instead of returning false
1368 $this->lasterror = $e->getMessage();
1370 if (!($stmt instanceof mysqli_stmt)) {
1371 if (empty($this->lasterror)) {
1372 $this->lasterror = $this->db->error;
1374 $this->lastqueryerror = $sql;
1390 public function execute($stmt, $params = array())
1392 if (!($stmt instanceof mysqli_stmt)) {
1393 $this->lasterror = '
execute() called with an invalid statement';
1400 $params = array_values($params);
1401 if (count($params) > 0) {
1403 foreach ($params as $k => $v) {
1404 if (is_int($v) || is_bool($v)) {
1406 $params[$k] = (int) $v;
1407 } elseif (is_float($v)) {
1414 $bind = array($types);
1415 foreach ($params as $k => $v) {
1416 $bind[] = &$params[$k];
1419 $ok = call_user_func_array(array($stmt,
'bind_param'), $bind);
1420 }
catch (Throwable $e) {
1422 $this->lasterror = $e->getMessage();
1425 if (empty($this->lasterror)) {
1426 $this->lasterror = $stmt->error;
1428 $this->lastqueryerror = $stmt->sqlstate;
1433 dol_syslog(get_class($this).
"::execute (".count($params).
" bound param(s))", LOG_DEBUG);
1436 $ok = $stmt->execute();
1437 }
catch (Throwable $e) {
1450 $res = $stmt->get_result();
1451 if ($res instanceof mysqli_result) {
1452 $this->_results = $res;
1462if (class_exists(
'mysqli')) {
1466 class mysqliDoli
extends mysqli
1479 public function __construct($host, $user, $pass, $name, $port = 0, $socket =
"")
1482 if (PHP_VERSION_ID >= 80100) {
1483 parent::__construct();
1488 if (strpos($host,
'ssl://') === 0) {
1489 $host = substr($host, 6);
1490 parent::options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, 0);
1492 parent::ssl_set(
null,
null,
"",
null,
null);
1493 $flags = MYSQLI_CLIENT_SSL;
1495 parent::real_connect($host, $user, $pass, $name, $port, $socket, $flags);
$propal type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
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()
Class to manage Dolibarr database access for a MySQL database using the MySQLi extension.
fetch_array($resultset)
Return data as an array.
free($resultset=null)
Free the last pointer resultset used by this connection.
escapeforlike($stringtoencode)
Escape a string to insert data into a like.
num_rows($resultset)
Return number of lines for result of a SELECT.
hintindex($nameofindex, $mode=1)
Return SQL string to force an index.
const VERSIONMIN
Version min database.
error()
Return description of last error.
escape($stringtoencode)
Escape a string to insert data.
getVersion()
Return version of database server.
fetch_object($resultset)
Returns the current line (as an object) for the resultset cursor.
encrypt($fieldorvalue, $withQuotes=1)
Encrypt sensitive data in database Warning: This function includes the escape and add the SQL simple ...
__construct($type, $host, $user, $pass, $name='', $port=0, $forcenew=false)
Constructor.
convertSQLFromMysql($line, $type='ddl')
Convert a SQL request in Mysql syntax to native syntax.
affected_rows($resultset)
Return the number of lines in the result of a request INSERT, DELETE or UPDATE.
select_db($database)
Select a database.
decrypt($value)
Decrypt sensitive data in database.
fetch_row($resultset)
Return data as an array.
last_insert_id($tab, $fieldid='rowid')
Get last ID after an insert INSERT.
const LABEL
Database label.
query($query, $usesavepoint=0, $type='auto', $result_mode=0)
Execute a SQL request and return the resultset.
errno()
Return generic error code of last operation.
execute($stmt, $params=array())
Execute a statement previously created with prepare().
static getCallerInfoString()
Get caller info.
connect($host, $login, $passwd, $name, $port=0, $forcenew=false)
Connect to server.
getDriverInfo()
Return version of database client driver.
close()
Close database connection.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
if(!defined( 'CSRFCHECK_WITH_TOKEN'))