dolibarr 18.0.6
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 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
28require_once DOL_DOCUMENT_ROOT.'/core/db/DoliDB.class.php';
29
33class DoliDBSqlite3 extends DoliDB
34{
36 public $type = 'sqlite3';
38 const LABEL = 'Sqlite3';
40 const VERSIONMIN = '3.0.0';
41
45 private $_results;
46
47 const WEEK_MONDAY_FIRST = 1;
48 const WEEK_YEAR = 2;
49 const WEEK_FIRST_WEEKDAY = 4;
50
51
63 public function __construct($type, $host, $user, $pass, $name = '', $port = 0)
64 {
65 global $conf;
66
67 // Note that having "static" property for "$forcecharset" and "$forcecollate" will make error here in strict mode, so they are not static
68 if (!empty($conf->db->character_set)) {
69 $this->forcecharset = $conf->db->character_set;
70 }
71 if (!empty($conf->db->dolibarr_main_db_collation)) {
72 $this->forcecollate = $conf->db->dolibarr_main_db_collation;
73 }
74
75 $this->database_user = $user;
76 $this->database_host = $host;
77 $this->database_port = $port;
78
79 $this->transaction_opened = 0;
80
81 //print "Name DB: $host,$user,$pass,$name<br>";
82
83 /*if (! function_exists("sqlite_query"))
84 {
85 $this->connected = false;
86 $this->ok = false;
87 $this->error="Sqlite PHP functions for using Sqlite driver are not available in this version of PHP. Try to use another driver.";
88 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);
89 return $this->ok;
90 }*/
91
92 /*if (! $host)
93 {
94 $this->connected = false;
95 $this->ok = false;
96 $this->error=$langs->trans("ErrorWrongHostParameter");
97 dol_syslog(get_class($this)."::DoliDBSqlite3 : Erreur Connect, wrong host parameters",LOG_ERR);
98 return $this->ok;
99 }*/
100
101 // Essai connexion serveur
102 // We do not try to connect to database, only to server. Connect to database is done later in constrcutor
103 $this->db = $this->connect($host, $user, $pass, $name, $port);
104
105 if ($this->db) {
106 $this->connected = true;
107 $this->ok = true;
108 $this->database_selected = true;
109 $this->database_name = $name;
110
111 $this->addCustomFunction('IF');
112 $this->addCustomFunction('MONTH');
113 $this->addCustomFunction('CURTIME');
114 $this->addCustomFunction('CURDATE');
115 $this->addCustomFunction('WEEK', 1);
116 $this->addCustomFunction('WEEK', 2);
117 $this->addCustomFunction('WEEKDAY');
118 $this->addCustomFunction('date_format');
119 //$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
120 } else {
121 // host, login ou password incorrect
122 $this->connected = false;
123 $this->ok = false;
124 $this->database_selected = false;
125 $this->database_name = '';
126 //$this->error=sqlite_connect_error();
127 dol_syslog(get_class($this)."::DoliDBSqlite3 : Error Connect ".$this->error, LOG_ERR);
128 }
129
130 return $this->ok;
131 }
132
133
141 public static function convertSQLFromMysql($line, $type = 'ddl')
142 {
143 // Removed empty line if this is a comment line for SVN tagging
144 if (preg_match('/^--\s\$Id/i', $line)) {
145 return '';
146 }
147 // Return line if this is a comment
148 if (preg_match('/^#/i', $line) || preg_match('/^$/i', $line) || preg_match('/^--/i', $line)) {
149 return $line;
150 }
151 if ($line != "") {
152 if ($type == 'auto') {
153 if (preg_match('/ALTER TABLE/i', $line)) {
154 $type = 'dml';
155 } elseif (preg_match('/CREATE TABLE/i', $line)) {
156 $type = 'dml';
157 } elseif (preg_match('/DROP TABLE/i', $line)) {
158 $type = 'dml';
159 }
160 }
161
162 if ($type == 'dml') {
163 $line = preg_replace('/\s/', ' ', $line); // Replace tabulation with space
164
165 // we are inside create table statement so lets process datatypes
166 if (preg_match('/(ISAM|innodb)/i', $line)) { // end of create table sequence
167 $line = preg_replace('/\‍)[\s\t]*type[\s\t]*=[\s\t]*(MyISAM|innodb);/i', ');', $line);
168 $line = preg_replace('/\‍)[\s\t]*engine[\s\t]*=[\s\t]*(MyISAM|innodb);/i', ');', $line);
169 $line = preg_replace('/,$/', '', $line);
170 }
171
172 // Process case: "CREATE TABLE llx_mytable(rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,code..."
173 if (preg_match('/[\s\t\‍(]*(\w*)[\s\t]+int.*auto_increment/i', $line, $reg)) {
174 $newline = preg_replace('/([\s\t\‍(]*)([a-zA-Z_0-9]*)[\s\t]+int.*auto_increment[^,]*/i', '\\1 \\2 integer PRIMARY KEY AUTOINCREMENT', $line);
175 //$line = "-- ".$line." replaced by --\n".$newline;
176 $line = $newline;
177 }
178
179 // tinyint type conversion
180 $line = str_replace('tinyint', 'smallint', $line);
181
182 // nuke unsigned
183 $line = preg_replace('/(int\w+|smallint)\s+unsigned/i', '\\1', $line);
184
185 // blob -> text
186 $line = preg_replace('/\w*blob/i', 'text', $line);
187
188 // tinytext/mediumtext -> text
189 $line = preg_replace('/tinytext/i', 'text', $line);
190 $line = preg_replace('/mediumtext/i', 'text', $line);
191
192 // change not null datetime field to null valid ones
193 // (to support remapping of "zero time" to null
194 $line = preg_replace('/datetime not null/i', 'datetime', $line);
195 $line = preg_replace('/datetime/i', 'timestamp', $line);
196
197 // double -> numeric
198 $line = preg_replace('/^double/i', 'numeric', $line);
199 $line = preg_replace('/(\s*)double/i', '\\1numeric', $line);
200 // float -> numeric
201 $line = preg_replace('/^float/i', 'numeric', $line);
202 $line = preg_replace('/(\s*)float/i', '\\1numeric', $line);
203
204 // unique index(field1,field2)
205 if (preg_match('/unique index\s*\‍((\w+\s*,\s*\w+)\‍)/i', $line)) {
206 $line = preg_replace('/unique index\s*\‍((\w+\s*,\s*\w+)\‍)/i', 'UNIQUE\‍(\\1\‍)', $line);
207 }
208
209 // We remove end of requests "AFTER fieldxxx"
210 $line = preg_replace('/AFTER [a-z0-9_]+/i', '', $line);
211
212 // We remove start of requests "ALTER TABLE tablexxx" if this is a DROP INDEX
213 $line = preg_replace('/ALTER TABLE [a-z0-9_]+ DROP INDEX/i', 'DROP INDEX', $line);
214
215 // Translate order to rename fields
216 if (preg_match('/ALTER TABLE ([a-z0-9_]+) CHANGE(?: COLUMN)? ([a-z0-9_]+) ([a-z0-9_]+)(.*)$/i', $line, $reg)) {
217 $line = "-- ".$line." replaced by --\n";
218 $line .= "ALTER TABLE ".$reg[1]." RENAME COLUMN ".$reg[2]." TO ".$reg[3];
219 }
220
221 // Translate order to modify field format
222 if (preg_match('/ALTER TABLE ([a-z0-9_]+) MODIFY(?: COLUMN)? ([a-z0-9_]+) (.*)$/i', $line, $reg)) {
223 $line = "-- ".$line." replaced by --\n";
224 $newreg3 = $reg[3];
225 $newreg3 = preg_replace('/ DEFAULT NULL/i', '', $newreg3);
226 $newreg3 = preg_replace('/ NOT NULL/i', '', $newreg3);
227 $newreg3 = preg_replace('/ NULL/i', '', $newreg3);
228 $newreg3 = preg_replace('/ DEFAULT 0/i', '', $newreg3);
229 $newreg3 = preg_replace('/ DEFAULT \'[0-9a-zA-Z_@]*\'/i', '', $newreg3);
230 $line .= "ALTER TABLE ".$reg[1]." ALTER COLUMN ".$reg[2]." TYPE ".$newreg3;
231 // TODO Add alter to set default value or null/not null if there is this in $reg[3]
232 }
233
234 // alter table add primary key (field1, field2 ...) -> We create a unique index instead as dynamic creation of primary key is not supported
235 // ALTER TABLE llx_dolibarr_modules ADD PRIMARY KEY pk_dolibarr_modules (numero, entity);
236 if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+PRIMARY\s+KEY\s*(.*)\s*\‍((.*)$/i', $line, $reg)) {
237 $line = "-- ".$line." replaced by --\n";
238 $line .= "CREATE UNIQUE INDEX ".$reg[2]." ON ".$reg[1]."(".$reg[3];
239 }
240
241 // Translate order to drop foreign keys
242 // ALTER TABLE llx_dolibarr_modules DROP FOREIGN KEY fk_xxx;
243 if (preg_match('/ALTER\s+TABLE\s*(.*)\s*DROP\s+FOREIGN\s+KEY\s*(.*)$/i', $line, $reg)) {
244 $line = "-- ".$line." replaced by --\n";
245 $line .= "ALTER TABLE ".$reg[1]." DROP CONSTRAINT ".$reg[2];
246 }
247
248 // alter table add [unique] [index] (field1, field2 ...)
249 // ALTER TABLE llx_accountingaccount ADD INDEX idx_accountingaccount_fk_pcg_version (fk_pcg_version)
250 if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+(UNIQUE INDEX|INDEX|UNIQUE)\s+(.*)\s*\‍(([\w,\s]+)\‍)/i', $line, $reg)) {
251 $fieldlist = $reg[4];
252 $idxname = $reg[3];
253 $tablename = $reg[1];
254 $line = "-- ".$line." replaced by --\n";
255 $line .= "CREATE ".(preg_match('/UNIQUE/', $reg[2]) ? 'UNIQUE ' : '')."INDEX ".$idxname." ON ".$tablename." (".$fieldlist.")";
256 }
257 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)) {
258 // Pour l'instant les contraintes ne sont pas créées
259 dol_syslog(get_class().'::query line emptied');
260 $line = 'SELECT 0;';
261 }
262
263 //if (preg_match('/rowid\s+.*\s+PRIMARY\s+KEY,/i', $line)) {
264 //preg_replace('/(rowid\s+.*\s+PRIMARY\s+KEY\s*,)/i', '/* \\1 */', $line);
265 //}
266 }
267
268 // Delete using criteria on other table must not declare twice the deleted table
269 // DELETE FROM tabletodelete USING tabletodelete, othertable -> DELETE FROM tabletodelete USING othertable
270 if (preg_match('/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i', $line, $reg)) {
271 if ($reg[1] == $reg[2]) { // If same table, we remove second one
272 $line = preg_replace('/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i', 'DELETE FROM \\1 USING \\3', $line);
273 }
274 }
275
276 // Remove () in the tables in FROM if one table
277 $line = preg_replace('/FROM\s*\‍((([a-z_]+)\s+as\s+([a-z_]+)\s*)\‍)/i', 'FROM \\1', $line);
278 //print $line."\n";
279
280 // Remove () in the tables in FROM if two table
281 $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);
282 //print $line."\n";
283
284 // Remove () in the tables in FROM if two table
285 $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);
286 //print $line."\n";
287
288 //print "type=".$type." newline=".$line."<br>\n";
289 }
290
291 return $line;
292 }
293
294 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
301 public function select_db($database)
302 {
303 // phpcs:enable
304 dol_syslog(get_class($this)."::select_db database=".$database, LOG_DEBUG);
305 // sqlite_select_db() does not exist
306 //return sqlite_select_db($this->db,$database);
307 return true;
308 }
309
310
322 public function connect($host, $login, $passwd, $name, $port = 0)
323 {
324 global $main_data_dir;
325
326 dol_syslog(get_class($this)."::connect name=".$name, LOG_DEBUG);
327
328 $dir = $main_data_dir;
329 if (empty($dir)) {
330 $dir = DOL_DATA_ROOT;
331 }
332 // With sqlite, port must be in connect parameters
333 //if (! $newport) $newport=3306;
334 $database_name = $dir.'/database_'.$name.'.sdb';
335 try {
336 /*** connect to SQLite database ***/
337 //$this->db = new PDO("sqlite:".$dir.'/database_'.$name.'.sdb');
338 $this->db = new SQLite3($database_name);
339 //$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
340 } catch (Exception $e) {
341 $this->error = self::LABEL.' '.$e->getMessage().' current dir='.$database_name;
342 return '';
343 }
344
345 //print "Resultat fonction connect: ".$this->db;
346 return $this->db;
347 }
348
349
355 public function getVersion()
356 {
357 $tmp = $this->db->version();
358 return $tmp['versionString'];
359 }
360
366 public function getDriverInfo()
367 {
368 return 'sqlite3 php driver';
369 }
370
371
378 public function close()
379 {
380 if ($this->db) {
381 if ($this->transaction_opened > 0) {
382 dol_syslog(get_class($this)."::close Closing a connection with an opened transaction depth=".$this->transaction_opened, LOG_ERR);
383 }
384 $this->connected = false;
385 $this->db->close();
386 unset($this->db); // Clean this->db
387 return true;
388 }
389 return false;
390 }
391
402 public function query($query, $usesavepoint = 0, $type = 'auto', $result_mode = 0)
403 {
404 global $conf, $dolibarr_main_db_readonly;
405
406 $ret = null;
407
408 $query = trim($query);
409
410 $this->error = '';
411
412 // Convert MySQL syntax to SQLite syntax
413 $reg = array();
414 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)) {
415 // Ajout d'une clef étrangère à la table
416 // procédure de remplacement de la table pour ajouter la contrainte
417 // Exemple : ALTER TABLE llx_adherent ADD CONSTRAINT adherent_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe (rowid)
418 // -> CREATE TABLE ( ... ,CONSTRAINT adherent_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe (rowid))
419 $foreignFields = $reg[5];
420 $foreignTable = $reg[4];
421 $localfields = $reg[3];
422 $constraintname = trim($reg[2]);
423 $tablename = trim($reg[1]);
424
425 $descTable = $this->db->querySingle("SELECT sql FROM sqlite_master WHERE name='".$this->escape($tablename)."'");
426
427 // 1- Renommer la table avec un nom temporaire
428 $this->query("ALTER TABLE ".$tablename." RENAME TO tmp_".$tablename);
429
430 // 2- Recréer la table avec la contrainte ajoutée
431
432 // on bricole la requete pour ajouter la contrainte
433 $descTable = substr($descTable, 0, strlen($descTable) - 1);
434 $descTable .= ", CONSTRAINT ".$constraintname." FOREIGN KEY (".$localfields.") REFERENCES ".$foreignTable."(".$foreignFields.")";
435
436 // fermeture de l'instruction
437 $descTable .= ')';
438
439 // Création proprement dite de la table
440 $this->query($descTable);
441
442 // 3- Transférer les données
443 $this->query("INSERT INTO ".$tablename." SELECT * FROM tmp_".$tablename);
444
445 // 4- Supprimer la table temporaire
446 $this->query("DROP TABLE tmp_".$tablename);
447
448 // dummy statement
449 $query = "SELECT 0";
450 } else {
451 $query = $this->convertSQLFromMysql($query, $type);
452 }
453 //print "After convertSQLFromMysql:\n".$query."<br>\n";
454
455 if (!in_array($query, array('BEGIN', 'COMMIT', 'ROLLBACK'))) {
456 $SYSLOG_SQL_LIMIT = 10000; // limit log to 10kb per line to limit DOS attacks
457 dol_syslog('sql='.substr($query, 0, $SYSLOG_SQL_LIMIT), LOG_DEBUG);
458 }
459 if (empty($query)) {
460 return false; // Return false = error if empty request
461 }
462
463 if (!empty($dolibarr_main_db_readonly)) {
464 if (preg_match('/^(INSERT|UPDATE|REPLACE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) {
465 $this->lasterror = 'Application in read-only mode';
466 $this->lasterrno = 'APPREADONLY';
467 $this->lastquery = $query;
468 return false;
469 }
470 }
471
472 // Ordre SQL ne necessitant pas de connexion a une base (exemple: CREATE DATABASE)
473 try {
474 //$ret = $this->db->exec($query);
475 $ret = $this->db->query($query); // $ret is a Sqlite3Result
476 if ($ret) {
477 $ret->queryString = $query;
478 }
479 } catch (Exception $e) {
480 $this->error = $this->db->lastErrorMsg();
481 }
482
483 if (!preg_match("/^COMMIT/i", $query) && !preg_match("/^ROLLBACK/i", $query)) {
484 // Si requete utilisateur, on la sauvegarde ainsi que son resultset
485 if (!is_object($ret) || $this->error) {
486 $this->lastqueryerror = $query;
487 $this->lasterror = $this->error();
488 $this->lasterrno = $this->errno();
489
490 dol_syslog(get_class($this)."::query SQL Error query: ".$query, LOG_ERR);
491
492 $errormsg = get_class($this)."::query SQL Error message: ".$this->lasterror;
493
494 if (preg_match('/[0-9]/', $this->lasterrno)) {
495 $errormsg .= ' ('.$this->lasterrno.')';
496 }
497
498 if ($conf->global->SYSLOG_LEVEL < LOG_DEBUG) {
499 dol_syslog(get_class($this)."::query SQL Error query: ".$query, LOG_ERR); // Log of request was not yet done previously
500 }
501 dol_syslog(get_class($this)."::query SQL Error message: ".$errormsg, LOG_ERR);
502 }
503 $this->lastquery = $query;
504 $this->_results = $ret;
505 }
506
507 return $ret;
508 }
509
510 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
517 public function fetch_object($resultset)
518 {
519 // phpcs:enable
520 // Si le resultset n'est pas fourni, on prend le dernier utilise sur cette connexion
521 if (!is_object($resultset)) {
522 $resultset = $this->_results;
523 }
524 //return $resultset->fetch(PDO::FETCH_OBJ);
525 $ret = $resultset->fetchArray(SQLITE3_ASSOC);
526 if ($ret) {
527 return (object) $ret;
528 }
529 return false;
530 }
531
532
533 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
540 public function fetch_array($resultset)
541 {
542 // phpcs:enable
543 // If resultset not provided, we take the last used by connexion
544 if (!is_object($resultset)) {
545 $resultset = $this->_results;
546 }
547 //return $resultset->fetch(PDO::FETCH_ASSOC);
548 $ret = $resultset->fetchArray(SQLITE3_ASSOC);
549 return $ret;
550 }
551
552 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
559 public function fetch_row($resultset)
560 {
561 // phpcs:enable
562 // If resultset not provided, we take the last used by connexion
563 if (!is_bool($resultset)) {
564 if (!is_object($resultset)) {
565 $resultset = $this->_results;
566 }
567 return $resultset->fetchArray(SQLITE3_NUM);
568 } else {
569 // si le curseur est un booleen on retourne la valeur 0
570 return false;
571 }
572 }
573
574 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
582 public function num_rows($resultset)
583 {
584 // phpcs:enable
585 // FIXME: SQLite3Result does not have a queryString member
586
587 // If resultset not provided, we take the last used by connexion
588 if (!is_object($resultset)) {
589 $resultset = $this->_results;
590 }
591 if (preg_match("/^SELECT/i", $resultset->queryString)) {
592 return $this->db->querySingle("SELECT count(*) FROM (".$resultset->queryString.") q");
593 }
594 return 0;
595 }
596
597 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
605 public function affected_rows($resultset)
606 {
607 // phpcs:enable
608 // FIXME: SQLite3Result does not have a queryString member
609
610 // If resultset not provided, we take the last used by connexion
611 if (!is_object($resultset)) {
612 $resultset = $this->_results;
613 }
614 if (preg_match("/^SELECT/i", $resultset->queryString)) {
615 return $this->num_rows($resultset);
616 }
617 // mysql necessite un link de base pour cette fonction contrairement
618 // a pqsql qui prend un resultset
619 return $this->db->changes();
620 }
621
622
629 public function free($resultset = null)
630 {
631 // If resultset not provided, we take the last used by connexion
632 if (!is_object($resultset)) {
633 $resultset = $this->_results;
634 }
635 // Si resultset en est un, on libere la memoire
636 if ($resultset && is_object($resultset)) {
637 $resultset->finalize();
638 }
639 }
640
647 public function escape($stringtoencode)
648 {
649 return Sqlite3::escapeString($stringtoencode);
650 }
651
658 public function escapeforlike($stringtoencode)
659 {
660 return str_replace(array('\\', '_', '%'), array('\\\\', '\_', '\%'), (string) $stringtoencode);
661 }
662
668 public function errno()
669 {
670 if (!$this->connected) {
671 // Si il y a eu echec de connexion, $this->db n'est pas valide.
672 return 'DB_ERROR_FAILED_TO_CONNECT';
673 } else {
674 // Constants to convert error code to a generic Dolibarr error code
675 /*$errorcode_map = array(
676 1004 => 'DB_ERROR_CANNOT_CREATE',
677 1005 => 'DB_ERROR_CANNOT_CREATE',
678 1006 => 'DB_ERROR_CANNOT_CREATE',
679 1007 => 'DB_ERROR_ALREADY_EXISTS',
680 1008 => 'DB_ERROR_CANNOT_DROP',
681 1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
682 1044 => 'DB_ERROR_ACCESSDENIED',
683 1046 => 'DB_ERROR_NODBSELECTED',
684 1048 => 'DB_ERROR_CONSTRAINT',
685 'HY000' => 'DB_ERROR_TABLE_ALREADY_EXISTS',
686 1051 => 'DB_ERROR_NOSUCHTABLE',
687 1054 => 'DB_ERROR_NOSUCHFIELD',
688 1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
689 1061 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
690 1062 => 'DB_ERROR_RECORD_ALREADY_EXISTS',
691 1064 => 'DB_ERROR_SYNTAX',
692 1068 => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
693 1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
694 1091 => 'DB_ERROR_NOSUCHFIELD',
695 1100 => 'DB_ERROR_NOT_LOCKED',
696 1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
697 1146 => 'DB_ERROR_NOSUCHTABLE',
698 1216 => 'DB_ERROR_NO_PARENT',
699 1217 => 'DB_ERROR_CHILD_EXISTS',
700 1451 => 'DB_ERROR_CHILD_EXISTS'
701 );
702
703 if (isset($errorcode_map[$this->db->errorCode()]))
704 {
705 return $errorcode_map[$this->db->errorCode()];
706 }*/
707 $errno = $this->db->lastErrorCode();
708 if ($errno == 'HY000' || $errno == 0) {
709 if (preg_match('/table.*already exists/i', $this->error)) {
710 return 'DB_ERROR_TABLE_ALREADY_EXISTS';
711 } elseif (preg_match('/index.*already exists/i', $this->error)) {
712 return 'DB_ERROR_KEY_NAME_ALREADY_EXISTS';
713 } elseif (preg_match('/syntax error/i', $this->error)) {
714 return 'DB_ERROR_SYNTAX';
715 }
716 }
717 if ($errno == '23000') {
718 if (preg_match('/column.* not unique/i', $this->error)) {
719 return 'DB_ERROR_RECORD_ALREADY_EXISTS';
720 } elseif (preg_match('/PRIMARY KEY must be unique/i', $this->error)) {
721 return 'DB_ERROR_RECORD_ALREADY_EXISTS';
722 }
723 }
724 if ($errno > 1) {
725 // TODO Voir la liste des messages d'erreur
726 }
727
728 return ($errno ? 'DB_ERROR_'.$errno : '0');
729 }
730 }
731
737 public function error()
738 {
739 if (!$this->connected) {
740 // Si il y a eu echec de connexion, $this->db n'est pas valide pour sqlite_error.
741 return 'Not connected. Check setup parameters in conf/conf.php file and your sqlite version';
742 } else {
743 return $this->error;
744 }
745 }
746
747 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
755 public function last_insert_id($tab, $fieldid = 'rowid')
756 {
757 // phpcs:enable
758 return $this->db->lastInsertRowId();
759 }
760
769 public function encrypt($fieldorvalue, $withQuotes = 1)
770 {
771 global $conf;
772
773 // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
774 $cryptType = (!empty($conf->db->dolibarr_main_db_encryption) ? $conf->db->dolibarr_main_db_encryption : 0);
775
776 //Encryption key
777 $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : '');
778
779 $escapedstringwithquotes = ($withQuotes ? "'" : "").$this->escape($fieldorvalue).($withQuotes ? "'" : "");
780
781 if ($cryptType && !empty($cryptKey)) {
782 if ($cryptType == 2) {
783 $escapedstringwithquotes = "AES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')";
784 } elseif ($cryptType == 1) {
785 $escapedstringwithquotes = "DES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')";
786 }
787 }
788
789 return $escapedstringwithquotes;
790 }
791
798 public function decrypt($value)
799 {
800 global $conf;
801
802 // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
803 $cryptType = ($conf->db->dolibarr_main_db_encryption ? $conf->db->dolibarr_main_db_encryption : 0);
804
805 //Encryption key
806 $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : '');
807
808 $return = $value;
809
810 if ($cryptType && !empty($cryptKey)) {
811 if ($cryptType == 2) {
812 $return = 'AES_DECRYPT('.$value.',\''.$cryptKey.'\')';
813 } elseif ($cryptType == 1) {
814 $return = 'DES_DECRYPT('.$value.',\''.$cryptKey.'\')';
815 }
816 }
817
818 return $return;
819 }
820
821
822 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
828 public function DDLGetConnectId()
829 {
830 // phpcs:enable
831 return '?';
832 }
833
834
835 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
847 public function DDLCreateDb($database, $charset = '', $collation = '', $owner = '')
848 {
849 // phpcs:enable
850 if (empty($charset)) {
851 $charset = $this->forcecharset;
852 }
853 if (empty($collation)) {
854 $collation = $this->forcecollate;
855 }
856
857 // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci
858 $sql = "CREATE DATABASE ".$this->escape($database);
859 $sql .= " DEFAULT CHARACTER SET ".$this->escape($charset)." DEFAULT COLLATE ".$this->escape($collation);
860
861 dol_syslog($sql, LOG_DEBUG);
862 $ret = $this->query($sql);
863
864 return $ret;
865 }
866
867 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
875 public function DDLListTables($database, $table = '')
876 {
877 // phpcs:enable
878 $listtables = array();
879
880 $like = '';
881 if ($table) {
882 $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i', '', $table);
883
884 $like = "LIKE '".$this->escape($tmptable)."'";
885 }
886 $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i', '', $database);
887
888 $sql = "SHOW TABLES FROM ".$tmpdatabase." ".$like.";";
889 //print $sql;
890 $result = $this->query($sql);
891 if ($result) {
892 while ($row = $this->fetch_row($result)) {
893 $listtables[] = $row[0];
894 }
895 }
896 return $listtables;
897 }
898
899 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
907 public function DDLListTablesFull($database, $table = '')
908 {
909 // phpcs:enable
910 $listtables = array();
911
912 $like = '';
913 if ($table) {
914 $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i', '', $table);
915
916 $like = "LIKE '".$this->escape($tmptable)."'";
917 }
918 $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i', '', $database);
919
920 $sql = "SHOW FULL TABLES FROM ".$tmpdatabase." ".$like.";";
921 //print $sql;
922 $result = $this->query($sql);
923 if ($result) {
924 while ($row = $this->fetch_row($result)) {
925 $listtables[] = $row;
926 }
927 }
928 return $listtables;
929 }
930
931 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
939 public function DDLInfoTable($table)
940 {
941 // phpcs:enable
942 $infotables = array();
943
944 $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i', '', $table);
945
946 $sql = "SHOW FULL COLUMNS FROM ".$tmptable.";";
947
948 dol_syslog($sql, LOG_DEBUG);
949 $result = $this->query($sql);
950 if ($result) {
951 while ($row = $this->fetch_row($result)) {
952 $infotables[] = $row;
953 }
954 }
955 return $infotables;
956 }
957
958 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
971 public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null)
972 {
973 // phpcs:enable
974 // FIXME: $fulltext_keys parameter is unused
975
976 // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra
977 // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
978 $sql = "create table ".$table."(";
979 $i = 0;
980 foreach ($fields as $field_name => $field_desc) {
981 $sqlfields[$i] = $field_name." ";
982 $sqlfields[$i] .= $field_desc['type'];
983 if (preg_match("/^[^\s]/i", $field_desc['value'])) {
984 $sqlfields[$i] .= "(".$field_desc['value'].")";
985 } elseif (preg_match("/^[^\s]/i", $field_desc['attribute'])) {
986 $sqlfields[$i] .= " ".$field_desc['attribute'];
987 } elseif (preg_match("/^[^\s]/i", $field_desc['default'])) {
988 if (preg_match("/null/i", $field_desc['default'])) {
989 $sqlfields[$i] .= " default ".$field_desc['default'];
990 } else {
991 $sqlfields[$i] .= " default '".$this->escape($field_desc['default'])."'";
992 }
993 } elseif (preg_match("/^[^\s]/i", $field_desc['null'])) {
994 $sqlfields[$i] .= " ".$field_desc['null'];
995 } elseif (preg_match("/^[^\s]/i", $field_desc['extra'])) {
996 $sqlfields[$i] .= " ".$field_desc['extra'];
997 }
998 $i++;
999 }
1000 if ($primary_key != "") {
1001 $pk = "primary key(".$primary_key.")";
1002 }
1003
1004 if (is_array($unique_keys)) {
1005 $i = 0;
1006 foreach ($unique_keys as $key => $value) {
1007 $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$this->escape($value)."')";
1008 $i++;
1009 }
1010 }
1011 if (is_array($keys)) {
1012 $i = 0;
1013 foreach ($keys as $key => $value) {
1014 $sqlk[$i] = "KEY ".$key." (".$value.")";
1015 $i++;
1016 }
1017 }
1018 $sql .= implode(',', $sqlfields);
1019 if ($primary_key != "") {
1020 $sql .= ",".$pk;
1021 }
1022 if (is_array($unique_keys)) {
1023 $sql .= ",".implode(',', $sqluq);
1024 }
1025 if (is_array($keys)) {
1026 $sql .= ",".implode(',', $sqlk);
1027 }
1028 $sql .= ") type=".$type;
1029
1030 dol_syslog($sql, LOG_DEBUG);
1031 if (!$this -> query($sql)) {
1032 return -1;
1033 }
1034 return 1;
1035 }
1036
1037 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1044 public function DDLDropTable($table)
1045 {
1046 // phpcs:enable
1047 $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i', '', $table);
1048
1049 $sql = "DROP TABLE ".$tmptable;
1050
1051 if (!$this->query($sql)) {
1052 return -1;
1053 } else {
1054 return 1;
1055 }
1056 }
1057
1058 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1066 public function DDLDescTable($table, $field = "")
1067 {
1068 // phpcs:enable
1069 $sql = "DESC ".$table." ".$field;
1070
1071 dol_syslog(get_class($this)."::DDLDescTable ".$sql, LOG_DEBUG);
1072 $this->_results = $this->query($sql);
1073 return $this->_results;
1074 }
1075
1076 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1086 public function DDLAddField($table, $field_name, $field_desc, $field_position = "")
1087 {
1088 // phpcs:enable
1089 // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra
1090 // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
1091 $sql = "ALTER TABLE ".$table." ADD ".$field_name." ";
1092 $sql .= $field_desc['type'];
1093 if (preg_match("/^[^\s]/i", $field_desc['value'])) {
1094 if (!in_array($field_desc['type'], array('date', 'datetime'))) {
1095 $sql .= "(".$field_desc['value'].")";
1096 }
1097 }
1098 if (preg_match("/^[^\s]/i", $field_desc['attribute'])) {
1099 $sql .= " ".$field_desc['attribute'];
1100 }
1101 if (preg_match("/^[^\s]/i", $field_desc['null'])) {
1102 $sql .= " ".$field_desc['null'];
1103 }
1104 if (preg_match("/^[^\s]/i", $field_desc['default'])) {
1105 if (preg_match("/null/i", $field_desc['default'])) {
1106 $sql .= " default ".$field_desc['default'];
1107 } else {
1108 $sql .= " default '".$this->escape($field_desc['default'])."'";
1109 }
1110 }
1111 if (preg_match("/^[^\s]/i", $field_desc['extra'])) {
1112 $sql .= " ".$field_desc['extra'];
1113 }
1114 $sql .= " ".$field_position;
1115
1116 dol_syslog(get_class($this)."::DDLAddField ".$sql, LOG_DEBUG);
1117 if (!$this->query($sql)) {
1118 return -1;
1119 }
1120 return 1;
1121 }
1122
1123 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1132 public function DDLUpdateField($table, $field_name, $field_desc)
1133 {
1134 // phpcs:enable
1135 $sql = "ALTER TABLE ".$table;
1136 $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type'];
1137 if ($field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int' || $field_desc['type'] == 'varchar') {
1138 $sql .= "(".$field_desc['value'].")";
1139 }
1140
1141 dol_syslog(get_class($this)."::DDLUpdateField ".$sql, LOG_DEBUG);
1142 if (!$this->query($sql)) {
1143 return -1;
1144 }
1145 return 1;
1146 }
1147
1148 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1156 public function DDLDropField($table, $field_name)
1157 {
1158 // phpcs:enable
1159 $tmp_field_name = preg_replace('/[^a-z0-9\.\-\_]/i', '', $field_name);
1160
1161 $sql = "ALTER TABLE ".$table." DROP COLUMN `".$tmp_field_name."`";
1162 if (!$this->query($sql)) {
1163 $this->error = $this->lasterror();
1164 return -1;
1165 }
1166 return 1;
1167 }
1168
1169
1170 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1180 public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
1181 {
1182 // phpcs:enable
1183 $sql = "INSERT INTO user ";
1184 $sql .= "(Host,User,password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_Priv,Alter_priv,Lock_tables_priv)";
1185 $sql .= " VALUES ('".$this->escape($dolibarr_main_db_host)."','".$this->escape($dolibarr_main_db_user)."',password('".addslashes($dolibarr_main_db_pass)."')";
1186 $sql .= ",'Y','Y','Y','Y','Y','Y','Y','Y','Y')";
1187
1188 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1189 $resql = $this->query($sql);
1190 if (!$resql) {
1191 return -1;
1192 }
1193
1194 $sql = "INSERT INTO db ";
1195 $sql .= "(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_Priv,Alter_priv,Lock_tables_priv)";
1196 $sql .= " VALUES ('".$this->escape($dolibarr_main_db_host)."','".$this->escape($dolibarr_main_db_name)."','".addslashes($dolibarr_main_db_user)."'";
1197 $sql .= ",'Y','Y','Y','Y','Y','Y','Y','Y','Y')";
1198
1199 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
1200 $resql = $this->query($sql);
1201 if (!$resql) {
1202 return -1;
1203 }
1204
1205 $sql = "FLUSH Privileges";
1206
1207 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
1208 $resql = $this->query($sql);
1209 if (!$resql) {
1210 return -1;
1211 }
1212 return 1;
1213 }
1214
1220 public function getDefaultCharacterSetDatabase()
1221 {
1222 return 'UTF-8';
1223 }
1224
1230 public function getListOfCharacterSet()
1231 {
1232 $liste = array();
1233 $i = 0;
1234 $liste[$i]['charset'] = 'UTF-8';
1235 $liste[$i]['description'] = 'UTF-8';
1236 return $liste;
1237 }
1238
1244 public function getDefaultCollationDatabase()
1245 {
1246 return 'UTF-8';
1247 }
1248
1254 public function getListOfCollation()
1255 {
1256 $liste = array();
1257 $i = 0;
1258 $liste[$i]['charset'] = 'UTF-8';
1259 $liste[$i]['description'] = 'UTF-8';
1260 return $liste;
1261 }
1262
1268 public function getPathOfDump()
1269 {
1270 // FIXME: not for SQLite
1271 $fullpathofdump = '/pathtomysqldump/mysqldump';
1272
1273 $resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
1274 if ($resql) {
1275 $liste = $this->fetch_array($resql);
1276 $basedir = $liste['Value'];
1277 $fullpathofdump = $basedir.(preg_match('/\/$/', $basedir) ? '' : '/').'bin/mysqldump';
1278 }
1279 return $fullpathofdump;
1280 }
1281
1287 public function getPathOfRestore()
1288 {
1289 // FIXME: not for SQLite
1290 $fullpathofimport = '/pathtomysql/mysql';
1291
1292 $resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
1293 if ($resql) {
1294 $liste = $this->fetch_array($resql);
1295 $basedir = $liste['Value'];
1296 $fullpathofimport = $basedir.(preg_match('/\/$/', $basedir) ? '' : '/').'bin/mysql';
1297 }
1298 return $fullpathofimport;
1299 }
1300
1307 public function getServerParametersValues($filter = '')
1308 {
1309 $result = array();
1310 static $pragmas;
1311 if (!isset($pragmas)) {
1312 // Définition de la liste des pragmas utilisés qui ne retournent qu'une seule valeur
1313 // indépendante de la base de données.
1314 // cf. http://www.sqlite.org/pragma.html
1315 $pragmas = array(
1316 'application_id', 'auto_vacuum', 'automatic_index', 'busy_timeout', 'cache_size',
1317 'cache_spill', 'case_sensitive_like', 'checkpoint_fullsync', 'collation_list',
1318 'compile_options', 'data_version', /*'database_list',*/
1319 'defer_foreign_keys', 'encoding', 'foreign_key_check', 'freelist_count',
1320 'full_column_names', 'fullsync', 'ingore_check_constraints', 'integrity_check',
1321 'journal_mode', 'journal_size_limit', 'legacy_file_format', 'locking_mode',
1322 'max_page_count', 'page_count', 'page_size', 'parser_trace',
1323 'query_only', 'quick_check', 'read_uncommitted', 'recursive_triggers',
1324 'reverse_unordered_selects', 'schema_version', 'user_version',
1325 'secure_delete', 'short_column_names', 'shrink_memory', 'soft_heap_limit',
1326 'synchronous', 'temp_store', /*'temp_store_directory',*/ 'threads',
1327 'vdbe_addoptrace', 'vdbe_debug', 'vdbe_listing', 'vdbe_trace',
1328 'wal_autocheckpoint',
1329 );
1330 }
1331
1332 // TODO prendre en compte le filtre
1333 foreach ($pragmas as $var) {
1334 $sql = "PRAGMA $var";
1335 $resql = $this->query($sql);
1336 if ($resql) {
1337 $obj = $this->fetch_row($resql);
1338 //dol_syslog(get_class($this)."::select_db getServerParametersValues $var=". print_r($obj, true), LOG_DEBUG);
1339 $result[$var] = $obj[0];
1340 } else {
1341 // TODO Récupérer le message
1342 $result[$var] = 'FAIL';
1343 }
1344 }
1345 return $result;
1346 }
1347
1354 public function getServerStatusValues($filter = '')
1355 {
1356 $result = array();
1357 /*
1358 $sql='SHOW STATUS';
1359 if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
1360 $resql=$this->query($sql);
1361 if ($resql)
1362 {
1363 while ($obj=$this->fetch_object($resql)) $result[$obj->Variable_name]=$obj->Value;
1364 }
1365 */
1366
1367 return $result;
1368 }
1369
1379 private function addCustomFunction($name, $arg_count = -1)
1380 {
1381 if ($this->db) {
1382 $newname = preg_replace('/_/', '', $name);
1383 $localname = __CLASS__.'::db'.$newname;
1384 $reflectClass = new ReflectionClass(__CLASS__);
1385 $reflectFunction = $reflectClass->getMethod('db'.$newname);
1386 if ($arg_count < 0) {
1387 $arg_count = $reflectFunction->getNumberOfParameters();
1388 }
1389 if (!$this->db->createFunction($name, $localname, $arg_count)) {
1390 $this->error = "unable to create custom function '$name'";
1391 }
1392 }
1393 }
1394
1395 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1404 private static function calc_daynr($year, $month, $day)
1405 {
1406 // phpcs:enable
1407 $y = $year;
1408 if ($y == 0 && $month == 0) {
1409 return 0;
1410 }
1411 $num = (365 * $y + 31 * ($month - 1) + $day);
1412 if ($month <= 2) {
1413 $y--;
1414 } else {
1415 $num -= floor(($month * 4 + 23) / 10);
1416 }
1417 $temp = floor(($y / 100 + 1) * 3 / 4);
1418 return $num + floor($y / 4) - $temp;
1419 }
1420
1421 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1429 private static function calc_weekday($daynr, $sunday_first_day_of_week)
1430 {
1431 // phpcs:enable
1432 $ret = floor(($daynr + 5 + ($sunday_first_day_of_week ? 1 : 0)) % 7);
1433 return $ret;
1434 }
1435
1436 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1443 private static function calc_days_in_year($year)
1444 {
1445 // phpcs:enable
1446 return (($year & 3) == 0 && ($year % 100 || ($year % 400 == 0 && $year)) ? 366 : 365);
1447 }
1448
1449 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1460 private static function calc_week($year, $month, $day, $week_behaviour, &$calc_year)
1461 {
1462 // phpcs:enable
1463 $daynr = self::calc_daynr($year, $month, $day);
1464 $first_daynr = self::calc_daynr($year, 1, 1);
1465 $monday_first = ($week_behaviour & self::WEEK_MONDAY_FIRST) ? 1 : 0;
1466 $week_year = ($week_behaviour & self::WEEK_YEAR) ? 1 : 0;
1467 $first_weekday = ($week_behaviour & self::WEEK_FIRST_WEEKDAY) ? 1 : 0;
1468
1469 $weekday = self::calc_weekday($first_daynr, !$monday_first);
1470 $calc_year = $year;
1471
1472 if ($month == 1 && $day <= 7 - $weekday) {
1473 if (!$week_year && (($first_weekday && $weekday != 0) || (!$first_weekday && $weekday >= 4))) {
1474 return 0;
1475 }
1476 $week_year = 1;
1477 $calc_year--;
1478 $first_daynr -= ($days = self::calc_days_in_year($calc_year));
1479 $weekday = ($weekday + 53 * 7 - $days) % 7;
1480 }
1481
1482 if (($first_weekday && $weekday != 0) || (!$first_weekday && $weekday >= 4)) {
1483 $days = $daynr - ($first_daynr + (7 - $weekday));
1484 } else {
1485 $days = $daynr - ($first_daynr - $weekday);
1486 }
1487
1488 if ($week_year && $days >= 52 * 7) {
1489 $weekday = ($weekday + self::calc_days_in_year($calc_year)) % 7;
1490 if ((!$first_weekday && $weekday < 4) || ($first_weekday && $weekday == 0)) {
1491 $calc_year++;
1492 return 1;
1493 }
1494 }
1495 return floor($days / 7 + 1);
1496 }
1497}
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 connexion.
static calc_days_in_year($year)
calc_days_in_year
static calc_daynr($year, $month, $day)
calc_daynr
escapeforlike($stringtoencode)
Escape a string to insert data into a like.
static calc_weekday($daynr, $sunday_first_day_of_week)
calc_weekday
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.
static calc_week($year, $month, $day, $week_behaviour, &$calc_year)
calc_week
getDriverInfo()
Return version of database client driver.
addCustomFunction($name, $arg_count=-1)
Permet le chargement d'une fonction personnalisee dans le moteur de base de donnees.
select_db($database)
Select a database.
connect($host, $login, $passwd, $name, $port=0)
Connexion to server.
num_rows($resultset)
Return number of lines for result of a SELECT.
static 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.
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall right right takeposterminal SELECT e rowid
Definition invoice.php:1632
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:120