You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ca...@apache.org on 2016/11/08 12:58:50 UTC

svn commit: r1768684 - in /jackrabbit/trunk/jackrabbit-jcr-commons/src: main/java/org/apache/jackrabbit/commons/query/GQL.java test/java/org/apache/jackrabbit/commons/query/GQLTest.java

Author: catholicon
Date: Tue Nov  8 12:58:50 2016
New Revision: 1768684

URL: http://svn.apache.org/viewvc?rev=1768684&view=rev
Log:
JCR-4042: Adding Escape Character in GQL

Adding support for escape sequence. Escape sequence character is backslash. Only double-quotes (as \"), backslash (as \\) and colon (as \:) characters can be escaped.

Modified:
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/query/GQL.java   (contents, props changed)
    jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/query/GQLTest.java   (contents, props changed)

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/query/GQL.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/query/GQL.java?rev=1768684&r1=1768683&r2=1768684&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/query/GQL.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/query/GQL.java Tue Nov  8 12:58:50 2016
@@ -94,6 +94,12 @@ import org.apache.jackrabbit.util.Text;
  * property name and the value. This also means that a value that contains
  * a colon does not need to be enclosed in double quotes.
  * <p>
+ * <b>Escaping</b>
+ * <p>
+ * To imply double-quotes(&quot;), backslash(\), and colon(:) literally you can
+ * escape them with a backslash. E.g. similar to example above in quoting for colon,
+ * <code>"jcr:title":apache</code> is equiavalent to jcr\:title:apache.
+ * <p>
  * <b>Auto prefixes</b>
  * <p>
  * When a property, node or node type name does not have a namespace prefix GQL
@@ -717,6 +723,7 @@ public final class GQL {
         StringBuffer property = new StringBuffer();
         StringBuffer value = new StringBuffer();
         boolean quoted = false;
+        boolean escaped = false;
         boolean optional = false;
         for (char c : stmt) {
             switch (c) {
@@ -739,7 +746,7 @@ public final class GQL {
                     }
                     break;
                 case ':':
-                    if (quoted) {
+                    if (quoted || escaped) {
                         value.append(c);
                     } else {
                         if (property.length() == 0) {
@@ -753,7 +760,17 @@ public final class GQL {
                     }
                     break;
                 case '"':
-                    quoted = !quoted;
+                    if (escaped) {
+                        value.append(c);
+                    } else {
+                        quoted = !quoted;
+                    }
+                    break;
+                case '\\':
+                    if (escaped) {
+                        value.append(c);
+                    }
+                    escaped = !escaped;
                     break;
                     // noise
                 case '*':
@@ -770,11 +787,13 @@ public final class GQL {
                 case '{':
                 case '}':
                 case '!':
-                case '\\':
                     break;
                 default:
                     value.append(c);
             }
+            if (c != '\\') {
+                escaped = false;
+            }
         }
     }
 

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/query/GQL.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/query/GQLTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/query/GQLTest.java?rev=1768684&r1=1768683&r2=1768684&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/query/GQLTest.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/query/GQLTest.java Tue Nov  8 12:58:50 2016
@@ -41,4 +41,54 @@ public class GQLTest extends TestCase {
         
     }
 
+    public void testEscaping() throws RepositoryException {
+        //simple things work
+        assertEquals("//*[jcr:contains(assets/@a, 'b')] order by @jcr:score descending",
+                GQL.translateToXPath("a:b", null, "assets"));
+
+        //backslash is ignored (same as earlier) and only ", \ and : are escaped
+        assertEquals("//*[jcr:contains(assets/@a, 'b')] order by @jcr:score descending",
+                GQL.translateToXPath("a:b\\", null, "assets"));
+        assertEquals("//*[jcr:contains(assets, 'ab')] order by @jcr:score descending",
+                GQL.translateToXPath("a\\b", null, "assets"));
+        assertEquals("//*[jcr:contains(assets/@a, 'b')] order by @jcr:score descending",
+                GQL.translateToXPath("a:\\b", null, "assets"));
+
+        //backward compatibility of quoted ":"
+        assertEquals("//*[jcr:contains(assets/@a, '1:1')] order by @jcr:score descending",
+                GQL.translateToXPath("a:\"1:1\"", null, "assets"));
+
+        //escaping ":"
+        assertEquals("//*[jcr:contains(assets/@a, '1:1')] order by @jcr:score descending",
+                GQL.translateToXPath("a:\"1\\:1\"", null, "assets"));
+
+        assertEquals("//*[jcr:contains(assets/@a, '1:1')] order by @jcr:score descending",
+                GQL.translateToXPath("a:1\\:1", null, "assets"));
+
+        assertEquals("//*[jcr:contains(assets/@a:, '1')] order by @jcr:score descending",
+                GQL.translateToXPath("a\\::1", null, "assets"));
+
+        //escaping \
+        assertEquals("//*[jcr:contains(assets/@a, '1\\1')] order by @jcr:score descending",
+                GQL.translateToXPath("a:\"1\\\\1\"", null, "assets"));
+
+        assertEquals("//*[jcr:contains(assets/@a, '1\\1')] order by @jcr:score descending",
+                GQL.translateToXPath("a:1\\\\1", null, "assets"));
+
+        assertEquals("//*[jcr:contains(assets/@a_x005c_, '1')] order by @jcr:score descending",
+                GQL.translateToXPath("a\\\\:1", null, "assets"));
+
+
+        //escaping "
+        assertEquals("//*[jcr:contains(assets/@a, '1\"1')] order by @jcr:score descending",
+                GQL.translateToXPath("a:\"1\\\"1\"", null, "assets"));
+
+        assertEquals("//*[jcr:contains(assets/@a, '1\"1')] order by @jcr:score descending",
+                GQL.translateToXPath("a:1\\\"1", null, "assets"));
+
+        assertEquals("//*[jcr:contains(assets/@a_x0022_, '1')] order by @jcr:score descending",
+                GQL.translateToXPath("a\\\":1", null, "assets"));
+
+    }
+
 }

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/query/GQLTest.java
------------------------------------------------------------------------------
    svn:executable = *