Skip to content

Commit 25e62cd

Browse files
committed
handle escaping fulltext search literal when converting from/to QOM/SQL2
1 parent 37d4953 commit 25e62cd

File tree

4 files changed

+75
-3
lines changed

4 files changed

+75
-3
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
Changelog
22
=========
33

4+
1.1.1
5+
-----
6+
7+
* **2014-06-11**: handle escaping fulltext search literal when converting from/to QOM/SQL2
8+
49
1.1.0
510
-----
611

src/PHPCR/Util/QOM/BaseQomToSqlQueryConverter.php

+2-3
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,8 @@ protected function convertFullTextSearchExpression($expr)
171171
if ($expr instanceof QOM\BindVariableValueInterface) {
172172
return $this->convertBindVariable($expr);
173173
}
174-
if ($expr instanceof QOM\LiteralInterface) {
175-
return $this->convertLiteral($expr);
176-
}
174+
175+
$expr = $this->generator->evalFullText($expr);
177176

178177
return "'$expr'";
179178
}

src/PHPCR/Util/QOM/BaseSqlGenerator.php

+20
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,26 @@ public function evalBindVariable($var)
217217
return '$' . $var;
218218
}
219219

220+
/**
221+
* Escape the illegal characters for inclusion in a fulltext statement. Escape Character is \\.
222+
*
223+
* @param string $string
224+
*
225+
* @return string Escaped String
226+
*
227+
* @see http://jackrabbit.apache.org/api/1.4/org/apache/jackrabbit/util/Text.html #escapeIllegalJcrChars
228+
*/
229+
public function evalFullText($string)
230+
{
231+
$illegalCharacters = array(
232+
'!' => '\\!', '(' => '\\(', ':' => '\\:', '^' => '\\^',
233+
'[' => '\\[', ']' => '\\]', '{' => '\\{', '}' => '\\}',
234+
'\"' => '\\\"', '?' => '\\?', "'" => "''",
235+
);
236+
237+
return strtr($string, $illegalCharacters);
238+
}
239+
220240
/**
221241
* Literal ::= CastLiteral | UncastLiteral
222242
*

src/PHPCR/Util/QOM/Sql2ToQomQueryConverter.php

+48
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,7 @@ protected function parseLiteral()
811811
}
812812
$token = substr($token, 1, -1);
813813
$token = str_replace('\\'.$quoteString, $quoteString, $token);
814+
$token = str_replace("''", "'", $token);
814815
if (preg_match('/^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d+)?$/', $token)) {
815816
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $token)) {
816817
$token.= ' 00:00:00';
@@ -828,6 +829,53 @@ protected function parseLiteral()
828829
return $this->factory->literal($token);
829830
}
830831

832+
/**
833+
* 6.7.34 Fulltext Literal
834+
* Parse an SQL2 literal value
835+
*
836+
* @return LiteralInterface
837+
*/
838+
protected function parseFulltextLiteral()
839+
{
840+
$token = $this->scanner->fetchNextToken();
841+
if ($this->scanner->tokenIs($token, 'CAST')) {
842+
return $this->parseCastLiteral($token);
843+
}
844+
845+
$quoteString = false;
846+
if (substr($token, 0, 1) === '\'') {
847+
$quoteString = "'";
848+
} elseif (substr($token, 0, 1) === '"') {
849+
$quoteString = '"';
850+
}
851+
852+
if ($quoteString) {
853+
while (substr($token, -1) !== $quoteString) {
854+
$nextToken = $this->scanner->fetchNextToken();
855+
if ('' === $nextToken) {
856+
break;
857+
}
858+
$token .= $this->scanner->getPreviousDelimiter();
859+
$token .= $nextToken;
860+
}
861+
862+
if (substr($token, -1) !== $quoteString) {
863+
throw new InvalidQueryException("Syntax error: unterminated quoted string $token in '{$this->sql2}'");
864+
}
865+
$token = substr($token, 1, -1);
866+
$token = str_replace('\\'.$quoteString, $quoteString, $token);
867+
$illegalCharacters = array(
868+
'\\!' => '!', '\\(' => '(', '\\:' => ':', '\\^' => '^',
869+
'\\[' => '[', '\\]' => ']', '\\{' => '{', '\\}' => '}',
870+
'\\\"' => '\"', '\\?' => '?', "''" => "'",
871+
);
872+
873+
$token = strtr($token, $illegalCharacters);
874+
875+
}
876+
877+
return $this->factory->literal($token);
878+
}
831879
/**
832880
* 6.7.37 Ordering
833881
*/

0 commit comments

Comments
 (0)