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 2015/02/04 19:27:38 UTC

svn commit: r1657364 - in /lucene/dev/branches/lucene_solr_4_10: ./ dev-tools/ lucene/ lucene/analysis/ lucene/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/ lucene/analysis/common/src/java/org/apache/lucene/analysis/standard/std40/...

Author: hossman
Date: Wed Feb  4 18:27:36 2015
New Revision: 1657364

URL: http://svn.apache.org/r1657364
Log:
SOLR-6780: Fixed a bug in how default/appends/invariants params were affecting the set of all keys found in the request parameters, resulting in some key=value param pairs being duplicated. (merge r1642727, r1657314)

Modified:
    lucene/dev/branches/lucene_solr_4_10/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/dev-tools/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/BUILD.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/CHANGES.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/JRE_VERSION_MIGRATION.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/LICENSE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/MIGRATE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/NOTICE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/README.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/SYSTEM_REQUIREMENTS.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/Lucene47WordDelimiterFilter.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/common/src/java/org/apache/lucene/analysis/standard/std40/ASCIITLD.jflex-macro   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/common/src/java/org/apache/lucene/analysis/standard/std40/SUPPLEMENTARY.jflex-macro   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/common/src/java/org/apache/lucene/analysis/standard/std40/StandardTokenizerImpl40.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/common/src/java/org/apache/lucene/analysis/standard/std40/StandardTokenizerImpl40.jflex   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/common/src/java/org/apache/lucene/analysis/standard/std40/UAX29URLEmailTokenizerImpl40.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/common/src/java/org/apache/lucene/analysis/standard/std40/UAX29URLEmailTokenizerImpl40.jflex   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/common/src/java/org/apache/lucene/analysis/standard/std40/package.html   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/common/src/test/org/apache/lucene/analysis/miscellaneous/TestLucene47WordDelimiterFilter.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/analysis/icu/src/java/org/apache/lucene/collation/ICUCollationKeyFilterFactory.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/backwards/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/benchmark/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/classification/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/classification/build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/classification/ivy.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/classification/src/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/codecs/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/common-build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/core/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/core/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions2.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/core/src/test/org/apache/lucene/index/index.410.cfs.zip   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/core/src/test/org/apache/lucene/index/index.410.nocfs.zip   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/core/src/test/org/apache/lucene/search/TestSort.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/core/src/test/org/apache/lucene/search/TestSortDocValues.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/core/src/test/org/apache/lucene/search/TestTopFieldCollector.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/core/src/test/org/apache/lucene/search/TestTotalHitCountCollector.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/demo/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/expressions/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/facet/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/grouping/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/highlighter/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/ivy-ignore-conflicts.properties   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/ivy-settings.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/ivy-versions.properties   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/join/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/licenses/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/memory/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/misc/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/module-build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/queries/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionQuerySort.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/queryparser/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/replicator/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/sandbox/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/site/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/spatial/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeAreaValueSource.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/spatial/src/test-files/data/simple-bbox.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/spatial/src/test-files/simple-Queries-BBox.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/spatial/src/test/org/apache/lucene/spatial/bbox/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/suggest/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/test-framework/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/lucene/tools/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/CHANGES.txt   (contents, props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/LICENSE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/NOTICE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/README.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/SYSTEM_REQUIREMENTS.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/bin/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/cloud-dev/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/common-build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/contrib/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/contrib/extraction/src/test-files/extraction/solr/collection1/conf/solrconfig.xml
    lucene/dev/branches/lucene_solr_4_10/solr/contrib/extraction/src/test/org/apache/solr/handler/extraction/ExtractingRequestHandlerTest.java
    lucene/dev/branches/lucene_solr_4_10/solr/core/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/core/src/java/org/apache/solr/request/DocValuesStats.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/core/src/java/org/apache/solr/spelling/suggest/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml
    lucene/dev/branches/lucene_solr_4_10/solr/core/src/test/org/apache/solr/core/TestConfig.java   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
    lucene/dev/branches/lucene_solr_4_10/solr/core/src/test/org/apache/solr/spelling/suggest/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/example/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/licenses/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/licenses/httpclient-LICENSE-ASL.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/licenses/httpclient-NOTICE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/licenses/httpcore-LICENSE-ASL.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/licenses/httpcore-NOTICE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/licenses/httpmime-LICENSE-ASL.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/licenses/httpmime-NOTICE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/scripts/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/site/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/solrj/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/java/org/apache/solr/common/params/DefaultSolrParams.java
    lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/java/org/apache/solr/common/util/IteratorChain.java
    lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/test/org/apache/solr/common/params/SolrParamTest.java
    lucene/dev/branches/lucene_solr_4_10/solr/test-framework/   (props changed)
    lucene/dev/branches/lucene_solr_4_10/solr/webapp/   (props changed)

Modified: lucene/dev/branches/lucene_solr_4_10/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_4_10/solr/CHANGES.txt?rev=1657364&r1=1657363&r2=1657364&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_4_10/solr/CHANGES.txt (original)
+++ lucene/dev/branches/lucene_solr_4_10/solr/CHANGES.txt Wed Feb  4 18:27:36 2015
@@ -25,6 +25,16 @@ Bug Fixes
 * SOLR-6931: We should do a limited retry when using HttpClient. 
  (Mark Miller, Hrishikesh Gadre, Gregory Chanan)
 
+* SOLR-6780: Fixed a bug in how default/appends/invariants params were affecting the set 
+  of all "keys" found in the request parameters, resulting in some key=value param pairs 
+  being duplicated.  This was noticeably affecting some areas of the code where iteration 
+  was done over the set of all params: 
+    * literal.* in ExtractingRequestHandler
+    * facet.* in FacetComponent
+    * spellcheck.[dictionary name].* and spellcheck.collateParam.* in SpellCheckComponent
+    * olap.* in AnalyticsComponent
+  (Alexandre Rafalovitch & hossman)
+
 ==================  4.10.3 ==================
 
 Bug Fixes

Modified: lucene/dev/branches/lucene_solr_4_10/solr/contrib/extraction/src/test-files/extraction/solr/collection1/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_4_10/solr/contrib/extraction/src/test-files/extraction/solr/collection1/conf/solrconfig.xml?rev=1657364&r1=1657363&r2=1657364&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_4_10/solr/contrib/extraction/src/test-files/extraction/solr/collection1/conf/solrconfig.xml (original)
+++ lucene/dev/branches/lucene_solr_4_10/solr/contrib/extraction/src/test-files/extraction/solr/collection1/conf/solrconfig.xml Wed Feb  4 18:27:36 2015
@@ -194,6 +194,18 @@
   
   <requestHandler name="/update/extract" class="org.apache.solr.handler.extraction.ExtractingRequestHandler"/>
 
+  <requestHandler name="/update/extract/lit-def" class="org.apache.solr.handler.extraction.ExtractingRequestHandler">
+    <lst name="defaults">
+      <str name="literal.foo_s">x</str>
+    </lst>
+    <lst name="appends">
+      <str name="literal.bar_s">y</str>
+    </lst>
+    <lst name="invariants">
+      <str name="literal.zot_s">z</str>
+      <str name="uprefix">ignored_</str>
+    </lst>
+  </requestHandler>
 
   <highlighting>
    <!-- Configure the standard fragmenter -->

Modified: lucene/dev/branches/lucene_solr_4_10/solr/contrib/extraction/src/test/org/apache/solr/handler/extraction/ExtractingRequestHandlerTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_4_10/solr/contrib/extraction/src/test/org/apache/solr/handler/extraction/ExtractingRequestHandlerTest.java?rev=1657364&r1=1657363&r2=1657364&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_4_10/solr/contrib/extraction/src/test/org/apache/solr/handler/extraction/ExtractingRequestHandlerTest.java (original)
+++ lucene/dev/branches/lucene_solr_4_10/solr/contrib/extraction/src/test/org/apache/solr/handler/extraction/ExtractingRequestHandlerTest.java Wed Feb  4 18:27:36 2015
@@ -286,6 +286,74 @@ public class ExtractingRequestHandlerTes
 
   }
 
+  public void testLiteralDefaults() throws Exception {
+
+    // sanity check config
+    loadLocalFromHandler("/update/extract/lit-def",
+                         "extraction/simple.html",
+                         "literal.id", "lit-def-simple");
+    assertU(commit());
+    assertQ(req("q", "id:lit-def-simple")
+            , "//*[@numFound='1']"
+            , "count(//arr[@name='foo_s']/str)=1"
+            , "//arr[@name='foo_s']/str[.='x']"
+            , "count(//arr[@name='bar_s']/str)=1"
+            , "//arr[@name='bar_s']/str[.='y']"
+            , "count(//arr[@name='zot_s']/str)=1"
+            , "//arr[@name='zot_s']/str[.='z']"
+            ); 
+    
+    // override the default foo_s
+    loadLocalFromHandler("/update/extract/lit-def",
+                         "extraction/simple.html",
+                         "literal.foo_s", "1111",
+                         "literal.id", "lit-def-simple");
+    assertU(commit());
+    assertQ(req("q", "id:lit-def-simple")
+            , "//*[@numFound='1']"
+            , "count(//arr[@name='foo_s']/str)=1"
+            , "//arr[@name='foo_s']/str[.='1111']"
+            , "count(//arr[@name='bar_s']/str)=1"
+            , "//arr[@name='bar_s']/str[.='y']"
+            , "count(//arr[@name='zot_s']/str)=1"
+            , "//arr[@name='zot_s']/str[.='z']"
+            ); 
+
+    // pre-pend the bar_s
+    loadLocalFromHandler("/update/extract/lit-def",
+                         "extraction/simple.html",
+                         "literal.bar_s", "2222",
+                         "literal.id", "lit-def-simple");
+    assertU(commit());
+    assertQ(req("q", "id:lit-def-simple")
+            , "//*[@numFound='1']"
+            , "count(//arr[@name='foo_s']/str)=1"
+            , "//arr[@name='foo_s']/str[.='x']"
+            , "count(//arr[@name='bar_s']/str)=2"
+            , "//arr[@name='bar_s']/str[.='2222']"
+            , "//arr[@name='bar_s']/str[.='y']"
+            , "count(//arr[@name='zot_s']/str)=1"
+            , "//arr[@name='zot_s']/str[.='z']"
+            ); 
+
+    // invariant zot_s can not be changed
+    loadLocalFromHandler("/update/extract/lit-def",
+                         "extraction/simple.html",
+                         "literal.zot_s", "3333",
+                         "literal.id", "lit-def-simple");
+    assertU(commit());
+    assertQ(req("q", "id:lit-def-simple")
+            , "//*[@numFound='1']"
+            , "count(//arr[@name='foo_s']/str)=1"
+            , "//arr[@name='foo_s']/str[.='x']"
+            , "count(//arr[@name='bar_s']/str)=1"
+            , "//arr[@name='bar_s']/str[.='y']"
+            , "count(//arr[@name='zot_s']/str)=1"
+            , "//arr[@name='zot_s']/str[.='z']"
+            ); 
+    
+  }
+
   @Test
   public void testPlainTextSpecifyingMimeType() throws Exception {
     ExtractingRequestHandler handler = (ExtractingRequestHandler) h.getCore().getRequestHandler("/update/extract");
@@ -608,7 +676,9 @@ public class ExtractingRequestHandlerTes
     assertQ(req("wdf_nocase:\"Test password protected word doc\""), "//*[@numFound='2']");
   }
   
-  SolrQueryResponse loadLocal(String filename, String... args) throws Exception {
+  SolrQueryResponse loadLocalFromHandler(String handler, String filename, 
+                                         String... args) throws Exception {
+                              
     LocalSolrQueryRequest req = (LocalSolrQueryRequest) req(args);
     try {
       // TODO: stop using locally defined streams once stream.file and
@@ -616,11 +686,15 @@ public class ExtractingRequestHandlerTes
       List<ContentStream> cs = new ArrayList<>();
       cs.add(new ContentStreamBase.FileStream(getFile(filename)));
       req.setContentStreams(cs);
-      return h.queryAndResponse("/update/extract", req);
+      return h.queryAndResponse(handler, req);
     } finally {
       req.close();
     }
   }
 
+  SolrQueryResponse loadLocal(String filename, String... args) throws Exception {
+    return loadLocalFromHandler("/update/extract", filename, args);
+  }
+
 
 }

Modified: lucene/dev/branches/lucene_solr_4_10/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_4_10/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml?rev=1657364&r1=1657363&r2=1657364&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_4_10/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml (original)
+++ lucene/dev/branches/lucene_solr_4_10/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml Wed Feb  4 18:27:36 2015
@@ -485,6 +485,21 @@
     </lst>
   </requestHandler>
 
+  <requestHandler name="/search-facet-def" class="solr.SearchHandler" >
+    <lst name="defaults">
+      <str name="facet.field">foo_s</str>
+    </lst>
+    <lst name="appends">
+      <str name="facet.query">foo_s:bar</str>
+    </lst>
+  </requestHandler>
+  <requestHandler name="/search-facet-invariants" class="solr.SearchHandler" >
+    <lst name="invariants">
+      <str name="facet.field">foo_s</str>
+      <str name="facet.query">foo_s:bar</str>
+    </lst>
+  </requestHandler>
+
   <admin>
     <defaultQuery>solr</defaultQuery>
     <gettableFiles>solrconfig.xml schema.xml admin-extra.html</gettableFiles>

Modified: lucene/dev/branches/lucene_solr_4_10/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_4_10/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java?rev=1657364&r1=1657363&r2=1657364&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_4_10/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java (original)
+++ lucene/dev/branches/lucene_solr_4_10/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java Wed Feb  4 18:27:36 2015
@@ -126,6 +126,59 @@ public class SimpleFacetsTest extends So
     add_doc("id", "2004", "hotel_s1", "b", "airport_s1", "ams", "duration_i1", "5");
   }
 
+
+  public void testDefaultsAndAppends() throws Exception {
+    // all defaults
+    assertQ( req("indent","true", "q","*:*", "rows","0", "facet","true", "qt","/search-facet-def")
+             // only one default facet.field
+             ,"//lst[@name='facet_fields']/lst[@name='foo_s']"
+             ,"count(//lst[@name='facet_fields']/lst[@name='foo_s'])=1"
+             ,"count(//lst[@name='facet_fields']/lst)=1"
+             // only one default facet.query
+             ,"//lst[@name='facet_queries']/int[@name='foo_s:bar']"
+             ,"count(//lst[@name='facet_queries']/int[@name='foo_s:bar'])=1"
+             ,"count(//lst[@name='facet_queries']/int)=1"
+             );
+
+    // override default & pre-pend to appends
+    assertQ( req("indent","true", "q","*:*", "rows","0", "facet","true", "qt","/search-facet-def",
+                 "facet.field", "bar_s",
+                 "facet.query", "bar_s:yak"
+                 )
+             // override single default facet.field
+             ,"//lst[@name='facet_fields']/lst[@name='bar_s']"
+             ,"count(//lst[@name='facet_fields']/lst[@name='bar_s'])=1"
+             ,"count(//lst[@name='facet_fields']/lst)=1"
+             // add an additional facet.query
+             ,"//lst[@name='facet_queries']/int[@name='foo_s:bar']"
+             ,"//lst[@name='facet_queries']/int[@name='bar_s:yak']"
+             ,"count(//lst[@name='facet_queries']/int[@name='foo_s:bar'])=1"
+             ,"count(//lst[@name='facet_queries']/int[@name='bar_s:yak'])=1"
+             ,"count(//lst[@name='facet_queries']/int)=2"
+             );
+  }
+
+  public void testInvariants() throws Exception {
+    // no matter if we try to use facet.field or facet.query, results shouldn't change
+    for (String ff : new String[] { "facet.field", "bogus" }) {
+      for (String fq : new String[] { "facet.query", "bogus" }) {
+        assertQ( req("indent","true", "q", "*:*", "rows","0", "facet","true", 
+                     "qt","/search-facet-invariants",
+                     ff, "bar_s",
+                     fq, "bar_s:yak")
+                 // only one invariant facet.field
+                 ,"//lst[@name='facet_fields']/lst[@name='foo_s']"
+                 ,"count(//lst[@name='facet_fields']/lst[@name='foo_s'])=1"
+                 ,"count(//lst[@name='facet_fields']/lst)=1"
+                 // only one invariant facet.query
+                 ,"//lst[@name='facet_queries']/int[@name='foo_s:bar']"
+                 ,"count(//lst[@name='facet_queries']/int[@name='foo_s:bar'])=1"
+                 ,"count(//lst[@name='facet_queries']/int)=1"
+                 );
+      }
+    }
+  }
+
   @Test
   public void testCachingBigTerms() throws Exception {
     assertQ( req("indent","true", "q", "id:[42 TO 47]",

Modified: lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/java/org/apache/solr/common/params/DefaultSolrParams.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/java/org/apache/solr/common/params/DefaultSolrParams.java?rev=1657364&r1=1657363&r2=1657364&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/java/org/apache/solr/common/params/DefaultSolrParams.java (original)
+++ lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/java/org/apache/solr/common/params/DefaultSolrParams.java Wed Feb  4 18:27:36 2015
@@ -18,8 +18,7 @@
 package org.apache.solr.common.params;
 
 import java.util.Iterator;
-
-import org.apache.solr.common.util.IteratorChain;
+import java.util.LinkedHashSet;
 
 /**
  *
@@ -52,10 +51,17 @@ public class DefaultSolrParams extends S
 
   @Override
   public Iterator<String> getParameterNamesIterator() {
-    final IteratorChain<String> c = new IteratorChain<>();
-    c.addIterator(defaults.getParameterNamesIterator());
-    c.addIterator(params.getParameterNamesIterator());
-    return c;
+    // We need to compute the set of all param names in advance 
+    // So we don't wind up with an iterator that returns the same
+    // String more then once (SOLR-6780)
+    LinkedHashSet<String> allKeys = new LinkedHashSet<>();
+    for (SolrParams p : new SolrParams [] {params, defaults}) {
+      Iterator<String> localKeys = p.getParameterNamesIterator();
+      while (localKeys.hasNext()) {
+        allKeys.add(localKeys.next());
+      }
+    }
+    return allKeys.iterator();
   }
 
   @Override

Modified: lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/java/org/apache/solr/common/util/IteratorChain.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/java/org/apache/solr/common/util/IteratorChain.java?rev=1657364&r1=1657363&r2=1657364&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/java/org/apache/solr/common/util/IteratorChain.java (original)
+++ lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/java/org/apache/solr/common/util/IteratorChain.java Wed Feb  4 18:27:36 2015
@@ -23,8 +23,10 @@ import java.util.List;
 
 /** Chain several Iterators, so that this iterates
  *  over all of them in sequence.
+ *
+ * @deprecated This class is no longer used by Solr, and may be removed in future versions
  */
-
+@Deprecated
 public class IteratorChain<E> implements Iterator<E> {
 
   private final List<Iterator<E>> iterators = new ArrayList<>();

Modified: lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/test/org/apache/solr/common/params/SolrParamTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/test/org/apache/solr/common/params/SolrParamTest.java?rev=1657364&r1=1657363&r2=1657364&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/test/org/apache/solr/common/params/SolrParamTest.java (original)
+++ lucene/dev/branches/lucene_solr_4_10/solr/solrj/src/test/org/apache/solr/common/params/SolrParamTest.java Wed Feb  4 18:27:36 2015
@@ -19,14 +19,93 @@ package org.apache.solr.common.params;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
 
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.common.SolrException;
 
 /**
  */
-public class SolrParamTest extends LuceneTestCase 
-{  
+public class SolrParamTest extends LuceneTestCase {  
+
+  public void testParamIterators() {
+
+    ModifiableSolrParams aaa = new ModifiableSolrParams();
+    aaa.add("foo", "a1");
+    aaa.add("foo", "a2");
+
+    assertIterSize("aaa: foo", 1, aaa);
+    assertIterSize("required aaa: foo", 1, aaa.required());
+
+    assertEquals(new String[] { "a1", "a2" }, aaa.getParams("foo"));
+
+    aaa.add("yak", "a3");
+
+    assertIterSize("aaa: foo & yak", 2, aaa);
+    assertIterSize("required aaa: foo & yak", 2, aaa.required());
+
+    assertEquals(new String[] { "a1", "a2" }, aaa.getParams("foo"));
+    assertEquals(new String[] { "a3" }, aaa.getParams("yak"));
+
+    ModifiableSolrParams bbb = new ModifiableSolrParams();
+    bbb.add("foo", "b1");
+    bbb.add("foo", "b2");
+    bbb.add("zot", "b3");
+
+    assertIterSize("bbb: foo & zot", 2, bbb);
+    assertIterSize("required bbb: foo & zot", 2, bbb.required());
+
+    assertEquals(new String[] { "b1", "b2" }, bbb.getParams("foo"));
+    assertEquals(new String[] { "b3" }, bbb.getParams("zot"));
+
+    SolrParams def = SolrParams.wrapDefaults(aaa, bbb);
+
+    assertIterSize("def: aaa + bbb", 3, def);
+    assertIterSize("required def: aaa + bbb", 3, def.required());
+
+    assertEquals(new String[] { "a1", "a2" }, def.getParams("foo"));
+    assertEquals(new String[] { "a3" }, def.getParams("yak"));
+    assertEquals(new String[] { "b3" }, def.getParams("zot"));
+
+    SolrParams append = SolrParams.wrapAppended(aaa, bbb);
+
+    assertIterSize("append: aaa + bbb", 3, append);
+    assertIterSize("required appended: aaa + bbb", 3, append.required());
+
+    assertEquals(new String[] { "a1", "a2", "b1", "b2", }, append.getParams("foo"));
+    assertEquals(new String[] { "a3" }, append.getParams("yak"));
+    assertEquals(new String[] { "b3" }, append.getParams("zot"));
+
+  }
+
+  public void testModParamAddParams() {
+
+    ModifiableSolrParams aaa = new ModifiableSolrParams();
+    aaa.add("foo", "a1");
+    aaa.add("foo", "a2");
+    aaa.add("yak", "a3");
+    
+    ModifiableSolrParams bbb = new ModifiableSolrParams();
+    bbb.add("foo", "b1");
+    bbb.add("foo", "b2");
+    bbb.add("zot", "b3");
+    
+    SolrParams def = SolrParams.wrapDefaults(aaa, bbb);
+    assertEquals(new String[] { "a1", "a2" }, def.getParams("foo"));
+    assertEquals(new String[] { "a3" }, def.getParams("yak"));
+    assertEquals(new String[] { "b3" }, def.getParams("zot"));
+
+    ModifiableSolrParams combined = new ModifiableSolrParams();
+    combined.add(def);
+
+    assertEquals(new String[] { "a1", "a2" }, combined.getParams("foo"));
+    assertEquals(new String[] { "a3" }, combined.getParams("yak"));
+    assertEquals(new String[] { "b3" }, combined.getParams("zot"));
+
+  }
+
   public void testGetParams() {
     Map<String,String> pmap = new HashMap<>();
     pmap.put( "str"        , "string"   );
@@ -194,4 +273,18 @@ public class SolrParamTest extends Lucen
     }
     return 200;
   }
+
+  static <T> List<T> iterToList(Iterator<T> iter) {
+    List<T> result = new ArrayList<>();
+    while (iter.hasNext()) {
+      result.add(iter.next());
+    }
+    return result;
+  }
+
+  static void assertIterSize(String msg, int expectedSize, SolrParams p) {
+    List<String> keys = iterToList(p.getParameterNamesIterator());
+    assertEquals(msg + " " + keys.toString(), expectedSize, keys.size());
+  }
+
 }