dolibarr 21.0.3
sqlite3.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-2009 Regis Houssin <regis.houssin@inodbox.com>
7 * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
8 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
9 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
30require_once DOL_DOCUMENT_ROOT.'/core/db/DoliDB.class.php';
31
35class DoliDBSqlite3 extends DoliDB
36{
38 public $type = 'sqlite3';
40 const LABEL = 'Sqlite3';
42 const VERSIONMIN = '3.0.0';
43
47 private $_results;
48
52 private $queryString;
53
54 const WEEK_MONDAY_FIRST = 1;
55 const WEEK_YEAR = 2;
56 const WEEK_FIRST_WEEKDAY = 4;
57
58
70 public function __construct($type, $host, $user, $pass, $name = '', $port = 0)
71 {
72 global $conf;
73
74 // Note that having "static" property for "$forcecharset" and "$forcecollate" will make error here in strict mode, so they are not static
75 if (!empty($conf->db->character_set)) {
76 $this->forcecharset = $conf->db->character_set;
77 }
78 if (!empty($conf->db->dolibarr_main_db_collation)) {
79 $this->forcecollate = $conf->db->dolibarr_main_db_collation;
80 }
81
82 $this->database_user = $user;
83 $this->database_host = $host;
84 $this->database_port = $port;
85
86 $this->transaction_opened = 0;
87
88 //print "Name DB: $host,$user,$pass,$name<br>";
89
90 /*if (! function_exists("sqlite_query"))
91 {
92 $this->connected = false;
93 $this->ok = false;
94 $this->error="Sqlite PHP functions for using Sqlite driver are not available in this version of PHP. Try to use another driver.";
95 dol_syslog(get_class($this)."::DoliDBSqlite3 : Sqlite PHP functions for using Sqlite driver are not available in this version of PHP. Try to use another driver.",LOG_ERR);
96 return;
97 }*/
98
99 /*if (! $host)
100 {
101 $this->connected = false;
102 $this->ok = false;
103 $this->error=$langs->trans("ErrorWrongHostParameter");
104 dol_syslog(get_class($this)."::DoliDBSqlite3 : Erreur Connect, wrong host parameters",LOG_ERR);
105 return;
106 }*/
107
108 // Essai connection serveur
109 // We do not try to connect to database, only to server. Connect to database is done later in constructor
110 $this->db = $this->connect($host, $user, $pass, $name, $port);
111
112 if ($this->db) {
113 $this->connected = true;
114 $this->ok = true;
115 $this->database_selected = true;
116 $this->database_name = $name;
117
118 $this->addCustomFunction('IF');
119 $this->addCustomFunction('MONTH');
120 $this->addCustomFunction('CURTIME');
121 $this->addCustomFunction('CURDATE');
122 $this->addCustomFunction('WEEK', 1);
123 $this->addCustomFunction('WEEK', 2);
124 $this->addCustomFunction('WEEKDAY');
125 $this->addCustomFunction('date_format');
126 //$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
127 } else {
128 // host, login ou password incorrect
129 $this->connected = false;
130 $this->ok = false;
131 $this->database_selected = false;
132 $this->database_name = '';
133 //$this->error=sqlite_connect_error();
134 dol_syslog(get_class($this)."::DoliDBSqlite3 : Error Connect ".$this->error, LOG_ERR);
135 }
136 }
137
138
146 public function convertSQLFromMysql($line, $type = 'ddl')
147 {
148 // Removed empty line if this is a comment line for SVN tagging
149 if (preg_match('/^--\s\$Id/i', $line)) {
150 return '';
151 }
152 // Return line if this is a comment
153 if (preg_match('/^#/i', $line) || preg_match('/^$/i', $line) || preg_match('/^--/i', $line)) {
154 return $line;
155 }
156 if ($line != "") {
157 if ($type == 'auto') {
158 if (preg_match('/ALTER TABLE/i', $line)) {
159 $type = 'dml';
160 } elseif (preg_match('/CREATE TABLE/i', $line)) {
161 $type = 'dml';
162 } elseif (preg_match('/DROP TABLE/i', $line)) {
163 $type = 'dml';
164 }
165 }
166
167 if ($type == 'dml') {
168 $line = preg_replace('/\s/', ' ', $line); // Replace tabulation with space
169
170 // we are inside create table statement so let's process datatypes
171 if (preg_match('/(ISAM|innodb)/i', $line)) { // end of create table sequence
172 $line = preg_replace('/\‍)[\s\t]*type[\s\t]*=[\s\t]*(MyISAM|innodb);/i', ');', $line);
173 $line = preg_replace('/\‍)[\s\t]*engine[\s\t]*=[\s\t]*(MyISAM|innodb);/i', ');', $line);
174 $line = preg_replace('/,$/', '', $line);
175 }
176
177 // Process case: "CREATE TABLE llx_mytable(rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,code..."
178 if (preg_match('/[\s\t\‍(]*(\w*)[\s\t]+int.*auto_increment/i', $line, $reg)) {
179 $newline = preg_replace('/([\s\t\‍(]*)([a-zA-Z_0-9]*)[\s\t]+int.*auto_increment[^,]*/i', '\\1 \\2 integer PRIMARY KEY AUTOINCREMENT', $line);
180 //$line = "-- ".$line." replaced by --\n".$newline;
181 $line = $newline;
182 }
183
184 // tinyint type conversion
185 $line = str_replace('tinyint', 'smallint', $line);
186
187 // nuke unsigned
188 $line = preg_replace('/(int\w+|smallint)\s+unsigned/i', '\\1', $line);
189
190 // blob -> text
191 $line = preg_replace('/\w*blob/i', 'text', $line);
192
193 // tinytext/mediumtext -> text
194 $line = preg_replace('/tinytext/i', 'text', $line);
195 $line = preg_replace('/mediumtext/i', 'text', $line);
196
197 // change not null datetime field to null valid ones
198 // (to support remapping of "zero time" to null
199 $line = preg_replace('/datetime not null/i', 'datetime', $line);
200 $line = preg_replace('/datetime/i', 'timestamp', $line);
201
202 // double -> numeric
203 $line = preg_replace('/^double/i', 'numeric', $line);
204 $line = preg_replace('/(\s*)double/i', '\\1numeric', $line);
205 // float -> numeric
206 $line = preg_replace('/^float/i', 'numeric', $line);
207 $line = preg_replace('/(\s*)float/i', '\\1numeric', $line);
208
209 // unique index(field1,field2)
210 if (preg_match('/unique index\s*\‍((\w+\s*,\s*\w+)\‍)/i', $line)) {
211 $line = preg_replace('/unique index\s*\‍((\w+\s*,\s*\w+)\‍)/i', 'UNIQUE\‍(\\1\‍)', $line);
212 }
213
214 // We remove end of requests "AFTER fieldxxx"
215 $line = preg_replace('/AFTER [a-z0-9_]+/i', '', $line);
216
217 // We remove start of requests "ALTER TABLE tablexxx" if this is a DROP INDEX
218 $line = preg_replace('/ALTER TABLE [a-z0-9_]+ DROP INDEX/i', 'DROP INDEX', $line);
219
220 // Translate order to rename fields
221 if (preg_match('/ALTER TABLE ([a-z0-9_]+) CHANGE(?: COLUMN)? ([a-z0-9_]+) ([a-z0-9_]+)(.*)$/i', $line, $reg)) {
222 $line = "-- ".$line." replaced by --\n";
223 $line .= "ALTER TABLE ".$reg[1]." RENAME COLUMN ".$reg[2]." TO ".$reg[3];
224 }
225
226 // Translate order to modify field format
227 if (preg_match('/ALTER TABLE ([a-z0-9_]+) MODIFY(?: COLUMN)? ([a-z0-9_]+) (.*)$/i', $line, $reg)) {
228 $line = "-- ".$line." replaced by --\n";
229 $newreg3 = $reg[3];
230 $newreg3 = preg_replace('/ DEFAULT NULL/i', '', $newreg3);
231 $newreg3 = preg_replace('/ NOT NULL/i', '', $newreg3);
232 $newreg3 = preg_replace('/ NULL/i', '', $newreg3);
233 $newreg3 = preg_replace('/ DEFAULT 0/i', '', $newreg3);
234 $newreg3 = preg_replace('/ DEFAULT \'[0-9a-zA-Z_@]*\'/i', '', $newreg3);
235 $line .= "ALTER TABLE ".$reg[1]." ALTER COLUMN ".$reg[2]." TYPE ".$newreg3;
236 // TODO Add alter to set default value or null/not null if there is this in $reg[3]
237 }
238
239 // alter table add primary key (field1, field2 ...) -> We create a unique index instead as dynamic creation of primary key is not supported
240 // ALTER TABLE llx_dolibarr_modules ADD PRIMARY KEY pk_dolibarr_modules (numero, entity);
241 if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+PRIMARY\s+KEY\s*(.*)\s*\‍((.*)$/i', $line, $reg)) {
242 $line = "-- ".$line." replaced by --\n";
243 $line .= "CREATE UNIQUE INDEX ".$reg[2]." ON ".$reg[1]."(".$reg[3];
244 }
245
246 // Translate order to drop foreign keys
247 // ALTER TABLE llx_dolibarr_modules DROP FOREIGN KEY fk_xxx;
248 if (preg_match('/ALTER\s+TABLE\s*(.*)\s*DROP\s+FOREIGN\s+KEY\s*(.*)$/i', $line, $reg)) {
249 $line = "-- ".$line." replaced by --\n";
250 $line .= "ALTER TABLE ".$reg[1]." DROP CONSTRAINT ".$reg[2];
251 }
252
253 // alter table add [unique] [index] (field1, field2 ...)
254 // ALTER TABLE llx_accountingaccount ADD INDEX idx_accountingaccount_fk_pcg_version (fk_pcg_version)
255 if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+(UNIQUE INDEX|INDEX|UNIQUE)\s+(.*)\s*\‍(([\w,\s]+)\‍)/i', $line, $reg)) {
256 $fieldlist = $reg[4];
257 $idxname = $reg[3];
258 $tablename = $reg[1];
259 $line = "-- ".$line." replaced by --\n";
260 $line .= "CREATE ".(preg_match('/UNIQUE/', $reg[2]) ? 'UNIQUE ' : '')."INDEX ".$idxname." ON ".$tablename." (".$fieldlist.")";
261 }
262 if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+CONSTRAINT\s+(.*)\s*FOREIGN\s+KEY\s*\‍(([\w,\s]+)\‍)\s*REFERENCES\s+(\w+)\s*\‍(([\w,\s]+)\‍)/i', $line, $reg)) {
263 // Pour l'instant les contraintes ne sont pas créées
264 dol_syslog(get_class().'::query line emptied');
265 $line = 'SELECT 0;';
266 }
267
268 //if (preg_match('/rowid\s+.*\s+PRIMARY\s+KEY,/i', $line)) {
269 //preg_replace('/(rowid\s+.*\s+PRIMARY\s+KEY\s*,)/i', '/* \\1 */', $line);
270 //}
271 }
272
273 // Delete using criteria on other table must not declare twice the deleted table
274 // DELETE FROM tabletodelete USING tabletodelete, othertable -> DELETE FROM tabletodelete USING othertable
275 if (preg_match('/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i', $line, $reg)) {
276 if ($reg[1] == $reg[2]) { // If same table, we remove second one
277 $line = preg_replace('/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i', 'DELETE FROM \\1 USING \\3', $line);
278 }
279 }
280
281 // Remove () in the tables in FROM if one table
282 $line = preg_replace('/FROM\s*\‍((([a-z_]+)\s+as\s+([a-z_]+)\s*)\‍)/i', 'FROM \\1', $line);
283 //print $line."\n";
284
285 // Remove () in the tables in FROM if two table
286 $line = preg_replace('/FROM\s*\‍(([a-z_]+\s+as\s+[a-z_]+)\s*,\s*([a-z_]+\s+as\s+[a-z_]+\s*)\‍)/i', 'FROM \\1, \\2', $line);
287 //print $line."\n";
288
289 // Remove () in the tables in FROM if two table
290 $line = preg_replace('/FROM\s*\‍(([a-z_]+\s+as\s+[a-z_]+)\s*,\s*([a-z_]+\s+as\s+[a-z_]+\s*),\s*([a-z_]+\s+as\s+[a-z_]+\s*)\‍)/i', 'FROM \\1, \\2, \\3', $line);
291 //print $line."\n";
292
293 //print "type=".$type." newline=".$line."<br>\n";
294 }
295
296 return $line;
297 }
298
299 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
306 public function select_db($database)
307 {
308 // phpcs:enable
309 dol_syslog(get_class($this)."::select_db database=".$database, LOG_DEBUG);
310 // sqlite_select_db() does not exist
311 //return sqlite_select_db($this->db,$database);
312 return true;
313 }
314
315
327 public function connect($host, $login, $passwd, $name, $port = 0)
328 {
329 global $main_data_dir;
330
331 dol_syslog(get_class($this)."::connect name=".$name, LOG_DEBUG);
332
333 $dir = $main_data_dir;
334 if (empty($dir)) {
335 $dir = DOL_DATA_ROOT;
336 }
337 // With sqlite, port must be in connect parameters
338 //if (! $newport) $newport=3306;
339 $database_name = $dir.'/database_'.$name.'.sdb';
340 try {
341 /*** connect to SQLite database ***/
342 //$this->db = new PDO("sqlite:".$dir.'/database_'.$name.'.sdb');
343 $this->db = new SQLite3($database_name);
344 //$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
345 } catch (Exception $e) {
346 $this->error = self::LABEL.' '.$e->getMessage().' current dir='.$database_name;
347 return false;
348 }
349
350 //print "Resultat fonction connect: ".$this->db;
351 return $this->db;
352 }
353
354
360 public function getVersion()
361 {
362 $tmp = $this->db->version();
363 return $tmp['versionString'];
364 }
365
371 public function getDriverInfo()
372 {
373 return 'sqlite3 php driver';
374 }
375
376
383 public function close()
384 {
385 if ($this->db) {
386 if ($this->transaction_opened > 0) {
387 dol_syslog(get_class($this)."::close Closing a connection with an opened transaction depth=".$this->transaction_opened, LOG_ERR);
388 }
389 $this->connected = false;
390 $this->db->close();
391 unset($this->db); // Clean this->db
392 return true;
393 }
394 return false;
395 }
396
407 public function query($query, $usesavepoint = 0, $type = 'auto', $result_mode = 0)
408 {
409 global $conf, $dolibarr_main_db_readonly;
410
411 $ret = false;
412
413 $query = trim($query);
414
415 $this->error = '';
416
417 // Convert MySQL syntax to SQLite syntax
418 $reg = array();
419 if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+CONSTRAINT\s+(.*)\s*FOREIGN\s+KEY\s*\‍(([\w,\s]+)\‍)\s*REFERENCES\s+(\w+)\s*\‍(([\w,\s]+)\‍)/i', $query, $reg)) {
420 // Ajout d'une clef étrangère à la table
421 // procédure de replacement de la table pour ajouter la contrainte
422 // Example : ALTER TABLE llx_adherent ADD CONSTRAINT adherent_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe (rowid)
423 // -> CREATE TABLE ( ... ,CONSTRAINT adherent_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe (rowid))
424 $foreignFields = $reg[5];
425 $foreignTable = $reg[4];
426 $localfields = $reg[3];
427 $constraintname = trim($reg[2]);
428 $tablename = trim($reg[1]);
429
430 $descTable = $this->db->querySingle("SELECT sql FROM sqlite_master WHERE name='".$this->escape($tablename)."'");
431
432 // 1- Renommer la table avec un nom temporaire
433 $this->query("ALTER TABLE ".$tablename." RENAME TO tmp_".$tablename);
434
435 // 2- Recréer la table avec la contrainte ajoutée
436
437 // on bricole la requete pour ajouter la contrainte
438 $descTable = substr($descTable, 0, strlen($descTable) - 1);
439 $descTable .= ", CONSTRAINT ".$constraintname." FOREIGN KEY (".$localfields.") REFERENCES ".$foreignTable."(".$foreignFields.")";
440
441 // fermeture de l'instruction
442 $descTable .= ')';
443
444 // Création proprement dite de la table
445 $this->query($descTable);
446
447 // 3- Transférer les données
448 $this->query("INSERT INTO ".$tablename." SELECT * FROM tmp_".$tablename);
449
450 // 4- Supprimer la table temporaire
451 $this->query("DROP TABLE tmp_".$tablename);
452
453 // dummy statement
454 $query = "SELECT 0";
455 } else {
456 $query = $this->convertSQLFromMysql($query, $type);
457 }
458 //print "After convertSQLFromMysql:\n".$query."<br>\n";
459
460 if (!in_array($query, array('BEGIN', 'COMMIT', 'ROLLBACK'))) {
461 $SYSLOG_SQL_LIMIT = 10000; // limit log to 10kb per line to limit DOS attacks
462 dol_syslog('sql='.substr($query, 0, $SYSLOG_SQL_LIMIT), LOG_DEBUG);
463 }
464 if (empty($query)) {
465 return false; // Return false = error if empty request
466 }
467
468 if (!empty($dolibarr_main_db_readonly)) {
469 if (preg_match('/^(INSERT|UPDATE|REPLACE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) {
470 $this->lasterror = 'Application in read-only mode';
471 $this->lasterrno = 'APPREADONLY';
472 $this->lastquery = $query;
473 return false;
474 }
475 }
476
477 // Ordre SQL ne necessitant pas de connection a une base (example: CREATE DATABASE)
478 try {
479 //$ret = $this->db->exec($query);
480 $ret = $this->db->query($query); // $ret is a Sqlite3Result
481 if ($ret) {
482 $this->queryString = $query;
483 }
484 } catch (Exception $e) {
485 $this->error = $this->db->lastErrorMsg();
486 }
487
488 if (!preg_match("/^COMMIT/i", $query) && !preg_match("/^ROLLBACK/i", $query)) {
489 // Si requete utilisateur, on la sauvegarde ainsi que son resultset
490 if (!is_object($ret) || $this->error) {
491 $this->lastqueryerror = $query;
492 $this->lasterror = $this->error();
493 $this->lasterrno = $this->errno();
494
495 dol_syslog(get_class($this)."::query SQL Error query: ".$query, LOG_ERR);
496
497 $errormsg = get_class($this)."::query SQL Error message: ".$this->lasterror;
498
499 if (preg_match('/[0-9]/', $this->lasterrno)) {
500 $errormsg .= ' ('.$this->lasterrno.')';
501 }
502
503 if ($conf->global->SYSLOG_LEVEL < LOG_DEBUG) {
504 dol_syslog(get_class($this)."::query SQL Error query: ".$query, LOG_ERR); // Log of request was not yet done previously
505 }
506 dol_syslog(get_class($this)."::query SQL Error message: ".$errormsg, LOG_ERR);
507 }
508 $this->lastquery = $query;
509 $this->_results = $ret;
510 }
511
512 return $ret;
513 }
514
515 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
522 public function fetch_object($resultset)
523 {
524 // phpcs:enable
525 // Si le resultset n'est pas fourni, on prend le dernier utilise sur cette connection
526 if (!is_object($resultset)) {
527 $resultset = $this->_results;
528 }
529 //return $resultset->fetch(PDO::FETCH_OBJ);
530 $ret = $resultset->fetchArray(SQLITE3_ASSOC);
531 if ($ret) {
532 return (object) $ret;
533 }
534 return false;
535 }
536
537
538 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
545 public function fetch_array($resultset)
546 {
547 // phpcs:enable
548 // If resultset not provided, we take the last used by connection
549 if (!is_object($resultset)) {
550 $resultset = $this->_results;
551 }
552 //return $resultset->fetch(PDO::FETCH_ASSOC);
553 $ret = $resultset->fetchArray(SQLITE3_ASSOC);
554 return $ret;
555 }
556
557 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
564 public function fetch_row($resultset)
565 {
566 // phpcs:enable
567 // If resultset not provided, we take the last used by connection
568 if (!is_bool($resultset)) {
569 if (!is_object($resultset)) {
570 $resultset = $this->_results;
571 }
572 return $resultset->fetchArray(SQLITE3_NUM);
573 } else {
574 // si le curseur est un boolean on retourne la valeur 0
575 return 0;
576 }
577 }
578
579 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
587 public function num_rows($resultset)
588 {
589 // phpcs:enable
590
591 // If resultset not provided, we take the last used by connection
592 if (!is_object($resultset)) {
593 $resultset = $this->_results;
594 }
595 // Ignore Phan - queryString is added as dynamic property @phan-suppress-next-line PhanUndeclaredProperty
596 if (preg_match("/^SELECT/i", $resultset->queryString)) {
597 // Ignore Phan - queryString is added as dynamic property @phan-suppress-next-line PhanUndeclaredProperty
598 return $this->db->querySingle("SELECT count(*) FROM (".$resultset->queryString.") q");
599 }
600 return 0;
601 }
602
603 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
611 public function affected_rows($resultset)
612 {
613 // phpcs:enable
614
615 // If resultset not provided, we take the last used by connection
616 if (!is_object($resultset)) {
617 $resultset = $this->_results;
618 }
619 if (preg_match("/^SELECT/i", $this->queryString)) {
620 return $this->num_rows($resultset);
621 }
622 // mysql necessite un link de base pour cette fonction contrairement
623 // a pqsql qui prend un resultset
624 return $this->db->changes();
625 }
626
627
634 public function free($resultset = null)
635 {
636 // If resultset not provided, we take the last used by connection
637 if (!is_object($resultset)) {
638 $resultset = $this->_results;
639 }
640 // Si resultset en est un, on libere la memoire
641 if ($resultset && is_object($resultset)) {
642 $resultset->finalize();
643 }
644 }
645
652 public function escape($stringtoencode)
653 {
654 return Sqlite3::escapeString($stringtoencode);
655 }
656
663 public function escapeforlike($stringtoencode)
664 {
665 return str_replace(array('\\', '_', '%'), array('\\\\', '\_', '\%'), (string) $stringtoencode);
666 }
667
673 public function errno()
674 {
675 if (!$this->connected) {
676 // Si il y a eu echec de connection, $this->db n'est pas valide.
677 return 'DB_ERROR_FAILED_TO_CONNECT';
678 } else {
679 // Constants to convert error code to a generic Dolibarr error code
680 /*$errorcode_map = array(
681 1004 => 'DB_ERROR_CANNOT_CREATE',
682 1005 => 'DB_ERROR_CANNOT_CREATE',
683 1006 => 'DB_ERROR_CANNOT_CREATE',
684 1007 => 'DB_ERROR_ALREADY_EXISTS',
685 1008 => 'DB_ERROR_CANNOT_DROP',
686 1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
687 1044 => 'DB_ERROR_ACCESSDENIED',
688 1046 => 'DB_ERROR_NODBSELECTED',
689 1048 => 'DB_ERROR_CONSTRAINT',
690 'HY000' => 'DB_ERROR_TABLE_ALREADY_EXISTS',
691 1051 => 'DB_ERROR_NOSUCHTABLE',
692 1054 => 'DB_ERROR_NOSUCHFIELD',
693 1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
694 1061 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
695 1062 => 'DB_ERROR_RECORD_ALREADY_EXISTS',
696 1064 => 'DB_ERROR_SYNTAX',
697 1068 => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
698 1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
699 1091 => 'DB_ERROR_NOSUCHFIELD',
700 1100 => 'DB_ERROR_NOT_LOCKED',
701 1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
702 1146 => 'DB_ERROR_NOSUCHTABLE',
703 1216 => 'DB_ERROR_NO_PARENT',
704 1217 => 'DB_ERROR_CHILD_EXISTS',
705 1451 => 'DB_ERROR_CHILD_EXISTS'
706 );
707
708 if (isset($errorcode_map[$this->db->errorCode()]))
709 {
710 return $errorcode_map[$this->db->errorCode()];
711 }*/
712 $errno = $this->db->lastErrorCode();
713 if ($errno == 'HY000' || $errno == 0) {
714 if (preg_match('/table.*already exists/i', $this->error)) {
715 return 'DB_ERROR_TABLE_ALREADY_EXISTS';
716 } elseif (preg_match('/index.*already exists/i', $this->error)) {
717 return 'DB_ERROR_KEY_NAME_ALREADY_EXISTS';
718 } elseif (preg_match('/syntax error/i', $this->error)) {
719 return 'DB_ERROR_SYNTAX';
720 }
721 }
722 if ($errno == '23000') {
723 if (preg_match('/column.* not unique/i', $this->error)) {
724 return 'DB_ERROR_RECORD_ALREADY_EXISTS';
725 } elseif (preg_match('/PRIMARY KEY must be unique/i', $this->error)) {
726 return 'DB_ERROR_RECORD_ALREADY_EXISTS';
727 }
728 }
729 if ($errno > 1) {
730 // TODO Voir la liste des messages d'erreur
731 }
732
733 return ($errno ? 'DB_ERROR_'.$errno : '0');
734 }
735 }
736
742 public function error()
743 {
744 if (!$this->connected) {
745 // Si il y a eu echec de connection, $this->db n'est pas valide pour sqlite_error.
746 return 'Not connected. Check setup parameters in conf/conf.php file and your sqlite version';
747 } else {
748 return $this->error;
749 }
750 }
751
752 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
760 public function last_insert_id($tab, $fieldid = 'rowid')
761 {
762 // phpcs:enable
763 return $this->db->lastInsertRowId();
764 }
765
774 public function encrypt($fieldorvalue, $withQuotes = 1)
775 {
776 global $conf;
777
778 // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
779 $cryptType = (!empty($conf->db->dolibarr_main_db_encryption) ? $conf->db->dolibarr_main_db_encryption : 0);
780
781 //Encryption key
782 $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : '');
783
784 $escapedstringwithquotes = ($withQuotes ? "'" : "").$this->escape($fieldorvalue).($withQuotes ? "'" : "");
785
786 if ($cryptType && !empty($cryptKey)) {
787 if ($cryptType == 2) {
788 $escapedstringwithquotes = "AES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')";
789 } elseif ($cryptType == 1) {
790 $escapedstringwithquotes = "DES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')";
791 }
792 }
793
794 return $escapedstringwithquotes;
795 }
796
803 public function decrypt($value)
804 {
805 global $conf;
806
807 // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
808 $cryptType = ($conf->db->dolibarr_main_db_encryption ? $conf->db->dolibarr_main_db_encryption : 0);
809
810 //Encryption key
811 $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : '');
812
813 $return = $value;
814
815 if ($cryptType && !empty($cryptKey)) {
816 if ($cryptType == 2) {
817 $return = 'AES_DECRYPT('.$value.',\''.$cryptKey.'\')';
818 } elseif ($cryptType == 1) {
819 $return = 'DES_DECRYPT('.$value.',\''.$cryptKey.'\')';
820 }
821 }
822
823 return $return;
824 }
825
826
827 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
833 public function DDLGetConnectId()
834 {
835 // phpcs:enable
836 return '?';
837 }
838
839
840 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
852 public function DDLCreateDb($database, $charset = '', $collation = '', $owner = '')
853 {
854 // phpcs:enable
855 if (empty($charset)) {
856 $charset = $this->forcecharset;
857 }
858 if (empty($collation)) {
859 $collation = $this->forcecollate;
860 }
861
862 // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci
863 $sql = "CREATE DATABASE ".$this->escape($database);
864 $sql .= " DEFAULT CHARACTER SET ".$this->escape($charset)." DEFAULT COLLATE ".$this->escape($collation);
865
866 dol_syslog($sql, LOG_DEBUG);
867 $ret = $this->query($sql);
868
869 return $ret;
870 }
871
872 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
880 public function DDLListTables($database, $table = '')
881 {
882 // phpcs:enable
883 $listtables = array();
884
885 $like = '';
886 if ($table) {
887 $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i', '', $table);
888
889 $like = "LIKE '".$this->escape($tmptable)."'";
890 }
891 $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i', '', $database);
892
893 $sql = "SHOW TABLES FROM ".$tmpdatabase." ".$like.";";
894 //print $sql;
895 $result = $this->query($sql);
896 if ($result) {
897 while ($row = $this->fetch_row($result)) {
898 $listtables[] = $row[0];
899 }
900 }
901 return $listtables;
902 }
903
904 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
912 public function DDLListTablesFull($database, $table = '')
913 {
914 // phpcs:enable
915 $listtables = array();
916
917 $like = '';
918 if ($table) {
919 $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i', '', $table);
920
921 $like = "LIKE '".$this->escape($tmptable)."'";
922 }
923 $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i', '', $database);
924
925 $sql = "SHOW FULL TABLES FROM ".$tmpdatabase." ".$like.";";
926 //print $sql;
927 $result = $this->query($sql);
928 if ($result) {
929 while ($row = $this->fetch_row($result)) {
930 $listtables[] = $row;
931 }
932 }
933 return $listtables;
934 }
935
936 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
945 public function DDLInfoTable($table)
946 {
947 // phpcs:enable
948 $infotables = array();
949
950 $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i', '', $table);
951
952 $sql = "SHOW FULL COLUMNS FROM ".$tmptable.";";
953
954 dol_syslog($sql, LOG_DEBUG);
955 $result = $this->query($sql);
956 if ($result) {
957 while ($row = $this->fetch_row($result)) {
958 $infotables[] = $row;
959 }
960 }
961 return $infotables;
962 }
963
964 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
977 public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null)
978 {
979 // phpcs:enable
980 // @TODO: $fulltext_keys parameter is unused
981
982 $sqlk = array();
983 $sqluq = array();
984
985 // Keys found into the array $fields: type,value,attribute,null,default,extra
986 // ex. : $fields['rowid'] = array(
987 // 'type'=>'int' or 'integer',
988 // 'value'=>'11',
989 // 'null'=>'not null',
990 // 'extra'=> 'auto_increment'
991 // );
992 $sql = "CREATE TABLE ".$this->sanitize($table)."(";
993 $i = 0;
994 $sqlfields = array();
995 foreach ($fields as $field_name => $field_desc) {
996 $sqlfields[$i] = $this->sanitize($field_name)." ";
997 $sqlfields[$i] .= $this->sanitize($field_desc['type']);
998 if (!is_null($field_desc['value']) && $field_desc['value'] !== '') {
999 $sqlfields[$i] .= "(".$this->sanitize($field_desc['value']).")";
1000 }
1001 if (!is_null($field_desc['attribute']) && $field_desc['attribute'] !== '') {
1002 $sqlfields[$i] .= " ".$this->sanitize($field_desc['attribute']);
1003 }
1004 if (!is_null($field_desc['default']) && $field_desc['default'] !== '') {
1005 if (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) {
1006 $sqlfields[$i] .= " DEFAULT ".((float) $field_desc['default']);
1007 } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP') {
1008 $sqlfields[$i] .= " DEFAULT ".$this->sanitize($field_desc['default']);
1009 } else {
1010 $sqlfields[$i] .= " DEFAULT '".$this->escape($field_desc['default'])."'";
1011 }
1012 }
1013 if (!is_null($field_desc['null']) && $field_desc['null'] !== '') {
1014 $sqlfields[$i] .= " ".$this->sanitize($field_desc['null'], 0, 0, 1);
1015 }
1016 if (!is_null($field_desc['extra']) && $field_desc['extra'] !== '') {
1017 $sqlfields[$i] .= " ".$this->sanitize($field_desc['extra'], 0, 0, 1);
1018 }
1019 $i++;
1020 }
1021 if ($primary_key != "") {
1022 $pk = "PRIMARY KEY(".$this->sanitize($primary_key).")";
1023 } else {
1024 $pk = "";
1025 }
1026
1027
1028 if (is_array($unique_keys)) {
1029 $i = 0;
1030 foreach ($unique_keys as $key => $value) {
1031 $sqluq[$i] = "UNIQUE KEY '".$this->sanitize($key)."' ('".$this->escape($value)."')";
1032 $i++;
1033 }
1034 }
1035 if (is_array($keys)) {
1036 $i = 0;
1037 foreach ($keys as $key => $value) {
1038 $sqlk[$i] = "KEY ".$this->sanitize($key)." (".$value.")";
1039 $i++;
1040 }
1041 }
1042 $sql .= implode(',', $sqlfields);
1043 if ($primary_key != "") {
1044 $sql .= ",".$pk;
1045 }
1046 if ($unique_keys != "") {
1047 $sql .= ",".implode(',', $sqluq);
1048 }
1049 if (is_array($keys)) {
1050 $sql .= ",".implode(',', $sqlk);
1051 }
1052 $sql .= ")";
1053 //$sql .= " engine=".$this->sanitize($type);
1054
1055 if (!$this->query($sql)) {
1056 return -1;
1057 } else {
1058 return 1;
1059 }
1060 }
1061
1062 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1069 public function DDLDropTable($table)
1070 {
1071 // phpcs:enable
1072 $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i', '', $table);
1073
1074 $sql = "DROP TABLE ".$tmptable;
1075
1076 if (!$this->query($sql)) {
1077 return -1;
1078 } else {
1079 return 1;
1080 }
1081 }
1082
1083 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1091 public function DDLDescTable($table, $field = "")
1092 {
1093 // phpcs:enable
1094 $sql = "DESC ".$table." ".$field;
1095
1096 dol_syslog(get_class($this)."::DDLDescTable ".$sql, LOG_DEBUG);
1097 $this->_results = $this->query($sql);
1098 return $this->_results;
1099 }
1100
1101 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1111 public function DDLAddField($table, $field_name, $field_desc, $field_position = "")
1112 {
1113 // phpcs:enable
1114 // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra
1115 // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
1116 $sql = "ALTER TABLE ".$table." ADD ".$field_name." ";
1117 $sql .= $this->sanitize($field_desc['type']);
1118 if (isset($field_desc['value']) && preg_match("/^[^\s]/i", $field_desc['value'])) {
1119 if (!in_array($field_desc['type'], array('date', 'datetime'))) {
1120 $sql .= "(".$this->sanitize($field_desc['value']).")";
1121 }
1122 }
1123 if (isset($field_desc['attribute']) && preg_match("/^[^\s]/i", $field_desc['attribute'])) {
1124 $sql .= " ".$this->sanitize($field_desc['attribute']);
1125 }
1126 if (isset($field_desc['null']) && preg_match("/^[^\s]/i", $field_desc['null'])) {
1127 if ($field_desc['null'] == 'NOT NULL') {
1128 $sql .= " ".$this->sanitize($field_desc['null'], 0, 0, 1);
1129 } else {
1130 $sql .= " ".$this->sanitize($field_desc['null']);
1131 }
1132 }
1133 if (isset($field_desc['default']) && preg_match("/^[^\s]/i", $field_desc['default'])) {
1134 if (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) {
1135 $sql .= " DEFAULT ".((float) $field_desc['default']);
1136 } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP') {
1137 $sql .= " DEFAULT ".$this->sanitize($field_desc['default']);
1138 } else {
1139 $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'";
1140 }
1141 }
1142 if (isset($field_desc['extra']) && preg_match("/^[^\s]/i", $field_desc['extra'])) {
1143 $sql .= " ".$this->sanitize($field_desc['extra'], 0, 0, 1);
1144 }
1145 $sql .= " ".$this->sanitize($field_position, 0, 0, 1);
1146
1147 dol_syslog(get_class($this)."::DDLAddField ".$sql, LOG_DEBUG);
1148 if (!$this->query($sql)) {
1149 return -1;
1150 }
1151 return 1;
1152 }
1153
1154 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1163 public function DDLUpdateField($table, $field_name, $field_desc)
1164 {
1165 // phpcs:enable
1166 $sql = "ALTER TABLE ".$this->sanitize($table);
1167 $sql .= " MODIFY COLUMN ".$this->sanitize($field_name)." ".$this->sanitize($field_desc['type']);
1168 if ($field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int' || $field_desc['type'] == 'varchar') {
1169 $sql .= "(".$this->sanitize($field_desc['value']).")";
1170 }
1171
1172 dol_syslog(get_class($this)."::DDLUpdateField ".$sql, LOG_DEBUG);
1173 if (!$this->query($sql)) {
1174 return -1;
1175 }
1176 return 1;
1177 }
1178
1179 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1187 public function DDLDropField($table, $field_name)
1188 {
1189 // phpcs:enable
1190 $tmp_field_name = preg_replace('/[^a-z0-9\.\-\_]/i', '', $field_name);
1191
1192 $sql = "ALTER TABLE ".$this->sanitize($table)." DROP COLUMN `".$this->sanitize($tmp_field_name)."`";
1193 if (!$this->query($sql)) {
1194 $this->error = $this->lasterror();
1195 return -1;
1196 }
1197 return 1;
1198 }
1199
1200
1201 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1211 public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
1212 {
1213 // phpcs:enable
1214 $sql = "INSERT INTO user ";
1215 $sql .= "(Host,User,password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_Priv,Alter_priv,Lock_tables_priv)";
1216 $sql .= " VALUES ('".$this->escape($dolibarr_main_db_host)."','".$this->escape($dolibarr_main_db_user)."',password('".addslashes($dolibarr_main_db_pass)."')";
1217 $sql .= ",'Y','Y','Y','Y','Y','Y','Y','Y','Y')";
1218
1219 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1220 $resql = $this->query($sql);
1221 if (!$resql) {
1222 return -1;
1223 }
1224
1225 $sql = "INSERT INTO db ";
1226 $sql .= "(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_Priv,Alter_priv,Lock_tables_priv)";
1227 $sql .= " VALUES ('".$this->escape($dolibarr_main_db_host)."','".$this->escape($dolibarr_main_db_name)."','".addslashes($dolibarr_main_db_user)."'";
1228 $sql .= ",'Y','Y','Y','Y','Y','Y','Y','Y','Y')";
1229
1230 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
1231 $resql = $this->query($sql);
1232 if (!$resql) {
1233 return -1;
1234 }
1235
1236 $sql = "FLUSH Privileges";
1237
1238 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
1239 $resql = $this->query($sql);
1240 if (!$resql) {
1241 return -1;
1242 }
1243 return 1;
1244 }
1245
1251 public function getDefaultCharacterSetDatabase()
1252 {
1253 return 'UTF-8';
1254 }
1255
1261 public function getListOfCharacterSet()
1262 {
1263 $liste = array();
1264 $i = 0;
1265 $liste[$i]['charset'] = 'UTF-8';
1266 $liste[$i]['description'] = 'UTF-8';
1267 return $liste;
1268 }
1269
1275 public function getDefaultCollationDatabase()
1276 {
1277 return 'UTF-8';
1278 }
1279
1285 public function getListOfCollation()
1286 {
1287 $liste = array();
1288 $i = 0;
1289 $liste[$i]['charset'] = 'UTF-8';
1290 $liste[$i]['description'] = 'UTF-8';
1291 return $liste;
1292 }
1293
1299 public function getPathOfDump()
1300 {
1301 // FIXME: not for SQLite
1302 $fullpathofdump = '/pathtomysqldump/mysqldump';
1303
1304 $resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
1305 if ($resql) {
1306 $liste = $this->fetch_array($resql);
1307 $basedir = $liste['Value'];
1308 $fullpathofdump = $basedir.(preg_match('/\/$/', $basedir) ? '' : '/').'bin/mysqldump';
1309 }
1310 return $fullpathofdump;
1311 }
1312
1318 public function getPathOfRestore()
1319 {
1320 // FIXME: not for SQLite
1321 $fullpathofimport = '/pathtomysql/mysql';
1322
1323 $resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
1324 if ($resql) {
1325 $liste = $this->fetch_array($resql);
1326 $basedir = $liste['Value'];
1327 $fullpathofimport = $basedir.(preg_match('/\/$/', $basedir) ? '' : '/').'bin/mysql';
1328 }
1329 return $fullpathofimport;
1330 }
1331
1338 public function getServerParametersValues($filter = '')
1339 {
1340 $result = array();
1341 static $pragmas;
1342 if (!isset($pragmas)) {
1343 // Définition de la liste des pragmas utilisés qui ne retournent qu'une seule valeur
1344 // indépendante de la base de données.
1345 // cf. http://www.sqlite.org/pragma.html
1346 $pragmas = array(
1347 'application_id', 'auto_vacuum', 'automatic_index', 'busy_timeout', 'cache_size',
1348 'cache_spill', 'case_sensitive_like', 'checkpoint_fullsync', 'collation_list',
1349 'compile_options', 'data_version', /*'database_list',*/
1350 'defer_foreign_keys', 'encoding', 'foreign_key_check', 'freelist_count',
1351 'full_column_names', 'fullsync', 'ingore_check_constraints', 'integrity_check',
1352 'journal_mode', 'journal_size_limit', 'legacy_file_format', 'locking_mode',
1353 'max_page_count', 'page_count', 'page_size', 'parser_trace',
1354 'query_only', 'quick_check', 'read_uncommitted', 'recursive_triggers',
1355 'reverse_unordered_selects', 'schema_version', 'user_version',
1356 'secure_delete', 'short_column_names', 'shrink_memory', 'soft_heap_limit',
1357 'synchronous', 'temp_store', /*'temp_store_directory',*/ 'threads',
1358 'vdbe_addoptrace', 'vdbe_debug', 'vdbe_listing', 'vdbe_trace',
1359 'wal_autocheckpoint',
1360 );
1361 }
1362
1363 // TODO prendre en compte le filtre
1364 foreach ($pragmas as $var) {
1365 $sql = "PRAGMA $var";
1366 $resql = $this->query($sql);
1367 if ($resql) {
1368 $obj = $this->fetch_row($resql);
1369 //dol_syslog(get_class($this)."::select_db getServerParametersValues $var=". print_r($obj, true), LOG_DEBUG);
1370 $result[$var] = $obj[0];
1371 } else {
1372 // TODO Récupérer le message
1373 $result[$var] = 'FAIL';
1374 }
1375 }
1376 return $result;
1377 }
1378
1385 public function getServerStatusValues($filter = '')
1386 {
1387 $result = array();
1388 /*
1389 $sql='SHOW STATUS';
1390 if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
1391 $resql=$this->query($sql);
1392 if ($resql)
1393 {
1394 while ($obj=$this->fetch_object($resql)) $result[$obj->Variable_name]=$obj->Value;
1395 }
1396 */
1397
1398 return $result;
1399 }
1400
1412 private function addCustomFunction($name, $arg_count = -1)
1413 {
1414 if ($this->db) {
1415 $newname = preg_replace('/_/', '', $name);
1416 $localname = __CLASS__.'::db'.$newname;
1417 $reflectClass = new ReflectionClass(__CLASS__);
1418 $reflectFunction = $reflectClass->getMethod('db'.$newname);
1419 if ($arg_count < 0) {
1420 $arg_count = $reflectFunction->getNumberOfParameters();
1421 }
1422 if (!$this->db->createFunction($name, $localname, $arg_count)) {
1423 $this->error = "unable to create custom function '$name'";
1424 }
1425 }
1426 }
1427
1428 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1429 /* Unused/commented
1430 * calc_daynr
1431 *
1432 * param int $year Year
1433 * param int $month Month
1434 * param int $day Day
1435 * return int Formatted date
1436 */
1437 /*
1438 private static function calc_daynr($year, $month, $day)
1439 {
1440 // phpcs:enable
1441 $y = $year;
1442 if ($y == 0 && $month == 0) {
1443 return 0;
1444 }
1445 $num = (365 * $y + 31 * ($month - 1) + $day);
1446 if ($month <= 2) {
1447 $y--;
1448 } else {
1449 $num -= floor(($month * 4 + 23) / 10);
1450 }
1451 $temp = floor(($y / 100 + 1) * 3 / 4);
1452 return (int) ($num + floor($y / 4) - $temp);
1453 }
1454 */
1455
1456 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1457 /* Unused/commented
1458 * calc_weekday
1459 *
1460 * param int $daynr ???
1461 * param bool $sunday_first_day_of_week ???
1462 * return int
1463 */
1464 /*
1465 private static function calc_weekday($daynr, $sunday_first_day_of_week)
1466 {
1467 // phpcs:enable
1468 $ret = (int) floor(($daynr + 5 + ($sunday_first_day_of_week ? 1 : 0)) % 7);
1469 return $ret;
1470 }
1471 */
1472
1473 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1474 /* Unused/commented
1475 * calc_days_in_year
1476 *
1477 * param int $year Year
1478 * return int Nb of days in year
1479 */
1480 /*
1481 private static function calc_days_in_year($year)
1482 {
1483 // phpcs:enable
1484 return (($year & 3) == 0 && ($year % 100 || ($year % 400 == 0 && $year)) ? 366 : 365);
1485 }
1486 */
1487
1488 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1489 /* Unused/commented
1490 * calc_week
1491 *
1492 * param int $year Year
1493 * param int $month Month
1494 * param int $day Day
1495 * param int $week_behaviour Week behaviour, bit masks: WEEK_MONDAY_FIRST, WEEK_YEAR, WEEK_FIRST_WEEKDAY
1496 * param int $calc_year ??? Year where the week started
1497 * return int ??? Week number in year
1498 */
1499 /*
1500 private static function calc_week($year, $month, $day, $week_behaviour, &$calc_year)
1501 {
1502 // phpcs:enable
1503 $daynr = self::calc_daynr($year, $month, $day);
1504 $first_daynr = self::calc_daynr($year, 1, 1);
1505 $monday_first = ($week_behaviour & self::WEEK_MONDAY_FIRST) ? 1 : 0;
1506 $week_year = ($week_behaviour & self::WEEK_YEAR) ? 1 : 0;
1507 $first_weekday = ($week_behaviour & self::WEEK_FIRST_WEEKDAY) ? 1 : 0;
1508
1509 $weekday = self::calc_weekday($first_daynr, !$monday_first);
1510 $calc_year = $year;
1511
1512 if ($month == 1 && $day <= 7 - $weekday) {
1513 if (!$week_year && (($first_weekday && $weekday != 0) || (!$first_weekday && $weekday >= 4))) {
1514 return 0;
1515 }
1516 $week_year = 1;
1517 $calc_year--;
1518 $first_daynr -= ($days = self::calc_days_in_year($calc_year));
1519 $weekday = ($weekday + 53 * 7 - $days) % 7;
1520 }
1521
1522 if (($first_weekday && $weekday != 0) || (!$first_weekday && $weekday >= 4)) {
1523 $days = $daynr - ($first_daynr + (7 - $weekday));
1524 } else {
1525 $days = $daynr - ($first_daynr - $weekday);
1526 }
1527
1528 if ($week_year && $days >= 52 * 7) {
1529 $weekday = ($weekday + self::calc_days_in_year($calc_year)) % 7;
1530 if ((!$first_weekday && $weekday < 4) || ($first_weekday && $weekday == 0)) {
1531 $calc_year++;
1532 return 1;
1533 }
1534 }
1535 return (int) floor($days / 7 + 1);
1536 }
1537 */
1538}
Class to manage Dolibarr database access.
lastqueryerror()
Return last query in error.
lasterror()
Return last error label.
lasterrno()
Return last error code.
lastquery()
Return last request executed with query()
Class to manage Dolibarr database access for a SQLite database.
fetch_object($resultset)
Returns the current line (as an object) for the resultset cursor.
escape($stringtoencode)
Escape a string to insert data.
fetch_array($resultset)
Return datas as an array.
query($query, $usesavepoint=0, $type='auto', $result_mode=0)
Execute a SQL request and return the resultset.
error()
Renvoie le texte de l'erreur mysql de l'operation precedente.
fetch_row($resultset)
Return datas as an array.
getPathOfRestore()
Return full path of restore program.
errno()
Renvoie le code erreur generique de l'operation precedente.
const LABEL
Database label.
close()
Close database connection.
escapeforlike($stringtoencode)
Escape a string to insert data into a like.
encrypt($fieldorvalue, $withQuotes=1)
Encrypt sensitive data in database Warning: This function includes the escape and add the SQL simple ...
last_insert_id($tab, $fieldid='rowid')
Get last ID after an insert INSERT.
affected_rows($resultset)
Return number of lines for result of a SELECT.
decrypt($value)
Decrypt sensitive data in database.
getDriverInfo()
Return version of database client driver.
addCustomFunction($name, $arg_count=-1)
Add a custom function in the database engine (STORED PROCEDURE) Notes:
select_db($database)
Select a database.
connect($host, $login, $passwd, $name, $port=0)
Connection to server.
num_rows($resultset)
Return number of lines for result of a SELECT.
convertSQLFromMysql($line, $type='ddl')
Convert a SQL request in Mysql syntax to native syntax.
getVersion()
Return version of database server.
getServerParametersValues($filter='')
Return value of server parameters.
free($resultset=null)
Free last resultset used.
__construct($type, $host, $user, $pass, $name='', $port=0)
Constructor.
const VERSIONMIN
Version min database.
getServerStatusValues($filter='')
Return value of server status.
$type
Database type.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:150