mysql.class.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. <?php
  2. /* Copyright (C) 2001 Fabien Seisen <seisen@linuxfr.org>
  3. * Copyright (C) 2002-2007 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@capnetworks.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. /**
  22. * \file htdocs/core/db/mysql.class.php
  23. * \brief Class file to manage Dolibarr database access for a MySQL database
  24. */
  25. require_once DOL_DOCUMENT_ROOT .'/core/db/DoliDB.class.php';
  26. /**
  27. * Class to manage Dolibarr database access for a MySQL database using the mysql extension
  28. *
  29. * @deprecated Use DoliDBMysqli
  30. */
  31. class DoliDBMysql extends DoliDB
  32. {
  33. //! Database type
  34. public $type='mysql';
  35. //! Database label
  36. const LABEL='MySQL';
  37. //! Version min database
  38. const VERSIONMIN='5.0.3';
  39. /** @var resource Resultset of last query */
  40. private $_results;
  41. /**
  42. * Constructor.
  43. * This create an opened connexion to a database server and eventually to a database
  44. *
  45. * @param string $type Type of database (mysql, pgsql...)
  46. * @param string $host Address of database server
  47. * @param string $user Nom de l'utilisateur autorise
  48. * @param string $pass Mot de passe
  49. * @param string $name Nom de la database
  50. * @param int $port Port of database server
  51. */
  52. function __construct($type, $host, $user, $pass, $name='', $port=0)
  53. {
  54. global $conf,$langs;
  55. // Note that having "static" property for "$forcecharset" and "$forcecollate" will make error here in strict mode, so they are not static
  56. if (! empty($conf->db->character_set)) $this->forcecharset=$conf->db->character_set;
  57. if (! empty($conf->db->dolibarr_main_db_collation)) $this->forcecollate=$conf->db->dolibarr_main_db_collation;
  58. $this->database_user=$user;
  59. $this->database_host=$host;
  60. $this->database_port=$port;
  61. $this->transaction_opened=0;
  62. //print "Name DB: $host,$user,$pass,$name<br>";
  63. if (! function_exists("mysql_connect"))
  64. {
  65. $this->connected = false;
  66. $this->ok = false;
  67. $this->error="Mysql PHP functions for using MySql driver are not available in this version of PHP. Try to use another driver.";
  68. dol_syslog(get_class($this)."::DoliDBMysql : Mysql PHP functions for using Mysql driver are not available in this version of PHP. Try to use another driver.",LOG_ERR);
  69. return $this->ok;
  70. }
  71. if (! $host)
  72. {
  73. $this->connected = false;
  74. $this->ok = false;
  75. $this->error=$langs->trans("ErrorWrongHostParameter");
  76. dol_syslog(get_class($this)."::DoliDBMysql : Erreur Connect, wrong host parameters",LOG_ERR);
  77. return $this->ok;
  78. }
  79. // Essai connexion serveur
  80. $this->db = $this->connect($host, $user, $pass, $name, $port);
  81. if ($this->db)
  82. {
  83. $this->connected = true;
  84. $this->ok = true;
  85. }
  86. else
  87. {
  88. // host, login ou password incorrect
  89. $this->connected = false;
  90. $this->ok = false;
  91. $this->error=mysql_error();
  92. dol_syslog(get_class($this)."::DoliDBMysql : Erreur Connect mysql_error=".$this->error,LOG_ERR);
  93. }
  94. // Si connexion serveur ok et si connexion base demandee, on essaie connexion base
  95. if ($this->connected && $name)
  96. {
  97. if ($this->select_db($name))
  98. {
  99. $this->database_selected = true;
  100. $this->database_name = $name;
  101. $this->ok = true;
  102. // If client connected with different charset than Dolibarr HTML output
  103. $clientmustbe='';
  104. if (preg_match('/UTF-8/i',$conf->file->character_set_client)) $clientmustbe='utf8';
  105. if (preg_match('/ISO-8859-1/i',$conf->file->character_set_client)) $clientmustbe='latin1';
  106. if (mysql_client_encoding($this->db) != $clientmustbe)
  107. {
  108. $this->query("SET NAMES '".$clientmustbe."'", $this->db);
  109. //$this->query("SET CHARACTER SET ". $this->forcecharset);
  110. }
  111. }
  112. else
  113. {
  114. $this->database_selected = false;
  115. $this->database_name = '';
  116. $this->ok = false;
  117. $this->error=$this->error();
  118. dol_syslog(get_class($this)."::DoliDBMysql : Erreur Select_db ".$this->error,LOG_ERR);
  119. }
  120. }
  121. else
  122. {
  123. // Pas de selection de base demandee, ok ou ko
  124. $this->database_selected = false;
  125. if ($this->connected)
  126. {
  127. // If client connected with different charset than Dolibarr HTML output
  128. $clientmustbe='';
  129. if (preg_match('/UTF-8/i',$conf->file->character_set_client)) $clientmustbe='utf8';
  130. if (preg_match('/ISO-8859-1/i',$conf->file->character_set_client)) $clientmustbe='latin1';
  131. if (mysql_client_encoding($this->db) != $clientmustbe)
  132. {
  133. $this->query("SET NAMES '".$clientmustbe."'", $this->db);
  134. //$this->query("SET CHARACTER SET ". $this->forcecharset);
  135. }
  136. }
  137. }
  138. return $this->ok;
  139. }
  140. /**
  141. * Convert a SQL request in Mysql syntax to native syntax
  142. *
  143. * @param string $line SQL request line to convert
  144. * @param string $type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
  145. * @return string SQL request line converted
  146. */
  147. static function convertSQLFromMysql($line,$type='ddl')
  148. {
  149. return $line;
  150. }
  151. /**
  152. * Select a database
  153. *
  154. * @param string $database Name of database
  155. * @return boolean true if OK, false if KO
  156. */
  157. function select_db($database)
  158. {
  159. dol_syslog(get_class($this)."::select_db database=".$database, LOG_DEBUG);
  160. return mysql_select_db($database, $this->db);
  161. }
  162. /**
  163. * Connection to server
  164. *
  165. * @param string $host database server host
  166. * @param string $login login
  167. * @param string $passwd password
  168. * @param string $name name of database (not used for mysql, used for pgsql)
  169. * @param integer $port Port of database server
  170. * @return resource|false Database access handler
  171. * @see close
  172. */
  173. function connect($host, $login, $passwd, $name, $port=0)
  174. {
  175. dol_syslog(get_class($this)."::connect host=$host, port=$port, login=$login, passwd=--hidden--, name=$name",LOG_DEBUG);
  176. $newhost=$host;
  177. // With mysql, port must be in hostname
  178. if ($port) $newhost.=':'.$port;
  179. $this->db = @mysql_connect($newhost, $login, $passwd);
  180. //print "Resultat fonction connect: ".$this->db;
  181. return $this->db;
  182. }
  183. /**
  184. * Return version of database server
  185. *
  186. * @return string Version string
  187. */
  188. function getVersion()
  189. {
  190. return mysql_get_server_info($this->db);
  191. }
  192. /**
  193. * Return version of database client driver
  194. *
  195. * @return string Version string
  196. */
  197. function getDriverInfo()
  198. {
  199. return mysql_get_client_info();
  200. }
  201. /**
  202. * Close database connexion
  203. *
  204. * @return boolean True if disconnect successfull, false otherwise
  205. * @see connect
  206. */
  207. function close()
  208. {
  209. if ($this->db)
  210. {
  211. if ($this->transaction_opened > 0) dol_syslog(get_class($this)."::close Closing a connection with an opened transaction depth=".$this->transaction_opened,LOG_ERR);
  212. $this->connected=false;
  213. return mysql_close($this->db);
  214. }
  215. return false;
  216. }
  217. /**
  218. * Execute a SQL request and return the resultset
  219. *
  220. * @param string $query SQL query string
  221. * @param int $usesavepoint 0=Default mode, 1=Run a savepoint before and a rollbock to savepoint if error (this allow to have some request with errors inside global transactions).
  222. * Note that with Mysql, this parameter is not used as Myssql can already commit a transaction even if one request is in error, without using savepoints.
  223. * @param string $type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
  224. * @return resource|true|false Resultset of answer
  225. */
  226. function query($query,$usesavepoint=0,$type='auto')
  227. {
  228. global $conf;
  229. $query = trim($query);
  230. if (! in_array($query,array('BEGIN','COMMIT','ROLLBACK'))) dol_syslog('sql='.$query, LOG_DEBUG);
  231. if (! $this->database_name)
  232. {
  233. // Ordre SQL ne necessitant pas de connexion a une base (exemple: CREATE DATABASE)
  234. $ret = mysql_query($query, $this->db);
  235. }
  236. else
  237. {
  238. mysql_select_db($this->database_name);
  239. $ret = mysql_query($query, $this->db);
  240. }
  241. if (! preg_match("/^COMMIT/i",$query) && ! preg_match("/^ROLLBACK/i",$query))
  242. {
  243. // Si requete utilisateur, on la sauvegarde ainsi que son resultset
  244. if (! $ret)
  245. {
  246. $this->lastqueryerror = $query;
  247. $this->lasterror = $this->error();
  248. $this->lasterrno = $this->errno();
  249. 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
  250. dol_syslog(get_class($this)."::query SQL Error message: ".$this->lasterrno." ".$this->lasterror, LOG_ERR);
  251. }
  252. $this->lastquery=$query;
  253. $this->_results = $ret;
  254. }
  255. return $ret;
  256. }
  257. /**
  258. * Renvoie la ligne courante (comme un objet) pour le curseur resultset
  259. *
  260. * @param resource $resultset Curseur de la requete voulue
  261. * @return resource|false Object result line or false if KO or end of cursor
  262. */
  263. function fetch_object($resultset)
  264. {
  265. // If resultset not provided, we take the last used by connexion
  266. if (! is_resource($resultset)) { $resultset=$this->_results; }
  267. return mysql_fetch_object($resultset);
  268. }
  269. /**
  270. * Return datas as an array
  271. *
  272. * @param resource $resultset Resultset of request
  273. * @return array Array
  274. */
  275. function fetch_array($resultset)
  276. {
  277. // If resultset not provided, we take the last used by connexion
  278. if (! is_resource($resultset)) { $resultset=$this->_results; }
  279. return mysql_fetch_array($resultset);
  280. }
  281. /**
  282. * Return datas as an array
  283. *
  284. * @param resource $resultset Resultset of request
  285. * @return array Array
  286. */
  287. function fetch_row($resultset)
  288. {
  289. // If resultset not provided, we take the last used by connexion
  290. if (! is_resource($resultset)) { $resultset=$this->_results; }
  291. return @mysql_fetch_row($resultset);
  292. }
  293. /**
  294. * Return number of lines for result of a SELECT
  295. *
  296. * @param resource $resultset Resulset of requests
  297. * @return int Nb of lines
  298. * @see affected_rows
  299. */
  300. function num_rows($resultset)
  301. {
  302. // If resultset not provided, we take the last used by connexion
  303. if (! is_resource($resultset)) { $resultset=$this->_results; }
  304. return mysql_num_rows($resultset);
  305. }
  306. /**
  307. * Renvoie le nombre de lignes dans le resultat d'une requete INSERT, DELETE ou UPDATE
  308. *
  309. * @param resource $resultset Curseur de la requete voulue
  310. * @return int Nombre de lignes
  311. * @see num_rows
  312. */
  313. function affected_rows($resultset)
  314. {
  315. // If resultset not provided, we take the last used by connexion
  316. if (! is_resource($resultset)) { $resultset=$this->_results; }
  317. // mysql necessite un link de base pour cette fonction contrairement
  318. // a pqsql qui prend un resultset
  319. return mysql_affected_rows($this->db);
  320. }
  321. /**
  322. * Free last resultset used.
  323. *
  324. * @param resource $resultset Curseur de la requete voulue
  325. * @return void
  326. */
  327. function free($resultset=null)
  328. {
  329. // If resultset not provided, we take the last used by connexion
  330. if (! is_resource($resultset)) { $resultset=$this->_results; }
  331. // Si resultset en est un, on libere la memoire
  332. if (is_resource($resultset)) mysql_free_result($resultset);
  333. }
  334. /**
  335. * Escape a string to insert data
  336. *
  337. * @param string $stringtoencode String to escape
  338. * @return string String escaped
  339. */
  340. function escape($stringtoencode)
  341. {
  342. return addslashes($stringtoencode);
  343. }
  344. /**
  345. * Return generic error code of last operation.
  346. *
  347. * @return string Error code (Exemples: DB_ERROR_TABLE_ALREADY_EXISTS, DB_ERROR_RECORD_ALREADY_EXISTS...)
  348. */
  349. function errno()
  350. {
  351. if (! $this->connected)
  352. {
  353. // Si il y a eu echec de connexion, $this->db n'est pas valide.
  354. return 'DB_ERROR_FAILED_TO_CONNECT';
  355. }
  356. else
  357. {
  358. // Constants to convert a MySql error code to a generic Dolibarr error code
  359. $errorcode_map = array(
  360. 1004 => 'DB_ERROR_CANNOT_CREATE',
  361. 1005 => 'DB_ERROR_CANNOT_CREATE',
  362. 1006 => 'DB_ERROR_CANNOT_CREATE',
  363. 1007 => 'DB_ERROR_ALREADY_EXISTS',
  364. 1008 => 'DB_ERROR_CANNOT_DROP',
  365. 1022 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
  366. 1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
  367. 1044 => 'DB_ERROR_ACCESSDENIED',
  368. 1046 => 'DB_ERROR_NODBSELECTED',
  369. 1048 => 'DB_ERROR_CONSTRAINT',
  370. 1050 => 'DB_ERROR_TABLE_ALREADY_EXISTS',
  371. 1051 => 'DB_ERROR_NOSUCHTABLE',
  372. 1054 => 'DB_ERROR_NOSUCHFIELD',
  373. 1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
  374. 1061 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
  375. 1062 => 'DB_ERROR_RECORD_ALREADY_EXISTS',
  376. 1064 => 'DB_ERROR_SYNTAX',
  377. 1068 => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
  378. 1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
  379. 1091 => 'DB_ERROR_NOSUCHFIELD',
  380. 1100 => 'DB_ERROR_NOT_LOCKED',
  381. 1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
  382. 1146 => 'DB_ERROR_NOSUCHTABLE',
  383. 1216 => 'DB_ERROR_NO_PARENT',
  384. 1217 => 'DB_ERROR_CHILD_EXISTS',
  385. 1396 => 'DB_ERROR_USER_ALREADY_EXISTS', // When creating user already existing
  386. 1451 => 'DB_ERROR_CHILD_EXISTS'
  387. );
  388. if (isset($errorcode_map[mysql_errno($this->db)]))
  389. {
  390. return $errorcode_map[mysql_errno($this->db)];
  391. }
  392. $errno=mysql_errno($this->db);
  393. return ($errno?'DB_ERROR_'.$errno:'0');
  394. }
  395. }
  396. /**
  397. * Return description of last error
  398. *
  399. * @return string Error text
  400. */
  401. function error()
  402. {
  403. if (! $this->connected) {
  404. // Si il y a eu echec de connexion, $this->db n'est pas valide pour mysql_error.
  405. return 'Not connected. Check setup parameters in conf/conf.php file and your mysql client and server versions';
  406. }
  407. else {
  408. return mysql_error($this->db);
  409. }
  410. }
  411. /**
  412. * Get last ID after an insert INSERT
  413. *
  414. * @param string $tab Table name concerned by insert. Ne sert pas sous MySql mais requis pour compatibilite avec Postgresql
  415. * @param string $fieldid Field name
  416. * @return int Id of row
  417. */
  418. function last_insert_id($tab,$fieldid='rowid')
  419. {
  420. return mysql_insert_id($this->db);
  421. }
  422. // Next functions are not required. Only minor features use them.
  423. //---------------------------------------------------------------
  424. /**
  425. * Encrypt sensitive data in database
  426. * Warning: This function includes the escape, so it must use direct value
  427. *
  428. * @param string $fieldorvalue Field name or value to encrypt
  429. * @param int $withQuotes Return string with quotes
  430. * @return string XXX(field) or XXX('value') or field or 'value'
  431. */
  432. function encrypt($fieldorvalue, $withQuotes=0)
  433. {
  434. global $conf;
  435. // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
  436. $cryptType = (! empty($conf->db->dolibarr_main_db_encryption)?$conf->db->dolibarr_main_db_encryption:0);
  437. //Encryption key
  438. $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey)?$conf->db->dolibarr_main_db_cryptkey:'');
  439. $return = ($withQuotes?"'":"").$this->escape($fieldorvalue).($withQuotes?"'":"");
  440. if ($cryptType && !empty($cryptKey))
  441. {
  442. if ($cryptType == 2)
  443. {
  444. $return = 'AES_ENCRYPT('.$return.',\''.$cryptKey.'\')';
  445. }
  446. else if ($cryptType == 1)
  447. {
  448. $return = 'DES_ENCRYPT('.$return.',\''.$cryptKey.'\')';
  449. }
  450. }
  451. return $return;
  452. }
  453. /**
  454. * Decrypt sensitive data in database
  455. *
  456. * @param string $value Value to decrypt
  457. * @return string Decrypted value if used
  458. */
  459. function decrypt($value)
  460. {
  461. global $conf;
  462. // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
  463. $cryptType = (!empty($conf->db->dolibarr_main_db_encryption)?$conf->db->dolibarr_main_db_encryption:0);
  464. //Encryption key
  465. $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey)?$conf->db->dolibarr_main_db_cryptkey:'');
  466. $return = $value;
  467. if ($cryptType && !empty($cryptKey))
  468. {
  469. if ($cryptType == 2)
  470. {
  471. $return = 'AES_DECRYPT('.$value.',\''.$cryptKey.'\')';
  472. }
  473. else if ($cryptType == 1)
  474. {
  475. $return = 'DES_DECRYPT('.$value.',\''.$cryptKey.'\')';
  476. }
  477. }
  478. return $return;
  479. }
  480. /**
  481. * Return connexion ID
  482. *
  483. * @return string Id connexion
  484. */
  485. function DDLGetConnectId()
  486. {
  487. $resql=$this->query('SELECT CONNECTION_ID()');
  488. if ($resql)
  489. {
  490. $row=$this->fetch_row($resql);
  491. return $row[0];
  492. }
  493. else return '?';
  494. }
  495. /**
  496. * Create a new database
  497. * Do not use function xxx_create_db (xxx=mysql, ...) as they are deprecated
  498. * We force to create database with charset this->forcecharset and collate this->forcecollate
  499. *
  500. * @param string $database Database name to create
  501. * @param string $charset Charset used to store data
  502. * @param string $collation Charset used to sort data
  503. * @param string $owner Username of database owner
  504. * @return false|resource|true resource defined if OK, null if KO
  505. */
  506. function DDLCreateDb($database,$charset='',$collation='',$owner='')
  507. {
  508. if (empty($charset)) $charset=$this->forcecharset;
  509. if (empty($collation)) $collation=$this->forcecollate;
  510. // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci
  511. $sql = "CREATE DATABASE `".$this->escape($database)."`";
  512. $sql.= " DEFAULT CHARACTER SET `".$this->escape($charset)."` DEFAULT COLLATE `".$this->escape($collation)."`";
  513. dol_syslog($sql,LOG_DEBUG);
  514. $ret=$this->query($sql);
  515. if (! $ret)
  516. {
  517. // We try again for compatibility with Mysql < 4.1.1
  518. $sql = "CREATE DATABASE `".$this->escape($database)."`";
  519. dol_syslog($sql,LOG_DEBUG);
  520. $ret=$this->query($sql);
  521. }
  522. return $ret;
  523. }
  524. /**
  525. * List tables into a database
  526. *
  527. * @param string $database Name of database
  528. * @param string $table Nmae of table filter ('xxx%')
  529. * @return array List of tables in an array
  530. */
  531. function DDLListTables($database, $table='')
  532. {
  533. $listtables=array();
  534. $like = '';
  535. if ($table) $like = "LIKE '".$table."'";
  536. $sql="SHOW TABLES FROM ".$database." ".$like.";";
  537. //print $sql;
  538. $result = $this->query($sql);
  539. while($row = $this->fetch_row($result))
  540. {
  541. $listtables[] = $row[0];
  542. }
  543. return $listtables;
  544. }
  545. /**
  546. * List information of columns into a table.
  547. *
  548. * @param string $table Name of table
  549. * @return array Tableau des informations des champs de la table
  550. */
  551. function DDLInfoTable($table)
  552. {
  553. $infotables=array();
  554. $sql="SHOW FULL COLUMNS FROM ".$table.";";
  555. dol_syslog($sql,LOG_DEBUG);
  556. $result = $this->query($sql);
  557. while($row = $this->fetch_row($result))
  558. {
  559. $infotables[] = $row;
  560. }
  561. return $infotables;
  562. }
  563. /**
  564. * Create a table into database
  565. *
  566. * @param string $table Nom de la table
  567. * @param array $fields Tableau associatif [nom champ][tableau des descriptions]
  568. * @param string $primary_key Nom du champ qui sera la clef primaire
  569. * @param string $type Type de la table
  570. * @param array $unique_keys Tableau associatifs Nom de champs qui seront clef unique => valeur
  571. * @param array $fulltext_keys Tableau des Nom de champs qui seront indexes en fulltext
  572. * @param array $keys Tableau des champs cles noms => valeur
  573. * @return int <0 if KO, >=0 if OK
  574. */
  575. function DDLCreateTable($table,$fields,$primary_key,$type,$unique_keys=null,$fulltext_keys=null,$keys=null)
  576. {
  577. // FIXME: $fulltext_keys parameter is unused
  578. // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra
  579. // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
  580. $sql = "CREATE TABLE ".$table."(";
  581. $i=0;
  582. foreach($fields as $field_name => $field_desc)
  583. {
  584. $sqlfields[$i] = $field_name." ";
  585. $sqlfields[$i] .= $field_desc['type'];
  586. if( preg_match("/^[^\s]/i",$field_desc['value'])) {
  587. $sqlfields[$i] .= "(".$field_desc['value'].")";
  588. }
  589. if( preg_match("/^[^\s]/i",$field_desc['attribute'])) {
  590. $sqlfields[$i] .= " ".$field_desc['attribute'];
  591. }
  592. if( preg_match("/^[^\s]/i",$field_desc['default']))
  593. {
  594. if ((preg_match("/null/i",$field_desc['default'])) || (preg_match("/CURRENT_TIMESTAMP/i",$field_desc['default']))) {
  595. $sqlfields[$i] .= " default ".$field_desc['default'];
  596. }
  597. else {
  598. $sqlfields[$i] .= " default '".$field_desc['default']."'";
  599. }
  600. }
  601. if( preg_match("/^[^\s]/i",$field_desc['null'])) {
  602. $sqlfields[$i] .= " ".$field_desc['null'];
  603. }
  604. if( preg_match("/^[^\s]/i",$field_desc['extra'])) {
  605. $sqlfields[$i] .= " ".$field_desc['extra'];
  606. }
  607. $i++;
  608. }
  609. if($primary_key != "")
  610. $pk = "primary key(".$primary_key.")";
  611. if(is_array($unique_keys))
  612. {
  613. $i = 0;
  614. foreach($unique_keys as $key => $value)
  615. {
  616. $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$value."')";
  617. $i++;
  618. }
  619. }
  620. if(is_array($keys))
  621. {
  622. $i = 0;
  623. foreach($keys as $key => $value)
  624. {
  625. $sqlk[$i] = "KEY ".$key." (".$value.")";
  626. $i++;
  627. }
  628. }
  629. $sql .= implode(',',$sqlfields);
  630. if($primary_key != "")
  631. $sql .= ",".$pk;
  632. if(is_array($unique_keys))
  633. $sql .= ",".implode(',',$sqluq);
  634. if(is_array($keys))
  635. $sql .= ",".implode(',',$sqlk);
  636. $sql .=") engine=".$type;
  637. dol_syslog($sql,LOG_DEBUG);
  638. if(! $this -> query($sql))
  639. return -1;
  640. else
  641. return 1;
  642. }
  643. /**
  644. * Return a pointer of line with description of a table or field
  645. *
  646. * @param string $table Name of table
  647. * @param string $field Optionnel : Name of field if we want description of field
  648. * @return false|resource|true Resource
  649. */
  650. function DDLDescTable($table,$field="")
  651. {
  652. $sql="DESC ".$table." ".$field;
  653. dol_syslog(get_class($this)."::DDLDescTable ".$sql,LOG_DEBUG);
  654. $this->_results = $this->query($sql);
  655. return $this->_results;
  656. }
  657. /**
  658. * Create a new field into table
  659. *
  660. * @param string $table Name of table
  661. * @param string $field_name Name of field to add
  662. * @param string $field_desc Tableau associatif de description du champ a inserer[nom du parametre][valeur du parametre]
  663. * @param string $field_position Optionnel ex.: "after champtruc"
  664. * @return int <0 if KO, >0 if OK
  665. */
  666. function DDLAddField($table,$field_name,$field_desc,$field_position="")
  667. {
  668. // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra
  669. // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
  670. $sql= "ALTER TABLE ".$table." ADD `".$field_name."` ";
  671. $sql.= $field_desc['type'];
  672. if(preg_match("/^[^\s]/i",$field_desc['value']))
  673. if (! in_array($field_desc['type'],array('date','datetime')))
  674. {
  675. $sql.= "(".$field_desc['value'].")";
  676. }
  677. if(preg_match("/^[^\s]/i",$field_desc['attribute']))
  678. $sql.= " ".$field_desc['attribute'];
  679. if(preg_match("/^[^\s]/i",$field_desc['null']))
  680. $sql.= " ".$field_desc['null'];
  681. if(preg_match("/^[^\s]/i",$field_desc['default']))
  682. {
  683. if(preg_match("/null/i",$field_desc['default']))
  684. $sql.= " default ".$field_desc['default'];
  685. else
  686. $sql.= " default '".$field_desc['default']."'";
  687. }
  688. if(preg_match("/^[^\s]/i",$field_desc['extra']))
  689. $sql.= " ".$field_desc['extra'];
  690. $sql.= " ".$field_position;
  691. dol_syslog(get_class($this)."::DDLAddField ".$sql,LOG_DEBUG);
  692. if(! $this->query($sql))
  693. {
  694. return -1;
  695. }
  696. else
  697. {
  698. return 1;
  699. }
  700. }
  701. /**
  702. * Update format of a field into a table
  703. *
  704. * @param string $table Name of table
  705. * @param string $field_name Name of field to modify
  706. * @param string $field_desc Array with description of field format
  707. * @return int <0 if KO, >0 if OK
  708. */
  709. function DDLUpdateField($table,$field_name,$field_desc)
  710. {
  711. $sql = "ALTER TABLE ".$table;
  712. $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type'];
  713. if ($field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int' || $field_desc['type'] == 'varchar') {
  714. $sql.="(".$field_desc['value'].")";
  715. }
  716. if ($field_desc['null'] == 'not null' || $field_desc['null'] == 'NOT NULL') $sql.=" NOT NULL";
  717. dol_syslog(get_class($this)."::DDLUpdateField ".$sql,LOG_DEBUG);
  718. if (! $this->query($sql))
  719. return -1;
  720. else
  721. return 1;
  722. }
  723. /**
  724. * Drop a field from table
  725. *
  726. * @param string $table Name of table
  727. * @param string $field_name Name of field to drop
  728. * @return int <0 if KO, >0 if OK
  729. */
  730. function DDLDropField($table,$field_name)
  731. {
  732. $sql= "ALTER TABLE ".$table." DROP COLUMN `".$field_name."`";
  733. dol_syslog(get_class($this)."::DDLDropField ".$sql,LOG_DEBUG);
  734. if (! $this->query($sql))
  735. {
  736. $this->error=$this->lasterror();
  737. return -1;
  738. }
  739. else return 1;
  740. }
  741. /**
  742. * Create a user and privileges to connect to database (even if database does not exists yet)
  743. *
  744. * @param string $dolibarr_main_db_host Ip serveur
  745. * @param string $dolibarr_main_db_user Nom user a creer
  746. * @param string $dolibarr_main_db_pass Mot de passe user a creer
  747. * @param string $dolibarr_main_db_name Database name where user must be granted
  748. * @return int <0 if KO, >=0 if OK
  749. */
  750. function DDLCreateUser($dolibarr_main_db_host,$dolibarr_main_db_user,$dolibarr_main_db_pass,$dolibarr_main_db_name)
  751. {
  752. $sql = "CREATE USER '".$this->escape($dolibarr_main_db_user)."'";
  753. dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
  754. $resql=$this->query($sql);
  755. if (! $resql)
  756. {
  757. if ($this->lasterrno != 'DB_ERROR_USER_ALREADY_EXISTS')
  758. {
  759. return -1;
  760. }
  761. else
  762. {
  763. // If user already exists, we continue to set permissions
  764. dol_syslog(get_class($this)."::DDLCreateUser sql=".$sql, LOG_WARNING);
  765. }
  766. }
  767. $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)."'";
  768. dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
  769. $resql=$this->query($sql);
  770. if (! $resql)
  771. {
  772. return -1;
  773. }
  774. $sql="FLUSH Privileges";
  775. dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
  776. $resql=$this->query($sql);
  777. if (! $resql)
  778. {
  779. return -1;
  780. }
  781. return 1;
  782. }
  783. /**
  784. * Return charset used to store data in database
  785. *
  786. * @return string Charset
  787. */
  788. function getDefaultCharacterSetDatabase()
  789. {
  790. $resql=$this->query('SHOW VARIABLES LIKE \'character_set_database\'');
  791. if (!$resql)
  792. {
  793. // version Mysql < 4.1.1
  794. return $this->forcecharset;
  795. }
  796. $liste=$this->fetch_array($resql);
  797. return $liste['Value'];
  798. }
  799. /**
  800. * Return list of available charset that can be used to store data in database
  801. *
  802. * @return array List of Charset
  803. */
  804. function getListOfCharacterSet()
  805. {
  806. $resql=$this->query('SHOW CHARSET');
  807. $liste = array();
  808. if ($resql)
  809. {
  810. $i = 0;
  811. while ($obj = $this->fetch_object($resql) )
  812. {
  813. $liste[$i]['charset'] = $obj->Charset;
  814. $liste[$i]['description'] = $obj->Description;
  815. $i++;
  816. }
  817. $this->free($resql);
  818. } else {
  819. // version Mysql < 4.1.1
  820. return null;
  821. }
  822. return $liste;
  823. }
  824. /**
  825. * Return collation used in database
  826. *
  827. * @return string Collation value
  828. */
  829. function getDefaultCollationDatabase()
  830. {
  831. $resql=$this->query('SHOW VARIABLES LIKE \'collation_database\'');
  832. if (!$resql)
  833. {
  834. // version Mysql < 4.1.1
  835. return $this->forcecollate;
  836. }
  837. $liste=$this->fetch_array($resql);
  838. return $liste['Value'];
  839. }
  840. /**
  841. * Return list of available collation that can be used for database
  842. *
  843. * @return array List of Collation
  844. */
  845. function getListOfCollation()
  846. {
  847. $resql=$this->query('SHOW COLLATION');
  848. $liste = array();
  849. if ($resql)
  850. {
  851. $i = 0;
  852. while ($obj = $this->fetch_object($resql) )
  853. {
  854. $liste[$i]['collation'] = $obj->Collation;
  855. $i++;
  856. }
  857. $this->free($resql);
  858. } else {
  859. // version Mysql < 4.1.1
  860. return null;
  861. }
  862. return $liste;
  863. }
  864. /**
  865. * Return full path of dump program
  866. *
  867. * @return string Full path of dump program
  868. */
  869. function getPathOfDump()
  870. {
  871. $fullpathofdump='/pathtomysqldump/mysqldump';
  872. $resql=$this->query('SHOW VARIABLES LIKE \'basedir\'');
  873. if ($resql)
  874. {
  875. $liste=$this->fetch_array($resql);
  876. $basedir=$liste['Value'];
  877. $fullpathofdump=$basedir.(preg_match('/\/$/',$basedir)?'':'/').'bin/mysqldump';
  878. }
  879. return $fullpathofdump;
  880. }
  881. /**
  882. * Return full path of restore program
  883. *
  884. * @return string Full path of restore program
  885. */
  886. function getPathOfRestore()
  887. {
  888. $fullpathofimport='/pathtomysql/mysql';
  889. $resql=$this->query('SHOW VARIABLES LIKE \'basedir\'');
  890. if ($resql)
  891. {
  892. $liste=$this->fetch_array($resql);
  893. $basedir=$liste['Value'];
  894. $fullpathofimport=$basedir.(preg_match('/\/$/',$basedir)?'':'/').'bin/mysql';
  895. }
  896. return $fullpathofimport;
  897. }
  898. /**
  899. * Return value of server parameters
  900. *
  901. * @param string $filter Filter list on a particular value
  902. * @return array Array of key-values (key=>value)
  903. */
  904. function getServerParametersValues($filter='')
  905. {
  906. $result=array();
  907. $sql='SHOW VARIABLES';
  908. if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
  909. $resql=$this->query($sql);
  910. if ($resql)
  911. {
  912. while ($obj=$this->fetch_object($resql)) $result[$obj->Variable_name]=$obj->Value;
  913. }
  914. return $result;
  915. }
  916. /**
  917. * Return value of server status
  918. *
  919. * @param string $filter Filter list on a particular value
  920. * @return array Array of key-values (key=>value)
  921. */
  922. function getServerStatusValues($filter='')
  923. {
  924. $result=array();
  925. $sql='SHOW STATUS';
  926. if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
  927. $resql=$this->query($sql);
  928. if ($resql)
  929. {
  930. while ($obj=$this->fetch_object($resql)) $result[$obj->Variable_name]=$obj->Value;
  931. }
  932. return $result;
  933. }
  934. }