dolibarr  13.0.2
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)) $this->forcecharset = $conf->db->character_set;
63  if (!empty($conf->db->dolibarr_main_db_collation)) $this->forcecollate = $conf->db->dolibarr_main_db_collation;
64 
65  $this->database_user = $user;
66  $this->database_host = $host;
67  $this->database_port = $port;
68 
69  $this->transaction_opened = 0;
70 
71  //print "Name DB: $host,$user,$pass,$name<br>";
72 
73  if (!class_exists('mysqli'))
74  {
75  $this->connected = false;
76  $this->ok = false;
77  $this->error = "Mysqli PHP functions for using Mysqli driver are not available in this version of PHP. Try to use another driver.";
78  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);
79  }
80 
81  if (!$host)
82  {
83  $this->connected = false;
84  $this->ok = false;
85  $this->error = $langs->trans("ErrorWrongHostParameter");
86  dol_syslog(get_class($this)."::DoliDBMysqli : Connect error, wrong host parameters", LOG_ERR);
87  }
88 
89  // Try server connection
90  // We do not try to connect to database, only to server. Connect to database is done later in constrcutor
91  $this->db = $this->connect($host, $user, $pass, '', $port);
92 
93  if ($this->db->connect_errno) {
94  $this->connected = false;
95  $this->ok = false;
96  $this->error = $this->db->connect_error;
97  dol_syslog(get_class($this)."::DoliDBMysqli Connect error: ".$this->error, LOG_ERR);
98  } else {
99  $this->connected = true;
100  $this->ok = true;
101  }
102 
103  // If server connection is ok, we try to connect to the database
104  if ($this->connected && $name)
105  {
106  if ($this->select_db($name))
107  {
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)) $clientmustbe = 'utf8';
115 
116  if ($this->db->character_set_name() != $clientmustbe) {
117  $this->db->set_charset($clientmustbe); // This set charset, but with a bad collation
118 
119  $collation = $conf->db->dolibarr_main_db_collation;
120  if (preg_match('/latin1/', $collation)) $collation = 'utf8_unicode_ci';
121 
122  if (!preg_match('/general/', $collation)) $this->db->query("SET collation_connection = ".$collation);
123  }
124  } else {
125  $this->database_selected = false;
126  $this->database_name = '';
127  $this->ok = false;
128  $this->error = $this->error();
129  dol_syslog(get_class($this)."::DoliDBMysqli : Select_db error ".$this->error, LOG_ERR);
130  }
131  } else {
132  // Pas de selection de base demandee, ok ou ko
133  $this->database_selected = false;
134 
135  if ($this->connected)
136  {
137  // If client is old latin, we force utf8
138  $clientmustbe = empty($conf->db->dolibarr_main_db_character_set) ? 'utf8' : $conf->db->dolibarr_main_db_character_set;
139  if (preg_match('/latin1/', $clientmustbe)) $clientmustbe = 'utf8';
140  if (preg_match('/utf8mb4/', $clientmustbe)) $clientmustbe = 'utf8';
141 
142  if ($this->db->character_set_name() != $clientmustbe) {
143  $this->db->set_charset($clientmustbe); // This set utf8_unicode_ci
144 
145  $collation = $conf->db->dolibarr_main_db_collation;
146  if (preg_match('/latin1/', $collation)) $collation = 'utf8_unicode_ci';
147  if (preg_match('/utf8mb4/', $collation)) $collation = 'utf8_unicode_ci';
148 
149  if (!preg_match('/general/', $collation)) $this->db->query("SET collation_connection = ".$collation);
150  }
151  }
152  }
153  }
154 
155 
163  public static function convertSQLFromMysql($line, $type = 'ddl')
164  {
165  return $line;
166  }
167 
168  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
175  public function select_db($database)
176  {
177  // phpcs:enable
178  dol_syslog(get_class($this)."::select_db database=".$database, LOG_DEBUG);
179  return $this->db->select_db($database);
180  }
181 
182 
194  public function connect($host, $login, $passwd, $name, $port = 0)
195  {
196  dol_syslog(get_class($this)."::connect host=$host, port=$port, login=$login, passwd=--hidden--, name=$name", LOG_DEBUG);
197 
198  // Can also be
199  // mysqli::init(); mysql::options(MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT = 0'); mysqli::options(MYSQLI_OPT_CONNECT_TIMEOUT, 5);
200  // return mysqli::real_connect($host, $user, $pass, $db, $port);
201  return new mysqli($host, $login, $passwd, $name, $port);
202  }
203 
209  public function getVersion()
210  {
211  return $this->db->server_info;
212  }
213 
219  public function getDriverInfo()
220  {
221  return $this->db->client_info;
222  }
223 
224 
231  public function close()
232  {
233  if ($this->db)
234  {
235  if ($this->transaction_opened > 0) dol_syslog(get_class($this)."::close Closing a connection with an opened transaction depth=".$this->transaction_opened, LOG_ERR);
236  $this->connected = false;
237  return $this->db->close();
238  }
239  return false;
240  }
241 
251  public function query($query, $usesavepoint = 0, $type = 'auto')
252  {
253  global $conf;
254 
255  $query = trim($query);
256 
257  if (!in_array($query, array('BEGIN', 'COMMIT', 'ROLLBACK')))
258  {
259  $SYSLOG_SQL_LIMIT = 10000; // limit log to 10kb per line to limit DOS attacks
260  dol_syslog('sql='.substr($query, 0, $SYSLOG_SQL_LIMIT), LOG_DEBUG);
261  }
262  if (empty($query)) return false; // Return false = error if empty request
263 
264  if (!$this->database_name)
265  {
266  // Ordre SQL ne necessitant pas de connexion a une base (exemple: CREATE DATABASE)
267  $ret = $this->db->query($query);
268  } else {
269  $ret = $this->db->query($query);
270  }
271 
272  if (!preg_match("/^COMMIT/i", $query) && !preg_match("/^ROLLBACK/i", $query))
273  {
274  // Si requete utilisateur, on la sauvegarde ainsi que son resultset
275  if (!$ret)
276  {
277  $this->lastqueryerror = $query;
278  $this->lasterror = $this->error();
279  $this->lasterrno = $this->errno();
280 
281  if ($conf->global->SYSLOG_LEVEL < LOG_DEBUG) dol_syslog(get_class($this)."::query SQL Error query: ".$query, LOG_ERR); // Log of request was not yet done previously
282  dol_syslog(get_class($this)."::query SQL Error message: ".$this->lasterrno." ".$this->lasterror, LOG_ERR);
283  //var_dump(debug_print_backtrace());
284  }
285  $this->lastquery = $query;
286  $this->_results = $ret;
287  }
288 
289  return $ret;
290  }
291 
292  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
299  public function fetch_object($resultset)
300  {
301  // phpcs:enable
302  // Si le resultset n'est pas fourni, on prend le dernier utilise sur cette connexion
303  if (!is_object($resultset)) { $resultset = $this->_results; }
304  return $resultset->fetch_object();
305  }
306 
307 
308  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
315  public function fetch_array($resultset)
316  {
317  // phpcs:enable
318  // If resultset not provided, we take the last used by connexion
319  if (!is_object($resultset)) { $resultset = $this->_results; }
320  return $resultset->fetch_array();
321  }
322 
323  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
330  public function fetch_row($resultset)
331  {
332  // phpcs:enable
333  // If resultset not provided, we take the last used by connexion
334  if (!is_bool($resultset))
335  {
336  if (!is_object($resultset)) { $resultset = $this->_results; }
337  return $resultset->fetch_row();
338  } else {
339  // si le curseur est un booleen on retourne la valeur 0
340  return 0;
341  }
342  }
343 
344  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
352  public function num_rows($resultset)
353  {
354  // phpcs:enable
355  // If resultset not provided, we take the last used by connexion
356  if (!is_object($resultset)) { $resultset = $this->_results; }
357  return $resultset->num_rows;
358  }
359 
360  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
368  public function affected_rows($resultset)
369  {
370  // phpcs:enable
371  // If resultset not provided, we take the last used by connexion
372  if (!is_object($resultset)) { $resultset = $this->_results; }
373  // mysql necessite un link de base pour cette fonction contrairement
374  // a pqsql qui prend un resultset
375  return $this->db->affected_rows;
376  }
377 
378 
385  public function free($resultset = null)
386  {
387  // If resultset not provided, we take the last used by connexion
388  if (!is_object($resultset)) { $resultset = $this->_results; }
389  // Si resultset en est un, on libere la memoire
390  if (is_object($resultset)) $resultset->free_result();
391  }
392 
399  public function escape($stringtoencode)
400  {
401  return $this->db->real_escape_string($stringtoencode);
402  }
403 
409  public function errno()
410  {
411  if (!$this->connected) {
412  // Si il y a eu echec de connexion, $this->db n'est pas valide.
413  return 'DB_ERROR_FAILED_TO_CONNECT';
414  } else {
415  // Constants to convert a MySql error code to a generic Dolibarr error code
416  $errorcode_map = array(
417  1004 => 'DB_ERROR_CANNOT_CREATE',
418  1005 => 'DB_ERROR_CANNOT_CREATE',
419  1006 => 'DB_ERROR_CANNOT_CREATE',
420  1007 => 'DB_ERROR_ALREADY_EXISTS',
421  1008 => 'DB_ERROR_CANNOT_DROP',
422  1022 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
423  1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
424  1044 => 'DB_ERROR_ACCESSDENIED',
425  1046 => 'DB_ERROR_NODBSELECTED',
426  1048 => 'DB_ERROR_CONSTRAINT',
427  1050 => 'DB_ERROR_TABLE_ALREADY_EXISTS',
428  1051 => 'DB_ERROR_NOSUCHTABLE',
429  1054 => 'DB_ERROR_NOSUCHFIELD',
430  1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
431  1061 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
432  1062 => 'DB_ERROR_RECORD_ALREADY_EXISTS',
433  1064 => 'DB_ERROR_SYNTAX',
434  1068 => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
435  1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
436  1091 => 'DB_ERROR_NOSUCHFIELD',
437  1100 => 'DB_ERROR_NOT_LOCKED',
438  1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
439  1146 => 'DB_ERROR_NOSUCHTABLE',
440  1215 => 'DB_ERROR_CANNOT_ADD_FOREIGN_KEY_CONSTRAINT',
441  1216 => 'DB_ERROR_NO_PARENT',
442  1217 => 'DB_ERROR_CHILD_EXISTS',
443  1396 => 'DB_ERROR_USER_ALREADY_EXISTS', // When creating a user that already existing
444  1451 => 'DB_ERROR_CHILD_EXISTS',
445  1826 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
446  );
447 
448  if (isset($errorcode_map[$this->db->errno])) {
449  return $errorcode_map[$this->db->errno];
450  }
451  $errno = $this->db->errno;
452  return ($errno ? 'DB_ERROR_'.$errno : '0');
453  }
454  }
455 
461  public function error()
462  {
463  if (!$this->connected) {
464  // Si il y a eu echec de connexion, $this->db n'est pas valide pour mysqli_error.
465  return 'Not connected. Check setup parameters in conf/conf.php file and your mysql client and server versions';
466  } else {
467  return $this->db->error;
468  }
469  }
470 
471  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
479  public function last_insert_id($tab, $fieldid = 'rowid')
480  {
481  // phpcs:enable
482  return $this->db->insert_id;
483  }
484 
494  public function encrypt($fieldorvalue, $withQuotes = 0)
495  {
496  global $conf;
497 
498  // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
499  $cryptType = (!empty($conf->db->dolibarr_main_db_encryption) ? $conf->db->dolibarr_main_db_encryption : 0);
500 
501  //Encryption key
502  $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : '');
503 
504  $return = ($withQuotes ? "'" : "").$this->escape($fieldorvalue).($withQuotes ? "'" : "");
505 
506  if ($cryptType && !empty($cryptKey))
507  {
508  if ($cryptType == 2)
509  {
510  $return = 'AES_ENCRYPT('.$return.',\''.$cryptKey.'\')';
511  } elseif ($cryptType == 1)
512  {
513  $return = 'DES_ENCRYPT('.$return.',\''.$cryptKey.'\')';
514  }
515  }
516 
517  return $return;
518  }
519 
526  public function decrypt($value)
527  {
528  global $conf;
529 
530  // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
531  $cryptType = (!empty($conf->db->dolibarr_main_db_encryption) ? $conf->db->dolibarr_main_db_encryption : 0);
532 
533  //Encryption key
534  $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : '');
535 
536  $return = $value;
537 
538  if ($cryptType && !empty($cryptKey))
539  {
540  if ($cryptType == 2)
541  {
542  $return = 'AES_DECRYPT('.$value.',\''.$cryptKey.'\')';
543  } elseif ($cryptType == 1)
544  {
545  $return = 'DES_DECRYPT('.$value.',\''.$cryptKey.'\')';
546  }
547  }
548 
549  return $return;
550  }
551 
552 
553  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
559  public function DDLGetConnectId()
560  {
561  // phpcs:enable
562  $resql = $this->query('SELECT CONNECTION_ID()');
563  if ($resql)
564  {
565  $row = $this->fetch_row($resql);
566  return $row[0];
567  } else return '?';
568  }
569 
570  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
582  public function DDLCreateDb($database, $charset = '', $collation = '', $owner = '')
583  {
584  // phpcs:enable
585  if (empty($charset)) $charset = $this->forcecharset;
586  if (empty($collation)) $collation = $this->forcecollate;
587 
588  // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci
589  $sql = "CREATE DATABASE `".$this->escape($database)."`";
590  $sql .= " DEFAULT CHARACTER SET `".$this->escape($charset)."` DEFAULT COLLATE `".$this->escape($collation)."`";
591 
592  dol_syslog($sql, LOG_DEBUG);
593  $ret = $this->query($sql);
594  if (!$ret)
595  {
596  // We try again for compatibility with Mysql < 4.1.1
597  $sql = "CREATE DATABASE `".$this->escape($database)."`";
598  dol_syslog($sql, LOG_DEBUG);
599  $ret = $this->query($sql);
600  }
601  return $ret;
602  }
603 
604  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
612  public function DDLListTables($database, $table = '')
613  {
614  // phpcs:enable
615  $listtables = array();
616 
617  $like = '';
618  if ($table) $like = "LIKE '".$table."'";
619  $sql = "SHOW TABLES FROM ".$database." ".$like.";";
620  //print $sql;
621  $result = $this->query($sql);
622  if ($result)
623  {
624  while ($row = $this->fetch_row($result))
625  {
626  $listtables[] = $row[0];
627  }
628  }
629  return $listtables;
630  }
631 
632  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
639  public function DDLInfoTable($table)
640  {
641  // phpcs:enable
642  $infotables = array();
643 
644  $sql = "SHOW FULL COLUMNS FROM ".$table.";";
645 
646  dol_syslog($sql, LOG_DEBUG);
647  $result = $this->query($sql);
648  if ($result)
649  {
650  while ($row = $this->fetch_row($result))
651  {
652  $infotables[] = $row;
653  }
654  }
655  return $infotables;
656  }
657 
658  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
671  public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null)
672  {
673  // phpcs:enable
674  // FIXME: $fulltext_keys parameter is unused
675 
676  // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra
677  // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
678  $sql = "CREATE TABLE ".$table."(";
679  $i = 0;
680  $sqlfields = array();
681  foreach ($fields as $field_name => $field_desc)
682  {
683  $sqlfields[$i] = $field_name." ";
684  $sqlfields[$i] .= $field_desc['type'];
685  if (preg_match("/^[^\s]/i", $field_desc['value'])) {
686  $sqlfields[$i] .= "(".$field_desc['value'].")";
687  }
688  if (preg_match("/^[^\s]/i", $field_desc['attribute'])) {
689  $sqlfields[$i] .= " ".$field_desc['attribute'];
690  }
691  if (preg_match("/^[^\s]/i", $field_desc['default']))
692  {
693  if ((preg_match("/null/i", $field_desc['default'])) || (preg_match("/CURRENT_TIMESTAMP/i", $field_desc['default']))) {
694  $sqlfields[$i] .= " default ".$field_desc['default'];
695  } else {
696  $sqlfields[$i] .= " default '".$this->escape($field_desc['default'])."'";
697  }
698  }
699  if (preg_match("/^[^\s]/i", $field_desc['null'])) {
700  $sqlfields[$i] .= " ".$field_desc['null'];
701  }
702  if (preg_match("/^[^\s]/i", $field_desc['extra'])) {
703  $sqlfields[$i] .= " ".$field_desc['extra'];
704  }
705  $i++;
706  }
707  if ($primary_key != "")
708  $pk = "primary key(".$primary_key.")";
709 
710  if (is_array($unique_keys)) {
711  $i = 0;
712  foreach ($unique_keys as $key => $value)
713  {
714  $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$this->escape($value)."')";
715  $i++;
716  }
717  }
718  if (is_array($keys))
719  {
720  $i = 0;
721  foreach ($keys as $key => $value)
722  {
723  $sqlk[$i] = "KEY ".$key." (".$value.")";
724  $i++;
725  }
726  }
727  $sql .= implode(',', $sqlfields);
728  if ($primary_key != "")
729  $sql .= ",".$pk;
730  if ($unique_keys != "")
731  $sql .= ",".implode(',', $sqluq);
732  if (is_array($keys))
733  $sql .= ",".implode(',', $sqlk);
734  $sql .= ") engine=".$type;
735 
736  if (!$this->query($sql))
737  return -1;
738  else return 1;
739  }
740 
741  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
748  public function DDLDropTable($table)
749  {
750  // phpcs:enable
751  $sql = "DROP TABLE ".$table;
752 
753  if (!$this->query($sql))
754  return -1;
755  else return 1;
756  }
757 
758  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
766  public function DDLDescTable($table, $field = "")
767  {
768  // phpcs:enable
769  $sql = "DESC ".$table." ".$field;
770 
771  dol_syslog(get_class($this)."::DDLDescTable ".$sql, LOG_DEBUG);
772  $this->_results = $this->query($sql);
773  return $this->_results;
774  }
775 
776  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
786  public function DDLAddField($table, $field_name, $field_desc, $field_position = "")
787  {
788  // phpcs:enable
789  // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra
790  // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
791  $sql = "ALTER TABLE ".$table." ADD ".$field_name." ";
792  $sql .= $field_desc['type'];
793  if (preg_match("/^[^\s]/i", $field_desc['value']))
794  {
795  if (!in_array($field_desc['type'], array('date', 'datetime')) && $field_desc['value'])
796  {
797  $sql .= "(".$field_desc['value'].")";
798  }
799  }
800  if (isset($field_desc['attribute']) && preg_match("/^[^\s]/i", $field_desc['attribute']))
801  {
802  $sql .= " ".$field_desc['attribute'];
803  }
804  if (isset($field_desc['null']) && preg_match("/^[^\s]/i", $field_desc['null']))
805  {
806  $sql .= " ".$field_desc['null'];
807  }
808  if (isset($field_desc['default']) && preg_match("/^[^\s]/i", $field_desc['default']))
809  {
810  if (preg_match("/null/i", $field_desc['default']))
811  $sql .= " default ".$field_desc['default'];
812  else $sql .= " default '".$this->escape($field_desc['default'])."'";
813  }
814  if (isset($field_desc['extra']) && preg_match("/^[^\s]/i", $field_desc['extra']))
815  {
816  $sql .= " ".$field_desc['extra'];
817  }
818  $sql .= " ".$field_position;
819 
820  dol_syslog(get_class($this)."::DDLAddField ".$sql, LOG_DEBUG);
821  if ($this->query($sql)) {
822  return 1;
823  }
824  return -1;
825  }
826 
827  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
836  public function DDLUpdateField($table, $field_name, $field_desc)
837  {
838  // phpcs:enable
839  $sql = "ALTER TABLE ".$table;
840  $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type'];
841  if (in_array($field_desc['type'], array('double', 'tinyint', 'int', 'varchar')) && $field_desc['value']) {
842  $sql .= "(".$field_desc['value'].")";
843  }
844  if ($field_desc['null'] == 'not null' || $field_desc['null'] == 'NOT NULL')
845  {
846  // 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
847  if ($field_desc['type'] == 'varchar' || $field_desc['type'] == 'text')
848  {
849  $sqlbis = "UPDATE ".$table." SET ".$field_name." = '".$this->escape($field_desc['default'] ? $field_desc['default'] : '')."' WHERE ".$field_name." IS NULL";
850  $this->query($sqlbis);
851  } elseif ($field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int')
852  {
853  $sqlbis = "UPDATE ".$table." SET ".$field_name." = ".((int) $this->escape($field_desc['default'] ? $field_desc['default'] : 0))." WHERE ".$field_name." IS NULL";
854  $this->query($sqlbis);
855  }
856 
857  $sql .= " NOT NULL";
858  }
859 
860  if ($field_desc['default'] != '')
861  {
862  if ($field_desc['type'] == 'double' || $field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int') $sql .= " DEFAULT ".$this->escape($field_desc['default']);
863  elseif ($field_desc['type'] != 'text') $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields
864  }
865 
866  dol_syslog(get_class($this)."::DDLUpdateField ".$sql, LOG_DEBUG);
867  if (!$this->query($sql))
868  return -1;
869  else return 1;
870  }
871 
872  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
880  public function DDLDropField($table, $field_name)
881  {
882  // phpcs:enable
883  $sql = "ALTER TABLE ".$table." DROP COLUMN `".$field_name."`";
884  dol_syslog(get_class($this)."::DDLDropField ".$sql, LOG_DEBUG);
885  if ($this->query($sql)) {
886  return 1;
887  }
888  $this->error = $this->lasterror();
889  return -1;
890  }
891 
892 
893  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
903  public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
904  {
905  // phpcs:enable
906  $sql = "CREATE USER '".$this->escape($dolibarr_main_db_user)."'";
907  dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
908  $resql = $this->query($sql);
909  if (!$resql)
910  {
911  if ($this->lasterrno != 'DB_ERROR_USER_ALREADY_EXISTS')
912  {
913  return -1;
914  } else {
915  // If user already exists, we continue to set permissions
916  dol_syslog(get_class($this)."::DDLCreateUser sql=".$sql, LOG_WARNING);
917  }
918  }
919 
920  // Redo with localhost forced (sometimes user is created on %)
921  $sql = "CREATE USER '".$this->escape($dolibarr_main_db_user)."'@'localhost'";
922  $resql = $this->query($sql);
923 
924  $sql = "GRANT ALL PRIVILEGES ON ".$this->escape($dolibarr_main_db_name).".* TO '".$this->escape($dolibarr_main_db_user)."'@'".$this->escape($dolibarr_main_db_host)."' IDENTIFIED BY '".$this->escape($dolibarr_main_db_pass)."'";
925  dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
926  $resql = $this->query($sql);
927  if (!$resql)
928  {
929  $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)."' IDENTIFIED BY '*****'";
930  return -1;
931  }
932 
933  $sql = "FLUSH Privileges";
934 
935  dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
936  $resql = $this->query($sql);
937  if (!$resql)
938  {
939  return -1;
940  }
941 
942  return 1;
943  }
944 
952  public function getDefaultCharacterSetDatabase()
953  {
954  $resql = $this->query('SHOW VARIABLES LIKE \'character_set_database\'');
955  if (!$resql)
956  {
957  // version Mysql < 4.1.1
958  return $this->forcecharset;
959  }
960  $liste = $this->fetch_array($resql);
961  $tmpval = $liste['Value'];
962 
963  return $tmpval;
964  }
965 
971  public function getListOfCharacterSet()
972  {
973  $resql = $this->query('SHOW CHARSET');
974  $liste = array();
975  if ($resql)
976  {
977  $i = 0;
978  while ($obj = $this->fetch_object($resql))
979  {
980  $liste[$i]['charset'] = $obj->Charset;
981  $liste[$i]['description'] = $obj->Description;
982  $i++;
983  }
984  $this->free($resql);
985  } else {
986  // version Mysql < 4.1.1
987  return null;
988  }
989  return $liste;
990  }
991 
998  public function getDefaultCollationDatabase()
999  {
1000  $resql = $this->query('SHOW VARIABLES LIKE \'collation_database\'');
1001  if (!$resql)
1002  {
1003  // version Mysql < 4.1.1
1004  return $this->forcecollate;
1005  }
1006  $liste = $this->fetch_array($resql);
1007  $tmpval = $liste['Value'];
1008 
1009  return $tmpval;
1010  }
1011 
1017  public function getListOfCollation()
1018  {
1019  $resql = $this->query('SHOW COLLATION');
1020  $liste = array();
1021  if ($resql)
1022  {
1023  $i = 0;
1024  while ($obj = $this->fetch_object($resql))
1025  {
1026  $liste[$i]['collation'] = $obj->Collation;
1027  $i++;
1028  }
1029  $this->free($resql);
1030  } else {
1031  // version Mysql < 4.1.1
1032  return null;
1033  }
1034  return $liste;
1035  }
1036 
1042  public function getPathOfDump()
1043  {
1044  $fullpathofdump = '/pathtomysqldump/mysqldump';
1045 
1046  $resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
1047  if ($resql)
1048  {
1049  $liste = $this->fetch_array($resql);
1050  $basedir = $liste['Value'];
1051  $fullpathofdump = $basedir.(preg_match('/\/$/', $basedir) ? '' : '/').'bin/mysqldump';
1052  }
1053  return $fullpathofdump;
1054  }
1055 
1061  public function getPathOfRestore()
1062  {
1063  $fullpathofimport = '/pathtomysql/mysql';
1064 
1065  $resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
1066  if ($resql)
1067  {
1068  $liste = $this->fetch_array($resql);
1069  $basedir = $liste['Value'];
1070  $fullpathofimport = $basedir.(preg_match('/\/$/', $basedir) ? '' : '/').'bin/mysql';
1071  }
1072  return $fullpathofimport;
1073  }
1074 
1081  public function getServerParametersValues($filter = '')
1082  {
1083  $result = array();
1084 
1085  $sql = 'SHOW VARIABLES';
1086  if ($filter) $sql .= " LIKE '".$this->escape($filter)."'";
1087  $resql = $this->query($sql);
1088  if ($resql)
1089  {
1090  while ($obj = $this->fetch_object($resql)) $result[$obj->Variable_name] = $obj->Value;
1091  }
1092 
1093  return $result;
1094  }
1095 
1102  public function getServerStatusValues($filter = '')
1103  {
1104  $result = array();
1105 
1106  $sql = 'SHOW STATUS';
1107  if ($filter) $sql .= " LIKE '".$this->escape($filter)."'";
1108  $resql = $this->query($sql);
1109  if ($resql)
1110  {
1111  while ($obj = $this->fetch_object($resql)) $result[$obj->Variable_name] = $obj->Value;
1112  }
1113 
1114  return $result;
1115  }
1116 }
getPathOfRestore()
Return full path of restore program.
lastqueryerror()
Return last query in error.
getListOfCharacterSet()
Return list of available charset that can be used to store data in database.
$type
Database type.
escape($stringtoencode)
Escape a string to insert data.
lastquery()
Return last request executed with query()
fetch_row($resultset)
Return datas as an array.
getPathOfDump()
Return full path of dump program.
select_db($database)
Select a database.
</td >< tdcolspan="3">< spanclass="opacitymedium"></span ></td ></tr >< trclass="liste_total"> CREANCES DETTES< tdcolspan="3"class="right"></td >< tdcolspan="3"class="right"></td ></tr > CREANCES DETTES RECETTES DEPENSES trips CREANCES DETTES Y m expensereport p date_valid Y m expensereport pe datep $db idate($date_start)."' AND $column < p rowid
Class to manage Dolibarr database access.
const LABEL
Database label.
lasterror()
Return last error label.
$conf db
API class for accounts.
Definition: inc.php:54
errno()
Return generic error code of last operation.
const VERSIONMIN
Version min database.
getServerParametersValues($filter= '')
Return value of server parameters.
error()
Return description of last error.
fetch_object($resultset)
Renvoie la ligne courante (comme un objet) pour le curseur resultset.
connect($host, $login, $passwd, $name, $port=0)
Connect to server.
__construct($type, $host, $user, $pass, $name= '', $port=0)
Constructor.
encrypt($fieldorvalue, $withQuotes=0)
Encrypt sensitive data in database Warning: This function includes the escape, so it must use direct ...
getDriverInfo()
Return version of database client driver.
query($query, $usesavepoint=0, $type= 'auto')
Execute a SQL request and return the resultset.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
close()
Close database connexion.
num_rows($resultset)
Return number of lines for result of a SELECT.
getServerStatusValues($filter= '')
Return value of server status (current indicators on memory, cache...)
fetch_array($resultset)
Return datas as an array.
getDefaultCollationDatabase()
Return collation used in current database.
last_insert_id($tab, $fieldid= 'rowid')
Get last ID after an insert INSERT.
Class to manage Dolibarr database access for a MySQL database using the MySQLi extension.
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
lasterrno()
Return last error code.
affected_rows($resultset)
Return the number of lines in the result of a request INSERT, DELETE or UPDATE.
static convertSQLFromMysql($line, $type= 'ddl')
Convert a SQL request in Mysql syntax to native syntax.
getVersion()
Return version of database server.
free($resultset=null)
Libere le dernier resultset utilise sur cette connexion.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:105
getListOfCollation()
Return list of available collation that can be used for database.