Browse Source

Add support for prepared mysql statements

spaghetti 7 years ago
parent
commit
c32c60ca8a
2 changed files with 62 additions and 43 deletions
  1. 60
    41
      classes/mysql.class.php
  2. 2
    2
      sections/store/store.php

+ 60
- 41
classes/mysql.class.php View File

@@ -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) {

+ 2
- 2
sections/store/store.php View File

@@ -15,12 +15,12 @@ if (!$LoggedUser['DisablePoints']) {
15 15
     LEFT JOIN torrents AS t ON t.ID=x.fid
16 16
     LEFT JOIN xbt_snatched AS xs ON x.uid=xs.uid AND x.fid=xs.fid
17 17
     WHERE
18
-      um.ID = $UserID
18
+      um.ID = ?
19 19
       AND um.Enabled = '1'
20 20
       AND x.active = 1
21 21
       AND x.completed = 0
22 22
       AND x.Remaining = 0
23
-    GROUP BY um.ID");
23
+    GROUP BY um.ID", $UserID);
24 24
   if ($DB->has_results()) {
25 25
     list($NumTorr, $TSize, $TTime, $TSeeds) = $DB->next_record();
26 26
     $PointsRate += (0.55*($NumTorr * (sqrt(($TSize/$NumTorr)/1073741824) * pow(1.5,($TTime/$NumTorr)/(24*365))))) / (max(1, sqrt(($TSeeds/$NumTorr)+4)/3));

Loading…
Cancel
Save