source: trunk/Packages/Common/Database.php

Last change on this file was 951, checked in by chronos, 18 months ago
  • Modified: Improved client contract generation.
  • Fixed: SQL query logging into file.
File size: 7.4 KB
Line 
1<?php
2
3// Extended database class
4// Date: 2020-11-10
5
6function microtime_float()
7{
8 list($usec, $sec) = explode(" ", microtime());
9 return (float)$usec + (float)$sec;
10}
11
12class DatabaseResult
13{
14 public PDOStatement $PDOStatement;
15 public int $num_rows = 0;
16
17 function fetch_assoc()
18 {
19 return $this->PDOStatement->fetch(PDO::FETCH_ASSOC);
20 }
21
22 function fetch_array()
23 {
24 return $this->PDOStatement->fetch(PDO::FETCH_BOTH);
25 }
26
27 function fetch_row()
28 {
29 return $this->PDOStatement->fetch(PDO::FETCH_NUM);
30 }
31}
32
33class Database
34{
35 public string $Prefix;
36 public array $Functions;
37 public string $Type;
38 public PDO $PDO;
39 public string $Error;
40 public string $insert_id;
41 public string $LastQuery;
42 public bool $ShowSQLError;
43 public bool $ShowSQLQuery;
44 public bool $LogSQLQuery;
45 public bool $MeasureDuration;
46 public string $LogFile;
47 public string $Database;
48
49 function __construct()
50 {
51 $this->Prefix = '';
52 $this->Functions = array('NOW(', 'CURDATE(', 'CURTIME(', 'UUID(', 'SHA1(');
53 $this->Type = 'mysql'; // mysql, pgsql
54 $this->Error = '';
55 $this->LastQuery = '';
56 $this->ShowSQLError = false;
57 $this->ShowSQLQuery = false;
58 $this->LogSQLQuery = false;
59 $this->MeasureDuration = false;
60 $this->LogFile = dirname(__FILE__).'/../../Query.log';
61 $this->Database = '';
62 }
63
64 function Connect(string $Host, string $User, string $Password, string $Database): void
65 {
66 if ($this->Type == 'mysql') $ConnectionString = 'mysql:host='.$Host.';dbname='.$Database;
67 else if ($this->Type == 'pgsql') $ConnectionString = 'pgsql:dbname='.$Database.';host='.$Host;
68 else $ConnectionString = '';
69 $this->Database = $Database;
70 try {
71 $this->PDO = new PDO($ConnectionString, $User, $Password);
72 } catch (Exception $E)
73 {
74 unset($this->PDO);
75 throw new Exception($E->getMessage());
76 }
77 }
78
79 function Disconnect(): void
80 {
81 unset($this->PDO);
82 }
83
84 function Connected(): bool
85 {
86 return isset($this->PDO);
87 }
88
89 function select_db(string $Database)
90 {
91 $this->query('USE `'.$Database.'`');
92 }
93
94 function query($Query): DatabaseResult
95 {
96 if (!$this->Connected()) throw new Exception(T('Not connected to database'));
97 $Duration = '';
98 if ($this->MeasureDuration)
99 {
100 $QueryStartTime = microtime_float();
101 }
102 $this->LastQuery = $Query;
103 $Result = new DatabaseResult();
104 $Statement = $this->PDO->query($Query);
105 if ($Statement)
106 {
107 $Result->PDOStatement = $Statement;
108 $Result->num_rows = $Statement->rowCount();
109 $this->insert_id = $this->PDO->lastInsertId();
110 } else
111 {
112 $Error = $this->PDO->errorInfo();
113 $this->Error = $Error[2];
114 if (($this->Error != '') and ($this->ShowSQLError == true))
115 echo('<div><strong>SQL Error: </strong>'.$this->Error.'<br />'.$Query.'</div>');
116 throw new Exception('SQL Error: '.$this->Error.', Query: '.$Query);
117 }
118 if ($this->MeasureDuration)
119 {
120 $Time = round(microtime_float() - $QueryStartTime, 4);
121 $Duration = ' ; '.$Time. ' s';
122 }
123 if ($this->ShowSQLQuery == true)
124 {
125 echo('<div style="border-bottom-width: 1px; border-bottom-style: solid; '.
126 'padding-bottom: 3px; padding-top: 3px; font-size: 12px; font-family: Arial;">'.$Query.$Duration.'</div>'."\n");
127 }
128 if ($this->LogSQLQuery == true)
129 {
130 file_put_contents($this->LogFile, $Query.$Duration."\n", FILE_APPEND);
131 }
132 return $Result;
133 }
134
135 function select(string $Table, string $What = '*', string $Condition = '1'): DatabaseResult
136 {
137 return $this->query('SELECT '.$What.' FROM `'.$this->Prefix.$Table.'` WHERE '.$Condition);
138 }
139
140 function delete(string $Table, string $Condition): void
141 {
142 $this->query('DELETE FROM `'.$this->Prefix.$Table.'` WHERE '.$Condition);
143 }
144
145 function insert(string $Table, array $Data): int
146 {
147 $this->query($this->GetInsert($Table, $Data));
148 $this->insert_id = $this->PDO->lastInsertId();
149 return $this->insert_id;
150 }
151
152 function IsFunction(string $Text): bool
153 {
154 $Pos = strpos($Text, '(');
155 return ($Pos !== false) && in_array(substr($Text, 0, $Pos + 1), $this->Functions);
156 }
157
158 function GetInsert(string $Table, array $Data): string
159 {
160 $Name = '';
161 $Values = '';
162 foreach ($Data as $Key => $Value)
163 {
164 $Name .= ',`'.$Key.'`';
165 if (is_null($Value)) $Value = 'NULL';
166 else if (!$this->IsFunction($Value))
167 {
168 $Value = $this->PDO->quote($Value);
169 }
170 $Values .= ','.$Value;
171 }
172 $Name = substr($Name, 1);
173 $Values = substr($Values, 1);
174 return 'INSERT INTO `'.$this->Prefix.$Table.'` ('.$Name.') VALUES('.$Values.')';
175 }
176
177 function update(string $Table, string $Condition, array $Data): void
178 {
179 $this->query($this->GetUpdate($Table, $Condition, $Data));
180 }
181
182 function GetUpdate(string $Table, string $Condition, array $Data): string
183 {
184 $Values = '';
185 foreach ($Data as $Key => $Value)
186 {
187 if (is_null($Value)) $Value = 'NULL';
188 else if (!$this->IsFunction($Value))
189 {
190 $Value = $this->PDO->quote($Value);
191 }
192 $Values .= ', `'.$Key.'`='.$Value;
193 }
194 $Values = substr($Values, 2);
195 return 'UPDATE `'.$this->Prefix.$Table.'` SET '.$Values.' WHERE ('.$Condition.')';
196 }
197
198 function replace(string $Table, array $Data): void
199 {
200 $Name = '';
201 $Values = '';
202 foreach ($Data as $Key => $Value)
203 {
204 if (is_null($Value)) $Value = 'NULL';
205 else if (!$this->IsFunction($Value))
206 {
207 $Value = $this->PDO->quote($Value);
208 }
209 $Name .= ',`'.$Key.'`';
210 $Values .= ','.$Value;
211 }
212 $Name = substr($Name, 1);
213 $Values = substr($Values, 1);
214 $this->query('REPLACE INTO `'.$this->Prefix.$Table.'` ('.$Name.') VALUES('.$Values.')');
215 }
216
217 function charset(string $Charset): void
218 {
219 $this->query('SET NAMES "'.$Charset.'"');
220 }
221
222 function real_escape_string(string $Text): string
223 {
224 return addslashes($Text);
225 }
226
227 function quote(string $Text): string
228 {
229 return $this->PDO->quote($Text);
230 }
231
232 public function __sleep(): array
233 {
234 return array('LastQuery');
235 }
236
237 public function __wakeup(): void
238 {
239 }
240
241 public function Transaction(array $Queries): void
242 {
243 $this->PDO->beginTransaction();
244 foreach ($Queries as $Query)
245 {
246 $Statement = $this->PDO->prepare($Query);
247 $Statement->execute();
248 }
249 $this->PDO->commit();
250 }
251
252 public function TableExists(string $Name): bool
253 {
254 $DbResult = $this->query('SELECT * FROM information_schema.tables WHERE table_schema = "'.$this->Database.
255 '" AND table_name = "'.$Name.'" LIMIT 1');
256 return $DbResult->num_rows != 0;
257 }
258}
259
260function TimeToMysqlDateTime($Time)
261{
262 if ($Time == NULL) return NULL;
263 else return date('Y-m-d H:i:s', $Time);
264}
265
266function TimeToMysqlDate($Time)
267{
268 if ($Time == NULL) return NULL;
269 else return date('Y-m-d', $Time);
270}
271
272function TimeToMysqlTime($Time)
273{
274 if ($Time == NULL) return NULL;
275 else return date('H:i:s', $Time);
276}
277
278function MysqlDateTimeToTime($DateTime)
279{
280 if ($DateTime == '') return NULL;
281 $Parts = explode(' ', $DateTime);
282 $DateParts = explode('-', $Parts[0]);
283 $TimeParts = explode(':', $Parts[1]);
284 $Result = mktime($TimeParts[0], $TimeParts[1], $TimeParts[2], $DateParts[1], $DateParts[2], $DateParts[0]);
285 return $Result;
286}
287
288function MysqlDateToTime($Date)
289{
290 if ($Date == '') return NULL;
291 return MysqlDateTimeToTime($Date.' 0:0:0');
292}
293
294function MysqlTimeToTime($Time)
295{
296 if ($Time == '') return NULL;
297 return MysqlDateTimeToTime('0000-00-00 '.$Time);
298}
Note: See TracBrowser for help on using the repository browser.