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
 class DB_MYSQL {
148
 class DB_MYSQL {
149
   public $LinkID = false;
149
   public $LinkID = false;
150
   protected $QueryID = false;
150
   protected $QueryID = false;
151
+  protected $StatementID = false;
151
   protected $Record = [];
152
   protected $Record = [];
152
   protected $Row;
153
   protected $Row;
153
   protected $Errno = 0;
154
   protected $Errno = 0;
178
     if ($this->Errno == 1194) {
179
     if ($this->Errno == 1194) {
179
       send_irc('PRIVMSG '.ADMIN_CHAN.' :'.$this->Error);
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
     $Debug->analysis('!dev DB Error', $DBError, 3600 * 24);
182
     $Debug->analysis('!dev DB Error', $DBError, 3600 * 24);
185
     if (DEBUG_MODE || check_perms('site_debug') || isset($argv[1])) {
183
     if (DEBUG_MODE || check_perms('site_debug') || isset($argv[1])) {
186
       echo '<pre>'.display_str($DBError).'</pre>';
184
       echo '<pre>'.display_str($DBError).'</pre>';
205
     mysqli_set_charset($this->LinkID, "utf8");
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
     global $Debug;
229
     global $Debug;
210
     /*
230
     /*
211
      * If there was a previous query, we store the warnings. We cannot do
231
      * If there was a previous query, we store the warnings. We cannot do
223
     $QueryStartTime = microtime(true);
243
     $QueryStartTime = microtime(true);
224
     $this->connect();
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
     $QueryEndTime = microtime(true);
280
     $QueryEndTime = microtime(true);
252
     $this->Queries[] = array($Query, ($QueryEndTime - $QueryStartTime) * 1000, null);
281
     $this->Queries[] = array($Query, ($QueryEndTime - $QueryStartTime) * 1000, null);
253
     $this->Time += ($QueryEndTime - $QueryStartTime) * 1000;
282
     $this->Time += ($QueryEndTime - $QueryStartTime) * 1000;
254
 
283
 
255
-    if (!$this->QueryID) {
284
+    if (!$this->QueryID && !$this->StatementID) {
256
       $this->Errno = mysqli_errno($this->LinkID);
285
       $this->Errno = mysqli_errno($this->LinkID);
257
       $this->Error = mysqli_error($this->LinkID);
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
     $this->Row = 0;
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
   function query_unb($Query) {
299
   function query_unb($Query) {

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

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