From 70c57c7f08808c02c7856a19b4e690d991c58197 Mon Sep 17 00:00:00 2001 From: zYne Date: Wed, 23 Aug 2006 10:11:40 +0000 Subject: [PATCH] Firebird LIMIT support updated, severe query parser bug fixed --- Doctrine/Connection/Firebird.php | 3 +- Doctrine/Query.php | 41 ++++++++++++++++++- Doctrine/RawSql.php | 2 +- tests/RawSqlTestCase.php | 69 ++++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/Doctrine/Connection/Firebird.php b/Doctrine/Connection/Firebird.php index 329c147f2..648d2a11b 100644 --- a/Doctrine/Connection/Firebird.php +++ b/Doctrine/Connection/Firebird.php @@ -4,7 +4,8 @@ */ class Doctrine_Connection_Firebird extends Doctrine_Connection { public function modifyLimitQuery($query,$limit,$offset) { - return preg_replace("/([\s(])*SELECT/i","\\1SELECT TOP($from, $count)", $query); + return preg_replace('/^([\s(])*SELECT(?!\s*FIRST\s*\d+)/i', + "SELECT FIRST $limit SKIP $offset", $query); } /** * returns the next value in the given sequence diff --git a/Doctrine/Query.php b/Doctrine/Query.php index f1cc3c45b..49cd5cdf7 100644 --- a/Doctrine/Query.php +++ b/Doctrine/Query.php @@ -380,7 +380,7 @@ class Doctrine_Query extends Doctrine_Hydrate { */ public function parseQuery($query) { $this->clear(); - $e = self::bracketExplode($query," ","(",")"); + $e = self::sqlExplode($query," ","(",")"); $parts = array(); @@ -533,6 +533,45 @@ class Doctrine_Query extends Doctrine_Hydrate { return $term; } + public static function sqlExplode($str,$d = " ",$e1 = '(',$e2 = ')') { + $str = explode("$d",$str); + $i = 0; + $term = array(); + foreach($str as $key => $val) { + if (empty($term[$i])) { + $term[$i] = trim($val); + + $s1 = substr_count($term[$i],"$e1"); + $s2 = substr_count($term[$i],"$e2"); + + if(substr($term[$i],0,1) == "(") { + if($s1 == $s2) + $i++; + } else { + if( ! (substr_count($term[$i], "'") & 1) && + ! (substr_count($term[$i], "\"") & 1) && + ! (substr_count($term[$i], "´") & 1) + ) $i++; + } + } else { + $term[$i] .= "$d".trim($val); + $c1 = substr_count($term[$i],"$e1"); + $c2 = substr_count($term[$i],"$e2"); + + if(substr($term[$i],0,1) == "(") { + if($c1 == $c2) + $i++; + } else { + if( ! (substr_count($term[$i], "'") & 1) && + ! (substr_count($term[$i], "\"") & 1) && + ! (substr_count($term[$i], "´") & 1) + ) $i++; + } + } + } + return $term; + } + /** * generateAlias * diff --git a/Doctrine/RawSql.php b/Doctrine/RawSql.php index ae70eb353..b3b6f414c 100644 --- a/Doctrine/RawSql.php +++ b/Doctrine/RawSql.php @@ -74,7 +74,7 @@ class Doctrine_RawSql extends Doctrine_Hydrate { $this->fields = $m[1]; $this->clear(); - $e = Doctrine_Query::bracketExplode($query,' '); + $e = Doctrine_Query::sqlExplode($query,' '); foreach($e as $k => $part): $low = strtolower($part); diff --git a/tests/RawSqlTestCase.php b/tests/RawSqlTestCase.php index f991e8ac0..7ae949425 100644 --- a/tests/RawSqlTestCase.php +++ b/tests/RawSqlTestCase.php @@ -150,6 +150,75 @@ class Doctrine_RawSql_TestCase extends Doctrine_UnitTestCase { $this->assertTrue(is_numeric($coll[7]->id)); } + public function testsqlExplode() { + $str = "word1 word2 word3"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "word2", "word3")); + + $str = "word1 (word2 word3)"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "(word2 word3)")); + + $str = "word1 'word2 word3'"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "'word2 word3'")); + + $str = "word1 ´word2 word3´"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "´word2 word3´")); + + $str = "word1 \"word2 word3\""; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "\"word2 word3\"")); + + $str = "word1 ((word2) word3)"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "((word2) word3)")); + + $str = "word1 ( (word2) 'word3')"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "( (word2) 'word3')")); + + $str = "word1 ( \"(word2) 'word3')"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "( \"(word2) 'word3')")); + + $str = "word1 ( ´´(word2) 'word3')"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "( ´´(word2) 'word3')")); + + $str = "word1 ( ´()()´(word2) 'word3')"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "( ´()()´(word2) 'word3')")); + + $str = "word1 'word2)() word3'"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "'word2)() word3'")); + + $str = "word1 ´word2)() word3´"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "´word2)() word3´")); + + $str = "word1 \"word2)() word3\""; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("word1", "\"word2)() word3\"")); + + $str = "something (subquery '')"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("something", "(subquery '')")); + + $str = "something (( ))"; + $a = Doctrine_Query::sqlExplode($str); + $this->assertEqual($a, array("something", "(( ))")); + } + public function testQueryParser2() { + $query = new Doctrine_RawSql(); + + $query->parseQuery("SELECT {entity.name} FROM (SELECT entity.name FROM entity WHERE entity.name = 'something') WHERE entity.id = 2 ORDER BY entity.name"); + + $this->assertEqual($query->getQuery(), + "SELECT entity.name AS entity__name, entity.id AS entity__id FROM (SELECT entity.name FROM entity WHERE entity.name = 'something') WHERE entity.id = 2 ORDER BY entity.name"); + } } ?>