TraceableDB.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. <?php
  2. /* Copyright (C) 2023 Laurent Destailleur <eldy@users.sourceforge.net>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. */
  17. /**
  18. * \file htdocs/debugbar/class/DataCollector/TraceableDB.php
  19. * \brief Class for debugbar DB
  20. * \ingroup debugbar
  21. */
  22. require_once DOL_DOCUMENT_ROOT.'/core/db/DoliDB.class.php';
  23. /**
  24. * TraceableDB class
  25. *
  26. * Used to log queries into DebugBar
  27. */
  28. class TraceableDB extends DoliDB
  29. {
  30. /**
  31. * @var DoliDb Database handler
  32. */
  33. public $db; // cannot be protected because of parent declaration
  34. /**
  35. * @var array Queries array
  36. */
  37. public $queries;
  38. /**
  39. * @var int Request start time
  40. */
  41. protected $startTime;
  42. /**
  43. * @var int Request start memory
  44. */
  45. protected $startMemory;
  46. /**
  47. * @var string type
  48. */
  49. public $type;
  50. /**
  51. * @const Database label
  52. */
  53. const LABEL = ''; // TODO: the right value should be $this->db::LABEL (but this is a constant? o_O)
  54. /**
  55. * @const Version min database
  56. */
  57. const VERSIONMIN = ''; // TODO: the same thing here, $this->db::VERSIONMIN is the right value
  58. /**
  59. * Constructor
  60. *
  61. * @param DoliDB $db Database handler
  62. */
  63. public function __construct($db)
  64. {
  65. $this->db = $db;
  66. $this->type = $this->db->type;
  67. $this->queries = array();
  68. }
  69. /**
  70. * Format a SQL IF
  71. *
  72. * @param string $test Test string (example: 'cd.statut=0', 'field IS NULL')
  73. * @param string $resok resultat si test egal
  74. * @param string $resko resultat si test non egal
  75. * @return string SQL string
  76. */
  77. public function ifsql($test, $resok, $resko)
  78. {
  79. return $this->db->ifsql($test, $resok, $resko);
  80. }
  81. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  82. /**
  83. * Return datas as an array
  84. *
  85. * @param resource $resultset Resultset of request
  86. * @return array Array
  87. */
  88. public function fetch_row($resultset)
  89. {
  90. // phpcs:enable
  91. return $this->db->fetch_row($resultset);
  92. }
  93. /**
  94. * Convert (by PHP) a GM Timestamp date into a string date with PHP server TZ to insert into a date field.
  95. * Function to use to build INSERT, UPDATE or WHERE predica
  96. *
  97. * @param int $param Date TMS to convert
  98. * @param mixed $gm 'gmt'=Input informations are GMT values, 'tzserver'=Local to server TZ
  99. * @return string Date in a string YYYY-MM-DD HH:MM:SS
  100. */
  101. public function idate($param, $gm = 'tzserver')
  102. {
  103. return $this->db->idate($param, $gm);
  104. }
  105. /**
  106. * Return last error code
  107. *
  108. * @return string lasterrno
  109. */
  110. public function lasterrno()
  111. {
  112. return $this->db->lasterrno();
  113. }
  114. /**
  115. * Start transaction
  116. *
  117. * @param string $textinlog Add a small text into log. '' by default.
  118. * @return int 1 if transaction successfuly opened or already opened, 0 if error
  119. */
  120. public function begin($textinlog = '')
  121. {
  122. return $this->db->begin($textinlog);
  123. }
  124. /**
  125. * Create a new database
  126. * Do not use function xxx_create_db (xxx=mysql, ...) as they are deprecated
  127. * We force to create database with charset this->forcecharset and collate this->forcecollate
  128. *
  129. * @param string $database Database name to create
  130. * @param string $charset Charset used to store data
  131. * @param string $collation Charset used to sort data
  132. * @param string $owner Username of database owner
  133. * @return resource resource defined if OK, null if KO
  134. */
  135. public function DDLCreateDb($database, $charset = '', $collation = '', $owner = '')
  136. {
  137. return $this->db->DDLCreateDb($database, $charset, $collation, $owner);
  138. }
  139. /**
  140. * Return version of database server into an array
  141. *
  142. * @return array Version array
  143. */
  144. public function getVersionArray()
  145. {
  146. return $this->db->getVersionArray();
  147. }
  148. /**
  149. * Convert a SQL request in Mysql syntax to native syntax
  150. *
  151. * @param string $line SQL request line to convert
  152. * @param string $type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
  153. * @return string SQL request line converted
  154. */
  155. public function convertSQLFromMysql($line, $type = 'ddl')
  156. {
  157. return $this->db->convertSQLFromMysql($line);
  158. }
  159. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  160. /**
  161. * Return the number o flines into the result of a request INSERT, DELETE or UPDATE
  162. *
  163. * @param resource $resultset Curseur de la requete voulue
  164. * @return int Number of lines
  165. * @see num_rows()
  166. */
  167. public function affected_rows($resultset)
  168. {
  169. // phpcs:enable
  170. return $this->db->affected_rows($resultset);
  171. }
  172. /**
  173. * Return description of last error
  174. *
  175. * @return string Error text
  176. */
  177. public function error()
  178. {
  179. return $this->db->error();
  180. }
  181. /**
  182. * List tables into a database
  183. *
  184. * @param string $database Name of database
  185. * @param string $table Nmae of table filter ('xxx%')
  186. * @return array List of tables in an array
  187. */
  188. public function DDLListTables($database, $table = '')
  189. {
  190. return $this->db->DDLListTables($database, $table);
  191. }
  192. /**
  193. * List tables into a database with table info
  194. *
  195. * @param string $database Name of database
  196. * @param string $table Nmae of table filter ('xxx%')
  197. * @return array List of tables in an array
  198. */
  199. public function DDLListTablesFull($database, $table = '')
  200. {
  201. return $this->db->DDLListTablesFull($database, $table);
  202. }
  203. /**
  204. * Return last request executed with query()
  205. *
  206. * @return string Last query
  207. */
  208. public function lastquery()
  209. {
  210. return $this->db->lastquery();
  211. }
  212. /**
  213. * Define sort criteria of request
  214. *
  215. * @param string $sortfield List of sort fields
  216. * @param string $sortorder Sort order
  217. * @return string String to provide syntax of a sort sql string
  218. */
  219. public function order($sortfield = null, $sortorder = null)
  220. {
  221. return $this->db->order($sortfield, $sortorder);
  222. }
  223. /**
  224. * Decrypt sensitive data in database
  225. *
  226. * @param string $value Value to decrypt
  227. * @return string Decrypted value if used
  228. */
  229. public function decrypt($value)
  230. {
  231. return $this->db->decrypt($value);
  232. }
  233. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  234. /**
  235. * Return datas as an array
  236. *
  237. * @param resource $resultset Resultset of request
  238. * @return array Array
  239. */
  240. public function fetch_array($resultset)
  241. {
  242. // phpcs:enable
  243. return $this->db->fetch_array($resultset);
  244. }
  245. /**
  246. * Return last error label
  247. *
  248. * @return string lasterror
  249. */
  250. public function lasterror()
  251. {
  252. return $this->db->lasterror();
  253. }
  254. /**
  255. * Escape a string to insert data
  256. *
  257. * @param string $stringtoencode String to escape
  258. * @return string String escaped
  259. */
  260. public function escape($stringtoencode)
  261. {
  262. return $this->db->escape($stringtoencode);
  263. }
  264. /**
  265. * Escape a string to insert data into a like
  266. *
  267. * @param string $stringtoencode String to escape
  268. * @return string String escaped
  269. */
  270. public function escapeforlike($stringtoencode)
  271. {
  272. return str_replace(array('_', '\\', '%'), array('\_', '\\\\', '\%'), (string) $stringtoencode);
  273. }
  274. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  275. /**
  276. * Get last ID after an insert INSERT
  277. *
  278. * @param string $tab Table name concerned by insert. Ne sert pas sous MySql mais requis pour compatibilite avec Postgresql
  279. * @param string $fieldid Field name
  280. * @return int Id of row
  281. */
  282. public function last_insert_id($tab, $fieldid = 'rowid')
  283. {
  284. // phpcs:enable
  285. return $this->db->last_insert_id($tab, $fieldid);
  286. }
  287. /**
  288. * Return full path of restore program
  289. *
  290. * @return string Full path of restore program
  291. */
  292. public function getPathOfRestore()
  293. {
  294. return $this->db->getPathOfRestore();
  295. }
  296. /**
  297. * Cancel a transaction and go back to initial data values
  298. *
  299. * @param string $log Add more log to default log line
  300. * @return resource|int 1 if cancelation is ok or transaction not open, 0 if error
  301. */
  302. public function rollback($log = '')
  303. {
  304. return $this->db->rollback($log);
  305. }
  306. /**
  307. * Execute a SQL request and return the resultset
  308. *
  309. * @param string $query SQL query string
  310. * @param int $usesavepoint 0=Default mode, 1=Run a savepoint before and a rollback to savepoint if error (this allow to have some request with errors inside global transactions).
  311. * 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.
  312. * @param string $type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
  313. * @param int $result_mode Result mode
  314. * @return resource Resultset of answer
  315. */
  316. public function query($query, $usesavepoint = 0, $type = 'auto', $result_mode = 0)
  317. {
  318. $this->startTracing();
  319. $resql = $this->db->query($query, $usesavepoint, $type, $result_mode);
  320. $this->endTracing($query, $resql);
  321. return $resql;
  322. }
  323. /**
  324. * Start query tracing
  325. *
  326. * @return void
  327. */
  328. protected function startTracing()
  329. {
  330. $this->startTime = microtime(true);
  331. $this->startMemory = memory_get_usage(true);
  332. }
  333. /**
  334. * End query tracing
  335. *
  336. * @param string $sql query string
  337. * @param string $resql query result
  338. * @return void
  339. */
  340. protected function endTracing($sql, $resql)
  341. {
  342. $endTime = microtime(true);
  343. $duration = $endTime - $this->startTime;
  344. $endMemory = memory_get_usage(true);
  345. $memoryDelta = $endMemory - $this->startMemory;
  346. $this->queries[] = array(
  347. 'sql' => $sql,
  348. 'duration' => $duration,
  349. 'memory_usage' => $memoryDelta,
  350. 'is_success' => $resql ? true : false,
  351. 'error_code' => $resql ? null : $this->db->lasterrno(),
  352. 'error_message' => $resql ? null : $this->db->lasterror()
  353. );
  354. }
  355. /**
  356. * Connexion to server
  357. *
  358. * @param string $host database server host
  359. * @param string $login login
  360. * @param string $passwd password
  361. * @param string $name name of database (not used for mysql, used for pgsql)
  362. * @param int $port Port of database server
  363. * @return resource Database access handler
  364. * @see close()
  365. */
  366. public function connect($host, $login, $passwd, $name, $port = 0)
  367. {
  368. return $this->db->connect($host, $login, $passwd, $name, $port);
  369. }
  370. /**
  371. * Define limits and offset of request
  372. *
  373. * @param int $limit Maximum number of lines returned (-1=conf->liste_limit, 0=no limit)
  374. * @param int $offset Numero of line from where starting fetch
  375. * @return string String with SQL syntax to add a limit and offset
  376. */
  377. public function plimit($limit = 0, $offset = 0)
  378. {
  379. return $this->db->plimit($limit, $offset);
  380. }
  381. /**
  382. * Return value of server parameters
  383. *
  384. * @param string $filter Filter list on a particular value
  385. * @return array Array of key-values (key=>value)
  386. */
  387. public function getServerParametersValues($filter = '')
  388. {
  389. return $this->db->getServerParametersValues($filter);
  390. }
  391. /**
  392. * Return value of server status
  393. *
  394. * @param string $filter Filter list on a particular value
  395. * @return array Array of key-values (key=>value)
  396. */
  397. public function getServerStatusValues($filter = '')
  398. {
  399. return $this->db->getServerStatusValues($filter);
  400. }
  401. /**
  402. * Return collation used in database
  403. *
  404. * @return string Collation value
  405. */
  406. public function getDefaultCollationDatabase()
  407. {
  408. return $this->db->getDefaultCollationDatabase();
  409. }
  410. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  411. /**
  412. * Return number of lines for result of a SELECT
  413. *
  414. * @param resource $resultset Resulset of requests
  415. * @return int Nb of lines
  416. * @see affected_rows()
  417. */
  418. public function num_rows($resultset)
  419. {
  420. // phpcs:enable
  421. return $this->db->num_rows($resultset);
  422. }
  423. /**
  424. * Return full path of dump program
  425. *
  426. * @return string Full path of dump program
  427. */
  428. public function getPathOfDump()
  429. {
  430. return $this->db->getPathOfDump();
  431. }
  432. /**
  433. * Return version of database client driver
  434. *
  435. * @return string Version string
  436. */
  437. public function getDriverInfo()
  438. {
  439. return $this->db->getDriverInfo();
  440. }
  441. /**
  442. * Return generic error code of last operation.
  443. *
  444. * @return string Error code (Exemples: DB_ERROR_TABLE_ALREADY_EXISTS, DB_ERROR_RECORD_ALREADY_EXISTS...)
  445. */
  446. public function errno()
  447. {
  448. return $this->db->errno();
  449. }
  450. /**
  451. * Create a table into database
  452. *
  453. * @param string $table Name of table
  454. * @param array $fields Tableau associatif [nom champ][tableau des descriptions]
  455. * @param string $primary_key Nom du champ qui sera la clef primaire
  456. * @param string $type Type de la table
  457. * @param array $unique_keys Tableau associatifs Nom de champs qui seront clef unique => valeur
  458. * @param array $fulltext_keys Tableau des Nom de champs qui seront indexes en fulltext
  459. * @param array $keys Tableau des champs cles noms => valeur
  460. * @return int Return integer <0 if KO, >=0 if OK
  461. */
  462. public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null)
  463. {
  464. return $this->db->DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys, $fulltext_keys, $keys);
  465. }
  466. /**
  467. * Drop a table into database
  468. *
  469. * @param string $table Name of table
  470. * @return int Return integer <0 if KO, >=0 if OK
  471. */
  472. public function DDLDropTable($table)
  473. {
  474. return $this->db->DDLDropTable($table);
  475. }
  476. /**
  477. * Return list of available charset that can be used to store data in database
  478. *
  479. * @return array List of Charset
  480. */
  481. public function getListOfCharacterSet()
  482. {
  483. return $this->db->getListOfCharacterSet();
  484. }
  485. /**
  486. * Create a new field into table
  487. *
  488. * @param string $table Name of table
  489. * @param string $field_name Name of field to add
  490. * @param string $field_desc Tableau associatif de description du champ a inserer[nom du parametre][valeur du parametre]
  491. * @param string $field_position Optionnel ex.: "after champtruc"
  492. * @return int Return integer <0 if KO, >0 if OK
  493. */
  494. public function DDLAddField($table, $field_name, $field_desc, $field_position = "")
  495. {
  496. return $this->db->DDLAddField($table, $field_name, $field_desc, $field_position);
  497. }
  498. /**
  499. * Drop a field from table
  500. *
  501. * @param string $table Name of table
  502. * @param string $field_name Name of field to drop
  503. * @return int Return integer <0 if KO, >0 if OK
  504. */
  505. public function DDLDropField($table, $field_name)
  506. {
  507. return $this->db->DDLDropField($table, $field_name);
  508. }
  509. /**
  510. * Update format of a field into a table
  511. *
  512. * @param string $table Name of table
  513. * @param string $field_name Name of field to modify
  514. * @param string $field_desc Array with description of field format
  515. * @return int Return integer <0 if KO, >0 if OK
  516. */
  517. public function DDLUpdateField($table, $field_name, $field_desc)
  518. {
  519. return $this->db->DDLUpdateField($table, $field_name, $field_desc);
  520. }
  521. /**
  522. * Return list of available collation that can be used for database
  523. *
  524. * @return array List of Collation
  525. */
  526. public function getListOfCollation()
  527. {
  528. return $this->db->getListOfCollation();
  529. }
  530. /**
  531. * Return a pointer of line with description of a table or field
  532. *
  533. * @param string $table Name of table
  534. * @param string $field Optionnel : Name of field if we want description of field
  535. * @return resource Resource
  536. */
  537. public function DDLDescTable($table, $field = "")
  538. {
  539. return $this->db->DDLDescTable($table, $field);
  540. }
  541. /**
  542. * Return version of database server
  543. *
  544. * @return string Version string
  545. */
  546. public function getVersion()
  547. {
  548. return $this->db->getVersion();
  549. }
  550. /**
  551. * Return charset used to store data in database
  552. *
  553. * @return string Charset
  554. */
  555. public function getDefaultCharacterSetDatabase()
  556. {
  557. return $this->db->getDefaultCharacterSetDatabase();
  558. }
  559. /**
  560. * Create a user and privileges to connect to database (even if database does not exists yet)
  561. *
  562. * @param string $dolibarr_main_db_host Ip serveur
  563. * @param string $dolibarr_main_db_user Nom user a creer
  564. * @param string $dolibarr_main_db_pass Mot de passe user a creer
  565. * @param string $dolibarr_main_db_name Database name where user must be granted
  566. * @return int Return integer <0 if KO, >=0 if OK
  567. */
  568. public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
  569. {
  570. return $this->db->DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name);
  571. }
  572. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  573. /**
  574. * Convert (by PHP) a PHP server TZ string date into a Timestamps date (GMT if gm=true)
  575. * 19700101020000 -> 3600 with TZ+1 and gmt=0
  576. * 19700101020000 -> 7200 whaterver is TZ if gmt=1
  577. *
  578. * @param string $string Date in a string (YYYYMMDDHHMMSS, YYYYMMDD, YYYY-MM-DD HH:MM:SS)
  579. * @param bool $gm 1=Input informations are GMT values, otherwise local to server TZ
  580. * @return int|string Date TMS or ''
  581. */
  582. public function jdate($string, $gm = false)
  583. {
  584. // phpcs:enable
  585. return $this->db->jdate($string, $gm);
  586. }
  587. /**
  588. * Encrypt sensitive data in database
  589. * Warning: This function includes the escape and add the SQL simple quotes on strings.
  590. *
  591. * @param string $fieldorvalue Field name or value to encrypt
  592. * @param int $withQuotes Return string including the SQL simple quotes. This param must always be 1 (Value 0 is bugged and deprecated).
  593. * @return string XXX(field) or XXX('value') or field or 'value'
  594. */
  595. public function encrypt($fieldorvalue, $withQuotes = 1)
  596. {
  597. return $this->db->encrypt($fieldorvalue, $withQuotes);
  598. }
  599. /**
  600. * Validate a database transaction
  601. *
  602. * @param string $log Add more log to default log line
  603. * @return int 1 if validation is OK or transaction level no started, 0 if ERROR
  604. */
  605. public function commit($log = '')
  606. {
  607. return $this->db->commit($log);
  608. }
  609. /**
  610. * List information of columns into a table.
  611. *
  612. * @param string $table Name of table
  613. * @return array Array with inforation on table
  614. */
  615. public function DDLInfoTable($table)
  616. {
  617. return $this->db->DDLInfoTable($table);
  618. }
  619. /**
  620. * Free last resultset used.
  621. *
  622. * @param resource $resultset Fre cursor
  623. * @return void
  624. */
  625. public function free($resultset = null)
  626. {
  627. $this->db->free($resultset);
  628. }
  629. /**
  630. * Close database connexion
  631. *
  632. * @return boolean True if disconnect successfull, false otherwise
  633. * @see connect()
  634. */
  635. public function close()
  636. {
  637. return $this->db->close();
  638. }
  639. /**
  640. * Return last query in error
  641. *
  642. * @return string lastqueryerror
  643. */
  644. public function lastqueryerror()
  645. {
  646. return $this->db->lastqueryerror();
  647. }
  648. /**
  649. * Return connexion ID
  650. *
  651. * @return string Id connexion
  652. */
  653. public function DDLGetConnectId()
  654. {
  655. return $this->db->DDLGetConnectId();
  656. }
  657. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  658. /**
  659. * Returns the current line (as an object) for the resultset cursor
  660. *
  661. * @param resource|PgSql\Connection $resultset Handler of the desired SQL request
  662. * @return Object Object result line or false if KO or end of cursor
  663. */
  664. public function fetch_object($resultset)
  665. {
  666. // phpcs:enable
  667. return $this->db->fetch_object($resultset);
  668. }
  669. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  670. /**
  671. * Select a database
  672. *
  673. * @param string $database Name of database
  674. * @return boolean true if OK, false if KO
  675. */
  676. public function select_db($database)
  677. {
  678. // phpcs:enable
  679. return $this->db->select_db($database);
  680. }
  681. }