diff options
Diffstat (limited to 'system/database/DB_driver.php')
-rw-r--r-- | system/database/DB_driver.php | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index 88a3b388f..d056bdb90 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -596,25 +596,51 @@ abstract class CI_DB_driver { */ public function compile_binds($sql, $binds) { - if (preg_match_all('/(>|<|=|!)\s*('.preg_quote($this->bind_marker).')/i', $sql, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE) !== count($binds)) + if (empty($binds) OR empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE) { return $sql; } elseif ( ! is_array($binds)) { $binds = array($binds); + $bind_count = 1; } else { // Make sure we're using numeric keys $binds = array_values($binds); + $bind_count = count($binds); } + // We'll need the marker length later + $ml = strlen($this->bind_marker); - for ($i = count($matches) - 1; $i >= 0; $i--) + // Make sure not to replace a chunk inside a string that happens to match the bind marker + if ($c = preg_match_all("/'[^']*'/i", $sql, $matches)) { - $sql = substr_replace($sql, $this->escape($binds[$i]), $matches[$i][2][1], 1); + $c = preg_match_all('/'.preg_quote($this->bind_marker).'/i', + str_replace($matches[0], + str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]), + $sql, $c), + $matches, PREG_OFFSET_CAPTURE); + + // Bind values' count must match the count of markers in the query + if ($bind_count !== $c) + { + return $sql; + } + } + elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker).'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count) + { + return $sql; + } + + do + { + $c--; + $sql = substr_replace($sql, $this->escape($binds[$c]), $matches[0][$c][1], $ml); } + while ($c !== 0); return $sql; } |