31require_once DOL_DOCUMENT_ROOT.
'/core/db/DoliDB.class.php';
44 const LABEL =
'MySQL or MariaDB';
67 if (!empty(
$conf->db->character_set)) {
68 $this->forcecharset =
$conf->db->character_set;
70 if (!empty(
$conf->db->dolibarr_main_db_collation)) {
71 $this->forcecollate =
$conf->db->dolibarr_main_db_collation;
74 $this->database_user = $user;
75 $this->database_host = $host;
76 $this->database_port = $port;
78 $this->transaction_opened = 0;
82 if (!class_exists(
'mysqli')) {
83 $this->connected =
false;
85 $this->
error =
"Mysqli PHP functions for using Mysqli driver are not available in this version of PHP. Try to use another driver.";
86 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);
90 $this->connected =
false;
92 $this->
error = $langs->trans(
"ErrorWrongHostParameter");
93 dol_syslog(get_class($this).
"::DoliDBMysqli : Connect error, wrong host parameters", LOG_ERR);
98 $this->db = $this->
connect($host, $user, $pass,
'', $port);
100 if ($this->db && empty($this->db->connect_errno)) {
101 $this->connected =
true;
104 $this->connected =
false;
106 $this->
error = empty($this->db) ?
'Failed to connect' : $this->db->connect_error;
107 dol_syslog(get_class($this).
"::DoliDBMysqli Connect error: ".$this->
error, LOG_ERR);
110 $disableforcecharset = 0;
113 if ($this->connected && $name) {
115 $this->database_selected =
true;
116 $this->database_name = $name;
120 $clientmustbe = empty(
$conf->db->character_set) ?
'utf8' : (
string)
$conf->db->character_set;
121 if (preg_match(
'/latin1/', $clientmustbe)) {
122 $clientmustbe =
'utf8';
125 if (empty($disableforcecharset) && $this->db->character_set_name() != $clientmustbe) {
127 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);
134 $this->db->set_charset($clientmustbe);
135 }
catch (Throwable $e) {
136 print
'Failed to force character_set_client to '.$clientmustbe.
" (according to setup) to match the one of the server database.<br>\n";
137 print $e->getMessage();
139 if ($clientmustbe !=
'utf8') {
140 print
'Edit conf/conf.php file to set a charset "utf8"';
141 if ($clientmustbe !=
'utf8mb4') {
142 print
' or "utf8mb4"';
144 print
' instead of "'.$clientmustbe.
'".'.
"\n";
149 $collation = (empty(
$conf) ?
'utf8_unicode_ci' : (
string)
$conf->db->dolibarr_main_db_collation);
150 if (preg_match(
'/latin1/', $collation)) {
151 $collation =
'utf8_unicode_ci';
154 if (!preg_match(
'/general/', $collation)) {
155 $this->db->query(
"SET collation_connection = ".$collation);
159 $this->database_selected =
false;
160 $this->database_name =
'';
163 dol_syslog(get_class($this).
"::DoliDBMysqli : Select_db error ".$this->
error, LOG_ERR);
167 $this->database_selected =
false;
169 if ($this->connected) {
171 $clientmustbe = empty(
$conf->db->character_set) ?
'utf8' : (
string)
$conf->db->character_set;
172 if (preg_match(
'/latin1/', $clientmustbe)) {
173 $clientmustbe =
'utf8';
176 if (empty($disableforcecharset) && $this->db->character_set_name() != $clientmustbe) {
177 $this->db->set_charset($clientmustbe);
179 $collation = (
string)
$conf->db->dolibarr_main_db_collation;
180 if (preg_match(
'/latin1/', $collation)) {
181 $collation =
'utf8_unicode_ci';
184 if (!preg_match(
'/general/', $collation)) {
185 $this->db->query(
"SET collation_connection = ".$collation);
202 return " ".($mode == 1 ?
'FORCE' :
'USE').
" INDEX(".preg_replace(
'/[^a-z0-9_]/',
'', $nameofindex).
")";
229 dol_syslog(get_class($this).
"::select_db database=".$database, LOG_DEBUG);
232 $result = $this->db->select_db($database);
233 }
catch (Throwable $e) {
251 public function connect($host, $login, $passwd, $name, $port = 0)
253 dol_syslog(get_class($this).
"::connect host=$host, port=$port, login=$login, passwd=--hidden--, name=$name", LOG_DEBUG);
259 if (!class_exists(
'mysqli')) {
263 if (strpos($host,
'ssl://') === 0) {
264 $tmp =
new mysqliDoli($host, $login, $passwd, $name, $port);
266 $tmp =
new mysqli($host, $login, $passwd, $name, $port);
268 }
catch (Throwable $e) {
269 dol_syslog(get_class($this).
"::connect failed", LOG_DEBUG);
281 return $this->db->server_info;
291 return $this->db->client_info;
304 if ($this->transaction_opened > 0) {
305 dol_syslog(get_class($this).
"::close Closing a connection with an opened transaction depth=".$this->transaction_opened, LOG_ERR);
307 $this->connected =
false;
308 return $this->db->close();
325 public function query($query, $usesavepoint = 0,
$type =
'auto', $result_mode = 0)
327 global $dolibarr_main_db_readonly;
329 $query = trim($query);
337 if (!in_array($query, array(
'BEGIN',
'COMMIT',
'ROLLBACK'))) {
338 $SYSLOG_SQL_LIMIT = 10000;
339 dol_syslog(
'sql='.substr($query, 0, $SYSLOG_SQL_LIMIT), LOG_DEBUG);
345 if (!empty($dolibarr_main_db_readonly)) {
346 if (preg_match(
'/^(INSERT|UPDATE|REPLACE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) {
347 $this->
lasterror =
'Application in read-only mode';
355 $ret = $this->db->query($query, $result_mode);
356 }
catch (Throwable $e) {
357 dol_syslog(get_class($this).
"::query Exception in query instead of returning an error: ".$e->getMessage(), LOG_ERR);
361 if (!preg_match(
"/^COMMIT/i", $query) && !preg_match(
"/^ROLLBACK/i", $query)) {
369 dol_syslog(get_class($this).
"::query SQL Error query: ".$query, LOG_ERR);
371 dol_syslog(get_class($this).
"::query SQL Error message: ".$this->
lasterrno.
" ".$this->lasterror.self::getCallerInfoString(), LOG_ERR);
381 $this->_results = $ret;
394 $backtrace = debug_backtrace();
396 if (count($backtrace) >= 1) {
397 $trace = $backtrace[1];
398 if (isset($trace[
'file'], $trace[
'line'])) {
399 $msg =
" From {$trace['file']}:{$trace['line']}.";
416 if (!is_object($resultset)) {
417 $resultset = $this->_results;
419 return $resultset->fetch_object();
434 if (!is_object($resultset)) {
435 $resultset = $this->_results;
437 return $resultset->fetch_array();
451 if (!is_bool($resultset)) {
452 if (!is_object($resultset)) {
453 $resultset = $this->_results;
455 return $resultset->fetch_row();
474 if (!is_object($resultset)) {
475 $resultset = $this->_results;
477 return isset($resultset->num_rows) ? $resultset->num_rows : 0;
492 if (!is_object($resultset)) {
493 $resultset = $this->_results;
496 return $this->db->affected_rows;
505 public function free($resultset =
null)
508 if (!is_object($resultset)) {
509 $resultset = $this->_results;
512 if (is_object($resultset)) {
513 $resultset->free_result();
525 return $this->db->real_escape_string((
string) $stringtoencode);
537 return str_replace(array(
'\\',
'_',
'%'), array(
'\\\\',
'\_',
'\%'), (
string) $stringtoencode);
547 if (!$this->connected) {
549 return 'DB_ERROR_FAILED_TO_CONNECT';
552 $errorcode_map = array(
553 1004 =>
'DB_ERROR_CANNOT_CREATE',
554 1005 =>
'DB_ERROR_CANNOT_CREATE',
555 1006 =>
'DB_ERROR_CANNOT_CREATE',
556 1007 =>
'DB_ERROR_ALREADY_EXISTS',
557 1008 =>
'DB_ERROR_CANNOT_DROP',
558 1022 =>
'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
559 1025 =>
'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
560 1044 =>
'DB_ERROR_ACCESSDENIED',
561 1046 =>
'DB_ERROR_NODBSELECTED',
562 1048 =>
'DB_ERROR_CONSTRAINT',
563 1050 =>
'DB_ERROR_TABLE_ALREADY_EXISTS',
564 1051 =>
'DB_ERROR_NOSUCHTABLE',
565 1054 =>
'DB_ERROR_NOSUCHFIELD',
566 1060 =>
'DB_ERROR_COLUMN_ALREADY_EXISTS',
567 1061 =>
'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
568 1062 =>
'DB_ERROR_RECORD_ALREADY_EXISTS',
569 1064 =>
'DB_ERROR_SYNTAX',
570 1068 =>
'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
571 1075 =>
'DB_ERROR_CANT_DROP_PRIMARY_KEY',
572 1091 =>
'DB_ERROR_NOSUCHFIELD',
573 1100 =>
'DB_ERROR_NOT_LOCKED',
574 1136 =>
'DB_ERROR_VALUE_COUNT_ON_ROW',
575 1146 =>
'DB_ERROR_NOSUCHTABLE',
576 1215 =>
'DB_ERROR_CANNOT_ADD_FOREIGN_KEY_CONSTRAINT',
577 1216 =>
'DB_ERROR_NO_PARENT',
578 1217 =>
'DB_ERROR_CHILD_EXISTS',
579 1396 =>
'DB_ERROR_USER_ALREADY_EXISTS',
580 1451 =>
'DB_ERROR_CHILD_EXISTS',
581 1824 =>
'DB_ERROR_CANNOT_CREATE',
582 1826 =>
'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
585 if (isset($errorcode_map[$this->db->errno])) {
586 return $errorcode_map[$this->db->errno];
588 $errno = $this->db->errno;
589 return ($errno ?
'DB_ERROR_'.$errno :
'0');
600 if (!$this->connected) {
602 return 'Not connected. Check setup parameters in conf/conf.php file and your mysql client and server versions';
604 return $this->db->error;
619 return $this->db->insert_id;
630 public function encrypt($fieldorvalue, $withQuotes = 1)
635 $cryptType = (!empty(
$conf->db->dolibarr_main_db_encryption) ?
$conf->db->dolibarr_main_db_encryption : 0);
638 $cryptKey = (!empty(
$conf->db->dolibarr_main_db_cryptkey) ?
$conf->db->dolibarr_main_db_cryptkey :
'');
640 $escapedstringwithquotes = ($withQuotes ?
"'" :
"").$this->
escape($fieldorvalue).($withQuotes ?
"'" :
"");
642 if ($cryptType && !empty($cryptKey)) {
643 if ($cryptType == 2) {
644 $escapedstringwithquotes =
"AES_ENCRYPT(".$escapedstringwithquotes.
", '".$this->
escape($cryptKey).
"')";
645 } elseif ($cryptType == 1) {
646 $escapedstringwithquotes =
"DES_ENCRYPT(".$escapedstringwithquotes.
", '".$this->
escape($cryptKey).
"')";
650 return $escapedstringwithquotes;
664 $cryptType = (!empty(
$conf->db->dolibarr_main_db_encryption) ?
$conf->db->dolibarr_main_db_encryption : 0);
667 $cryptKey = (!empty(
$conf->db->dolibarr_main_db_cryptkey) ?
$conf->db->dolibarr_main_db_cryptkey :
'');
671 if ($cryptType && !empty($cryptKey)) {
672 if ($cryptType == 2) {
673 $return =
'AES_DECRYPT('.$value.
',\''.$cryptKey.
'\')
';
674 } elseif ($cryptType == 1) {
675 $return = 'DES_DECRYPT(
'.$value.',\
''.$cryptKey.
'\')
';
683 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
689 public function DDLGetConnectId()
692 $resql = $this->query('SELECT CONNECTION_ID()
');
694 $row = $this->fetch_row($resql);
701 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
713 public function DDLCreateDb($database, $charset = '
', $collation = '', $owner = '')
716 if (empty($charset)) {
717 $charset = $this->forcecharset;
719 if (empty($collation)) {
720 $collation = $this->forcecollate;
723 // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci
724 $sql = "CREATE DATABASE `".$this->sanitize($database)."`";
725 $sql .= " DEFAULT CHARACTER SET `".$this->sanitize($charset)."` DEFAULT COLLATE `".$this->sanitize($collation)."`";
727 dol_syslog($sql, LOG_DEBUG);
728 $ret = $this->query($sql);
730 // We try again for compatibility with Mysql < 4.1.1
731 $sql = "CREATE DATABASE `".$this->sanitize($database)."`";
732 dol_syslog($sql, LOG_DEBUG);
733 $ret = $this->query($sql);
739 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
747 public function DDLListTables($database, $table = '
')
750 $listtables = array();
754 $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i
', '', $table);
756 $like = "LIKE '".$this->escape($tmptable)."'";
758 $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $database);
760 $sql = "SHOW TABLES FROM `".$tmpdatabase."` ".$like.";";
762 $result = $this->query($sql);
764 while ($row = $this->fetch_row($result)) {
765 $listtables[] = $row[0];
771 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
779 public function DDLListTablesFull($database, $table = '
')
782 $listtables = array();
786 $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i
', '', $table);
788 $like = "LIKE '".$this->escape($tmptable)."'";
790 $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $database);
792 $sql = "SHOW FULL TABLES FROM `".$tmpdatabase."` ".$like.";";
794 $result = $this->query($sql);
796 while ($row = $this->fetch_row($result)) {
797 $listtables[] = $row;
803 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
810 public function DDLInfoTable($table)
813 $infotables = array();
815 $sanitizedtmptable = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $table);
817 $sql = "SHOW FULL COLUMNS FROM ".$sanitizedtmptable.";";
819 dol_syslog($sql, LOG_DEBUG);
820 $result = $this->query($sql);
822 while ($row = $this->fetch_row($result)) {
823 $infotables[] = $row;
829 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
842 public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null)
845 // @TODO: $fulltext_keys parameter is unused
855 // Keys found into the array $fields: type,value,attribute,null,default,extra
856 // ex. : $fields['rowid
'] = array(
857 // 'type'=>'int' or 'integer
',
859 // 'null'=>'not
null',
860 // 'extra
'=> 'auto_increment
'
862 $sql = "CREATE TABLE ".$this->sanitize($table)."(";
864 $sqlfields = array();
865 foreach ($fields as $field_name => $field_desc) {
866 $sqlfields[$i] = $this->sanitize($field_name)." ";
867 $sqlfields[$i] .= $this->sanitize($field_desc['type']);
868 if (isset($field_desc['value
']) && $field_desc['value
'] !== '') {
869 $sqlfields[$i] .= "(".$this->sanitize($field_desc['value
']).")";
871 if (isset($field_desc['attribute
']) && $field_desc['attribute
'] !== '') {
872 $sqlfields[$i] .= " ".$this->sanitize($field_desc['attribute
'], 0, 0, 1); // Allow space to accept attributes like "ON UPDATE CURRENT_TIMESTAMP"
874 if (isset($field_desc['default']) && $field_desc['default'] !== '') {
875 if (in_array($field_desc['type'], array('tinyint
', 'smallint
', 'int', 'double'))) {
876 $sqlfields[$i] .= " DEFAULT ".((float) $field_desc['default']);
877 } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP
') {
878 $sqlfields[$i] .= " DEFAULT ".$this->sanitize($field_desc['default']);
880 $sqlfields[$i] .= " DEFAULT '".$this->escape($field_desc['default'])."'";
883 if (isset($field_desc['null']) && $field_desc['null'] !== '') {
884 $sqlfields[$i] .= " ".$this->sanitize($field_desc['null'], 0, 0, 1);
886 if (isset($field_desc['extra
']) && $field_desc['extra
'] !== '') {
887 $sqlfields[$i] .= " ".$this->sanitize($field_desc['extra
'], 0, 0, 1);
889 if (!empty($primary_key) && $primary_key == $field_name) {
890 $sqlfields[$i] .= " AUTO_INCREMENT PRIMARY KEY"; // mysql instruction that will be converted by driver late
895 if (is_array($unique_keys)) {
897 foreach ($unique_keys as $key => $value) {
898 $sqluq[$i] = "UNIQUE KEY '".$this->sanitize($key)."' ('".$this->escape($value)."')";
902 if (is_array($keys)) {
904 foreach ($keys as $key => $value) {
905 $sqlk[$i] = "KEY ".$this->sanitize($key)." (".$value.")";
909 $sql .= implode(',
', $sqlfields);
910 if (!is_array($unique_keys) && $unique_keys != "") {
911 $sql .= ",".implode(',
', $sqluq);
913 if (is_array($keys)) {
914 $sql .= ",".implode(',
', $sqlk);
917 $sql .= " engine=".$this->sanitize($type);
919 if (!$this->query($sql)) {
926 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
933 public function DDLDropTable($table)
936 $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $table);
938 $sql = "DROP TABLE ".$this->sanitize($tmptable);
940 if (!$this->query($sql)) {
947 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
955 public function DDLDescTable($table, $field = "")
958 $sql = "DESC ".$this->sanitize($table)." ".$this->sanitize($field);
960 dol_syslog(get_class($this)."::DDLDescTable ".$sql, LOG_DEBUG);
961 $this->_results = $this->query($sql);
962 return $this->_results;
965 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
975 public function DDLAddField($table, $field_name, $field_desc, $field_position = "")
978 // keys looked up in the descriptions array (field_desc): type,value,attribute,null,default,extra
979 // ex. : $field_desc = array('
type'=>'int','value
'=>'11
','null'=>'not
null','extra
'=> 'auto_increment
');
980 $sql = "ALTER TABLE ".$this->sanitize($table)." ADD ".$this->sanitize($field_name)." ";
982 if ($field_desc['type'] !== 'datetimegmt
') {
983 $sql .= $this->sanitize($field_desc['type']);
988 if (in_array($field_desc['type'], array('double', 'int', 'varchar
')) && array_key_exists('value
', $field_desc) && !empty($field_desc['value
'])) {
989 $sql .= "(".$this->sanitize($field_desc['value
']).")";
991 if (isset($field_desc['attribute
']) && preg_match("/^[^\s]/i", $field_desc['attribute
'])) {
992 $sql .= " ".$this->sanitize($field_desc['attribute
']);
994 if (isset($field_desc['null']) && preg_match("/^[^\s]/i", $field_desc['null'])) {
995 if ($field_desc['null'] == 'NOT NULL
') {
996 $sql .= " ".$this->sanitize($field_desc['null'], 0, 0, 1);
998 $sql .= " ".$this->sanitize($field_desc['null']);
1001 if (isset($field_desc['default']) && preg_match("/^[^\s]/i", $field_desc['default'])) {
1002 if (in_array($field_desc['type'], array('tinyint
', 'smallint
', 'int', 'double'))) {
1003 $sql .= " DEFAULT ".((float) $field_desc['default']);
1004 } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP
') {
1005 $sql .= " DEFAULT ".$this->sanitize($field_desc['default']);
1007 $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'";
1010 if (isset($field_desc['extra
']) && preg_match("/^[^\s]/i", $field_desc['extra
'])) {
1011 $sql .= " ".$this->sanitize($field_desc['extra
'], 0, 0, 1);
1013 $sql .= " ".$this->sanitize($field_position, 0, 0, 1);
1015 dol_syslog(get_class($this)."::DDLAddField ".$sql, LOG_DEBUG);
1016 if ($this->query($sql)) {
1022 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1031 public function DDLUpdateField($table, $field_name, $field_desc)
1034 $sql = "ALTER TABLE ".$this->sanitize($table);
1035 $sql .= " MODIFY COLUMN ".$this->sanitize($field_name)." ";
1037 if ($field_desc['
type'] !== 'datetimegmt
') {
1038 $sql .= $this->sanitize($field_desc['type']);
1043 if (in_array($field_desc['type'], array('double', 'int', 'varchar
')) && array_key_exists('value
', $field_desc) && !empty($field_desc['value
'])) {
1044 $sql .= "(".$this->sanitize($field_desc['value
']).")";
1046 if (isset($field_desc['null']) && ($field_desc['null'] == 'not
null' || $field_desc['null'] == 'NOT NULL
')) {
1047 // 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
1048 if ($field_desc['type'] == 'varchar
' || $field_desc['type'] == 'text
') {
1049 $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";
1050 $this->query($sqlbis);
1051 } elseif (in_array($field_desc['type'], array('tinyint
', 'smallint
', 'int', 'double'))) {
1052 $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";
1053 $this->query($sqlbis);
1056 $sql .= " NOT NULL";
1059 if (isset($field_desc['default']) && $field_desc['default'] != '') {
1060 if (in_array($field_desc['type'], array('tinyint
', 'smallint
', 'int', 'double'))) {
1061 $sql .= " DEFAULT ".((float) $field_desc['default']);
1062 } elseif ($field_desc['type'] != 'text
') {
1063 $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields
1068 dol_syslog(get_class($this)."::DDLUpdateField ".$sql, LOG_DEBUG);
1069 if (!$this->query($sql)) {
1076 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1084 public function DDLDropField($table, $field_name)
1087 $tmp_field_name = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $field_name);
1089 $sql = "ALTER TABLE ".$this->sanitize($table)." DROP COLUMN `".$this->sanitize($tmp_field_name)."`";
1090 if ($this->query($sql)) {
1093 $this->error = $this->lasterror();
1098 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1108 public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
1111 $sql = "CREATE USER '
".$this->escape($dolibarr_main_db_user)."' IDENTIFIED BY '".$this->escape($dolibarr_main_db_pass)."'";
1112 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1113 $resql = $this->query($sql);
1115 if ($this->lasterrno != 'DB_ERROR_USER_ALREADY_EXISTS
') {
1118 // If user already exists, we continue to set permissions
1119 dol_syslog(get_class($this)."::DDLCreateUser sql=".$sql, LOG_WARNING);
1123 // Redo with localhost forced (sometimes user is created on %)
1124 $sql = "CREATE USER '".$this->escape($dolibarr_main_db_user)."'@'localhost
' IDENTIFIED BY '".$this->escape($dolibarr_main_db_pass)."'";
1125 $resql = $this->query($sql);
1127 $sql = "GRANT ALL PRIVILEGES ON `".$this->sanitize($dolibarr_main_db_name)."`.* TO '".$this->escape($dolibarr_main_db_user)."'@'".$this->escape($dolibarr_main_db_host)."'";
1128 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1129 $resql = $this->query($sql);
1131 $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)."'";
1135 $sql = "FLUSH Privileges";
1137 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
1138 $resql = $this->query($sql);
1153 public function getDefaultCharacterSetDatabase()
1155 $resql = $this->query("SHOW VARIABLES LIKE 'character_set_database
'");
1157 // version Mysql < 4.1.1
1158 return $this->forcecharset;
1160 $liste = $this->fetch_array($resql);
1161 $tmpval = $liste['Value
'];
1171 public function getListOfCharacterSet()
1173 $resql = $this->query('SHOW CHARSET
');
1177 while ($obj = $this->fetch_object($resql)) {
1178 $liste[$i]['charset
'] = $obj->Charset;
1182 $this->free($resql);
1184 // version Mysql < 4.1.1
1196 public function getDefaultCollationDatabase()
1198 $resql = $this->query("SHOW VARIABLES LIKE 'collation_database
'");
1200 // version Mysql < 4.1.1
1201 return $this->forcecollate;
1203 $liste = $this->fetch_array($resql);
1204 $tmpval = $liste['Value
'];
1214 public function getListOfCollation()
1216 $resql = $this->query('SHOW COLLATION
');
1220 while ($obj = $this->fetch_object($resql)) {
1221 $liste[$i]['collation
'] = $obj->Collation;
1224 $this->free($resql);
1226 // version Mysql < 4.1.1
1237 public function getPathOfDump()
1239 $fullpathofdump = '/pathtomysqldump/mysqldump
';
1241 $resql = $this->query("SHOW VARIABLES LIKE 'basedir
'");
1243 $liste = $this->fetch_array($resql);
1244 $basedir = $liste['Value
'];
1245 $fullpathofdump = $basedir.(preg_match('/\/$/
', $basedir) ? '' : '/
').'bin/mysqldump
';
1247 return $fullpathofdump;
1255 public function getPathOfRestore()
1257 $fullpathofimport = '/pathtomysql/mysql
';
1259 $resql = $this->query("SHOW VARIABLES LIKE 'basedir
'");
1261 $liste = $this->fetch_array($resql);
1262 $basedir = $liste['Value
'];
1263 $fullpathofimport = $basedir.(preg_match('/\/$/
', $basedir) ? '' : '/
').'bin/mysql
';
1265 return $fullpathofimport;
1274 public function getServerParametersValues($filter = '
')
1278 $sql = 'SHOW VARIABLES
';
1280 $sql .= " LIKE '".$this->escape($filter)."'";
1282 $resql = $this->query($sql);
1284 while ($obj = $this->fetch_object($resql)) {
1285 $result[$obj->Variable_name] = $obj->Value;
1298 public function getServerStatusValues($filter = '
')
1302 $sql = 'SHOW STATUS
';
1304 $sql .= " LIKE '".$this->escape($filter)."'";
1306 $resql = $this->query($sql);
1308 while ($obj = $this->fetch_object($resql)) {
1309 $result[$obj->Variable_name] = $obj->Value;
1322 public function getNextAutoIncrementId($table)
1324 // Request to get last status of table
1325 $sql = "SHOW TABLE STATUS LIKE '
".$this->escape($table)."'";
1326 $result = $this->query($sql);
1329 $obj = $this->fetch_object($result);
1330 if ($obj && isset($obj->Auto_increment)) {
1331 return (int) $obj->Auto_increment;
1344 public function prepare($sql)
1346 if (!$this->connected) {
1347 $this->lasterror = 'Not connected to database
';
1350 $stmt = $this->db->prepare($sql);
1351 if ($stmt === false) {
1352 $this->lasterror = $this->db->error;
1353 $this->lastqueryerror = $sql;
1361if (class_exists('mysqli
')) {
1365 class mysqliDoli extends mysqli
1378 public function __construct($host, $user, $pass, $name, $port = 0, $socket = "") // @phpstan-ignore constructor.unusedParameter
1381 if (PHP_VERSION_ID >= 80100) {
1382 parent::__construct();
1384 // @phan-suppress-next-line PhanDeprecatedFunctionInternal
1387 if (strpos($host, 'ssl:
1388 $host = substr($host, 6);
1389 parent::options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, 0);
1391 parent::ssl_set(
null,
null,
"",
null,
null);
1392 $flags = MYSQLI_CLIENT_SSL;
1394 parent::real_connect($host, $user, $pass, $name, $port, $socket, $flags);
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.
__construct($type, $host, $user, $pass, $name='', $port=0)
Constructor.
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 ...
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.
connect($host, $login, $passwd, $name, $port=0)
Connect to server.
errno()
Return generic error code of last operation.
static getCallerInfoString()
Get caller info.
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.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...