bhabegger commented on code in PR #3139:
URL: https://github.com/apache/jackrabbit-oak/pull/3139#discussion_r4193148445
##########
oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java:
##########
@@ -168,13 +169,194 @@ public void testCoalesce() throws ParseException {
.convert("//*[fn:coalesce(fn:coalesce(j:c/@a, b),
fn:coalesce(c, c:d)) = 'a']"));
}
+ @Test
+ public void testCoalesceWithStringLiteral() throws ParseException {
+ // a literal is a valid dynamic operand anywhere, not just for op()
+ Query q = p.parse("SELECT * FROM [nt:base] WHERE COALESCE([a],
'default')='default'");
+ assertEquals("select [nt:base].[jcr:primaryType] as
[nt:base.jcr:primaryType] " +
+ "from [nt:base] as [nt:base] " +
+ "where coalesce([nt:base].[a], 'default') = 'default'",
q.toString());
+ q = p.parse("SELECT * FROM [nt:base] WHERE COALESCE('default',
[a])='default'");
+ assertEquals("select [nt:base].[jcr:primaryType] as
[nt:base.jcr:primaryType] " +
+ "from [nt:base] as [nt:base] " +
+ "where coalesce('default', [nt:base].[a]) = 'default'",
q.toString());
+ }
+
+ @Test
+ public void testTypedLiteral() throws ParseException {
+ // the function token is the same as the one FunctionIndexProcessor
creates
+ Query q = p.parse("SELECT * FROM [nt:base] WHERE COALESCE([a],
'lon:0') > 1");
+ assertTrue(q.toString(),
q.toString().contains("coalesce([nt:base].[a], 'lon:0')"));
+ }
+
+ @Test(expected = ParseException.class)
+ public void testNumberLiteralNotSupported() throws ParseException {
+ p.parse("SELECT * FROM [nt:base] WHERE COALESCE([a], 0) > 1");
+ }
+
+ @Test(expected = ParseException.class)
+ public void testSignedNumberLiteralNotSupported() throws ParseException {
+ p.parse("SELECT * FROM [nt:base] WHERE COALESCE([a], +0) > 1");
+ }
+
+ @Test(expected = ParseException.class)
+ public void testInvalidTypedLiteral() throws ParseException {
+ p.parse("SELECT * FROM [nt:base] WHERE COALESCE([a], 'lon:abc') > 1");
+ }
+
+ @Test
+ public void testCoalesceWithEscapedQuoteLiteral() throws ParseException {
+ // a single quote within a literal is escaped as two single quotes;
+ // the resulting function-restriction token must round-trip with the
+ // same escaping FunctionIndexProcessor uses, since index-restriction
+ // matching relies on exact string equality between the two
+ Query query = p.parse("SELECT * FROM [nt:base] WHERE COALESCE([a],
'it''s a test')='x'");
+ assertTrue("expected the literal's escaping to be preserved, got: " +
query,
+ query.toString().contains("'it''s a test'"));
+ }
+
@Test
public void testFirst() throws ParseException {
p.parse("SELECT * FROM [nt:base] WHERE FIRST([d:t])='a'");
p.parse("SELECT * FROM [nt:base] WHERE FIRST([jcr:mixinTypes])='a'");
}
+ @Test
+ public void testIf() throws ParseException {
+ p.parse("SELECT * FROM [nt:base] WHERE IF([cond], [a], [b])='x'");
+
+ p.parse("SELECT * FROM [nt:base] WHERE IF(EXISTS([alias]), PATH(),
null)='x'");
+
+ p.parse("SELECT * FROM [nt:base] WHERE IF([cond], IF([cond2], [a],
[b]), [c])='x'");
+
+ // XPath uses the "jcr:" prefix
+ p.parse(new XPathToSQL2Converter()
+ .convert("//*[jcr:if(@cond, @a, @b) = 'x']"));
+
+ p.parse(new XPathToSQL2Converter()
+ .convert("//*[jcr:if(jcr:exists(@alias), fn:path(), @b) =
'x']"));
+
+ // jcr:null() is the XPath spelling of the "null" literal
+ String sql2 = new XPathToSQL2Converter()
+ .convert("//*[jcr:if(jcr:exists(@alias), fn:path(),
jcr:null()) = 'x']");
+ assertTrue("expected a bare null literal, got: " + sql2,
+ sql2.contains("null)") && !sql2.contains("[null]"));
+ p.parse(sql2);
+ }
+
+ @Test(expected = ParseException.class)
+ public void ifFailsWithTwoParams() throws ParseException {
+ p.parse("SELECT * FROM [nt:base] WHERE IF([cond], [a])='x'");
+ }
+
+ @Test
+ public void testExists() throws ParseException {
+ Query q = p.parse("SELECT * FROM [nt:base] WHERE
EXISTS([alias])=true");
+ assertEquals("select [nt:base].[jcr:primaryType] as
[nt:base.jcr:primaryType] " +
+ "from [nt:base] as [nt:base] " +
+ "where exists([nt:base].[alias]) = cast('true' as boolean)",
q.toString());
+
+ q = p.parse("SELECT * FROM [nt:base] WHERE
EXISTS(UPPER([alias]))=true");
+ assertEquals("select [nt:base].[jcr:primaryType] as
[nt:base.jcr:primaryType] " +
+ "from [nt:base] as [nt:base] " +
+ "where exists(upper([nt:base].[alias])) = cast('true' as
boolean)", q.toString());
+
+ // XPath uses the "jcr:" prefix
+ q = p.parse(new XPathToSQL2Converter()
+ .convert("//*[jcr:exists(@alias) = true()]"));
+ assertEquals("select [a].[jcr:path] as [jcr:path], [a].[jcr:score] as
[jcr:score], [a].[jcr:primaryType] as [a.jcr:primaryType] " +
+ "from [nt:base] as [a] " +
+ "where exists([a].[alias]) = cast('true' as boolean)",
q.toString());
+ }
+
+ @Test(expected = ParseException.class)
+ public void existsFailsWithNoParam() throws ParseException {
+ p.parse("SELECT * FROM [nt:base] WHERE EXISTS()=true");
+ }
+
+ @Test(expected = ParseException.class)
+ public void opFailsWhenDisabledByDefault() throws ParseException {
+ // the op(a, operator, b) function is disabled by default
+ p.parse("SELECT * FROM [nt:base] WHERE OP([a], '+', [b])=3");
+ }
+
+ @Test(expected = ParseException.class)
+ public void opXPathFailsWhenDisabledByDefault() throws ParseException {
+ // the XPath -> SQL-2 conversion itself always succeeds (it's purely
+ // syntactic); the toggle is enforced when the resulting SQL-2 is
parsed
+ p.parse(new XPathToSQL2Converter()
+ .convert("//*[jcr:op(@a, '+', @b) = 3]"));
+ }
+
+ @Test
+ public void testOpWhenEnabled() throws ParseException {
Review Comment:
`@ParameterizedTest` ?? using EnumSource (but that may require JUnit 5)
with an enum
enum ParseCases {
PLUS(
"SELECT * FROM [nt:base] WHERE OP([a], '+', [b])=3",
"select [nt:base].[jcr:primaryType] as [nt:base.jcr:primaryType] " +
"from [nt:base] as [nt:base] " +
"where op([nt:base].[a], '+', [nt:base].[b]) = 3"
),
...
}
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]