Exponential Basic 2.4.0.1 Exponential Basic CMS — PHP Class Reference

ezsqlite3db.php
Go to the documentation of this file.
1 <?php
3 //
4 // $Id: ezsqlite3db.php 9473 2025-08-08 20:20:00Z gb $
5 //
6 // Definition of eZSQLite3DB class
7 //
8 // Created on: <08-Aug-2025 16:09:31 gb>
9 //
10 // This source file is part of Exponential Basic, publishing software.
11 //
12 // Copyright (C) 1999-2025 7x and eZ Systems. All rights reserved.
13 //
14 // This program is free software; you can redistribute it and/or
15 // modify it under the terms of the GNU General Public License
16 // as published by the Free Software Foundation; either version 2
17 // of the License, or (at your option) any later version.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US
27 //
28
31
36 class eZSQLite3DB
37 {
38 function __construct( $databaseFileName )
39 {
40 $this->DB = $db;
41 $this->Type = 'sqlite';
42 $this->DatabaseFileName = $databaseFileName;
43
44 $ini =& eZINI::instance( 'site.ini' );
45 // $databaseFilePath =& $ini->variable( "site", "DabaseSQLiteFile" );
46
47 $this->Database = $this->connect( $this->DatabaseFileName );
48 $numAttempts = 1;
49 while ( $this->Database == false && $numAttempts < 5 )
50 {
51 sleep(5);
52 $this->Database = $this->connect( $this->DatabaseFileName );
53 $numAttempts++;
54 }
55
56 if ( $this->Database == false )
57 {
58 // No reason to continue as nothing will work.
59 print( "<H1>Couldn't connect to database</H1>Please try again later or inform the system administrator." );
60 exit;
61 }
62
63 // WAL mode has better control over concurrency.
64 // Source: https://www.sqlite.org/wal.html
65 $ret = $this->query( 'PRAGMA journal_mode = wal;' );
66 //$ret = $this->query( 'PRAGMA busy_timeout = 15000;' );
67
68 if ( !$ret )
69 {
70 // No reason to continue as nothing will work.
71 print( "<H1>SQLite Error</H1><br />" . $this->error( $this->Database ) . ": " . $this->error( $this->Database )."<br /><hr />Please inform the system administrator." );
72 exit;
73 }
74 }
75
80 private function connect( $fileName )
81 {
82 /*
83 print( $sql . PHP_EOL . PHP_EOL );
84
85 $backtrace = debug_backtrace();
86 $cleanedBackTrace = array();
87 foreach ( $backtrace as $call )
88 {
89 $item = '';
90 if ( isset( $call['class'] ) )
91 {
92 $item .= $call['class'];
93 }
94
95 if ( isset( $call['type'] ) )
96 {
97 $item .= $call['type'];
98 }
99
100 $item .= $call['function'] . " in file " . $call['file'] . " line " . $call['line'];
101
102 //$item .= var_export( $call['args'], true );
103 $cleanedBacktrace[] = $item;
104 }
105
106 print( implode( PHP_EOL, $cleanedBacktrace ) . PHP_EOL . PHP_EOL );
107 */
108 $connection = false;
109 $error = 0;
110
111 $maxAttempts = $this->connectRetryCount() + 1;
112 $waitTime = $this->connectRetryWaitTime();
113 $numAttempts = 1;
114
115 $ini = eZINI::instance( 'site.ini' );
116 $directoryPath = $ini->variable( 'site', 'DatabaseSQLitePath' );
117 $directoryPathFileName = $directoryPath . $fileName;
118
119 while ( ( $connection == false || $error !== 0 ) && $numAttempts <= $maxAttempts )
120 {
121 $fullPath = $fileName == ':memory:' ? $fileName : $directoryPathFileName;
122 // var_dump($databaseFileName);
123 if( !file_exists( $directoryPath ) )
124 mkdir( $directoryPath, 0775 );
125
126 // var_dump( $fullPath ); echo '<hr>'; // die();
127
128 if( !file_exists( $fullPath ) )
129 $fh = fopen($fullPath, 'w') or eZDebug::writeError( "Connection error: Couldn't create database file. Please try again later or inform the system administrator.", "eZSQLite3DB" );
130
131 // echo $fullPath; echo "<hr>";
132 $connection = new SQLite3( $fullPath );
133 eZDebug::writeDebug( $connection );
134
135 if ( $connection )
136 {
137 $error = $connection->lastErrorCode();
138 eZDebug::writeDebug( gettype( $error ) . '(' . ( $error ? 'true' : 'false' ) . ')' );
139 }
140 $numAttempts++;
141 }
142
143 // var_dump( $error ); echo '<hr>';
144
145 if ( $error !== 0 )
146 {
147 $this->ErrorNumber = $error;
148 $this->ErrorMessage = $connection->lastErrorMsg();
149 eZDebug::writeError( "Connection error: Couldn't connect to database. Please try again later or inform the system administrator.", "eZSQLite3DB" );
150 $this->IsConnected = false;
151 }
152 else
153 {
154 $connection->createFunction( 'md5', array( $this, 'md5UDF' ) );
155 $this->IsConnected = true;
156 }
157
158 return $connection;
159 }
160
164 function isA()
165 {
166 return "sqlite";
167 }
168
169 function error()
170 {
171 return $this->Database->lastErrorMsg();
172 }
173
178 function &query( $sql, $print=false, $debug=false )
179 {
180 if ( $debug == true )
181 {
182 echo "Executing SQL: $sql<hr>";
183
184 // include_once( "kernel/classes/ezbenchmark.php" );
185
186 $bench = new eZBenchmark();
187 $bench->start();
188
189 $result = $this->Database->exec( $sql );
190 $bench->stop();
191 if ( $bench->elapsed() > 0.01 )
192 {
193 $GLOBALS["DDD"] .= $sql . "<br>";
194 $GLOBALS["DDD"] .= $bench->printResults( true ) . "<br>";
195 }
196
197 }
198 else
199 {
200 $result = $this->Database->exec( $sql );
201 }
202
203 // eZPBLog::writeNotice( $sql );
204 $ini = eZINI::instance( 'site.ini' );
205 $debug = $ini->variable( 'site', 'DebugOutput' ) == 'enabled' ? true : false;
206 $debugDatabaseTransactions = $ini->variable( 'site', 'DebugDatabaseTransactions' ) == 'enabled' ? true : false;
207
208 if ( $result === false )
209 {
210 $errorNum = $this->Database->lastErrorCode();
211 $errorMsg = $this->Database->lastErrorMsg();
212
213 if ( $debugDatabaseTransactions )
214 {
215 echo "<hr>";
216 var_dump( $errorNum, $errorMsg );
217 echo "<hr>";
218 echo $sql;
219 echo "<hr>";
220 }
221 }
222 else
223 {
224 $errorNum = 0;
225 $errorMsg = '';
226 if ( $debug && $debugDatabaseTransactions )
227 {
228 echo "<hr> Last: <br>";
229 echo $sql;
230 echo "<hr>";
231 }
232 }
233
234 if ( $print )
235 {
236 if ( $debug )
237 {
238 print( $sql . "<hr>");
239 }
240 }
241
242 if ( $result == true )
243 {
244 return $result;
245 }
246 else
247 {
248 $this->unlock();
249 $this->Error = "<code>" . htmlentities( $sql ) . "</code><br>\n<b>" . htmlentities($this->error( $this->Database)) . "</b>\n" ;
250 if ( $debug )
251 {
252 print( "<b>MySQL Query Error</b>: " . htmlentities( $sql ) . "<br><b> Error number:</b>" . $errorNum . "<br><b> Error message:</b> ". $errorMsg ."<br>" );
253 }
254 return false;
255 }
256 }
257
268 function array_query( &$array, $sql, $min = 0, $max = -1, $column = false )
269 {
270 $array = array();
271 $results = $this->array_query_append( $array, $sql, $min, $max, $column );
272 return $array;
273 }
274
279 function query_single( &$row, $sql, $column = false )
280 {
281 $array = array();
282 $ret = $this->array_query_append( $array, $sql, 1, 1, $column );
283 if ( isset( $array[0] ) )
284 $row = $array[0];
285 else
286 $row = "";
287 return $row;
288 }
289
294 function array_query_append( &$array, $sql, $min = 0, $max = -1, $column = false )
295 {
296 $limit = -1;
297 $offset = 0;
298 $retArray = array();
299 // echo $sql . "<hr><hr>";
300 // check for array parameters
301 if ( is_array( $min ) )
302 {
303 $params = $min;
304
305 if ( isset( $params["Limit"] ) and is_numeric( $params["Limit"] ) )
306 {
307 $limit = $params["Limit"];
308 }
309
310 if ( isset( $params["Offset"] ) and is_numeric( $params["Offset"] ) )
311 {
312 $offset = $params["Offset"];
313 }
314 }
315
316 if ( $limit != -1 )
317 {
318 $sql .= " LIMIT $offset, $limit ";
319 }
320 $results = $this->Database->query( $sql );
321
322 if ( $results == false )
323 {
324 $this->Error = $this->Database->lastErrorCode();
325 // print( $this->Error );
326 // eZPBLog::writeWarning( $this->Error );
327 // return false;
328 }
329
330 $offset = count( $array );
331 if ( $results || is_array( $results ) && count( $results ) > 0 )
332 {
333 $i = 0;
334 while ( $row = $results->fetchArray( SQLITE3_ASSOC ) )
335 {
336 // eZDebug::accumulatorStart( 'sqlite3_loop', 'sqlite3_total', 'Looping result' );
337
338 // SQLite sometimes gives back column names prefixed with the table name
339 // we need to transform the row so that there are no table names
340 $transformedRow = array();
341 foreach ( $row as $identifier => $value )
342 {
343 if ( strpos( $identifier, '.' ) !== false )
344 {
345 $parts = explode( '.', $identifier );
346 $newIdentifier = array_pop( $parts );
347 }
348 else
349 {
350 $newIdentifier = $identifier;
351 }
352
353 $transformedRow[$newIdentifier] = $value;
354 }
355
356 $array[$i + $offset] = is_string( $column ) ? $transformedRow[$column] : $transformedRow;
357 $i++;
358 // eZDebug::accumulatorStop( 'sqlite3_loop' );
359 }
360 // $results->finalize();
361
362 if ( count( $array ) < $min )
363 {
364 $this->Error = "<code>" . htmlentities( $sql ) . "</code><br>\n<b>" .
365 htmlentities( "Received " . count( $array ) . " rows, minimum is " . (int) $min ) . "</b>\n" ;
366 }
367 if ( $max >= 0 )
368 {
369 if ( count( $array ) > $max )
370 {
371 $this->Error = "<code>" . htmlentities( $sql ) . "</code><br>\n<b>" .
372 htmlentities( "Received " . count( $array ) . " rows, maximum is $max" ) . "</b>\n" ;
373 }
374 }
375 }
376
377 // var_dump($array); echo "<HR>";echo "<HR>";
378 //die('this solution suffers from the same problem.');
379 return $array;
380 }
381
382
383 function dateToNative( &$date )
384 {
385 $ret = false;
386 if ( is_a( $date, "eZDate" ) )
387 {
388 $ret = $date->year() . "-" . eZDate::addZero( $date->month() ) . "-" . eZDate::addZero( $date->day() );
389 }
390 else
391 print( "Wrong date type, must be an eZDate object." );
392
393 return $ret;
394 }
395
399 function lock( $table )
400 {
401 //$this->query( "BEGIN IMMEDIATE TRANSACTION;" );
402 }
403
407 function unlock()
408 {
409 //$this->query( "UNLOCK TABLES" );
410 }
411
415 function begin()
416 {
417 $this->query( "BEGIN TRANSACTION;" );
418 }
419
423 function commit()
424 {
425 $this->query( "COMMIT;" );
426 }
427
431 function rollback()
432 {
433 $this->query( "ROLLBACK;" );
434 }
435
441 function nextID( $table, $field="ID" )
442 {
443 $results = array();
444 $query = "SELECT max($field) as ID FROM $table Order BY $field DESC LIMIT 1";
445 $result = $this->array_query( $results, $query );
446
447 $id = null;
448 if ( !is_bool( $result ) )
449 {
450 if ( !$this->Database->changes() == 0 )
451 {
452 // $array = $result->fetchArray( SQLITE3_ASSOC );
453 // $id = $array[0];
454 // $id++;
455
456 $array = $result[0];
457 $id = $array["ID"] + 1;
458 }
459 else
460 {
461 $array = $result[0];
462 $id = $array["ID"] + 1;
463 }
464 }
465 return $id;
466 }
467
471 function escapeString( $str )
472 {
473 if( is_null( $str ) )
474 return false;
475 return $this->Database->escapeString( $str );
476 }
477
482 function fieldName( $str )
483 {
484 return $str;
485 }
486
490 function close()
491 {
492 $this->Database->close();
493 }
494
495 function printConnection()
496 {
497 print "DatabaseFile: " . $this->Server . "<br>\n";
498 print "Database: " . $this->DB . "<br>\n";
499 print "Username: " . $this->User . "<br>\n";
500 print "Password: " . $this->Password . "<br>\n";
501 }
502
503 function counter()
504 {
505 return $this->Counter;
506 }
507
508 function md5( $str )
509 {
510 return " MD5( $str ) ";
511 }
512
513 function md5UDF( $str )
514 {
515 return md5( $str );
516 }
517
523 function connectRetryCount()
524 {
525 return $this->ConnectRetries;
526 }
527
533 function connectRetryWaitTime()
534 {
535 return 3;
536 }
537
538 var $Server;
539 var $DB;
540 var $User;
541 var $Password;
542 var $Database;
543 var $Error;
544 var $Counter;
545 var $DatabaseFileName;
546 var $DatabaseSQLitePath;
547 var $IsConnected;
548 var $ConnectRetries;
549
550 }
551
552 ?>
$i
$i
Definition: admin/adlist.php:91
$date
$date
Definition: bugpreview.php:66
eZBenchmark
Definition: ezbenchmark.php:47
eZDate\addZero
addZero( $value)
Definition: ezdate.php:227
eZDebug\writeError
static writeError( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:546
eZDebug\writeDebug
static writeDebug( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:589
eZSQLite3DB
Definition: ezsqlite3db.php:37
eZSQLite3DB\$DatabaseFileName
$DatabaseFileName
Definition: ezsqlite3db.php:545
eZSQLite3DB\counter
counter()
Definition: ezsqlite3db.php:503
eZSQLite3DB\connect
connect( $fileName)
Definition: ezsqlite3db.php:80
eZSQLite3DB\$Counter
$Counter
Definition: ezsqlite3db.php:544
eZSQLite3DB\nextID
nextID( $table, $field="ID")
Definition: ezsqlite3db.php:441
eZSQLite3DB\begin
begin()
Definition: ezsqlite3db.php:415
eZSQLite3DB\$Server
$Server
Definition: ezsqlite3db.php:538
eZSQLite3DB\$User
$User
Definition: ezsqlite3db.php:540
eZSQLite3DB\fieldName
fieldName( $str)
Definition: ezsqlite3db.php:482
eZSQLite3DB\unlock
unlock()
Definition: ezsqlite3db.php:407
eZSQLite3DB\array_query_append
array_query_append(&$array, $sql, $min=0, $max=-1, $column=false)
Definition: ezsqlite3db.php:294
eZSQLite3DB\escapeString
escapeString( $str)
Definition: ezsqlite3db.php:471
eZSQLite3DB\error
error()
Definition: ezsqlite3db.php:169
eZSQLite3DB\commit
commit()
Definition: ezsqlite3db.php:423
eZSQLite3DB\$ConnectRetries
$ConnectRetries
Definition: ezsqlite3db.php:548
eZSQLite3DB\md5UDF
md5UDF( $str)
Definition: ezsqlite3db.php:513
eZSQLite3DB\$Database
$Database
Definition: ezsqlite3db.php:542
eZSQLite3DB\isA
isA()
Definition: ezsqlite3db.php:164
eZSQLite3DB\close
close()
Definition: ezsqlite3db.php:490
eZSQLite3DB\dateToNative
dateToNative(&$date)
Definition: ezsqlite3db.php:383
eZSQLite3DB\array_query
array_query(&$array, $sql, $min=0, $max=-1, $column=false)
Definition: ezsqlite3db.php:268
eZSQLite3DB\rollback
rollback()
Definition: ezsqlite3db.php:431
eZSQLite3DB\$DB
$DB
Definition: ezsqlite3db.php:539
eZSQLite3DB\md5
md5( $str)
Definition: ezsqlite3db.php:508
eZSQLite3DB\$DatabaseSQLitePath
$DatabaseSQLitePath
Definition: ezsqlite3db.php:546
eZSQLite3DB\$Password
$Password
Definition: ezsqlite3db.php:541
eZSQLite3DB\__construct
__construct( $databaseFileName)
Definition: ezsqlite3db.php:38
eZSQLite3DB\$Error
$Error
Definition: ezsqlite3db.php:543
eZSQLite3DB\connectRetryCount
connectRetryCount()
Definition: ezsqlite3db.php:523
eZSQLite3DB\query
& query( $sql, $print=false, $debug=false)
Definition: ezsqlite3db.php:178
eZSQLite3DB\connectRetryWaitTime
connectRetryWaitTime()
Definition: ezsqlite3db.php:533
eZSQLite3DB\printConnection
printConnection()
Definition: ezsqlite3db.php:495
eZSQLite3DB\$IsConnected
$IsConnected
Definition: ezsqlite3db.php:547
eZSQLite3DB\query_single
query_single(&$row, $sql, $column=false)
Definition: ezsqlite3db.php:279
eZSQLite3DB\lock
lock( $table)
Definition: ezsqlite3db.php:399
$ini
$ini
Definition: classes/admin/linklist.php:64
$result
$result
Definition: companysearch.php:94
$results
$results
Definition: companysearch.php:81
$id
$id
Definition: companytypelist.php:193
file_exists
static file_exists( $inifilename)
Definition: eZPBINIFile.php:195
$query
if(isset( $Year) &&!is_numeric( $Year)||isset( $Month) &&!is_numeric( $Month)) $query
Definition: entryexitpages.php:65
$error
$error
Definition: ezarticle/admin/categoryedit.php:51
$str
$str
Definition: ezarticle/modules/content.php:30
$db
$db
Definition: ezarticle/user/authorlist.php:53
$row
$row
Definition: ezcalendar/user/dayview.php:403
$fh
$fh
Definition: ezfilemanager/user/filedownload.php:254
$fileName
if(eZObjectPermission::hasPermission( $file->id(), "filemanager_file", "r", $user)==false) $fileName
Definition: ezfilemanager/user/filedownload.php:43
$limit
$limit
Definition: ezimagecatalogue/admin/imagelist.php:312
$ret
$ret
Definition: ezsitemanager/admin/filelist.php:88
$debug
$debug
Definition: ezstats/admin/cron.php:36
$offset
$offset
Definition: ezstats/admin/cron.php:51
exit
exit
Definition: folder.php:81
$field
$field
Definition: listtable.php:41
Password
</td ></tr >< tr >< td style="color:<?= isset( $error['password1'] ) ?> Password
Definition: step1.php:146
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.