Skip to content

Instantly share code, notes, and snippets.

@miau
Created May 18, 2014 08:24
Show Gist options
  • Save miau/f84374fe13b9a1ef5523 to your computer and use it in GitHub Desktop.
Save miau/f84374fe13b9a1ef5523 to your computer and use it in GitHub Desktop.
Doctrine DBAL のパラメータ置換処理(「?」を「:param1」等に書き換える処理)を高速化するパッチ。
Index: Doctrine/DBAL/Driver/OCI8/OCI8Statement.php
===================================================================
--- Doctrine/DBAL/Driver/OCI8/OCI8Statement.php
+++ Doctrine/DBAL/Driver/OCI8/OCI8Statement.php
@@ -72,26 +72,23 @@
* @return string
*/
static public function convertPositionalToNamedPlaceholders($statement)
- {
- $count = 1;
- $inLiteral = false; // a valid query never starts with quotes
- $stmtLen = strlen($statement);
- $paramMap = array();
- for ($i = 0; $i < $stmtLen; $i++) {
- if ($statement[$i] == '?' && !$inLiteral) {
- // real positional parameter detected
- $paramMap[$count] = ":param$count";
- $len = strlen($paramMap[$count]);
- $statement = substr_replace($statement, ":param$count", $i, 1);
- $i += $len-1; // jump ahead
- $stmtLen = strlen($statement); // adjust statement length
- ++$count;
- } else if ($statement[$i] == "'" || $statement[$i] == '"') {
- $inLiteral = ! $inLiteral; // switch state!
- }
- }
-
- return array($statement, $paramMap);
+ {
+ // 高速化のために正規表現を使った処理に書き換えている。
+ // 元の処理ではシングルクォートとダブルクォートを同一視していた
+ // (これはこれで問題がある)が、書き換え後の処理ではシングルクォート
+ // のみ考慮している。
+ // そのためダブルクォート内に「?」や「'」が出現する場合にうまく処理
+ // できないが、そのような識別子は通常使われないので問題ないはず。
+ $count = 0;
+ $paramMap = array();
+ $replaced = preg_replace_callback(
+ "/\\G(?>((?:'[^']*'|[^'?]+)*))\\?/",
+ function($matches) use (&$count, &$paramMap) {
+ return $matches[1] . ($paramMap[++$count] = ':param' . $count);
+ },
+ $statement
+ );
+ return array($replaced ?: $statement, $paramMap);
}
/**
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment