|
@@ -148,6 +148,7 @@ function db_array($Array, $DontEscape = [], $Quote = false) {
|
148
|
148
|
class DB_MYSQL {
|
149
|
149
|
public $LinkID = false;
|
150
|
150
|
protected $QueryID = false;
|
|
151
|
+ protected $StatementID = false;
|
151
|
152
|
protected $Record = [];
|
152
|
153
|
protected $Row;
|
153
|
154
|
protected $Errno = 0;
|
|
@@ -178,9 +179,6 @@ class DB_MYSQL {
|
178
|
179
|
if ($this->Errno == 1194) {
|
179
|
180
|
send_irc('PRIVMSG '.ADMIN_CHAN.' :'.$this->Error);
|
180
|
181
|
}
|
181
|
|
- /*if ($this->Errno == 1194) {
|
182
|
|
- preg_match("Table '(\S+)' is marked as crashed and should be repaired", $this->Error, $Matches);
|
183
|
|
- } */
|
184
|
182
|
$Debug->analysis('!dev DB Error', $DBError, 3600 * 24);
|
185
|
183
|
if (DEBUG_MODE || check_perms('site_debug') || isset($argv[1])) {
|
186
|
184
|
echo '<pre>'.display_str($DBError).'</pre>';
|
|
@@ -205,7 +203,29 @@ class DB_MYSQL {
|
205
|
203
|
mysqli_set_charset($this->LinkID, "utf8");
|
206
|
204
|
}
|
207
|
205
|
|
208
|
|
- function query($Query, $AutoHandle = 1) {
|
|
206
|
+ function query_p($Query, &...$BindVars) {
|
|
207
|
+ $QueryStartTime = microtime(true);
|
|
208
|
+ $this->connect();
|
|
209
|
+
|
|
210
|
+ $this->StatementID = mysqli_prepare($this->LinkID, $Query);
|
|
211
|
+ if (!empty($BindVars)) {
|
|
212
|
+ $Types = '';
|
|
213
|
+ $TypeMap = ['string'=>'s', 'double'=>'d', 'integer'=>'i', 'boolean'=>'i'];
|
|
214
|
+ foreach ($BindVars as $BindVar) {
|
|
215
|
+ $Types .= $TypeMap[gettype($BindVar)] ?? 'b';
|
|
216
|
+ }
|
|
217
|
+ mysqli_stmt_bind_param($this->StatementID, $Types, ...$BindVars);
|
|
218
|
+ }
|
|
219
|
+ mysqli_stmt_execute($this->StatementID);
|
|
220
|
+ $this->QueryID = mysqli_stmt_get_result($this->StatementID);
|
|
221
|
+ $QueryRunTime = (microtime(true) - $QueryStartTime) * 1000;
|
|
222
|
+ $this->Queries[] = [$Query, $QueryRunTime, null];
|
|
223
|
+ $this->Time += $QueryRunTime;
|
|
224
|
+
|
|
225
|
+ return $this->StatementID;
|
|
226
|
+ }
|
|
227
|
+
|
|
228
|
+ function query($Query, &...$BindVars) {
|
209
|
229
|
global $Debug;
|
210
|
230
|
/*
|
211
|
231
|
* If there was a previous query, we store the warnings. We cannot do
|
|
@@ -223,58 +243,57 @@ class DB_MYSQL {
|
223
|
243
|
$QueryStartTime = microtime(true);
|
224
|
244
|
$this->connect();
|
225
|
245
|
|
226
|
|
- if (DEBUG_MODE) {
|
227
|
|
- $this->QueryID = mysqli_query($this->LinkID, $Query);
|
228
|
|
-
|
229
|
|
- // in DEBUG_MODE, return the full trace on a SQL error (super useful for debugging).
|
230
|
|
- // do not attempt to retry to query
|
231
|
|
- if (!$this->QueryID) {
|
232
|
|
- echo '<pre>' . mysqli_error($this->LinkID) . '<br><br>';
|
233
|
|
- debug_print_backtrace();
|
234
|
|
- echo '</pre>';
|
235
|
|
- die();
|
|
246
|
+ // In the event of a MySQL deadlock, we sleep allowing MySQL time to unlock, then attempt again for a maximum of 5 tries
|
|
247
|
+ for ($i = 1; $i < 6; $i++) {
|
|
248
|
+ $this->StatementID = mysqli_prepare($this->LinkID, $Query);
|
|
249
|
+ if (!empty($BindVars)) {
|
|
250
|
+ $Types = '';
|
|
251
|
+ $TypeMap = ['string'=>'s', 'double'=>'d', 'integer'=>'i', 'boolean'=>'i'];
|
|
252
|
+ foreach ($BindVars as $BindVar) {
|
|
253
|
+ $Types .= $TypeMap[gettype($BindVar)] ?? 'b';
|
|
254
|
+ }
|
|
255
|
+ mysqli_stmt_bind_param($this->StatementID, $Types, ...$BindVars);
|
236
|
256
|
}
|
237
|
|
- } else {
|
238
|
|
- // In the event of a MySQL deadlock, we sleep allowing MySQL time to unlock, then attempt again for a maximum of 5 tries
|
239
|
|
- for ($i = 1; $i < 6; $i++) {
|
240
|
|
- $this->QueryID = mysqli_query($this->LinkID, $Query);
|
241
|
|
- if (!in_array(mysqli_errno($this->LinkID), array(1213, 1205))) {
|
242
|
|
- break;
|
|
257
|
+ mysqli_stmt_execute($this->StatementID);
|
|
258
|
+ $this->QueryID = mysqli_stmt_get_result($this->StatementID);
|
|
259
|
+
|
|
260
|
+ if (DEBUG_MODE) {
|
|
261
|
+ // in DEBUG_MODE, return the full trace on a SQL error (super useful
|
|
262
|
+ // for debugging). do not attempt to retry to query
|
|
263
|
+ if (!$this->QueryID) {
|
|
264
|
+ echo '<pre>' . mysqli_error($this->LinkID) . '<br><br>';
|
|
265
|
+ debug_print_backtrace();
|
|
266
|
+ echo '</pre>';
|
|
267
|
+ die();
|
243
|
268
|
}
|
244
|
|
- $Debug->analysis('Non-Fatal Deadlock:', $Query, 3600 * 24);
|
245
|
|
- trigger_error("Database deadlock, attempt $i");
|
|
269
|
+ }
|
246
|
270
|
|
247
|
|
- sleep($i * rand(2, 5)); // Wait longer as attempts increase
|
|
271
|
+ if (!in_array(mysqli_errno($this->LinkID), array(1213, 1205))) {
|
|
272
|
+ break;
|
248
|
273
|
}
|
|
274
|
+ $Debug->analysis('Non-Fatal Deadlock:', $Query, 3600 * 24);
|
|
275
|
+ trigger_error("Database deadlock, attempt $i");
|
|
276
|
+
|
|
277
|
+ sleep($i * rand(2, 5)); // Wait longer as attempts increase
|
249
|
278
|
}
|
250
|
279
|
|
251
|
280
|
$QueryEndTime = microtime(true);
|
252
|
281
|
$this->Queries[] = array($Query, ($QueryEndTime - $QueryStartTime) * 1000, null);
|
253
|
282
|
$this->Time += ($QueryEndTime - $QueryStartTime) * 1000;
|
254
|
283
|
|
255
|
|
- if (!$this->QueryID) {
|
|
284
|
+ if (!$this->QueryID && !$this->StatementID) {
|
256
|
285
|
$this->Errno = mysqli_errno($this->LinkID);
|
257
|
286
|
$this->Error = mysqli_error($this->LinkID);
|
258
|
|
-
|
259
|
|
- if ($AutoHandle) {
|
260
|
|
- $this->halt("Invalid Query: $Query");
|
261
|
|
- } else {
|
262
|
|
- return $this->Errno;
|
263
|
|
- }
|
|
287
|
+ $this->halt("Invalid Query: $Query");
|
264
|
288
|
}
|
265
|
289
|
|
266
|
|
- /*
|
267
|
|
- $QueryType = substr($Query, 0, 6);
|
268
|
|
- if ($QueryType === 'DELETE' || $QueryType === 'UPDATE') {
|
269
|
|
- if ($this->affected_rows() > 50) {
|
270
|
|
- $Debug->analysis($this->affected_rows().' rows altered:', $Query, 3600 * 24);
|
271
|
|
- }
|
272
|
|
- }
|
273
|
|
- */
|
274
|
290
|
$this->Row = 0;
|
275
|
|
- if ($AutoHandle) {
|
276
|
|
- return $this->QueryID;
|
277
|
|
- }
|
|
291
|
+ return $this->QueryID;
|
|
292
|
+ }
|
|
293
|
+
|
|
294
|
+ function reexec_query() {
|
|
295
|
+ mysqli_stmt_execute($this->StatementID);
|
|
296
|
+ $this->QueryID = mysqli_stmt_get_result($this->StatementID);
|
278
|
297
|
}
|
279
|
298
|
|
280
|
299
|
function query_unb($Query) {
|