You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2020/08/22 00:32:48 UTC

[lucene-solr] 01/02: Demonstrate equivilence of more compact syntax w/o param refs (that requires careful escaping of nest path '/' chars)

This is an automated email from the ASF dual-hosted git repository.

hossman pushed a commit to branch jira/SOLR-14383
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git

commit 0e026d6357a53e7e32cdc0b5f413a74931202e0d
Author: Chris Hostetter <ho...@apache.org>
AuthorDate: Fri Aug 21 10:44:14 2020 -0700

    Demonstrate equivilence of more compact syntax w/o param refs (that requires careful escaping of nest path '/' chars)
---
 .../test-files/solr/collection1/conf/schema15.xml  |  2 +
 .../org/apache/solr/search/QueryEqualityTest.java  | 65 ++++++++++++++++------
 .../solr/update/TestNestedUpdateProcessor.java     | 61 +++++++++++++++-----
 3 files changed, 98 insertions(+), 30 deletions(-)

diff --git a/solr/core/src/test-files/solr/collection1/conf/schema15.xml b/solr/core/src/test-files/solr/collection1/conf/schema15.xml
index c2a8bbb..b585df5 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema15.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema15.xml
@@ -560,6 +560,8 @@
   <field name="_version_" type="long" indexed="false" stored="false" docValues="true"/>
   <!-- points to the root document of a block of nested documents -->
   <field name="_root_" type="string" indexed="true" stored="true"/>
+  <!-- for nested documents (relationship tracking) -->
+  <field name="_nest_path_" type="_nest_path_" /><fieldType name="_nest_path_" class="solr.NestPathField" />
 
   <field name="multi_int_with_docvals" type="tint" multiValued="true" docValues="true" indexed="false"/>
 
diff --git a/solr/core/src/test/org/apache/solr/search/QueryEqualityTest.java b/solr/core/src/test/org/apache/solr/search/QueryEqualityTest.java
index 419619d..1d65406 100644
--- a/solr/core/src/test/org/apache/solr/search/QueryEqualityTest.java
+++ b/solr/core/src/test/org/apache/solr/search/QueryEqualityTest.java
@@ -523,25 +523,56 @@ public class QueryEqualityTest extends SolrTestCaseJ4 {
     assertQueryEquals(null, "{!parent which='+*:* -foo_s:parent'}",
         "{!child of=foo_s:parent}");
 
-    final SolrQueryRequest req = req(
-        "fq","bar_s:baz","fq","{!tag=fqban}bar_s:ban",
-        "ffq","bar_s:baz","ffq","{!tag=ffqban}bar_s:ban");
-    try {
-    assertQueryEquals("filters", req,
-        "{!parent which=foo_s:parent param=$fq}foo_s:bar",
-        "{!parent which=foo_s:parent param=$ffq}foo_s:bar" // differently named params
-        );
-    assertQueryEquals("filters", req,
-        "{!parent which=foo_s:parent param=$fq excludeTags=fqban}foo_s:bar",
-        "{!parent which=foo_s:parent param=$ffq excludeTags=ffqban}foo_s:bar" // differently named params
-        );
+    try (SolrQueryRequest req = req("fq","bar_s:baz","fq","{!tag=fqban}bar_s:ban",
+                                    "ffq","bar_s:baz","ffq","{!tag=ffqban}bar_s:ban")) {
+      assertQueryEquals("filters", req,
+                        "{!parent which=foo_s:parent param=$fq}foo_s:bar",
+                        "{!parent which=foo_s:parent param=$ffq}foo_s:bar" // differently named params
+                        );
+      assertQueryEquals("filters", req,
+                        "{!parent which=foo_s:parent param=$fq excludeTags=fqban}foo_s:bar",
+                        "{!parent which=foo_s:parent param=$ffq excludeTags=ffqban}foo_s:bar" // differently named params
+                        );
+
+      QueryUtils.checkUnequal(// parent filter is not an equal to child
+                              QParser.getParser("{!child of=foo_s:parent}", req).getQuery(),
+                              QParser.getParser("{!parent which=foo_s:parent}", req).getQuery());
+    }
 
-    QueryUtils.checkUnequal(// parent filter is not an equal to child
-        QParser.getParser("{!child of=foo_s:parent}", req).getQuery(),
-        QParser.getParser("{!parent which=foo_s:parent}", req).getQuery());
+    // sanity check multiple ways of specifing _nest_path_ prefixes
+    final String parent_path = "/aa/bb";
+    try (SolrQueryRequest req = req("parent_filt", "(*:* -{!prefix f='_nest_path_' v='"+parent_path+"/'})",
+                                    "child_q", "(+foo +{!prefix f='_nest_path_' v='"+parent_path+"/'})",
+                                    "parent_q", "(+bar +{!field f='_nest_path_' v='"+parent_path+"'})")) {
+      
+      assertQueryEquals("parent", req,
+                        
+                        // using local params to refer to other query params using 'prefix' parser...
+                        "{!parent which=$parent_filt v=$child_q}",
+                        
+                        // using 'inline' prefix query syntax...
+                        //
+                        // '/' has to be escaped other wise it will be treated as a regex query...
+                        // ...and when used inside the 'which' param it has to be escaped *AGAIN* because of
+                        // the "quoted" localparam evaluation layer...
+                        // (and of course '\' escaping is the java syntax as well, we have to double it)
+                        "{!parent which='*:* -_nest_path_:"+(parent_path + "/").replace("/","\\\\/") +"*'}"
+                        + "(+foo +_nest_path_:" + (parent_path + "/").replace("/", "\\/") + "*)");
+
+      assertQueryEquals("child", req,
+                        
+                        // using local params to refer to other query params using 'prefix' parser...
+                        "{!child of=$parent_filt v=$parent_q}",
+                        
+                        // using 'inline' prefix query syntax...
+                        //
+                        // '/' has to be escaped other wise it will be treated as a regex query...
+                        // ...and when used inside the 'which' param it has to be escaped *AGAIN* because of
+                        // the "quoted" localparam evaluation layer...
+                        // (and of course '\' escaping is the java syntax as well, we have to double it)
+                        "{!child of='*:* -_nest_path_:"+(parent_path + "/").replace("/","\\\\/") +"*'}"
+                        + "(+bar +_nest_path_:" + parent_path.replace("/", "\\/") + ")");
 
-    } finally {
-      req.close();
     }
   }
 
diff --git a/solr/core/src/test/org/apache/solr/update/TestNestedUpdateProcessor.java b/solr/core/src/test/org/apache/solr/update/TestNestedUpdateProcessor.java
index 83305a8..a3844ad 100644
--- a/solr/core/src/test/org/apache/solr/update/TestNestedUpdateProcessor.java
+++ b/solr/core/src/test/org/apache/solr/update/TestNestedUpdateProcessor.java
@@ -450,15 +450,32 @@ public class TestNestedUpdateProcessor extends SolrTestCaseJ4 {
      */
     private SolrParams parentQueryMaker(String parent_path, String inner_child_query) {
       assertValidPathSytax(parent_path);
-
+      final boolean verbose = random().nextBoolean();
+      
       if (parent_path.equals("/")) {
-        return params("q", "{!parent which=$parent_filt v=$child_q}",
-                      "parent_filt", "(*:* -_nest_path_:*)",
-                      "child_q", "(+" + inner_child_query + " +_nest_path_:*)");
+        if (verbose) {
+          return params("q", "{!parent which=$parent_filt v=$child_q}",
+                        "parent_filt", "(*:* -_nest_path_:*)",
+                        "child_q", "(+" + inner_child_query + " +_nest_path_:*)");
+        } else {
+          return params("q", "{!parent which='(*:* -_nest_path_:*)'}(+" + inner_child_query + " +_nest_path_:*)");
+        }
       } // else...
-      return params("q", "{!parent which=$parent_filt v=$child_q})",
-                    "parent_filt", "(*:* -{!prefix f='_nest_path_' v='"+parent_path+"/'})",
-                    "child_q", "(+" + inner_child_query + " +{!prefix f='_nest_path_' v='"+parent_path+"/'})");
+
+      if (verbose) {
+        final String path = parent_path + "/";
+        return params("q", "{!parent which=$parent_filt v=$child_q}",
+                      "parent_filt", "(*:* -{!prefix f='_nest_path_' v='"+path+"'})",
+                      "child_q", "(+" + inner_child_query + " +{!prefix f='_nest_path_' v='"+path+"'})");
+      } else {
+        // '/' has to be escaped other wise it will be treated as a regex query...
+        // (and of course '\' escaping is the java syntax as well, we have to double it)
+        final String path = (parent_path + "/").replace("/", "\\/");
+        // ...and when used inside the 'which' param it has to be escaped *AGAIN* because of
+        // the "quoted" localparam evaluation layer...
+        return params("q", "{!parent which='(*:* -_nest_path_:" + path.replace("\\/","\\\\/") + "*)'}"
+                      + "(+" + inner_child_query + " +_nest_path_:" + path + "*)");
+      }
     }
 
     /** 
@@ -503,14 +520,32 @@ public class TestNestedUpdateProcessor extends SolrTestCaseJ4 {
      */
     private SolrParams childQueryMaker(String parent_path, String inner_parent_query) {
       assertValidPathSytax(parent_path);
+      final boolean verbose = random().nextBoolean();
+      
       if (parent_path.equals("/")) {
-        return params("q", "{!child of=$parent_filt v=$parent_q})",
-                      "parent_filt", "(*:* -_nest_path_:*)",
-                      "parent_q", "(+" + inner_parent_query + " -_nest_path_:*)");
+        if (verbose) {
+          return params("q", "{!child of=$parent_filt v=$parent_q})",
+                        "parent_filt", "(*:* -_nest_path_:*)",
+                        "parent_q", "(+" + inner_parent_query + " -_nest_path_:*)");
+        } else {
+          return params("q", "{!child of='(*:* -_nest_path_:*)'}(+" + inner_parent_query + " -_nest_path_:*)");
+        }
       } // else...
-      return params("q", "{!child of=$parent_filt v=$parent_q})",
-                    "parent_filt", "(*:* -{!prefix f='_nest_path_' v='"+parent_path+"/'})",
-                    "parent_q", "(+" + inner_parent_query + " +{!field f='_nest_path_' v='"+parent_path+"'})");
+      
+      if (verbose) {
+        return params("q", "{!child of=$parent_filt v=$parent_q})",
+                      "parent_filt", "(*:* -{!prefix f='_nest_path_' v='"+parent_path+"/'})",
+                      "parent_q", "(+" + inner_parent_query + " +{!field f='_nest_path_' v='"+parent_path+"'})");
+      } else {
+        // '/' has to be escaped other wise it will be treated as a regex query...
+        // (and of course '\' escaping is the java syntax as well, we have to double it)
+        final String exact_path = parent_path.replace("/", "\\/");
+        // ...and when used inside the 'which' param it has to be escaped *AGAIN* because of
+        // the "quoted" localparam evaluation layer...
+        final String prefix_path = (parent_path + "/").replace("/","\\\\/");
+        return params("q", "{!child of='(*:* -_nest_path_:"+prefix_path+"*)'}"
+                      + "(+" + inner_parent_query + " +_nest_path_:" + exact_path + ")");
+      }
     }
 
     private void assertValidPathSytax(String path) {