dolibarr  16.0.5
mysqli.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-2011 Laurent Destailleur <eldy@users.sourceforge.net>
5  * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
6  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
7  * Copyright (C) 2015 RaphaĆ«l Doursenaud <rdoursenaud@gpcsolutions.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  */
22 
28 require_once DOL_DOCUMENT_ROOT.'/core/db/DoliDB.class.php';
29 
33 class DoliDBMysqli extends DoliDB
34 {
36  public $db;
38  public $type = 'mysqli';
40  const LABEL = 'MySQL or MariaDB';
42  const VERSIONMIN = '5.0.3';
44  private $_results;
45 
57  public function __construct($type, $host, $user, $pass, $name = '', $port = 0)
58  {
59  global $conf, $langs;
60 
61  // Note that having "static" property for "$forcecharset" and "$forcecollate" will make error here in strict mode, so they are not static
62  if (!empty($conf->db->character_set)) {
63  $this->forcecharset = $conf->db->character_set;
64  }
65  if (!empty($conf->db->dolibarr_main_db_collation)) {
66  $this->forcecollate = $conf->db->dolibarr_main_db_collation;
67  }
68 
69  $this->database_user = $user;
70  $this->database_host = $host;
71  $this->database_port = $port;
72 
73  $this->transaction_opened = 0;
74 
75  //print "Name DB: $host,$user,$pass,$name<br>";
76 
77  if (!class_exists('mysqli')) {
78  $this->connected = false;
79  $this->ok = false;
80  $this->error = "Mysqli PHP functions for using Mysqli driver are not available in this version of PHP. Try to use another driver.";
81  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);
82  }
83 
84  if (!$host) {
85  $this->connected = false;
86  $this->ok = false;
87  $this->error = $langs->trans("ErrorWrongHostParameter");
88  dol_syslog(get_class($this)."::DoliDBMysqli : Connect error, wrong host parameters", LOG_ERR);
89  }
90 
91  // Try server connection
92  // We do not try to connect to database, only to server. Connect to database is done later in constrcutor
93  $this->db = $this->connect($host, $user, $pass, '', $port);
94 
95  if ($this->db && empty($this->db->connect_errno)) {
96  $this->connected = true;
97  $this->ok = true;
98  } else {
99  $this->connected = false;
100  $this->ok = false;
101  $this->error = empty($this->db) ? 'Failed to connect' : $this->db->connect_error;
102  dol_syslog(get_class($this)."::DoliDBMysqli Connect error: ".$this->error, LOG_ERR);
103  }
104 
105  // If server connection is ok, we try to connect to the database
106  if ($this->connected && $name) {
107  if ($this->select_db($name)) {
108  $this->database_selected = true;
109  $this->database_name = $name;
110  $this->ok = true;
111 
112  // If client is old latin, we force utf8
113  $clientmustbe = empty($conf->db->dolibarr_main_db_character_set) ? 'utf8' : $conf->db->dolibarr_main_db_character_set;
114  if (preg_match('/latin1/', $clientmustbe)) {
115  $clientmustbe = 'utf8';
116  }
117 
118  if ($this->db->character_set_name() != $clientmustbe) {
119  $this->db->set_charset($clientmustbe); // This set charset, but with a bad collation
120 
121  $collation = $conf->db->dolibarr_main_db_collation;
122  if (preg_match('/latin1/', $collation)) {
123  $collation = 'utf8_unicode_ci';
124  }
125 
126  if (!preg_match('/general/', $collation)) {
127  $this->db->query("SET collation_connection = ".$collation);
128  }
129  }
130  } else {
131  $this->database_selected = false;
132  $this->database_name = '';
133  $this->ok = false;
134  $this->error = $this->error();
135  dol_syslog(get_class($this)."::DoliDBMysqli : Select_db error ".$this->error, LOG_ERR);
136  }
137  } else {
138  // Pas de selection de base demandee, ok ou ko
139  $this->database_selected = false;
140 
141  if ($this->connected) {
142  // If client is old latin, we force utf8
143  $clientmustbe = empty($conf->db->dolibarr_main_db_character_set) ? 'utf8' : $conf->db->dolibarr_main_db_character_set;
144  if (preg_match('/latin1/', $clientmustbe)) {
145  $clientmustbe = 'utf8';
146  }
147  if (preg_match('/utf8mb4/', $clientmustbe)) {
148  $clientmustbe = 'utf8';
149  }
150 
151  if ($this->db->character_set_name() != $clientmustbe) {
152  $this->db->set_charset($clientmustbe); // This set utf8_unicode_ci
153 
154  $collation = $conf->db->dolibarr_main_db_collation;
155  if (preg_match('/latin1/', $collation)) {
156  $collation = 'utf8_unicode_ci';
157  }
158  if (preg_match('/utf8mb4/', $collation)) {
159  $collation = 'utf8_unicode_ci';
160  }
161 
162  if (!preg_match('/general/', $collation)) {
163  $this->db->query("SET collation_connection = ".$collation);
164  }
165  }
166  }
167  }
168  }
169 
170 
177  public function hintindex($nameofindex)
178  {
179  return " FORCE INDEX(".preg_replace('/[^a-z0-9_]/', '', $nameofindex).")";
180  }
181 
182 
190  public static function convertSQLFromMysql($line, $type = 'ddl')
191  {
192  return $line;
193  }
194 
195 
196  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
203  public function select_db($database)
204  {
205  // phpcs:enable
206  dol_syslog(get_class($this)."::select_db database=".$database, LOG_DEBUG);
207  $result = false;
208  try {
209  $result = $this->db->select_db($database);
210  } catch (Exception $e) {
211  // Nothing done on error
212  }
213  return $result;
214  }
215 
216 
228  public function connect($host, $login, $passwd, $name, $port = 0)
229  {
230  dol_syslog(get_class($this)."::connect host=$host, port=$port, login=$login, passwd=--hidden--, name=$name", LOG_DEBUG);
231 
232  //mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
233 
234  // Can also be
235  // mysqli::init(); mysql::options(MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT = 0'); mysqli::options(MYSQLI_OPT_CONNECT_TIMEOUT, 5);
236  // return mysqli::real_connect($host, $user, $pass, $db, $port);
237  $tmp = false;
238  try {
239  $tmp = new mysqli($host, $login, $passwd, $name, $port);
240  } catch (Exception $e) {
241  dol_syslog(get_class($this)."::connect failed", LOG_DEBUG);
242  }
243  return $tmp;
244  }
245 
251  public function getVersion()
252  {
253  return $this->db->server_info;
254  }
255 
261  public function getDriverInfo()
262  {
263  return $this->db->client_info;
264  }
265 
266 
273  public function close()
274  {
275  if ($this->db) {
276  if ($this->transaction_opened > 0) {
277  dol_syslog(get_class($this)."::close Closing a connection with an opened transaction depth=".$this->transaction_opened, LOG_ERR);
278  }
279  $this->connected = false;
280  return $this->db->close();
281  }
282  return false;
283  }
284 
285 
286 
297  public function query($query, $usesavepoint = 0, $type = 'auto', $result_mode = 0)
298  {
299  global $conf, $dolibarr_main_db_readonly;
300 
301  $query = trim($query);
302 
303  if (!in_array($query, array('BEGIN', 'COMMIT', 'ROLLBACK'))) {
304  $SYSLOG_SQL_LIMIT = 10000; // limit log to 10kb per line to limit DOS attacks
305  dol_syslog('sql='.substr($query, 0, $SYSLOG_SQL_LIMIT), LOG_DEBUG);
306  }
307  if (empty($query)) {
308  return false; // Return false = error if empty request
309  }
310 
311  if (!empty($dolibarr_main_db_readonly)) {
312  if (preg_match('/^(INSERT|UPDATE|REPLACE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) {
313  $this->lasterror = 'Application in read-only mode';
314  $this->lasterrno = 'APPREADONLY';
315  $this->lastquery = $query;
316  return false;
317  }
318  }
319 
320  try {
321  if (!$this->database_name) {
322  // Ordre SQL ne necessitant pas de connexion a une base (exemple: CREATE DATABASE)
323  $ret = $this->db->query($query, $result_mode);
324  } else {
325  $ret = $this->db->query($query, $result_mode);
326  }
327  } catch (Exception $e) {
328  dol_syslog(get_class($this)."::query Exception in query instead of returning an error: ".$e->getMessage(), LOG_ERR);
329  $ret = false;
330  }
331 
332  if (!preg_match("/^COMMIT/i", $query) && !preg_match("/^ROLLBACK/i", $query)) {
333  // Si requete utilisateur, on la sauvegarde ainsi que son resultset
334  if (!$ret) {
335  $this->lastqueryerror = $query;
336  $this->lasterror = $this->error();
337  $this->lasterrno = $this->errno();
338 
339  if ($conf->global->SYSLOG_LEVEL < LOG_DEBUG) {
340  dol_syslog(get_class($this)."::query SQL Error query: ".$query, LOG_ERR); // Log of request was not yet done previously
341  }
342  dol_syslog(get_class($this)."::query SQL Error message: ".$this->lasterrno." ".$this->lasterror, LOG_ERR);
343  //var_dump(debug_print_backtrace());
344  }
345  $this->lastquery = $query;
346  $this->_results = $ret;
347  }
348 
349  return $ret;
350  }
351 
352  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
359  public function fetch_object($resultset)
360  {
361  // phpcs:enable
362  // Si le resultset n'est pas fourni, on prend le dernier utilise sur cette connexion
363  if (!is_object($resultset)) {
364  $resultset = $this->_results;
365  }
366  return $resultset->fetch_object();
367  }
368 
369 
370  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
377  public function fetch_array($resultset)
378  {
379  // phpcs:enable
380  // If resultset not provided, we take the last used by connexion
381  if (!is_object($resultset)) {
382  $resultset = $this->_results;
383  }
384  return $resultset->fetch_array();
385  }
386 
387  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
394  public function fetch_row($resultset)
395  {
396  // phpcs:enable
397  // If resultset not provided, we take the last used by connexion
398  if (!is_bool($resultset)) {
399  if (!is_object($resultset)) {
400  $resultset = $this->_results;
401  }
402  return $resultset->fetch_row();
403  } else {
404  // si le curseur est un booleen on retourne la valeur 0
405  return 0;
406  }
407  }
408 
409  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
417  public function num_rows($resultset)
418  {
419  // phpcs:enable
420  // If resultset not provided, we take the last used by connexion
421  if (!is_object($resultset)) {
422  $resultset = $this->_results;
423  }
424  return $resultset->num_rows;
425  }
426 
427  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
435  public function affected_rows($resultset)
436  {
437  // phpcs:enable
438  // If resultset not provided, we take the last used by connexion
439  if (!is_object($resultset)) {
440  $resultset = $this->_results;
441  }
442  // mysql necessite un link de base pour cette fonction contrairement
443  // a pqsql qui prend un resultset
444  return $this->db->affected_rows;
445  }
446 
447 
454  public function free($resultset = null)
455  {
456  // If resultset not provided, we take the last used by connexion
457  if (!is_object($resultset)) {
458  $resultset = $this->_results;
459  }
460  // Si resultset en est un, on libere la memoire
461  if (is_object($resultset)) {
462  $resultset->free_result();
463  }
464  }
465 
472  public function escape($stringtoencode)
473  {
474  return $this->db->real_escape_string((string) $stringtoencode);
475  }
476 
484  public function escapeunderscore($stringtoencode)
485  {
486  return str_replace('_', '\_', (string) $stringtoencode);
487  }
488 
495  public function escapeforlike($stringtoencode)
496  {
497  return str_replace(array('_', '\\', '%'), array('\_', '\\\\', '\%'), (string) $stringtoencode);
498  }
499 
505  public function errno()
506  {
507  if (!$this->connected) {
508  // Si il y a eu echec de connexion, $this->db n'est pas valide.
509  return 'DB_ERROR_FAILED_TO_CONNECT';
510  } else {
511  // Constants to convert a MySql error code to a generic Dolibarr error code
512  $errorcode_map = array(
513  1004 => 'DB_ERROR_CANNOT_CREATE',
514  1005 => 'DB_ERROR_CANNOT_CREATE',
515  1006 => 'DB_ERROR_CANNOT_CREATE',
516  1007 => 'DB_ERROR_ALREADY_EXISTS',
517  1008 => 'DB_ERROR_CANNOT_DROP',
518  1022 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
519  1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
520  1044 => 'DB_ERROR_ACCESSDENIED',
521  1046 => 'DB_ERROR_NODBSELECTED',
522  1048 => 'DB_ERROR_CONSTRAINT',
523  1050 => 'DB_ERROR_TABLE_ALREADY_EXISTS',
524  1051 => 'DB_ERROR_NOSUCHTABLE',
525  1054 => 'DB_ERROR_NOSUCHFIELD',
526  1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
527  1061 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
528  1062 => 'DB_ERROR_RECORD_ALREADY_EXISTS',
529  1064 => 'DB_ERROR_SYNTAX',
530  1068 => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
531  1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
532  1091 => 'DB_ERROR_NOSUCHFIELD',
533  1100 => 'DB_ERROR_NOT_LOCKED',
534  1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
535  1146 => 'DB_ERROR_NOSUCHTABLE',
536  1215 => 'DB_ERROR_CANNOT_ADD_FOREIGN_KEY_CONSTRAINT',
537  1216 => 'DB_ERROR_NO_PARENT',
538  1217 => 'DB_ERROR_CHILD_EXISTS',
539  1396 => 'DB_ERROR_USER_ALREADY_EXISTS', // When creating a user that already existing
540  1451 => 'DB_ERROR_CHILD_EXISTS',
541  1826 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
542  );
543 
544  if (isset($errorcode_map[$this->db->errno])) {
545  return $errorcode_map[$this->db->errno];
546  }
547  $errno = $this->db->errno;
548  return ($errno ? 'DB_ERROR_'.$errno : '0');
549  }
550  }
551 
557  public function error()
558  {
559  if (!$this->connected) {
560  // Si il y a eu echec de connexion, $this->db n'est pas valide pour mysqli_error.
561  return 'Not connected. Check setup parameters in conf/conf.php file and your mysql client and server versions';
562  } else {
563  return $this->db->error;
564  }
565  }
566 
567  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
575  public function last_insert_id($tab, $fieldid = 'rowid')
576  {
577  // phpcs:enable
578  return $this->db->insert_id;
579  }
580 
589  public function encrypt($fieldorvalue, $withQuotes = 1)
590  {
591  global $conf;
592 
593  // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
594  $cryptType = (!empty($conf->db->dolibarr_main_db_encryption) ? $conf->db->dolibarr_main_db_encryption : 0);
595 
596  //Encryption key
597  $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : '');
598 
599  $escapedstringwithquotes = ($withQuotes ? "'" : "").$this->escape($fieldorvalue).($withQuotes ? "'" : "");
600 
601  if ($cryptType && !empty($cryptKey)) {
602  if ($cryptType == 2) {
603  $escapedstringwithquotes = "AES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')";
604  } elseif ($cryptType == 1) {
605  $escapedstringwithquotes = "DES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')";
606  }
607  }
608 
609  return $escapedstringwithquotes;
610  }
611 
618  public function decrypt($value)
619  {
620  global $conf;
621 
622  // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
623  $cryptType = (!empty($conf->db->dolibarr_main_db_encryption) ? $conf->db->dolibarr_main_db_encryption : 0);
624 
625  //Encryption key
626  $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : '');
627 
628  $return = $value;
629 
630  if ($cryptType && !empty($cryptKey)) {
631  if ($cryptType == 2) {
632  $return = 'AES_DECRYPT('.$value.',\''.$cryptKey.'\')';
633  } elseif ($cryptType == 1) {
634  $return = 'DES_DECRYPT('.$value.',\''.$cryptKey.'\')';
635  }
636  }
637 
638  return $return;
639  }
640 
641 
642  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
648  public function DDLGetConnectId()
649  {
650  // phpcs:enable
651  $resql = $this->query('SELECT CONNECTION_ID()');
652  if ($resql) {
653  $row = $this->fetch_row($resql);
654  return $row[0];
655  } else {
656  return '?';
657  }
658  }
659 
660  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
672  public function DDLCreateDb($database, $charset = '', $collation = '', $owner = '')
673  {
674  // phpcs:enable
675  if (empty($charset)) {
676  $charset = $this->forcecharset;
677  }
678  if (empty($collation)) {
679  $collation = $this->forcecollate;
680  }
681 
682  // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci
683  $sql = "CREATE DATABASE `".$this->escape($database)."`";
684  $sql .= " DEFAULT CHARACTER SET `".$this->escape($charset)."` DEFAULT COLLATE `".$this->escape($collation)."`";
685 
686  dol_syslog($sql, LOG_DEBUG);
687  $ret = $this->query($sql);
688  if (!$ret) {
689  // We try again for compatibility with Mysql < 4.1.1
690  $sql = "CREATE DATABASE `".$this->escape($database)."`";
691  dol_syslog($sql, LOG_DEBUG);
692  $ret = $this->query($sql);
693  }
694  return $ret;
695  }
696 
697  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
705  public function DDLListTables($database, $table = '')
706  {
707  // phpcs:enable
708  $listtables = array();
709 
710  $like = '';
711  if ($table) {
712  $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i', '', $table);
713 
714  $like = "LIKE '".$this->escape($tmptable)."'";
715  }
716  $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i', '', $database);
717 
718  $sql = "SHOW TABLES FROM `".$tmpdatabase."` ".$like.";";
719  //print $sql;
720  $result = $this->query($sql);
721  if ($result) {
722  while ($row = $this->fetch_row($result)) {
723  $listtables[] = $row[0];
724  }
725  }
726  return $listtables;
727  }
728 
729  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
736  public function DDLInfoTable($table)
737  {
738  // phpcs:enable
739  $infotables = array();
740 
741  $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i', '', $table);
742 
743  $sql = "SHOW FULL COLUMNS FROM ".$tmptable.";";
744 
745  dol_syslog($sql, LOG_DEBUG);
746  $result = $this->query($sql);
747  if ($result) {
748  while ($row = $this->fetch_row($result)) {
749  $infotables[] = $row;
750  }
751  }
752  return $infotables;
753  }
754 
755  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
768  public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null)
769  {
770  // phpcs:enable
771  // FIXME: $fulltext_keys parameter is unused
772 
773  // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra
774  // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
775  $sql = "CREATE TABLE ".$table."(";
776  $i = 0;
777  $sqlfields = array();
778  foreach ($fields as $field_name => $field_desc) {
779  $sqlfields[$i] = $field_name." ";
780  $sqlfields[$i] .= $field_desc['type'];
781  if (preg_match("/^[^\s]/i", $field_desc['value'])) {
782  $sqlfields[$i] .= "(".$field_desc['value'].")";
783  }
784  if (preg_match("/^[^\s]/i", $field_desc['attribute'])) {
785  $sqlfields[$i] .= " ".$field_desc['attribute'];
786  }
787  if (preg_match("/^[^\s]/i", $field_desc['default'])) {
788  if ((preg_match("/null/i", $field_desc['default'])) || (preg_match("/CURRENT_TIMESTAMP/i", $field_desc['default']))) {
789  $sqlfields[$i] .= " default ".$field_desc['default'];
790  } else {
791  $sqlfields[$i] .= " default '".$this->escape($field_desc['default'])."'";
792  }
793  }
794  if (preg_match("/^[^\s]/i", $field_desc['null'])) {
795  $sqlfields[$i] .= " ".$field_desc['null'];
796  }
797  if (preg_match("/^[^\s]/i", $field_desc['extra'])) {
798  $sqlfields[$i] .= " ".$field_desc['extra'];
799  }
800  $i++;
801  }
802  if ($primary_key != "") {
803  $pk = "primary key(".$primary_key.")";
804  }
805 
806  if (is_array($unique_keys)) {
807  $i = 0;
808  foreach ($unique_keys as $key => $value) {
809  $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$this->escape($value)."')";
810  $i++;
811  }
812  }
813  if (is_array($keys)) {
814  $i = 0;
815  foreach ($keys as $key => $value) {
816  $sqlk[$i] = "KEY ".$key." (".$value.")";
817  $i++;
818  }
819  }
820  $sql .= implode(',', $sqlfields);
821  if ($primary_key != "") {
822  $sql .= ",".$pk;
823  }
824  if ($unique_keys != "") {
825  $sql .= ",".implode(',', $sqluq);
826  }
827  if (is_array($keys)) {
828  $sql .= ",".implode(',', $sqlk);
829  }
830  $sql .= ") engine=".$type;
831 
832  if (!$this->query($sql)) {
833  return -1;
834  } else {
835  return 1;
836  }
837  }
838 
839  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
846  public function DDLDropTable($table)
847  {
848  // phpcs:enable
849  $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i', '', $table);
850 
851  $sql = "DROP TABLE ".$tmptable;
852 
853  if (!$this->query($sql)) {
854  return -1;
855  } else {
856  return 1;
857  }
858  }
859 
860  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
868  public function DDLDescTable($table, $field = "")
869  {
870  // phpcs:enable
871  $sql = "DESC ".$table." ".$field;
872 
873  dol_syslog(get_class($this)."::DDLDescTable ".$sql, LOG_DEBUG);
874  $this->_results = $this->query($sql);
875  return $this->_results;
876  }
877 
878  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
888  public function DDLAddField($table, $field_name, $field_desc, $field_position = "")
889  {
890  // phpcs:enable
891  // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra
892  // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
893  $sql = "ALTER TABLE ".$table." ADD ".$field_name." ";
894  $sql .= $field_desc['type'];
895  if (preg_match("/^[^\s]/i", $field_desc['value'])) {
896  if (!in_array($field_desc['type'], array('date', 'datetime')) && $field_desc['value']) {
897  $sql .= "(".$field_desc['value'].")";
898  }
899  }
900  if (isset($field_desc['attribute']) && preg_match("/^[^\s]/i", $field_desc['attribute'])) {
901  $sql .= " ".$field_desc['attribute'];
902  }
903  if (isset($field_desc['null']) && preg_match("/^[^\s]/i", $field_desc['null'])) {
904  $sql .= " ".$field_desc['null'];
905  }
906  if (isset($field_desc['default']) && preg_match("/^[^\s]/i", $field_desc['default'])) {
907  if (preg_match("/null/i", $field_desc['default'])) {
908  $sql .= " default ".$field_desc['default'];
909  } else {
910  $sql .= " default '".$this->escape($field_desc['default'])."'";
911  }
912  }
913  if (isset($field_desc['extra']) && preg_match("/^[^\s]/i", $field_desc['extra'])) {
914  $sql .= " ".$field_desc['extra'];
915  }
916  $sql .= " ".$field_position;
917 
918  dol_syslog(get_class($this)."::DDLAddField ".$sql, LOG_DEBUG);
919  if ($this->query($sql)) {
920  return 1;
921  }
922  return -1;
923  }
924 
925  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
934  public function DDLUpdateField($table, $field_name, $field_desc)
935  {
936  // phpcs:enable
937  $sql = "ALTER TABLE ".$table;
938  $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type'];
939  if (in_array($field_desc['type'], array('double', 'tinyint', 'int', 'varchar')) && $field_desc['value']) {
940  $sql .= "(".$field_desc['value'].")";
941  }
942  if ($field_desc['null'] == 'not null' || $field_desc['null'] == 'NOT NULL') {
943  // 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
944  if ($field_desc['type'] == 'varchar' || $field_desc['type'] == 'text') {
945  $sqlbis = "UPDATE ".$table." SET ".$field_name." = '".$this->escape($field_desc['default'] ? $field_desc['default'] : '')."' WHERE ".$field_name." IS NULL";
946  $this->query($sqlbis);
947  } elseif ($field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int') {
948  $sqlbis = "UPDATE ".$table." SET ".$field_name." = ".((int) $this->escape($field_desc['default'] ? $field_desc['default'] : 0))." WHERE ".$field_name." IS NULL";
949  $this->query($sqlbis);
950  }
951 
952  $sql .= " NOT NULL";
953  }
954 
955  if ($field_desc['default'] != '') {
956  if ($field_desc['type'] == 'double' || $field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int') {
957  $sql .= " DEFAULT ".$this->escape($field_desc['default']);
958  } elseif ($field_desc['type'] != 'text') {
959  $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields
960  }
961  }
962 
963  dol_syslog(get_class($this)."::DDLUpdateField ".$sql, LOG_DEBUG);
964  if (!$this->query($sql)) {
965  return -1;
966  } else {
967  return 1;
968  }
969  }
970 
971  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
979  public function DDLDropField($table, $field_name)
980  {
981  // phpcs:enable
982  $tmp_field_name = preg_replace('/[^a-z0-9\.\-\_]/i', '', $field_name);
983 
984  $sql = "ALTER TABLE ".$table." DROP COLUMN `".$tmp_field_name."`";
985  if ($this->query($sql)) {
986  return 1;
987  }
988  $this->error = $this->lasterror();
989  return -1;
990  }
991 
992 
993  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1003  public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
1004  {
1005  // phpcs:enable
1006  $sql = "CREATE USER '".$this->escape($dolibarr_main_db_user)."' IDENTIFIED BY '".$this->escape($dolibarr_main_db_pass)."'";
1007  dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1008  $resql = $this->query($sql);
1009  if (!$resql) {
1010  if ($this->lasterrno != 'DB_ERROR_USER_ALREADY_EXISTS') {
1011  return -1;
1012  } else {
1013  // If user already exists, we continue to set permissions
1014  dol_syslog(get_class($this)."::DDLCreateUser sql=".$sql, LOG_WARNING);
1015  }
1016  }
1017 
1018  // Redo with localhost forced (sometimes user is created on %)
1019  $sql = "CREATE USER '".$this->escape($dolibarr_main_db_user)."'@'localhost' IDENTIFIED BY '".$this->escape($dolibarr_main_db_pass)."'";
1020  $resql = $this->query($sql);
1021 
1022  $sql = "GRANT ALL PRIVILEGES ON ".$this->escape($dolibarr_main_db_name).".* TO '".$this->escape($dolibarr_main_db_user)."'@'".$this->escape($dolibarr_main_db_host)."'";
1023  dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1024  $resql = $this->query($sql);
1025  if (!$resql) {
1026  $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)."'";
1027  return -1;
1028  }
1029 
1030  $sql = "FLUSH Privileges";
1031 
1032  dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
1033  $resql = $this->query($sql);
1034  if (!$resql) {
1035  return -1;
1036  }
1037 
1038  return 1;
1039  }
1040 
1048  public function getDefaultCharacterSetDatabase()
1049  {
1050  $resql = $this->query('SHOW VARIABLES LIKE \'character_set_database\'');
1051  if (!$resql) {
1052  // version Mysql < 4.1.1
1053  return $this->forcecharset;
1054  }
1055  $liste = $this->fetch_array($resql);
1056  $tmpval = $liste['Value'];
1057 
1058  return $tmpval;
1059  }
1060 
1066  public function getListOfCharacterSet()
1067  {
1068  $resql = $this->query('SHOW CHARSET');
1069  $liste = array();
1070  if ($resql) {
1071  $i = 0;
1072  while ($obj = $this->fetch_object($resql)) {
1073  $liste[$i]['charset'] = $obj->Charset;
1074  $liste[$i]['description'] = $obj->Description;
1075  $i++;
1076  }
1077  $this->free($resql);
1078  } else {
1079  // version Mysql < 4.1.1
1080  return null;
1081  }
1082  return $liste;
1083  }
1084 
1092  {
1093  $resql = $this->query('SHOW VARIABLES LIKE \'collation_database\'');
1094  if (!$resql) {
1095  // version Mysql < 4.1.1
1096  return $this->forcecollate;
1097  }
1098  $liste = $this->fetch_array($resql);
1099  $tmpval = $liste['Value'];
1100 
1101  return $tmpval;
1102  }
1103 
1109  public function getListOfCollation()
1110  {
1111  $resql = $this->query('SHOW COLLATION');
1112  $liste = array();
1113  if ($resql) {
1114  $i = 0;
1115  while ($obj = $this->fetch_object($resql)) {
1116  $liste[$i]['collation'] = $obj->Collation;
1117  $i++;
1118  }
1119  $this->free($resql);
1120  } else {
1121  // version Mysql < 4.1.1
1122  return null;
1123  }
1124  return $liste;
1125  }
1126 
1132  public function getPathOfDump()
1133  {
1134  $fullpathofdump = '/pathtomysqldump/mysqldump';
1135 
1136  $resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
1137  if ($resql) {
1138  $liste = $this->fetch_array($resql);
1139  $basedir = $liste['Value'];
1140  $fullpathofdump = $basedir.(preg_match('/\/$/', $basedir) ? '' : '/').'bin/mysqldump';
1141  }
1142  return $fullpathofdump;
1143  }
1144 
1150  public function getPathOfRestore()
1151  {
1152  $fullpathofimport = '/pathtomysql/mysql';
1153 
1154  $resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
1155  if ($resql) {
1156  $liste = $this->fetch_array($resql);
1157  $basedir = $liste['Value'];
1158  $fullpathofimport = $basedir.(preg_match('/\/$/', $basedir) ? '' : '/').'bin/mysql';
1159  }
1160  return $fullpathofimport;
1161  }
1162 
1169  public function getServerParametersValues($filter = '')
1170  {
1171  $result = array();
1172 
1173  $sql = 'SHOW VARIABLES';
1174  if ($filter) {
1175  $sql .= " LIKE '".$this->escape($filter)."'";
1176  }
1177  $resql = $this->query($sql);
1178  if ($resql) {
1179  while ($obj = $this->fetch_object($resql)) {
1180  $result[$obj->Variable_name] = $obj->Value;
1181  }
1182  }
1183 
1184  return $result;
1185  }
1186 
1193  public function getServerStatusValues($filter = '')
1194  {
1195  $result = array();
1196 
1197  $sql = 'SHOW STATUS';
1198  if ($filter) {
1199  $sql .= " LIKE '".$this->escape($filter)."'";
1200  }
1201  $resql = $this->query($sql);
1202  if ($resql) {
1203  while ($obj = $this->fetch_object($resql)) {
1204  $result[$obj->Variable_name] = $obj->Value;
1205  }
1206  }
1207 
1208  return $result;
1209  }
1210 }
DoliDBMysqli\connect
connect($host, $login, $passwd, $name, $port=0)
Connect to server.
Definition: mysqli.class.php:228
DoliDBMysqli\getDriverInfo
getDriverInfo()
Return version of database client driver.
Definition: mysqli.class.php:261
DoliDBMysqli\fetch_object
fetch_object($resultset)
Returns the current line (as an object) for the resultset cursor.
Definition: mysqli.class.php:359
DoliDBMysqli\convertSQLFromMysql
static convertSQLFromMysql($line, $type='ddl')
Convert a SQL request in Mysql syntax to native syntax.
Definition: mysqli.class.php:190
db
$conf db
API class for accounts.
Definition: inc.php:41
DoliDB\lasterror
lasterror()
Return last error label.
Definition: DoliDB.class.php:309
DoliDB
Class to manage Dolibarr database access.
Definition: DoliDB.class.php:30
DoliDBMysqli\close
close()
Close database connexion.
Definition: mysqli.class.php:273
DoliDBMysqli\num_rows
num_rows($resultset)
Return number of lines for result of a SELECT.
Definition: mysqli.class.php:417
DoliDBMysqli\decrypt
decrypt($value)
Decrypt sensitive data in database.
Definition: mysqli.class.php:618
DoliDBMysqli\fetch_array
fetch_array($resultset)
Return datas as an array.
Definition: mysqli.class.php:377
DoliDBMysqli\getDefaultCollationDatabase
getDefaultCollationDatabase()
Return collation used in current database.
Definition: mysqli.class.php:1091
rowid
print *****$script_file(".$version.") pid c cd cd cd description as p label as s rowid
Definition: email_expire_services_to_representatives.php:79
DoliDBMysqli\getVersion
getVersion()
Return version of database server.
Definition: mysqli.class.php:251
DoliDB\lastquery
lastquery()
Return last request executed with query()
Definition: DoliDB.class.php:254
DoliDBMysqli\__construct
__construct($type, $host, $user, $pass, $name='', $port=0)
Constructor.
Definition: mysqli.class.php:57
Exception
DoliDBMysqli\affected_rows
affected_rows($resultset)
Return the number of lines in the result of a request INSERT, DELETE or UPDATE.
Definition: mysqli.class.php:435
DoliDBMysqli\free
free($resultset=null)
Libere le dernier resultset utilise sur cette connexion.
Definition: mysqli.class.php:454
DoliDBMysqli\getPathOfRestore
getPathOfRestore()
Return full path of restore program.
Definition: mysqli.class.php:1150
DoliDBMysqli\getListOfCollation
getListOfCollation()
Return list of available collation that can be used for database.
Definition: mysqli.class.php:1109
DoliDBMysqli\$type
$type
Database type.
Definition: mysqli.class.php:38
DoliDBMysqli\getServerStatusValues
getServerStatusValues($filter='')
Return value of server status (current indicators on memory, cache...)
Definition: mysqli.class.php:1193
DoliDB\lasterrno
lasterrno()
Return last error code.
Definition: DoliDB.class.php:129
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1603
DoliDBMysqli\escape
escape($stringtoencode)
Escape a string to insert data.
Definition: mysqli.class.php:472
DoliDBMysqli
Class to manage Dolibarr database access for a MySQL database using the MySQLi extension.
Definition: mysqli.class.php:33
DoliDBMysqli\select_db
select_db($database)
Select a database.
Definition: mysqli.class.php:203
DoliDBMysqli\getListOfCharacterSet
getListOfCharacterSet()
Return list of available charset that can be used to store data in database.
Definition: mysqli.class.php:1066
DoliDBMysqli\getPathOfDump
getPathOfDump()
Return full path of dump program.
Definition: mysqli.class.php:1132
DoliDBMysqli\escapeforlike
escapeforlike($stringtoencode)
Escape a string to insert data into a like.
Definition: mysqli.class.php:495
DoliDBMysqli\query
query($query, $usesavepoint=0, $type='auto', $result_mode=0)
Execute a SQL request and return the resultset.
Definition: mysqli.class.php:297
DoliDBMysqli\fetch_row
fetch_row($resultset)
Return datas as an array.
Definition: mysqli.class.php:394
DoliDB\lastqueryerror
lastqueryerror()
Return last query in error.
Definition: DoliDB.class.php:340
DoliDBMysqli\encrypt
encrypt($fieldorvalue, $withQuotes=1)
Encrypt sensitive data in database Warning: This function includes the escape and add the SQL simple ...
Definition: mysqli.class.php:589
DoliDBMysqli\LABEL
const LABEL
Database label.
Definition: mysqli.class.php:40
$resql
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
DoliDBMysqli\getServerParametersValues
getServerParametersValues($filter='')
Return value of server parameters.
Definition: mysqli.class.php:1169
DoliDBMysqli\VERSIONMIN
const VERSIONMIN
Version min database.
Definition: mysqli.class.php:42
DoliDBMysqli\error
error()
Return description of last error.
Definition: mysqli.class.php:557
DoliDBMysqli\hintindex
hintindex($nameofindex)
Return SQL string to force an index.
Definition: mysqli.class.php:177
DoliDBMysqli\escapeunderscore
escapeunderscore($stringtoencode)
Escape a string to insert data.
Definition: mysqli.class.php:484
DoliDBMysqli\last_insert_id
last_insert_id($tab, $fieldid='rowid')
Get last ID after an insert INSERT.
Definition: mysqli.class.php:575
type
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:119
DoliDBMysqli\errno
errno()
Return generic error code of last operation.
Definition: mysqli.class.php:505