diff --git a/.gitignore b/.gitignore index 7937befa7c4..b3146a5d317 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ dependency-reduced-pom.xml # OS specific files .DS_Store +plans/ \ No newline at end of file diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/FT_AttTest_complex.xml b/extensions/indexes/lucene/src/test/xquery/lucene/FT_AttTest_complex.xml deleted file mode 100644 index 6a9439a330b..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/FT_AttTest_complex.xml +++ /dev/null @@ -1,189 +0,0 @@ - - - tests for queries on different indexes on different collection contexts - -

tests for queries on different indexes on different collection contexts

- Ron Van den Branden -
- - - - - - - - - - - - - - - - - - - - - - -

this is a test document

-
-
- {$term} - }; - ]]> - - - - - - [query] lucene FT index (qname), attribute context (@) - - val1 - - - [query] lucene FT index (path), attribute context (@) - - val2 - - - [query] lucene FT index (qname), attribute context (attribute::) - - val1 - - - [query] lucene FT index (path), attribute context (attribute::) - - val2 - - - [query] lucene FT index (qname), element context - - -

this is a test document

-
-
- - [query] lucene FT index (path), element context - - -

this is a test document

-
-
- - [query] lucene FT index (qname), attribute context inside predicate - - -

this is a test document

-
-
- - [query] lucene FT index (path), attribute context inside predicate - - -

this is a test document

-
-
- - - [index] lucene FT index (qname), attribute context (@) - - - val1 - - - - [index] lucene FT index (path), attribute context (@) - - - val2 - - - - [index] lucene FT index (qname), attribute context (attribute::) - - - val1 - - - - [index] lucene FT index (path), attribute context (attribute::) - - - val2 - - - - [index] lucene FT index (qname), element context - - - val1 - - - - [index] lucene FT index (path), element context - - - val2 - - -
diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/LuceneFT+range_indexRetrievalTest.xml b/extensions/indexes/lucene/src/test/xquery/lucene/LuceneFT+range_indexRetrievalTest.xml deleted file mode 100644 index f621d0438a1..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/LuceneFT+range_indexRetrievalTest.xml +++ /dev/null @@ -1,212 +0,0 @@ - - - tests for index retrieval of Lucene FT and range indexed nodes - -

these tests test whether the util:index-keys() function returns correct nodes for the Lucene FT and range indexex

- Ron Van den Branden -
- - - - - - - - - - - - - - - - - - - - - - - - - - - some text inside an element - - some text inside a paragraph - - some text inside an element - - some text inside a paragraph - - - - - - some text inside an element - - some text inside a paragraph - - some text inside an element - - some text inside a paragraph - - - - {normalize-space($term)} {$data[1]} {$data[2]} {$data[3]} - }; - ]]> - - - - - - - index scan on path-based Lucene FT indexed nodes - - - - element - 2 - 2 - 1 - - - inside - 4 - 2 - 2 - - - paragraph - 2 - 2 - 3 - - - some - 4 - 2 - 4 - - - text - 4 - 2 - 5 - - - - - index scan on qname-based Lucene FT indexed nodes - - - - element - 2 - 2 - 1 - - - inside - 4 - 2 - 2 - - - paragraph - 2 - 2 - 3 - - - some - 4 - 2 - 4 - - - text - 4 - 2 - 5 - - - - - index scan on path-based range indexed nodes - - - - some text inside an element - 2 - 2 - 1 - - - some text inside a paragraph - 2 - 2 - 2 - - - - - index scan on qname-based range indexed nodes - - - - some text inside an element - 2 - 2 - 1 - - - some text inside a paragraph - 2 - 2 - 2 - - - -
diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/analyzers-index.xql b/extensions/indexes/lucene/src/test/xquery/lucene/analyzers-index.xql new file mode 100644 index 00000000000..ebace05873e --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/analyzers-index.xql @@ -0,0 +1,228 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for Lucene analyzers (German, Whitespace, Keyword, query-analyzer-id, fields). + : Refactored from analyzers.xml (TestSet). + : + : @author Wolfgang Meier + :) +module namespace anix="http://exist-db.org/xquery/lucene/analyzers-index/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ Collection config: l (line, de with l_ws, l_nostop), @n (lineno keyword). :) +declare variable $anix:XCONF as element(collection) := + + + + + + + + + + + + + + + + + + + ; + +(:~ German poetry test document. :) +declare variable $anix:XML as document-node() := + document { + + + + Habe nun, ach! Philosophie, + Juristerei und Medizin, + Und leider auch Theologie + Durchaus studiert, mit heißem Bemühn. + Da steh ich nun, ich armer Tor! + Und bin so klug als wie zuvor; + Heiße Magister, heiße Doktor gar + Und ziehe schon an die zehen Jahr + Herauf, herab und quer und krumm + Meine Schüler an der Nase herum – + Und sehe, daß wir nichts wissen können! + Das will mir schier das Herz verbrennen. + + + + }; + +declare variable $anix:COLLECTION_NAME := "analyzers-index"; +declare variable $anix:COLLECTION := "/db/" || $anix:COLLECTION_NAME; + +(:~ setUp: create collection, config, store doc, reindex. + : @return empty sequence + :) +declare + %test:setUp +function anix:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $anix:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $anix:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $anix:COLLECTION_NAME, "collection.xconf", $anix:XCONF), + xmldb:store($anix:COLLECTION, "text.xml", $anix:XML), + xmldb:reindex($anix:COLLECTION) ) +}; + +(:~ tearDown: remove data and config collections. + : @return empty sequence + :) +declare + %test:tearDown +function anix:tearDown() { + xmldb:remove($anix:COLLECTION), + xmldb:remove("/db/system/config/db/" || $anix:COLLECTION_NAME) +}; + +(:~ German Analyzer: standard search. :) +declare %test:assertTrue function anix:german-standard-search() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query(., 'philosophie')] + return deep-equal($result, Habe nun, ach! Philosophie,) +}; + +(:~ German Analyzer: stemmed verb. :) +declare %test:assertTrue function anix:german-stemmed-verb() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query(., 'jahre')] + return deep-equal($result, Und ziehe schon an die zehen Jahr) +}; + +(:~ German Analyzer: plural finds singular. :) +declare %test:assertTrue function anix:german-plural-finds-singular() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query(., 'herzen')] + return deep-equal($result, Das will mir schier das Herz verbrennen.) +}; + +(:~ query-analyzer-id de (options as XML). :) +declare %test:assertTrue function anix:query-analyzer-id-de-xml() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query(., 'herzen', de)] + return deep-equal($result, Das will mir schier das Herz verbrennen.) +}; + +(:~ query-analyzer-id:de :) +declare %test:assertTrue function anix:query-analyzer-id-de-map() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query(., 'herzen', map { "query-analyzer-id": "de" })] + return deep-equal($result, Das will mir schier das Herz verbrennen.) +}; + +(:~ query-analyzer-id keyword (options as XML). :) +declare %test:assertEmpty function anix:query-analyzer-id-keyword-xml() { + doc($anix:COLLECTION || "/text.xml")//l[ft:query(., 'herzen', keyword)] +}; + +(:~ query-analyzer-id:keyword :) +declare %test:assertEmpty function anix:query-analyzer-id-keyword-map() { + doc($anix:COLLECTION || "/text.xml")//l[ft:query(., 'herzen', map { "query-analyzer-id": "keyword" })] +}; + +(:~ query new field "l_no-stop" with the GermanAnalyzer without stopwords :) +declare %test:assertTrue function anix:query-field-l-nostop() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query(., 'l_nostop:(ich OR bin)')] + return deep-equal($result, (Da steh ich nun, ich armer Tor!, Und bin so klug als wie zuvor;)) +}; + +(:~ query new field "l_no-stop" with the default GermanAnalyzer :) +declare %test:assertEmpty function anix:query-field-l-nostop-de() { + doc($anix:COLLECTION || "/text.xml")//l[ft:query(., 'l_nostop:(ich OR bin)', map { "query-analyzer-id": "de" })] +}; + +(:~ query new field "l_ws" with the WhitespaceAnalyzer - no result :) +declare %test:assertEmpty function anix:query-field-l-ws-no-result() { + doc($anix:COLLECTION || "/text.xml")//l[ft:query(., "l_ws:(nun\!)")] +}; + +(:~ query new field "l_ws" with GermanAnalyzer :) +declare %test:assertEmpty function anix:query-field-l-ws-de-no-result() { + doc($anix:COLLECTION || "/text.xml")//l[ft:query(., "l_ws:(nun\!)", map { "query-analyzer-id": "de" })] +}; + +(:~ query new field "l_ws" with the WhitespaceAnalyzer - 2 results :) +declare %test:assertTrue function anix:query-field-l-ws-two-results() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query(., "l_ws:(nun,)")] + return deep-equal($result, (Habe nun, ach! Philosophie,, Da steh ich nun, ich armer Tor!)) +}; + +(:~ query new field "l_ws" with the GermanAnalyzer - still no results :) +declare %test:assertEmpty function anix:query-field-l-ws-de-still-no-results() { + doc($anix:COLLECTION || "/text.xml")//l[ft:query(., "l_ws:(nun,)", map { "query-analyzer-id": "de" })] +}; + +(:~ query new field "l_ws" with the GermanAnalyzer and wildcard - 2 results :) +declare %test:assertTrue function anix:query-field-l-ws-de-wildcard() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query(., "l_ws:(nun*)", map { "query-analyzer-id": "de" })] + return deep-equal($result, (Habe nun, ach! Philosophie,, Da steh ich nun, ich armer Tor!)) +}; + +(:~ Query field with standard analyzer, no match :) +declare %test:assertEmpty function anix:query-field-line-no-match() { + ft:query-field("line", "herzen") +}; + +(:~ Query field with query analyzer overridden (options as map) :) +declare %test:assertTrue function anix:query-field-line-map-de() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query-field("line", "herzen", map { "query-analyzer-id": "de" })], + $expected := doc($anix:COLLECTION || "/text.xml")//l[@n = "l1.12"] + return count($result) eq 1 and deep-equal($result, $expected) +}; + +(:~ Query field with query analyzer overridden (options as xml) :) +declare %test:assertTrue function anix:query-field-line-xml-de() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query-field("line", "herzen", de)], + $expected := doc($anix:COLLECTION || "/text.xml")//l[@n = "l1.12"] + return count($result) eq 1 and deep-equal($result, $expected) +}; + +(:~ Query field with standard analyzer and without context :) +declare %test:assertTrue function anix:query-field-line-klug() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query-field("line", 'klug')], + $expected := doc($anix:COLLECTION || "/text.xml")//l[@n = "l1.6"] + return count($result) eq 1 and deep-equal($result, $expected) +}; + +(:~ Query field with keyword analyzer, no match :) +declare %test:assertEmpty function anix:query-field-lineno-no-match() { + ft:query-field("lineno", "10") +}; + +(:~ Query field with keyword analyzer and without context :) +declare %test:assertTrue function anix:query-field-lineno-without-context() { + let $result := ft:query-field("lineno", "l1.10")/.., + $expected := doc($anix:COLLECTION || "/text.xml")//l[@n = "l1.10"] + return count($result) eq 1 and deep-equal($result, $expected) +}; + +(:~ Query field with keyword analyzer and context :) +declare %test:assertTrue function anix:query-field-lineno-with-context() { + let $result := doc($anix:COLLECTION || "/text.xml")//l[ft:query-field("lineno", "l1.10")], + $expected := doc($anix:COLLECTION || "/text.xml")//l[@n = "l1.10"] + return count($result) eq 1 and deep-equal($result, $expected) +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/analyzers.xml b/extensions/indexes/lucene/src/test/xquery/lucene/analyzers.xml deleted file mode 100644 index fd04077920b..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/analyzers.xml +++ /dev/null @@ -1,227 +0,0 @@ - - - - Lucene indexing tests: analyzers - - Tests for Lucene analyzers - Wolfgang Meier - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Habe nun, ach! Philosophie, - Juristerei und Medizin, - Und leider auch Theologie - Durchaus studiert, mit heißem Bemühn. - Da steh ich nun, ich armer Tor! - Und bin so klug als wie zuvor; - Heiße Magister, heiße Doktor gar - Und ziehe schon an die zehen Jahr - Herauf, herab und quer und krumm - Meine Schüler an der Nase herum – - Und sehe, daß wir nichts wissen können! - Das will mir schier das Herz verbrennen. - - - - - - - - - - - German Analyzer: standard search - doc("/db/lucene/text.xml")//l[ft:query(., 'philosophie')] - - Habe nun, ach! Philosophie, - - - - German Analyzer: stemmed verb - doc("/db/lucene/text.xml")//l[ft:query(., 'jahre')] - - Und ziehe schon an die zehen Jahr - - - - German Analyzer: plural finds singular - doc("/db/lucene/text.xml")//l[ft:query(., 'herzen')] - - Das will mir schier das Herz verbrennen. - - - - <query-analyzer-id>de<... - doc("/db/lucene/text.xml")//l[ft:query(., 'herzen', - <options><query-analyzer-id>de</query-analyzer-id></options> - )] - - - Das will mir schier das Herz verbrennen. - - - - query-analyzer-id:de - doc("/db/lucene/text.xml")//l[ft:query(., 'herzen', map { "query-analyzer-id": "de" })] - - Das will mir schier das Herz verbrennen. - - - - <query-analyzer-id>keyword<... - doc("/db/lucene/text.xml")//l[ft:query(., 'herzen', - <options><query-analyzer-id>keyword</query-analyzer-id></options> - )] - - - - - query-analyzer-id:keyword - doc("/db/lucene/text.xml")//l[ft:query(., 'herzen', map { "query-analyzer-id": "keyword" })] - - - - query new field "l_no-stop" with the GermanAnalyzer without stopwords - doc("/db/lucene/text.xml")//l[ft:query(., 'l_nostop:(ich OR bin)')] - - Da steh ich nun, ich armer Tor! - Und bin so klug als wie zuvor; - - - - query new field "l_no-stop" with the default GermanAnalyzer - doc("/db/lucene/text.xml")//l[ft:query(., 'l_nostop:(ich OR bin)', map { "query-analyzer-id": "de" })] - - - - query new field "l_ws" with the WhitespaceAnalyzer - no result - doc("/db/lucene/text.xml")//l[ft:query(., "l_ws:(nun\!)")] - - - - query new field "l_ws" with GermanAnalyzer - doc("/db/lucene/text.xml")//l[ft:query(., "l_ws:(nun\!)", map { "query-analyzer-id": "de" })] - - - - query new field "l_ws" with the WhitespaceAnalyzer - 2 results - doc("/db/lucene/text.xml")//l[ft:query(., "l_ws:(nun,)")] - - Habe nun, ach! Philosophie, - Da steh ich nun, ich armer Tor! - - - - query new field "l_ws" with the GermanAnalyzer - still no results - doc("/db/lucene/text.xml")//l[ft:query(., "l_ws:(nun,)", map { "query-analyzer-id": "de" })] - - - - query new field "l_ws" with the GermanAnalyzer and wildcard - 2 results - doc("/db/lucene/text.xml")//l[ft:query(., "l_ws:(nun*)", map { "query-analyzer-id": "de" })] - - Habe nun, ach! Philosophie, - Da steh ich nun, ich armer Tor! - - - - Query field with standard analyzer, no match - ft:query-field("line", "herzen") - - - - Query field with query analyzer overridden (options as map) - ft:query-field("line", "herzen", map { "query-analyzer-id": "de" }) - - Das will mir schier das Herz verbrennen. - - - - Query field with query analyzer overridden (options as xml) - ft:query-field("line", "herzen", - <options><query-analyzer-id>de</query-analyzer-id></options> - ) - - - Das will mir schier das Herz verbrennen. - - - - Query field with standard analyzer and without context - ft:query-field("line", 'klug') - - Und bin so klug als wie zuvor; - - - - Query field with keyword analyzer, no match - ft:query-field("lineno", "10") - - - - Query field with keyword analyzer and without context - - - Meine Schüler an der Nase herum – - - - - Query field with keyword analyzer and context - doc("/db/lucene/text.xml")//l[ft:query-field("lineno", "l1.10")] - - Meine Schüler an der Nase herum – - - - diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/analyzers.xql b/extensions/indexes/lucene/src/test/xquery/lucene/analyzers.xql index fc75ad1af60..0da9c8ff252 100644 --- a/extensions/indexes/lucene/src/test/xquery/lucene/analyzers.xql +++ b/extensions/indexes/lucene/src/test/xquery/lucene/analyzers.xql @@ -53,6 +53,7 @@ declare variable $analyze:XCONF2 := declare %test:setUp function analyze:setup() { + let $_ := (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")) let $testCol := xmldb:create-collection("/db", "lucenetest") let $testCol1 := xmldb:create-collection("/db/lucenetest", "test1") let $testCol2 := xmldb:create-collection("/db/lucenetest", "test2") diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/facets.xql b/extensions/indexes/lucene/src/test/xquery/lucene/facets.xql index 43ab07b16c1..780c4a4fd4e 100644 --- a/extensions/indexes/lucene/src/test/xquery/lucene/facets.xql +++ b/extensions/indexes/lucene/src/test/xquery/lucene/facets.xql @@ -285,6 +285,7 @@ declare variable $facet:XCONF1 := declare %test:setUp function facet:setup() { + let $_ := (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")) let $testCol := xmldb:create-collection("/db", "lucenetest") let $personsCol := xmldb:create-collection("/db/lucenetest", "persons") let $confCol := xmldb:create-collection("/db/system/config/db", "lucenetest") diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/ft-attr-context.xql b/extensions/indexes/lucene/src/test/xquery/lucene/ft-attr-context.xql new file mode 100644 index 00000000000..d76ed060a6e --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/ft-attr-context.xql @@ -0,0 +1,207 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for queries on different indexes on different collection contexts. + : Attribute context ft:query and util:index-keys (qname/path, @att vs attribute axis). + : Refactored from FT_AttTest_complex.xml (TestSet). + : + : @author Ron Van den Branden + :) +module namespace ftac="http://exist-db.org/xquery/lucene/ft-attr-context/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : Collection config: p, @att1, //@att2 Lucene + range. + :) +declare variable $ftac:XCONF as element(collection) := + + + + + + + + + + + + + + ; + +(:~ + : Test document: p with att1, att2. + :) +declare variable $ftac:XML as document-node() := + document { +

this is a test document

+ }; + +declare variable $ftac:COLLECTION_NAME := "ft-attr-context"; +declare variable $ftac:COLLECTION := "/db/" || $ftac:COLLECTION_NAME; + +(:~ Callback for util:index-keys. :) +declare %private function ftac:term-callback($term as xs:string, $data as xs:int+) as element(term) { + { $term } +}; + +(:~ + : setUp: create collection, config, store doc, reindex. + :) +declare + %test:setUp +function ftac:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $ftac:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $ftac:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $ftac:COLLECTION_NAME, "collection.xconf", $ftac:XCONF), + xmldb:store($ftac:COLLECTION, "test.xml", $ftac:XML), + xmldb:reindex($ftac:COLLECTION) ) +}; + +(:~ + : tearDown: remove data and config collections. + :) +declare + %test:tearDown +function ftac:tearDown() { + xmldb:remove($ftac:COLLECTION), + xmldb:remove("/db/system/config/db/" || $ftac:COLLECTION_NAME) +}; + +(:~ + : [query] lucene FT index (qname), attribute context @att + :) +declare %test:assertEquals("val1") function ftac:query-qname-attr-at() { + collection($ftac:COLLECTION)//p/@att1[ft:query(., 'val1')]/string() +}; + +(:~ + : [query] lucene FT index (path), attribute context @att + :) +declare %test:assertEquals("val2") function ftac:query-path-attr-at() { + collection($ftac:COLLECTION)//p/@att2[ft:query(., 'val2')]/string() +}; + +(:~ + : [query] lucene FT index (qname), attribute context attribute axis + :) +declare %test:assertEquals("val1") function ftac:query-qname-attr-attribute-axis() { + collection($ftac:COLLECTION)//p/attribute::att1[ft:query(., 'val1')]/string() +}; + +(:~ + : [query] lucene FT index (path), attribute context attribute axis + :) +declare %test:assertEquals("val2") function ftac:query-path-attr-attribute-axis() { + collection($ftac:COLLECTION)//p/attribute::att2[ft:query(., 'val2')]/string() +}; + +(:~ + : [query] lucene FT index (qname), element context + :) +declare %test:assertTrue function ftac:query-qname-element-context() { + let $result := collection($ftac:COLLECTION)//p[ft:query(@att1, 'val1')] + return deep-equal($result, collection($ftac:COLLECTION)//p) +}; + +(:~ + : [query] lucene FT index (path), element context + :) +declare %test:assertTrue function ftac:query-path-element-context() { + let $result := collection($ftac:COLLECTION)//p[ft:query(@att2, 'val2')] + return deep-equal($result, collection($ftac:COLLECTION)//p) +}; + +(:~ + : [query] lucene FT index (qname), attribute context inside predicate + :) +declare %test:assertTrue function ftac:query-qname-attr-in-predicate() { + let $result := collection($ftac:COLLECTION)/*[descendant-or-self::p/@att1[ft:query(., 'val1')]] + return deep-equal($result, collection($ftac:COLLECTION)//p) +}; + +(:~ + : [query] lucene FT index (path), attribute context inside predicate + :) +declare %test:assertTrue function ftac:query-path-attr-in-predicate() { + let $result := collection($ftac:COLLECTION)/*[descendant-or-self::p/@att2[ft:query(., 'val2')]] + return deep-equal($result, collection($ftac:COLLECTION)//p) +}; + +(:~ + : [index] lucene FT index (qname), attribute context @att + :) +declare %test:assertTrue function ftac:index-qname-attr-at() { + let $a := collection($ftac:COLLECTION)//p/@att1 + let $result := util:index-keys($a, '', util:function(xs:QName('ftac:term-callback'), 2), 100, 'lucene-index') + return deep-equal($result, val1) +}; + +(:~ + : [index] lucene FT index (path), attribute context @att + :) +declare %test:assertTrue function ftac:index-path-attr-at() { + let $a := collection($ftac:COLLECTION)//p/@att2 + let $result := util:index-keys($a, '', util:function(xs:QName('ftac:term-callback'), 2), 100, 'lucene-index') + return deep-equal($result, val2) +}; + +(:~ + : [index] lucene FT index (qname), attribute context attribute axis + :) +declare %test:assertTrue function ftac:index-qname-attr-attribute-axis() { + let $a := collection($ftac:COLLECTION)//p/attribute::att1 + let $result := util:index-keys($a, '', util:function(xs:QName('ftac:term-callback'), 2), 100, 'lucene-index') + return deep-equal($result, val1) +}; + +(:~ + : [index] lucene FT index (path), attribute context attribute axis + :) +declare %test:assertTrue function ftac:index-path-attr-attribute-axis() { + let $a := collection($ftac:COLLECTION)//p/attribute::att2 + let $result := util:index-keys($a, '', util:function(xs:QName('ftac:term-callback'), 2), 100, 'lucene-index') + return deep-equal($result, val2) +}; + +(:~ + : [index] lucene FT index (qname), element context + :) +declare %test:assertTrue function ftac:index-qname-element-context() { + let $a := collection($ftac:COLLECTION)//p + let $result := util:index-keys($a/@att1, '', util:function(xs:QName('ftac:term-callback'), 2), 100, 'lucene-index') + return deep-equal($result, val1) +}; + +(:~ + : [index] lucene FT index (path), element context + :) +declare %test:assertTrue function ftac:index-path-element-context() { + let $a := collection($ftac:COLLECTION)//p + let $result := util:index-keys($a/@att2, '', util:function(xs:QName('ftac:term-callback'), 2), 100, 'lucene-index') + return deep-equal($result, val2) +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/ft-match.xql b/extensions/indexes/lucene/src/test/xquery/lucene/ft-match.xql index 1aec9d9cc8f..a0baf191ba1 100644 --- a/extensions/indexes/lucene/src/test/xquery/lucene/ft-match.xql +++ b/extensions/indexes/lucene/src/test/xquery/lucene/ft-match.xql @@ -54,6 +54,7 @@ declare variable $ftt:COLLECTION := "/db/" || $ftt:COLLECTION_NAME; declare %test:setUp function ftt:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", $ftt:COLLECTION_NAME), xmldb:store("/db/system/config/db/" || $ftt:COLLECTION_NAME, "collection.xconf", $ftt:COLLECTION_CONFIG), xmldb:create-collection("/db", $ftt:COLLECTION_NAME), @@ -80,4 +81,29 @@ declare function ftt:highlight($query as xs:string) { count(util:expand(collection($ftt:COLLECTION)//div[ft:query(., $query)][1])//exist:match), count(util:expand(collection($ftt:COLLECTION)//div[ft:query(., $query)][2])//exist:match) +}; + +(:~ + : Asserts that string proximity '"Introduction text"~1' and XML + : <near slop="1"><term>Introduction</term><term>text</term></near> + : return identical match counts (from util:expand//exist:match). + : + : @see https://github.com/eXist-db/exist/issues/833 + : @return xs:integer+ (match-count for string query, match-count for XML query) + :) +declare + %test:pending("Proximity/slop string vs XML match-count equality, see #833") + %test:assertEquals(1, 1) +function ftt:slop-string-vs-xml-equality() { + let $queries := ( + '"Introduction text"~1', + Introductiontext + ), + $results := + for $query in $queries + let $hits := collection($ftt:COLLECTION)//div[ft:query(., $query)], + $expanded := util:expand($hits), + $match-count := count($expanded//exist:match) + return $match-count + return ($results[1], $results[2]) }; \ No newline at end of file diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/ignore-condition.xql b/extensions/indexes/lucene/src/test/xquery/lucene/ignore-condition.xql new file mode 100644 index 00000000000..68d4de1ecc4 --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/ignore-condition.xql @@ -0,0 +1,115 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for Lucene <ignore> with condition (predicate). + : Only elements matching the condition should be ignored; others stay indexed. + : + : @see https://github.com/eXist-db/exist/issues/1113 + :) +module namespace igc="http://exist-db.org/xquery/lucene/ignore-condition/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : Collection config: index doc; ignore note only when @type='editorial'. @return element + :) +declare variable $igc:XCONF as element(collection) := + + + + + + + + + ; + +(:~ + : Test document: author note has "needle", editorial note has "onlyhere". @return document-node + :) +declare variable $igc:XML as document-node() := + document { + + needle + onlyhere + + }; + +declare variable $igc:COLLECTION_NAME := "ignore-condition-1113"; +declare variable $igc:COLLECTION := "/db/" || $igc:COLLECTION_NAME; + +(:~ + : setUp: create collection, config with conditional ignore, store doc, reindex. + : @see https://github.com/eXist-db/exist/issues/1113 + :) +declare + %test:setUp +function igc:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $igc:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $igc:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $igc:COLLECTION_NAME, "collection.xconf", $igc:XCONF), + xmldb:store($igc:COLLECTION, "test.xml", $igc:XML), + xmldb:reindex($igc:COLLECTION) ) +}; + +(:~ + : tearDown: remove data and config collections. + :) +declare + %test:tearDown +function igc:tearDown() { + xmldb:remove($igc:COLLECTION), + xmldb:remove("/db/system/config/db/" || $igc:COLLECTION_NAME), + xmldb:reindex($igc:COLLECTION) +}; + +(:~ + : With ignore condition @type='editorial', author note is indexed so "needle" should match once. + : @param $query full-text query + : @return count of doc elements matching the query + : @see https://github.com/eXist-db/exist/issues/1113 + :) +declare + %test:args("needle") + %test:pending("ignore with condition not implemented, see #1113") + %test:assertEquals(1) +function igc:author-note-indexed($query as xs:string) { + count(collection($igc:COLLECTION)//doc[ft:query(., $query)]) +}; + +(:~ + : With ignore condition @type='editorial', editorial note is not indexed so "onlyhere" should not match. + : (Currently passes because all note are ignored; after #1113 only editorial would be ignored.) + : @param $query full-text query + : @return count of doc elements matching the query + : @see https://github.com/eXist-db/exist/issues/1113 + :) +declare + %test:args("onlyhere") + %test:assertEquals(0) +function igc:editorial-note-ignored($query as xs:string) { + count(collection($igc:COLLECTION)//doc[ft:query(., $query)]) +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/index-keys.xql b/extensions/indexes/lucene/src/test/xquery/lucene/index-keys.xql new file mode 100644 index 00000000000..06cfa794bb1 --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/index-keys.xql @@ -0,0 +1,219 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for util:index-keys on Lucene FT and range indexed nodes (path/qname). + : Refactored from LuceneFT+range_indexRetrievalTest.xml (TestSet). + : + : @author Ron Van den Branden + :) +module namespace idxk="http://exist-db.org/xquery/lucene/index-keys/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : Collection config: pPath, @typePath, pQname, @typeQname Lucene + range. + :) +declare variable $idxk:XCONF as element(collection) := + + + + + + + + + + + + + + + + ; + +(:~ + : Test document (same for test1 and test2). + :) +declare variable $idxk:TEST_DOC as element(test) := + + + some text inside an element + + some text inside a paragraph + + some text inside an element + + some text inside a paragraph + ; + +declare variable $idxk:COLLECTION_NAME := "index-keys"; +declare variable $idxk:COLLECTION := "/db/" || $idxk:COLLECTION_NAME; + +(:~ + : Callback for util:index-keys. + :) +declare %private function idxk:term-callback($term as xs:string, $data as xs:int+) as element(entry) { + + { normalize-space($term) } + { $data[1] } + { $data[2] } + { $data[3] } + +}; + +(:~ + : Expected entries for path-based Lucene index scan. + :) +declare variable $idxk:EXPECTED_PATH_LUCENE as element(entry)+ := ( + + element + 2 + 2 + 1 + , + + inside + 4 + 2 + 2 + , + + paragraph + 2 + 2 + 3 + , + + some + 4 + 2 + 4 + , + + text + 4 + 2 + 5 + +); + +(:~ + : Expected entries for path-based range index scan. + :) +declare variable $idxk:EXPECTED_PATH_RANGE as element(entry)+ := ( + + some text inside an element + 2 + 2 + 1 + , + + some text inside a paragraph + 2 + 2 + 2 + +); + +(:~ + : setUp: create collection, config, store two docs, reindex. + :) +declare + %test:setUp +function idxk:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $idxk:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $idxk:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $idxk:COLLECTION_NAME, "collection.xconf", $idxk:XCONF), + xmldb:store($idxk:COLLECTION, "test1.xml", document { $idxk:TEST_DOC }), + xmldb:store($idxk:COLLECTION, "test2.xml", document { $idxk:TEST_DOC }), + xmldb:reindex($idxk:COLLECTION) ) +}; + +(:~ + : tearDown: remove data and config collections. + :) +declare + %test:tearDown +function idxk:tearDown() { + xmldb:remove($idxk:COLLECTION), + xmldb:remove("/db/system/config/db/" || $idxk:COLLECTION_NAME) +}; + +(:~ + : index scan on path-based Lucene FT indexed nodes + :) +declare + %test:assertTrue +function idxk:index-scan-path-lucene() { + let $callback := util:function(xs:QName("idxk:term-callback"), 2), + $hits := collection($idxk:COLLECTION)//pPath, + $result := util:index-keys($hits, '', $callback, 1000, 'lucene-index') + return deep-equal($result, $idxk:EXPECTED_PATH_LUCENE) +}; + +(:~ + : index scan on qname-based Lucene FT indexed nodes + :) +declare + %test:assertTrue +function idxk:index-scan-qname-lucene() { + let $callback := util:function(xs:QName("idxk:term-callback"), 2), + $hits := collection($idxk:COLLECTION)//pQname, + $result := util:index-keys($hits, '', $callback, 1000, 'lucene-index') + return deep-equal($result, $idxk:EXPECTED_PATH_LUCENE) +}; + +(:~ + : index scan on path-based range indexed nodes. + : Compare term, frequency, documents only (position is enumeration order and may differ). + :) +declare + %test:assertTrue +function idxk:index-scan-path-range() { + let $callback := util:function(xs:QName("idxk:term-callback"), 2), + $hits := collection($idxk:COLLECTION)//pPath, + $result := util:index-keys($hits, '', $callback, 1000) + return deep-equal( + for $e in $result order by $e/term return { $e/term/text() }{ $e/frequency/xs:integer(.) }{ $e/documents/xs:integer(.) }, + for $e in $idxk:EXPECTED_PATH_RANGE order by $e/term return { $e/term/text() }{ $e/frequency/xs:integer(.) }{ $e/documents/xs:integer(.) } + ) +}; + +(:~ + : index scan on qname-based range indexed nodes. + : Compare term, frequency, documents only (position is enumeration order and may differ). + :) +declare + %test:assertTrue +function idxk:index-scan-qname-range() { + let $callback := util:function(xs:QName("idxk:term-callback"), 2), + $hits := collection($idxk:COLLECTION)//pQname, + $result := util:index-keys($hits, '', $callback, 1000) + return deep-equal( + for $e in $result order by $e/term return { $e/term/text() }{ $e/frequency/xs:integer(.) }{ $e/documents/xs:integer(.) }, + for $e in $idxk:EXPECTED_PATH_RANGE order by $e/term return { $e/term/text() }{ $e/frequency/xs:integer(.) }{ $e/documents/xs:integer(.) } + ) +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/indirect-queries.xql b/extensions/indexes/lucene/src/test/xquery/lucene/indirect-queries.xql new file mode 100644 index 00000000000..7fc4bc5dd66 --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/indirect-queries.xql @@ -0,0 +1,285 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for direct vs indirect queries on Lucene FT and range indexed element nodes. + : qname/path; positive match and false match (nested/non-nested attribute). + : Refactored from indirectQueriesTest.xml (TestSet). + : + : @author Ron Van den Branden + :) +module namespace indq="http://exist-db.org/xquery/lucene/indirect-queries/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : Collection config: p1, @att1, //p2, //@att2 Lucene + range. + :) +declare variable $indq:XCONF as element(collection) := + + + + + + + + + + + + + + + + ; + +(:~ + : Test document. + :) +declare variable $indq:XML as document-node() := + document { + + some text inside a qname-based indexed element + some text inside a path-based indexed element + + }; + +declare variable $indq:COLLECTION_NAME := "indirect-queries"; +declare variable $indq:COLLECTION := "/db/" || $indq:COLLECTION_NAME; + +(:~ + : Expected results: direct and indirect both have one p1 (qname match). + :) +declare variable $indq:EXPECTED_P1_MATCH as element(results) := + + some text inside a qname-based indexed element + some text inside a qname-based indexed element + ; + +(:~ + : Expected results: direct and indirect both empty. + :) +declare variable $indq:EXPECTED_EMPTY as element(results) := + ; + +(:~ + : Expected results: direct and indirect both have one p2 (path match). + :) +declare variable $indq:EXPECTED_P2_MATCH as element(results) := + + some text inside a path-based indexed element + some text inside a path-based indexed element + ; + +(:~ + : setUp: create collection, config, store doc, reindex. + :) +declare + %test:setUp +function indq:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $indq:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $indq:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $indq:COLLECTION_NAME, "collection.xconf", $indq:XCONF), + xmldb:store($indq:COLLECTION, "test.xml", $indq:XML), + xmldb:reindex($indq:COLLECTION) ) +}; + +(:~ + : tearDown: remove data and config collections. + :) +declare + %test:tearDown +function indq:tearDown() { + xmldb:remove($indq:COLLECTION), + xmldb:remove("/db/system/config/db/" || $indq:COLLECTION_NAME) +}; + +(:~ + : [Lucene FT index, qname] in/direct hits on element nodes + :) +declare + %test:assertTrue +function indq:lucene-qname-match() { + let $query := 'qname', + $hits := collection($indq:COLLECTION)//p1, + $hits_direct := collection($indq:COLLECTION)//p1[ft:query(., $query)], + $hits_indirect := $hits[ft:query(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_P1_MATCH) +}; + +(:~ + : [Lucene FT index, qname] in/direct hits on element nodes, false match condition on value of nested attribute + :) +declare + %test:assertTrue +function indq:lucene-qname-false-nested-att() { + let $query := 'value1', + $hits := collection($indq:COLLECTION)//p1, + $hits_direct := collection($indq:COLLECTION)//p1[ft:query(., $query)], + $hits_indirect := $hits[ft:query(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_EMPTY) +}; + +(:~ + : [Lucene FT index, qname] in/direct hits on element nodes, false match condition on value of non-nested attribute + :) +declare + %test:assertTrue +function indq:lucene-qname-false-non-nested-att() { + let $query := 'value2', + $hits := collection($indq:COLLECTION)//p1, + $hits_direct := collection($indq:COLLECTION)//p1[ft:query(., $query)], + $hits_indirect := $hits[ft:query(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_EMPTY) +}; + +(:~ + : [Lucene FT index, path] in/direct hits on element nodes + :) +declare + %test:assertTrue +function indq:lucene-path-match() { + let $query := 'path', + $hits := collection($indq:COLLECTION)//p2, + $hits_direct := collection($indq:COLLECTION)//p2[ft:query(., $query)], + $hits_indirect := $hits[ft:query(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_P2_MATCH) +}; + +(:~ + : [Lucene FT index, path] in/direct hits on element nodes, false match condition on value of nested attribute + :) +declare + %test:assertTrue +function indq:lucene-path-false-nested-att() { + let $query := 'value2', + $hits := collection($indq:COLLECTION)//p2, + $hits_direct := collection($indq:COLLECTION)//p2[ft:query(., $query)], + $hits_indirect := $hits[ft:query(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_EMPTY) +}; + +(:~ + : [Lucene FT index, path] in/direct hits on element nodes, false match condition on value of non-nested attribute + :) +declare + %test:assertTrue +function indq:lucene-path-false-non-nested-att() { + let $query := 'value1', + $hits := collection($indq:COLLECTION)//p2, + $hits_direct := collection($indq:COLLECTION)//p2[ft:query(., $query)], + $hits_indirect := $hits[ft:query(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_EMPTY) +}; + +(:~ + : [range index, qname] in/direct hits on element nodes + :) +declare + %test:assertTrue +function indq:range-qname-match() { + let $query := 'qname', + $hits := collection($indq:COLLECTION)//p1, + $hits_direct := collection($indq:COLLECTION)//p1[matches(., $query)], + $hits_indirect := $hits[matches(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_P1_MATCH) +}; + +(:~ + : [range index, qname] in/direct hits on element nodes, false match condition on value of nested attribute + :) +declare + %test:assertTrue +function indq:range-qname-false-nested-att() { + let $query := 'value1', + $hits := collection($indq:COLLECTION)//p1, + $hits_direct := collection($indq:COLLECTION)//p1[matches(., $query)], + $hits_indirect := $hits[matches(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_EMPTY) +}; + +(:~ + : [range index, qname] in/direct hits on element nodes, false match condition on value of non-nested attribute + :) +declare + %test:assertTrue +function indq:range-qname-false-non-nested-att() { + let $query := 'value2', + $hits := collection($indq:COLLECTION)//p1, + $hits_direct := collection($indq:COLLECTION)//p1[matches(., $query)], + $hits_indirect := $hits[matches(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_EMPTY) +}; + +(:~ + : [range index, path] in/direct hits on element nodes + :) +declare + %test:assertTrue +function indq:range-path-match() { + let $query := 'path', + $hits := collection($indq:COLLECTION)//p2, + $hits_direct := collection($indq:COLLECTION)//p2[matches(., $query)], + $hits_indirect := $hits[matches(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_P2_MATCH) +}; + +(:~ + : [range index, path] in/direct hits on element nodes, false match condition on value of nested attribute + :) +declare + %test:assertTrue +function indq:range-path-false-nested-att() { + let $query := 'value2', + $hits := collection($indq:COLLECTION)//p2, + $hits_direct := collection($indq:COLLECTION)//p2[matches(., $query)], + $hits_indirect := $hits[matches(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_EMPTY) +}; + +(:~ + : [range index, path] in/direct hits on element nodes, false match condition on value of non-nested attribute + :) +declare + %test:assertTrue +function indq:range-path-false-non-nested-att() { + let $query := 'value1', + $hits := collection($indq:COLLECTION)//p2, + $hits_direct := collection($indq:COLLECTION)//p2[matches(., $query)], + $hits_indirect := $hits[matches(., $query)], + $result := { $hits_direct }{ $hits_indirect } + return deep-equal($result, $indq:EXPECTED_EMPTY) +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/indirectQueriesTest.xml b/extensions/indexes/lucene/src/test/xquery/lucene/indirectQueriesTest.xml deleted file mode 100644 index 0dfcdb1afd1..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/indirectQueriesTest.xml +++ /dev/null @@ -1,327 +0,0 @@ - - - tests for differences between in/direct queries on element nodes - -

These tests test for differences when element nodes are queried directly, or first stored in a variable. Following test situations are included: -

- These tests are repeated for both qname-based and path-based index definitions, with different index types: the old FT index (match-any()), Lucene FT index (ft:query()), and range index (matches()) search functions. -

- Ron Van den Branden -
- - - - - - - - - - - - - - - - - - - - - - - - - - some text inside a qname-based indexed element - some text inside a path-based indexed element - - - - - - - - - [Lucene FT index, qname] in/direct hits on element nodes - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - some text inside a qname-based indexed element - - - some text inside a qname-based indexed element - - - - - - [Lucene FT index, qname] in/direct hits on element nodes, false match condition on value of nested attribute - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - - - - - - [Lucene FT index, qname] in/direct hits on element nodes, false match condition on value of non-nested attribute - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - - - - - - [Lucene FT index, path] in/direct hits on element nodes - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - some text inside a path-based indexed element - - - some text inside a path-based indexed element - - - - - - [Lucene FT index, path] in/direct hits on element nodes, false match condition on value of nested attribute - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - - - - - - [Lucene FT index, path] in/direct hits on element nodes, false match condition on value of non-nested attribute - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - - - - - - [range index, qname] in/direct hits on element nodes - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - some text inside a qname-based indexed element - - - some text inside a qname-based indexed element - - - - - - [range index, qname] in/direct hits on element nodes, false match condition on value of nested attribute - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - - - - - - [range index, qname] in/direct hits on element nodes, false match condition on value of non-nested attribute - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - - - - - - [range index, path] in/direct hits on element nodes - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - some text inside a path-based indexed element - - - some text inside a path-based indexed element - - - - - - [range index, path] in/direct hits on element nodes, false match condition on value of nested attribute - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - - - - - - [range index, path] in/direct hits on element nodes, false match condition on value of non-nested attribute - - {$hits_direct} - {$hits_indirect} - - ]]> - - - - - - - -
diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/inline-ignore.xql b/extensions/indexes/lucene/src/test/xquery/lucene/inline-ignore.xql new file mode 100644 index 00000000000..9bf1c7cbd37 --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/inline-ignore.xql @@ -0,0 +1,155 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for Lucene configuration inline and ignore nodes. + : Refactored from inline.xml (TestSet). + : + : @author Wolfgang Meier + :) +module namespace inlg="http://exist-db.org/xquery/lucene/inline-ignore/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : Collection config: size, p with inline b and ignore note. + :) +declare variable $inlg:XCONF as element(collection) := + + + + + + + + + + + + ; + +(:~ + : Test document: size, p with inline b, p with ignored note. + :) +declare variable $inlg:XML as document-node() := + document { + + 128 +

This is unclear.

+

This is a paragraphcontaining an inline note.

+
+ }; + +declare variable $inlg:COLLECTION_NAME := "inline-ignore"; +declare variable $inlg:COLLECTION := "/db/" || $inlg:COLLECTION_NAME; + +(:~ + : Expected: size for default processing. + :) +declare variable $inlg:EXPECTED_DEFAULT as element(size) := + 128; + +(:~ + : Expected: p for inline node. + :) +declare variable $inlg:EXPECTED_INLINE as element(p) := +

This is unclear.

; + +(:~ + : Expected: p for ignored node match outside. + :) +declare variable $inlg:EXPECTED_IGNORED_MATCH as element(p) := +

This is a paragraphcontaining an inline note.

; + +(:~ + : setUp: create collection, config, store doc, reindex. + :) +declare + %test:setUp +function inlg:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $inlg:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $inlg:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $inlg:COLLECTION_NAME, "collection.xconf", $inlg:XCONF), + xmldb:store($inlg:COLLECTION, "text.xml", $inlg:XML), + xmldb:reindex($inlg:COLLECTION) ) +}; + +(:~ + : tearDown: remove data and config collections. + :) +declare + %test:tearDown +function inlg:tearDown() { + xmldb:remove($inlg:COLLECTION), + xmldb:remove("/db/system/config/db/" || $inlg:COLLECTION_NAME) +}; + +(:~ + : Default processing. + :) +declare + %test:assertTrue +function inlg:default-processing() { + let $result := doc($inlg:COLLECTION || "/text.xml")//size[ft:query(., '12')] + return deep-equal($result, $inlg:EXPECTED_DEFAULT) +}; + +(:~ + : Inline node. + :) +declare + %test:assertTrue +function inlg:inline-node() { + let $result := doc($inlg:COLLECTION || "/text.xml")//p[ft:query(., 'unclear')] + return deep-equal($result, $inlg:EXPECTED_INLINE) +}; + +(:~ + : Inline node: no match. + :) +declare + %test:assertEmpty +function inlg:inline-node-no-match() { + doc($inlg:COLLECTION || "/text.xml")//p[ft:query(., 'clear')] +}; + +(:~ + : Ignored node: match outside. + :) +declare + %test:assertTrue +function inlg:ignored-node-match-outside() { + let $result := doc($inlg:COLLECTION || "/text.xml")//p[ft:query(., 'paragraph')] + return deep-equal($result, $inlg:EXPECTED_IGNORED_MATCH) +}; + +(:~ + : Ignored node: no match. + :) +declare + %test:assertEmpty +function inlg:ignored-node-no-match() { + doc($inlg:COLLECTION || "/text.xml")//p[ft:query(., 'inline')] +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/inline.xml b/extensions/indexes/lucene/src/test/xquery/lucene/inline.xml deleted file mode 100644 index 97df7faad45..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/inline.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - Lucene indexing tests: inline and ignore nodes - - Tests for Lucene configuration inline and ignore nodes - Wolfgang Meier - - - - - - - - - - - - - - - - - - - - - - - - 128 -

This is unclear.

-

This is a paragraphcontaining an inline note.

-
-
-
- - - - - - Default processing - doc("/db/lucene/text.xml")//size[ft:query(., '12')] - - 128 - - - - Inline node - doc("/db/lucene/text.xml")//p[ft:query(., 'unclear')] - -

This is unclear.

-
-
- - Inline node: no match - doc("/db/lucene/text.xml")//p[ft:query(., 'clear')] - - - - Ignored node: match outside - doc("/db/lucene/text.xml")//p[ft:query(., 'paragraph')] - -

This is a paragraphcontaining an inline note.

-
-
- - Ignored node: no match - doc("/db/lucene/text.xml")//p[ft:query(., 'inline')] - - -
diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/inline_elements.xql b/extensions/indexes/lucene/src/test/xquery/lucene/inline_elements.xql index 0eb8679c014..cbd4d834856 100644 --- a/extensions/indexes/lucene/src/test/xquery/lucene/inline_elements.xql +++ b/extensions/indexes/lucene/src/test/xquery/lucene/inline_elements.xql @@ -50,6 +50,7 @@ declare variable $fti:COLLECTION := "/db/" || $fti:COLLECTION_NAME; declare %test:setUp function fti:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", $fti:COLLECTION_NAME), xmldb:store("/db/system/config/db/" || $fti:COLLECTION_NAME, "collection.xconf", $fti:COLLECTION_CONFIG), xmldb:create-collection("/db", $fti:COLLECTION_NAME), diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/match-highlighting.xql b/extensions/indexes/lucene/src/test/xquery/lucene/match-highlighting.xql new file mode 100644 index 00000000000..49f421c89c8 --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/match-highlighting.xql @@ -0,0 +1,181 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for match highlighting behaviour on Lucene FT (util:expand highlight-matches). + : Refactored from matchHighlighting_ftquery_Tests.xml (TestSet). + : These tests verify that matches are highlighted correctly. They are repeated for matches + : in both elements and attributes, and for each setting of highlight-matches: none, + : attributes, elements, both. + : Note: the kind of index definition (qname / path) does not seem to affect this + : behaviour, so for clarity only qname-based indexes are included. + : + : @author Ron Van den Branden + :) +module namespace mhlt="http://exist-db.org/xquery/lucene/match-highlighting/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : Collection config: el, @att. + :) +declare variable $mhlt:XCONF as element(collection) := + + + + + + + + + + ; + +(:~ + : Test document. + :) +declare variable $mhlt:XML as document-node() := + document { + + onetwo tree + + }; + +declare variable $mhlt:COLLECTION_NAME := "match-highlighting"; +declare variable $mhlt:COLLECTION := "/db/" || $mhlt:COLLECTION_NAME; + +(:~ + : Expected: no highlighting. + :) +declare variable $mhlt:EXPECTED_NONE as element(el) := + onetwo tree; + +(:~ + : setUp: create collection, config, store doc, reindex. + :) +declare + %test:setUp +function mhlt:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $mhlt:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $mhlt:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $mhlt:COLLECTION_NAME, "collection.xconf", $mhlt:XCONF), + xmldb:store($mhlt:COLLECTION, "test.xml", $mhlt:XML), + xmldb:reindex($mhlt:COLLECTION) ) +}; + +(:~ + : tearDown: remove data and config collections. + :) +declare + %test:tearDown +function mhlt:tearDown() { + xmldb:remove($mhlt:COLLECTION), + xmldb:remove("/db/system/config/db/" || $mhlt:COLLECTION_NAME) +}; + +(:~ + : [lucene FT] element match, match-highlighting=none. + :) +declare + %test:assertTrue +function mhlt:element-match-highlight-none() { + let $result := doc($mhlt:COLLECTION || "/test.xml")//el[ft:query(., 'tree')]/util:expand(., 'highlight-matches=none') + return deep-equal($result, $mhlt:EXPECTED_NONE) +}; + +(:~ + : [lucene FT] element match, match-highlighting=attributes. + :) +declare + %test:pending("previously ignored; match-highlighting=attributes") + %test:assertTrue +function mhlt:element-match-highlight-attributes() { + let $result := doc($mhlt:COLLECTION || "/test.xml")//el[ft:query(., 'tree')]/util:expand(., 'highlight-matches=attributes') + return deep-equal($result, $mhlt:EXPECTED_NONE) +}; + +(:~ + : [lucene FT] element match, match-highlighting=elements. + :) +declare + %test:pending("previously ignored; match-highlighting=elements") + %test:assertTrue +function mhlt:element-match-highlight-elements() { + let $result := doc($mhlt:COLLECTION || "/test.xml")//el[ft:query(., 'tree')]/util:expand(., 'highlight-matches=elements') + return deep-equal($result, onetwo tree) +}; + +(:~ + : [lucene FT] element match, match-highlighting=both. + :) +declare + %test:pending("previously ignored; match-highlighting=both") + %test:assertTrue +function mhlt:element-match-highlight-both() { + let $result := doc($mhlt:COLLECTION || "/test.xml")//el[ft:query(., 'tree')]/util:expand(., 'highlight-matches=both') + return deep-equal($result, onetwo tree) +}; + +(:~ + : [lucene FT] attribute match, match-highlighting=none. + :) +declare + %test:assertTrue +function mhlt:attribute-match-highlight-none() { + let $result := doc($mhlt:COLLECTION || "/test.xml")//el[ft:query(@att, 'val')]/util:expand(., 'highlight-matches=none') + return deep-equal($result, $mhlt:EXPECTED_NONE) +}; + +(:~ + : [lucene FT] attribute match, match-highlighting=attributes. + :) +declare + %test:pending("previously ignored; match-highlighting=attributes") + %test:assertTrue +function mhlt:attribute-match-highlight-attributes() { + let $result := doc($mhlt:COLLECTION || "/test.xml")//el[ft:query(@att, 'val')]/util:expand(., 'highlight-matches=attributes') + return deep-equal($result, onetwo tree) +}; + +(:~ + : [lucene FT] attribute match, match-highlighting=elements. + :) +declare + %test:assertTrue +function mhlt:attribute-match-highlight-elements() { + let $result := doc($mhlt:COLLECTION || "/test.xml")//el[ft:query(@att, 'val')]/util:expand(., 'highlight-matches=elements') + return deep-equal($result, $mhlt:EXPECTED_NONE) +}; + +(:~ + : [lucene FT] attribute match, match-highlighting=both. + :) +declare + %test:pending("previously ignored; match-highlighting=both") + %test:assertTrue +function mhlt:attribute-match-highlight-both() { + let $result := doc($mhlt:COLLECTION || "/test.xml")//el[ft:query(@att, 'val')]/util:expand(., 'highlight-matches=both') + return deep-equal($result, onetwo tree) +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/matchHighlighting_ftquery_Tests.xml b/extensions/indexes/lucene/src/test/xquery/lucene/matchHighlighting_ftquery_Tests.xml deleted file mode 100644 index f1b49ba86b2..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/matchHighlighting_ftquery_Tests.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - tests for match highlighting behaviour on different index types - -

These tests test whether matches are highlighted correctly. Tests are grouped - per index type supporting match highlighting (old FT, lucene FT, ngram), and - repeated -

- Note: the kind of index definition (qname / path) doesn't seem to effect this - behaviour, so for clarity's sake, only qname-based indexes are included in these tests. -

- Ron Van den Branden -
- - - - - - - - - - - - - - - - - - - - onetwo tree - - - - - - - - - [lucene FT] element match, match-highlighting=none - - - onetwo tree - - - - [lucene FT] element match, match-highlighting=attributes - - - onetwo tree - - - - [lucene FT] element match, match-highlighting=elements - - - onetwo tree - - - - [lucene FT] element match, match-highlighting=both - - - onetwo tree - - - - [lucene FT] attribute match, match-highlighting=none - - - onetwo tree - - - - [lucene FT] attribute match, match-highlighting=attributes - - - onetwo tree - - - - [lucene FT] attribute match, match-highlighting=elements - - - onetwo tree - - - - [lucene FT] attribute match, match-highlighting=both - - - onetwo tree - - -
diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/optimizer-ft.xql b/extensions/indexes/lucene/src/test/xquery/lucene/optimizer-ft.xql index 5c9ddd877e9..22ad233ab3b 100644 --- a/extensions/indexes/lucene/src/test/xquery/lucene/optimizer-ft.xql +++ b/extensions/indexes/lucene/src/test/xquery/lucene/optimizer-ft.xql @@ -27,6 +27,8 @@ xquery version "3.0"; : : Expressions use the @test:stats annotation to retrieve execution statistics : for each test function. + : + : @see https://github.com/eXist-db/exist/issues/873 indirect query optimizer regression :) module namespace fto="http://exist-db.org/xquery/ft-optimizer/test"; @@ -74,10 +76,12 @@ declare variable $fto:COLLECTION := "/db/" || $fto:COLLECTION_NAME; declare %test:setUp function fto:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", $fto:COLLECTION_NAME), xmldb:store("/db/system/config/db/" || $fto:COLLECTION_NAME, "collection.xconf", $fto:COLLECTION_CONFIG), xmldb:create-collection("/db", $fto:COLLECTION_NAME), - xmldb:store($fto:COLLECTION, "test.xml", $fto:DATA) + xmldb:store($fto:COLLECTION, "test.xml", $fto:DATA), + xmldb:reindex($fto:COLLECTION) }; declare @@ -113,3 +117,37 @@ declare function fto:do-not-simplify($name as xs:string) { fto:collection-helper($fto:COLLECTION)[ft:query(name, $name)]/city/string() }; + +(:~ + : Direct vs indirect Lucene ft:query must return the same hit count (optimizer regression). + : Direct: collection(...)//name[ft:query(., $term)]; indirect: let $hits := collection(...)//name return $hits[ft:query(., $term)]. + : @param $term full-text search term + : @return (direct-count, indirect-count) for assertion + : @see https://github.com/eXist-db/exist/issues/873 + :) +declare + %test:args("Rudi Rüssel") + %test:assertEquals(1, 1) +function fto:indirect-vs-direct-lucene-same-count($term as xs:string) { + let $hits := collection($fto:COLLECTION)//name, + $direct := count(collection($fto:COLLECTION)//name[ft:query(., $term)]), + $indirect := count($hits[ft:query(., $term)]) + return ($direct, $indirect) +}; + +(:~ + : Indirect Lucene ft:query should use index (optimizer); assert index calls = 1. + : @param $term full-text search term + : @return stats (for assertXPath) + : @see https://github.com/eXist-db/exist/issues/873 + : @see https://github.com/eXist-db/exist/issues/873#issuecomment-199351350 + :) +declare + %test:stats + %test:args("Rudi Rüssel") + %test:pending("optimizer does not use index for indirect query, see #873") + %test:assertXPath("$result//stats:index[@calls = 1]") +function fto:indirect-query-uses-index($term as xs:string) { + let $hits := collection($fto:COLLECTION)//name + return $hits[ft:query(., $term)] +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/parenthesized-context.xql b/extensions/indexes/lucene/src/test/xquery/lucene/parenthesized-context.xql new file mode 100644 index 00000000000..8174875daf5 --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/parenthesized-context.xql @@ -0,0 +1,405 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for behaviour of retrieval, query and index functions on different index types, + : on entirely parenthesised contexts. + : Refactored from parenthesizedContext_ftquery_Tests.xml (TestSet). + : + : Three major sections: [retrieval] bare retrieval of parenthesized nodes; [query] queries on + : different index types; [index] lookup of index terms on different index types. + : + : The degree of the problems depends on the type of index and search context. Influencing factors: + : index definition (qname / path-based); type of query (direct XPath / indirect FLWR); context + : node (parenthesized context node / parenthesized location step + self axis); type of node + : (element / attribute); location step (parenthesized attribute in child step / in descendant step). + : + : @author Ron Van den Branden + :) +module namespace pctx="http://exist-db.org/xquery/lucene/parenthesized-context/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : Collection config: qname, @att.qname, path, @att.path Lucene + range. + :) +declare variable $pctx:XCONF as element(collection) := + + + + + + + + + + + + + + + + ; + +(:~ + : Test document. + :) +declare variable $pctx:XML as document-node() := + document { + + this is a test document + this is a test document + + }; + +declare variable $pctx:COLLECTION_NAME := "parenthesized-context"; +declare variable $pctx:COLLECTION := "/db/" || $pctx:COLLECTION_NAME; + +(:~ + : Expected qname element. + :) +declare variable $pctx:EXPECTED_QNAME as element(qname) := this is a test document; +(:~ + : Expected path element. + :) +declare variable $pctx:EXPECTED_PATH as element(path) := this is a test document; +(:~ + : Expected index-keys terms (element node). + :) +declare variable $pctx:EXPECTED_TERMS_ELEMENT as element(term)+ := (document, test); +(:~ + : Expected index-keys term (attribute). + :) +declare variable $pctx:EXPECTED_TERM_ATTR as element(term) := test; + +(:~ + : Callback for util:index-keys. + : @param $term term + : @param $data (freq, docs, n) + :) +declare + %private +function pctx:term-callback($term as xs:string, $data as xs:int+) as element(term) { + { $term } +}; + +(:~ + : setUp: create collection, config, store doc, reindex. + :) +declare + %test:setUp +function pctx:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $pctx:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $pctx:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $pctx:COLLECTION_NAME, "collection.xconf", $pctx:XCONF), + xmldb:store($pctx:COLLECTION, "test.xml", $pctx:XML), + xmldb:reindex($pctx:COLLECTION) ) +}; + +(:~ + : tearDown: remove data and config collections. + :) +declare + %test:tearDown +function pctx:tearDown() { + xmldb:remove($pctx:COLLECTION), + xmldb:remove("/db/system/config/db/" || $pctx:COLLECTION_NAME) +}; + +(:~ + : [query] fully parenthesized element node. + :) +declare + %test:assertTrue +function pctx:query-qname-direct-fully-paren() { + deep-equal((collection($pctx:COLLECTION)//test/qname)[ft:query(., 'test')], $pctx:EXPECTED_QNAME) +}; +declare + %test:assertTrue +function pctx:query-qname-indirect-fully-paren() { + let $a := (collection($pctx:COLLECTION)//test/qname) return deep-equal($a[ft:query(., 'test')], $pctx:EXPECTED_QNAME) +}; +declare + %test:assertTrue +function pctx:query-path-direct-fully-paren() { + deep-equal((collection($pctx:COLLECTION)//test/path)[ft:query(., 'test')], $pctx:EXPECTED_PATH) +}; +declare + %test:assertTrue +function pctx:query-path-indirect-fully-paren() { + let $a := (collection($pctx:COLLECTION)//test/path) return deep-equal($a[ft:query(., 'test')], $pctx:EXPECTED_PATH) +}; + +(:~ + : [query] fully parenthesized element node + self axis. + :) +declare + %test:assertTrue +function pctx:query-qname-direct-self() { + deep-equal((collection($pctx:COLLECTION)//test/qname/self::*)[ft:query(., 'test')], $pctx:EXPECTED_QNAME) +}; +declare + %test:assertTrue +function pctx:query-qname-indirect-self() { + let $a := (collection($pctx:COLLECTION)//test/qname/self::*) return deep-equal($a[ft:query(., 'test')], $pctx:EXPECTED_QNAME) +}; +declare + %test:assertTrue +function pctx:query-path-direct-self() { + deep-equal((collection($pctx:COLLECTION)//test/path/self::*)[ft:query(., 'test')], $pctx:EXPECTED_PATH) +}; +declare + %test:assertTrue +function pctx:query-path-indirect-self() { + let $a := (collection($pctx:COLLECTION)//test/path/self::*) return deep-equal($a[ft:query(., 'test')], $pctx:EXPECTED_PATH) +}; + +(:~ + : [query] child/descendant step with fully parenthesized attribute node. + :) +declare + %test:assertEquals("test") +function pctx:query-qname-direct-child-attr() { + (collection($pctx:COLLECTION)//test/qname/@att.qname)[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-qname-indirect-child-attr() { + let $a := (collection($pctx:COLLECTION)//test/qname/@att.qname) return $a[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-qname-direct-desc-attr() { + (collection($pctx:COLLECTION)//test/qname//@att.qname)[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-qname-indirect-desc-attr() { + let $a := (collection($pctx:COLLECTION)//test/qname//@att.qname) return $a[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-path-direct-child-attr() { + (collection($pctx:COLLECTION)//test/path/@att.path)[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-path-indirect-child-attr() { + let $a := (collection($pctx:COLLECTION)//test/path/@att.path) return $a[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-path-direct-desc-attr() { + (collection($pctx:COLLECTION)//test/path//@att.path)[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-path-indirect-desc-attr() { + let $a := (collection($pctx:COLLECTION)//test/path//@att.path) return $a[ft:query(., 'test')]/string() +}; + +(:~ + : [index] fully parenthesized element node. + :) +declare + %test:assertTrue +function pctx:index-qname-fully-paren() { + let $a := (collection($pctx:COLLECTION)//test/qname) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERMS_ELEMENT) +}; +declare + %test:assertTrue +function pctx:index-path-fully-paren() { + let $a := (collection($pctx:COLLECTION)//test/path) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERMS_ELEMENT) +}; +declare + %test:assertTrue +function pctx:index-qname-fully-paren-self() { + let $a := (collection($pctx:COLLECTION)//test/qname/self::*) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERMS_ELEMENT) +}; +declare + %test:assertTrue +function pctx:index-path-fully-paren-self() { + let $a := (collection($pctx:COLLECTION)//test/path/self::*) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERMS_ELEMENT) +}; +declare + %test:assertTrue +function pctx:index-qname-child-fully-paren-attr() { + let $a := (collection($pctx:COLLECTION)//test/qname/@att.qname) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERM_ATTR) +}; +declare + %test:assertTrue +function pctx:index-qname-desc-fully-paren-attr() { + let $a := (collection($pctx:COLLECTION)//test/qname//@att.qname) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERM_ATTR) +}; +declare + %test:assertTrue +function pctx:index-path-child-fully-paren-attr() { + let $a := (collection($pctx:COLLECTION)//test/path/@att.path) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERM_ATTR) +}; +declare + %test:assertTrue +function pctx:index-path-desc-fully-paren-attr() { + let $a := (collection($pctx:COLLECTION)//test/path//@att.path) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERM_ATTR) +}; + +(:~ + : [query] parenthesized element node. + :) +declare + %test:assertTrue +function pctx:query-qname-direct-paren() { + deep-equal(collection($pctx:COLLECTION)//test/(qname)[ft:query(., 'test')], $pctx:EXPECTED_QNAME) +}; +declare + %test:assertTrue +function pctx:query-qname-indirect-paren() { + let $a := collection($pctx:COLLECTION)//test/(qname) return deep-equal($a[ft:query(., 'test')], $pctx:EXPECTED_QNAME) +}; +declare + %test:assertTrue +function pctx:query-path-direct-paren() { + deep-equal(collection($pctx:COLLECTION)//test/(path)[ft:query(., 'test')], $pctx:EXPECTED_PATH) +}; +declare + %test:assertTrue +function pctx:query-path-indirect-paren() { + let $a := collection($pctx:COLLECTION)//test/(path) return deep-equal($a[ft:query(., 'test')], $pctx:EXPECTED_PATH) +}; + +(:~ + : [query] parenthesized element node + self axis. + :) +declare + %test:assertTrue +function pctx:query-qname-direct-paren-self() { + deep-equal(collection($pctx:COLLECTION)//test/(qname)/self::*[ft:query(., 'test')], $pctx:EXPECTED_QNAME) +}; +declare + %test:assertTrue +function pctx:query-qname-indirect-paren-self() { + let $a := collection($pctx:COLLECTION)//test/(qname)/self::* return deep-equal($a[ft:query(., 'test')], $pctx:EXPECTED_QNAME) +}; +declare + %test:assertTrue +function pctx:query-path-direct-paren-self() { + deep-equal(collection($pctx:COLLECTION)//test/(path)/self::*[ft:query(., 'test')], $pctx:EXPECTED_PATH) +}; +declare + %test:assertTrue +function pctx:query-path-indirect-paren-self() { + let $a := collection($pctx:COLLECTION)//test/(path)/self::* return deep-equal($a[ft:query(., 'test')], $pctx:EXPECTED_PATH) +}; + +(:~ + : [query] child/descendant step with parenthesized attribute node. + :) +declare + %test:assertEquals("test") +function pctx:query-qname-direct-child-paren-attr() { + collection($pctx:COLLECTION)//test/qname/(@att.qname)[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-qname-indirect-child-paren-attr() { + let $a := collection($pctx:COLLECTION)//test/qname/(@att.qname) return $a[ft:query(., 'test')]/string() +}; +declare + %test:pending("previously ignored") + %test:assertEquals("test") +function pctx:query-qname-direct-desc-paren-attr() { + collection($pctx:COLLECTION)//test/qname//(@att.qname)[ft:query(., 'test')]/string() +}; +declare + %test:pending("previously ignored") + %test:assertEquals("test") +function pctx:query-qname-indirect-desc-paren-attr() { + let $a := collection($pctx:COLLECTION)//test/qname//(@att.qname) return $a[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-path-direct-child-paren-attr() { + collection($pctx:COLLECTION)//test/path/(@att.path)[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-path-indirect-child-paren-attr() { + let $a := collection($pctx:COLLECTION)//test/path/(@att.path) return $a[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-path-direct-desc-paren-attr() { + collection($pctx:COLLECTION)//test/path/(@att.path)[ft:query(., 'test')]/string() +}; +declare + %test:assertEquals("test") +function pctx:query-path-indirect-desc-paren-attr() { + let $a := collection($pctx:COLLECTION)//test/path/(@att.path) return $a[ft:query(., 'test')]/string() +}; + +(:~ + : [index] parenthesized element node. + :) +declare + %test:assertTrue +function pctx:index-qname-paren() { + let $a := collection($pctx:COLLECTION)//test/(qname) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERMS_ELEMENT) +}; +declare + %test:assertTrue +function pctx:index-path-paren() { + let $a := collection($pctx:COLLECTION)//test/(path) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERMS_ELEMENT) +}; +declare + %test:assertTrue +function pctx:index-qname-paren-self() { + let $a := collection($pctx:COLLECTION)//test/(qname)/self::* return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERMS_ELEMENT) +}; +declare + %test:assertTrue +function pctx:index-path-paren-self() { + let $a := collection($pctx:COLLECTION)//test/(path)/self::* return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERMS_ELEMENT) +}; +declare + %test:assertTrue +function pctx:index-qname-child-paren-attr() { + let $a := collection($pctx:COLLECTION)//test/qname/(@att.qname) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERM_ATTR) +}; +declare + %test:pending("previously ignored") + %test:assertTrue +function pctx:index-qname-desc-paren-attr() { + let $a := collection($pctx:COLLECTION)//test/qname//(@att.qname) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERM_ATTR) +}; +declare + %test:assertTrue +function pctx:index-path-child-paren-attr() { + let $a := collection($pctx:COLLECTION)//test/path/(@att.path) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERM_ATTR) +}; +declare + %test:pending("previously ignored") + %test:assertTrue +function pctx:index-path-desc-paren-attr() { + let $a := collection($pctx:COLLECTION)//test/path//(@att.path) return deep-equal(util:index-keys($a,'', util:function(xs:QName('pctx:term-callback'), 2), 100, 'lucene-index'), $pctx:EXPECTED_TERM_ATTR) +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/parenthesized-location-step.xql b/extensions/indexes/lucene/src/test/xquery/lucene/parenthesized-location-step.xql new file mode 100644 index 00000000000..20c62b96d1b --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/parenthesized-location-step.xql @@ -0,0 +1,245 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for behaviour of ft:query() on context nodes in a parenthesized location step. + : Refactored from parenthesizedLocationStep_ftquery_Tests.xml (TestSet). + : + : Three sections: [element] ft:query on parenthesized context selecting an element; [attribute] + : ft:query on parenthesized context selecting an attribute; [attribute retrieval] retrieval of + : parenthesized context selecting an attribute. + : + : The degree of the problems depends on the context node type: elements — queries fail when the + : parenthesized context node is not immediately preceded by a non-parenthesized location step + : (unless the preceding step is self::*); attributes — queries always fail with parenthesized + : context nodes, with the problem appearing at retrieval level. Note: parenthesized context + : selecting a non-existent attribute whose name matches an element name can cause erroneous + : bleed-through results; non-parenthesized context does not. + : + : @author Ron Van den Branden + :) +module namespace plst="http://exist-db.org/xquery/lucene/parenthesized-location-step/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : Collection config: @att1, @att2, el1, el2. + :) +declare variable $plst:XCONF as element(collection) := + + + + + + + + + + ; + +(:~ + : Test document: two level1/level2 with p, el1, el2. + :) +declare variable $plst:XML as document-node() := + document { + + + +

this is text with test strings in test elements

+
+
+ + +

this is text with test strings in test elements

+
+
+
+ }; + +declare variable $plst:COLLECTION_NAME := "parenthesized-location-step"; +declare variable $plst:COLLECTION := "/db/" || $plst:COLLECTION_NAME; + +(:~ + : Expected: two el1 elements. + :) +declare variable $plst:EXPECTED_EL1 as element(el1)+ := ( + test, + test +); + +(:~ + : Expected: two result elements with att1. + :) +declare variable $plst:EXPECTED_ATTR_RESULT as element(result)+ := ( + , + +); + +(:~ + : setUp: create collection, config, store doc, reindex. + :) +declare + %test:setUp +function plst:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $plst:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $plst:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $plst:COLLECTION_NAME, "collection.xconf", $plst:XCONF), + xmldb:store($plst:COLLECTION, "test.xml", $plst:XML), + xmldb:reindex($plst:COLLECTION) ) +}; + +(:~ + : tearDown: remove data and config collections. + :) +declare + %test:tearDown +function plst:tearDown() { + xmldb:remove($plst:COLLECTION), + xmldb:remove("/db/system/config/db/" || $plst:COLLECTION_NAME) +}; + +(:~ + : [element] parenthesized final location step, non-parenthesized preceding step. + :) +declare + %test:assertTrue +function plst:element-parenthesized-preceding-non-paren() { + let $result := collection($plst:COLLECTION)//level1//(el1)[ft:query(., 'test')] + return deep-equal($result, $plst:EXPECTED_EL1) +}; + +(:~ + : [element] parenthesized final location step, no preceding step. + :) +declare + %test:assertTrue +function plst:element-parenthesized-no-preceding() { + let $result := collection($plst:COLLECTION)//(el1)[ft:query(., 'test')] + return deep-equal($result, $plst:EXPECTED_EL1) +}; + +(:~ + : [element] parenthesized final location step, parenthesized preceding step. + :) +declare + %test:assertTrue +function plst:element-parenthesized-preceding-paren() { + let $result := collection($plst:COLLECTION)//(level1)//(el1)[ft:query(., 'test')] + return deep-equal($result, $plst:EXPECTED_EL1) +}; + +(:~ + : [element] parenthesized final location step, non-parenthesized preceding step with self selector. + :) +declare + %test:assertTrue +function plst:element-parenthesized-preceding-self() { + let $result := collection($plst:COLLECTION)//level1//.//(el1)[ft:query(., 'test')] + return deep-equal($result, $plst:EXPECTED_EL1) +}; + +(:~ + : [attribute] parenthesized final location step, non-parenthesized preceding step. + :) +declare + %test:pending("previously ignored; parenthesized attribute context") + %test:assertTrue +function plst:attribute-parenthesized-preceding-non-paren() { + let $result := for $a in collection($plst:COLLECTION)//level1//(@att1)[ft:query(., 'test')] return { $a } + return deep-equal($result, $plst:EXPECTED_ATTR_RESULT) +}; + +(:~ + : [attribute] parenthesized final location step, no preceding step. + :) +declare + %test:pending("previously ignored; parenthesized attribute context") + %test:assertTrue +function plst:attribute-parenthesized-no-preceding() { + let $result := for $a in collection($plst:COLLECTION)//(@att1)[ft:query(., 'test')] return { $a } + return deep-equal($result, $plst:EXPECTED_ATTR_RESULT) +}; + +(:~ + : [attribute] parenthesized final location step, parenthesized preceding step. + :) +declare + %test:pending("previously ignored; parenthesized attribute context") + %test:assertTrue +function plst:attribute-parenthesized-preceding-paren() { + let $result := for $a in collection($plst:COLLECTION)//(level1)//(@att1)[ft:query(., 'test')] return { $a } + return deep-equal($result, $plst:EXPECTED_ATTR_RESULT) +}; + +(:~ + : [attribute] parenthesized final location step, non-parenthesized preceding step with self selector. + :) +declare + %test:pending("previously ignored; parenthesized attribute context") + %test:assertTrue +function plst:attribute-parenthesized-preceding-self() { + let $result := for $a in collection($plst:COLLECTION)//level1//.//(@att1)[ft:query(., 'test')] return { $a } + return deep-equal($result, $plst:EXPECTED_ATTR_RESULT) +}; + +(:~ + : [attribute retrieval] parenthesized final location step. + :) +declare + %test:pending("previously ignored; attribute retrieval parenthesized") + %test:assertTrue +function plst:attribute-retrieval-parenthesized() { + let $result := for $a in collection($plst:COLLECTION)//level1//(@att1) return { $a } + return deep-equal($result, $plst:EXPECTED_ATTR_RESULT) +}; + +(:~ + : [attribute retrieval] non-parenthesized final location step. + :) +declare + %test:assertTrue +function plst:attribute-retrieval-non-parenthesized() { + let $result := for $a in collection($plst:COLLECTION)//level1//@att1 return { $a } + return deep-equal($result, $plst:EXPECTED_ATTR_RESULT) +}; + +(:~ + : [attribute retrieval] parenthesized attribute context causes bleed-through when name equals element name. + :) +declare + %test:pending("previously ignored; bleed-through behaviour") + %test:assertEmpty +function plst:attribute-retrieval-parenthesized-bleed-through() { + for $a in collection($plst:COLLECTION)//level1//(@el1) return { $a } +}; + +(:~ + : [attribute retrieval] non-parenthesized attribute context behaves correctly. + :) +declare + %test:assertEmpty +function plst:attribute-retrieval-non-paren-correct() { + for $a in collection($plst:COLLECTION)//level1//@el1 return { $a } +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/parenthesizedContext_ftquery_Tests.xml b/extensions/indexes/lucene/src/test/xquery/lucene/parenthesizedContext_ftquery_Tests.xml deleted file mode 100644 index e8b375db572..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/parenthesizedContext_ftquery_Tests.xml +++ /dev/null @@ -1,528 +0,0 @@ - - - tests for queries on entirely parenthesized contexts - -

Tests for behaviour of retrieval, query and index functions on different index types, on entirely parenthesised contexts. - Three major sections: -

    -
  • [retrieval]: bare retrieval of parenthesized nodes (tests #1-#6)
  • -
  • [query]: queries on different index types (tests #7-#54)
  • -
  • [index]: lookup of index terms on different index types (tests #55-#78)
  • -

-

The degree of the problems depends on the type of index and search context. Influencing factors are: -

    -
  • index definition: qname / path-based
  • -
  • type of query: expressed directly (XPath expression) / indirectly (FLWR expression)
  • -
  • context node: parenthesized context node / parenthesized location step + self axis location step
  • -
  • type of node: element / attribute
  • -
  • location step: parenthesized attribute node in child step / parenthesized attribute node in descendant step (attributes only)
  • -
-

- Ron Van den Branden -
- - - - - - - - - - - - - - - - - - - - - - - - - - this is a test document - this is a test document - - - - {$term} - }; - ]]> - - - - - - [query, Lucene FT index, qname, direct] fully parenthesized element node - - - this is a test document - - - - [query, Lucene FT index, qname, indirect] fully parenthesized element node - - - this is a test document - - - - [query, Lucene FT index, path, direct] fully parenthesized element node - - - this is a test document - - - - [query, Lucene FT index, path, indirect] fully parenthesized element node - - - this is a test document - - - - [query, Lucene FT index, qname, direct] fully parenthesized element node + self axis - - - this is a test document - - - - [query, Lucene FT index, qname, indirect] fully parenthesized element node + self axis - - - this is a test document - - - - [query, Lucene FT index, path, direct] fully parenthesized element node + self axis - - - this is a test document - - - - [query, Lucene FT index, path, indirect] fully parenthesized element node + self axis - - - this is a test document - - - - [query, Lucene FT index, qname, direct] child step with fully parenthesized attribute node - - test - - - [query, Lucene FT index, qname, indirect] child step with fully parenthesized attribute node - - test - - - [query, Lucene FT index, qname, direct] descendant step with fully parenthesized attribute node - - test - - - [query, Lucene FT index, qname, indirect] descendant step with fully parenthesized attribute node - - test - - - [query, Lucene FT index, path, direct] child step with fully parenthesized attribute node - - test - - - [query, Lucene FT index, path, indirect] child step with fully parenthesized attribute node - - test - - - [query, Lucene FT index, path, direct] descendant step with fully parenthesized attribute node - - test - - - [query, Lucene FT index, path, indirect] descendant step with fully parenthesized attribute node - - test - - - - - [index, Lucene FT index, qname] fully parenthesized element node - - - document - test - - - - [index, Lucene FT index, path] fully parenthesized element node - - - document - test - - - - [index, Lucene FT index, qname] fully parenthesized element node + self axis - - - document - test - - - - [index, Lucene FT index, path] fully parenthesized element node + self axis - - - document - test - - - - [index, Lucene FT index, qname] child step with fully parenthesized attribute node - - - test - - - - [index, Lucene FT index, qname] descendant step with fully parenthesized attribute node - - - test - - - - [index, Lucene FT index, path] child step with fully parenthesized attribute node - - - test - - - - [index, Lucene FT index, path] descendant step with fully parenthesized attribute node - - - test - - - - - [query, Lucene FT index, qname, direct] parenthesized element node - - - this is a test document - - - - [query, Lucene FT index, qname, indirect] parenthesized element node - - - this is a test document - - - - [query, Lucene FT index, path, direct] parenthesized element node - - - this is a test document - - - - [query, Lucene FT index, path, indirect] parenthesized element node - - - this is a test document - - - - [query, Lucene FT index, qname, direct] parenthesized element node + self axis - - - this is a test document - - - - [query, Lucene FT index, qname, indirect] parenthesized element node + self axis - - - this is a test document - - - - [query, Lucene FT index, path, direct] parenthesized element node + self axis - - - this is a test document - - - - [query, Lucene FT index, path, indirect] parenthesized element node + self axis - - - this is a test document - - - - [query, Lucene FT index, qname, direct] child step with parenthesized attribute node - - test - - - [query, Lucene FT index, qname, indirect] child step with parenthesized attribute node - - test - - - [query, Lucene FT index, qname, direct] descendant step with parenthesized attribute node - - test - - - [query, Lucene FT index, qname, indirect] descendant step with parenthesized attribute node - - test - - - [query, Lucene FT index, path, direct] child step with parenthesized attribute node - - test - - - [query, Lucene FT index, path, indirect] child step with parenthesized attribute node - - test - - - [query, Lucene FT index, path, direct] descendant step with parenthesized attribute node - - test - - - [query, Lucene FT index, path, indirect] descendant step with parenthesized attribute node - - test - - - - [index, Lucene FT index, qname] parenthesized element node - - - document - test - - - - [index, Lucene FT index, path] parenthesized element node - - - document - test - - - - [index, Lucene FT index, qname] parenthesized element node + self axis - - - document - test - - - - [index, Lucene FT index, path] parenthesized element node + self axis - - - document - test - - - - [index, Lucene FT index, qname] child step with parenthesized attribute node - - - test - - - - [index, Lucene FT index, qname] descendant step with parenthesized attribute node - - - test - - - - [index, Lucene FT index, path] child step with parenthesized attribute node - - - test - - - - [index, Lucene FT index, path] descendant step with parenthesized attribute node - - - test - - -
diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/parenthesizedLocationStep_ftquery_Tests.xml b/extensions/indexes/lucene/src/test/xquery/lucene/parenthesizedLocationStep_ftquery_Tests.xml deleted file mode 100644 index 1b87d08c8cc..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/parenthesizedLocationStep_ftquery_Tests.xml +++ /dev/null @@ -1,202 +0,0 @@ - - - tests for queries on context nodes in a parenthesized location step - -

Tests for behaviour of ft:query() function on context nodes in a parenthesized location step. - Two major sections: -

    -
  • [element]: ft:query() on parenthesized context node selecting an element (tests #1-#4)
  • -
  • [attribute]: ft:query() on parenthesized context node selecting an attribute (tests #5-#8)
  • -
  • [attribute retrieval]: retrieval of parenthesized context node selecting an attribute (tests #9-#12)
  • -

-

The degree of the problems depends on the context node type: -

    -
  • elements: queries fail when parenthesized context node is not immediately preceded by a non-parenthesized location step (unless immediately preceding location step selects self::* axis)
  • -
  • attributes: queries always fail with parenthesized context nodes, though the problem seems to lie at retrieval level (see tests #9-#12)
  • -
-

-

Note: additional tests #-11-#12 illustrate some kind of erroneous 'bleed-through' behaviour: when a parenthesized context node selects a non-existent attribute whose name corresponds to an element name, ft:query will produce (incorrect) results (failing test #9). This behaviour does not occur when context node is not parenthesized (succeeding test #10).

- Ron Van den Branden -
- - - - - - - - - - - - - - - - - - - - - -

this is text with test strings in test elements

-
-
- - -

this is text with test strings in test elements

-
-
-
-
-
- - - - - - - [element] parenthesized final location step, non-parenthesized preceding step - - - test - test - - - - [element] parenthesized final location step, no preceding step - - - test - test - - - - [element] parenthesized final location step, parenthesized preceding step - - - test - test - - - - [element] parenthesized final location step, non-parenthesized preceding step with self selector - - - test - test - - - - [attribute] parenthesized final location step, non-parenthesized preceding step - {$a}
- ]]> - - - - - - - [attribute] parenthesized final location step, no preceding step - {$a}
- ]]> - - - - - - - [attribute] parenthesized final location step, parenthesized preceding step - {$a} - ]]> - - - - - - - [attribute] parenthesized final location step, non-parenthesized preceding step with self selector - {$a} - ]]> - - - - - - - [attribute retrieval] parenthesized final location step - {$a} - ]]> - - - - - - - [attribute retrieval] non-parenthesized final location step - {$a} - ]]> - - - - - - - [attribute retrieval] parenthesized attribute context node causes 'bleed-through' when name equals element name - {$a} - ]]> - - - - [attribute retrieval] non-parenthesized attribute context behaves correctly - {$a} - ]]> - - - \ No newline at end of file diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/plain-ft-functions.xml b/extensions/indexes/lucene/src/test/xquery/lucene/plain-ft-functions.xml deleted file mode 100644 index 94d3d9a9fbd..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/plain-ft-functions.xml +++ /dev/null @@ -1,179 +0,0 @@ - - - - nonXML data query tests - -

nonXML tests

- Dannes Wessels -
- - - - - - - - - - - AAAAAA - BBBBBB - CCCCCC - DDDDDD - - - - - - - Create Index for stored documents - - text - some text - ), - ft:index( "/db/binary/data2.txt", - - more text - even more text - ), - ft:index( "/db/binary/data3.txt", - - foobar title - even more foobar - ), - ft:index( "/db/binary/data4.txt", - - another foobar title - foobaar even more foobar - ) - ]]> - - - - - - - Test Index 1 - search title - - /db/binary/data1.txt /db/binary/data2.txt - - - - Test Index 1a - search on different level - - /db/binary/data1.txt /db/binary/data2.txt - - - - Test Index 2 - search title - - /db/binary/data3.txt /db/binary/data4.txt - - - - Test Index 2a - search title - - /db/binary/data3.txt - - - - Test Index 2b - search title - - /db/binary/data3.txt /db/binary/data4.txt - - - - Test Index 3 - search paragraph - - /db/binary/data4.txt - - - - Test Index 3a - search paragraph - - - - - - Test Index 3b - one existing one non existing collection - - /db/binary/data4.txt - - - - Test Index 3c - two times the same collection - - /db/binary/data4.txt - - - - Test Index 4 - expect one result - - /db/binary/data4.txt - - - Test Index 5 - retrieving values - - another foobar title - - - Test Index 6 - get-field - - another foobar title - - - Test Index 7 - search term range (resulted in UnsupportedOperationException) - - 3 - -
diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/plain-ft-functions.xql b/extensions/indexes/lucene/src/test/xquery/lucene/plain-ft-functions.xql new file mode 100644 index 00000000000..3a3e801cc9e --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/plain-ft-functions.xql @@ -0,0 +1,199 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for non-XML data query (ft:index, ft:search on binary). + : Refactored from plain-ft-functions.xml (TestSet). nonXML data query tests. + : + : @author Dannes Wessels + :) +module namespace pftf="http://exist-db.org/xquery/lucene/plain-ft-functions/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; +declare namespace exist="http://exist.sourceforge.net/NS/exist"; + +(:~ + : Empty collection config for /db. + :) +declare variable $pftf:XCONF as element(collection) := + + + ; + +declare variable $pftf:COLLECTION_BINARY := "/db/binary"; + +(:~ + : setUp: create /db/system/config/db, store collection.xconf, create /db/binary, store 4 text files. + :) +declare + %test:setUp +function pftf:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:store("/db/system/config/db", "collection.xconf", $pftf:XCONF), + xmldb:create-collection("/db", "binary"), + xmldb:store($pftf:COLLECTION_BINARY, "data1.txt", "AAAAAA", "text/plain"), + xmldb:store($pftf:COLLECTION_BINARY, "data2.txt", "BBBBBB", "text/plain"), + xmldb:store($pftf:COLLECTION_BINARY, "data3.txt", "CCCCCC", "text/plain"), + xmldb:store($pftf:COLLECTION_BINARY, "data4.txt", "DDDDDD", "text/plain") ) +}; + +(:~ + : tearDown: remove /db/binary, remove config document. + :) +declare + %test:tearDown +function pftf:tearDown() { + xmldb:remove($pftf:COLLECTION_BINARY), + xmldb:remove("/db/system/config/db") +}; + +(:~ + : Create Index for stored documents. + :) +declare + %test:assertEmpty +function pftf:create-index() { + ( ft:index($pftf:COLLECTION_BINARY || "/data1.txt", textsome text), + ft:index($pftf:COLLECTION_BINARY || "/data2.txt", more texteven more text), + ft:index($pftf:COLLECTION_BINARY || "/data3.txt", foobar titleeven more foobar), + ft:index($pftf:COLLECTION_BINARY || "/data4.txt", another foobar titlefoobaar even more foobar) ) +}; + +(:~ + : Test Index 1 - search title. + :) +declare + %test:assertEquals("/db/binary/data1.txt /db/binary/data2.txt") +function pftf:search-title-text() { + string-join(data(ft:search($pftf:COLLECTION_BINARY || "/", "title:text")//@uri), ' ') +}; + +(:~ + : Test Index 1a - search on different level. + :) +declare + %test:assertEquals("/db/binary/data1.txt /db/binary/data2.txt") +function pftf:search-title-text-db() { + string-join(data(ft:search("/db/", "title:text")//@uri), ' ') +}; + +(:~ + : Test Index 2 - search title foobar. + :) +declare + %test:assertEquals("/db/binary/data3.txt /db/binary/data4.txt") +function pftf:search-title-foobar() { + string-join(data(ft:search($pftf:COLLECTION_BINARY || "/", "title:foobar")//@uri), ' ') +}; + +(:~ + : Test Index 2a - search title foobar on single doc. + :) +declare + %test:assertEquals("/db/binary/data3.txt") +function pftf:search-title-foobar-single() { + string-join(data(ft:search($pftf:COLLECTION_BINARY || "/data3.txt", "title:foobar")//@uri), ' ') +}; + +(:~ + : Test Index 2b - search title foobar on two paths. + :) +declare + %test:assertEquals("/db/binary/data3.txt /db/binary/data4.txt") +function pftf:search-title-foobar-two-paths() { + string-join(data(ft:search(($pftf:COLLECTION_BINARY || "/data3.txt", $pftf:COLLECTION_BINARY || "/data4.txt"), "title:foobar")//@uri), ' ') +}; + +(:~ + : Test Index 3 - search paragraph foobaar. + :) +declare + %test:assertEquals("/db/binary/data4.txt") +function pftf:search-para-foobaar() { + string-join(data(ft:search($pftf:COLLECTION_BINARY || "/", "para:foobaar")//@uri), ' ') +}; + +(:~ + : Test Index 3a - search on non-existing collection. + :) +declare + %test:assertEquals("") +function pftf:search-para-non-existing-collection() { + string-join(data(ft:search("/db/binarya/", "para:foobaar")//@uri), ' ') +}; + +(:~ + : Test Index 3b - one existing one non-existing collection. + :) +declare + %test:assertEquals("/db/binary/data4.txt") +function pftf:search-para-mixed-collections() { + string-join(data(ft:search(("/db/binarya/", $pftf:COLLECTION_BINARY || "/"), "para:foobaar")//@uri), ' ') +}; + +(:~ + : Test Index 3c - two times the same collection. + :) +declare + %test:assertEquals("/db/binary/data4.txt") +function pftf:search-para-same-collection-twice() { + string-join(data(ft:search(($pftf:COLLECTION_BINARY || "/", $pftf:COLLECTION_BINARY || "/"), "para:foobaar")//@uri), ' ') +}; + +(:~ + : Test Index 4 - expect one result. + :) +declare + %test:assertEquals("/db/binary/data4.txt") +function pftf:search-para-collection-and-doc() { + string-join(data(ft:search(($pftf:COLLECTION_BINARY || "/", $pftf:COLLECTION_BINARY || "/data4.txt"), "para:foobaar")//@uri), ' ') +}; + +(:~ + : Test Index 5 - retrieving values (field with exist:match). + :) +declare + %test:assertTrue +function pftf:search-retrieve-values() { + let $result := ft:search($pftf:COLLECTION_BINARY || "/", 'title:"another foobar"', "title")//field + return deep-equal($result, another foobar title) +}; + +(:~ + : Test Index 6 - get-field. + :) +declare + %test:assertEquals("another foobar title") +function pftf:get-field() { + ft:get-field($pftf:COLLECTION_BINARY || "/data4.txt", "title") +}; + +(:~ + : Test Index 7 - search term range. + :) +declare + %test:assertEquals(3) +function pftf:search-term-range() { + count(ft:search($pftf:COLLECTION_BINARY || "/", "para:[even TO foobaar]")//@uri) +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/plain-store.xml b/extensions/indexes/lucene/src/test/xquery/lucene/plain-store.xml deleted file mode 100644 index 92870b0c184..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/plain-store.xml +++ /dev/null @@ -1,215 +0,0 @@ - - - - nonXML data indexing tests - - -

nonXML tests

- Dannes Wessels -
- - - - AAAAAA - BBBBBB - CCCCCC - - - - - - - - - - - - - - - - - - - - - - - - - - Store index document 1 - - Dannes Wessels - Some text for a paragraph - ) - ]]> - - - - - Store index document 2 - - Adam Retter - Some text for a paragraph Some text for a paragraph Some text for a paragraph. - ) - ]]> - - - - - Store index document 3 - - Harry Potter - Some blah for a paragraph Some blah for a paragraph Some blah for a paragraph paragraph paragraph. - ) - ]]> - - - - - - Query for text in para - - /db/morebinary/index1.txt /db/morebinary/index2.txt - - - - Query for text in non-stored field - - //search[@uri = "/db/morebinary/index3.txt"] - - - - Query for text in stored field: only some entries are stored - - //search/field - - - - - - Validate scores - $score[2] , $score[2]>$score[3] , $score[1] > $score[3] ) - ]]> - true true true - - - - Get content of stored field - - - Some blah for a paragraph Some blah for a paragraph Some blah for a paragraph paragraph paragraph. - - - - - Add additional index to XML document - - {$scene/TITLE/text()} - { - for $speech in $scene//SPEECH - return ( - {string-join($speech/*/text(), ' ')} - ) - } - -}; - -let $path := "/db/morebinary/shakespeare/macbeth.xml" -let $doc := doc($path) -let $index := - for $scene in $doc//SCENE return ft:index($path, local:index-data($scene)) -return - count(ft:search($path, 'speech:"boil and bake"')//search) - ]]> - 1 - - - - Query on parent collection should include subcollections - - 1 - - - - Remove single document - - 0 - - - - Remove collection - - - -
\ No newline at end of file diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/plain-store.xql b/extensions/indexes/lucene/src/test/xquery/lucene/plain-store.xql new file mode 100644 index 00000000000..26a3c4db522 --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/plain-store.xql @@ -0,0 +1,218 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for non-XML data indexing (ft:index on binary + XML). + : Refactored from plain-store.xml (TestSet). nonXML data indexing tests. + : Uses self-contained sample documents; no classpath resources. + : + : @author Dannes Wessels + :) +module namespace pstor="http://exist-db.org/xquery/lucene/plain-store/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; +declare namespace exist="http://exist.sourceforge.net/NS/exist"; + +(:~ + : Self-contained sample play (SCENE/SPEECH) for ft:index tests. Contains "boil and bake" + : so speech phrase and term searches match. Used as hamlet.xml, macbeth.xml, r_and_j.xml. + :) +declare variable $pstor:SAMPLE_PLAY as document-node() := + document { + + + Scene 1 + boil and bake in the cauldron + + + }; + +(:~ + : setUp: create morebinary, morebinary2, morebinary3; store text files and sample XML. + : No ft:index here — Store index 1/2/3 build the index; query tests run after and depend on it. + :) +declare + %test:setUp +function pstor:setUp() { + ( xmldb:create-collection("/db", "morebinary"), + xmldb:store("/db/morebinary", "index1.txt", "AAAAAA", "text/plain"), + xmldb:store("/db/morebinary", "index2.txt", "BBBBBB", "text/plain"), + xmldb:store("/db/morebinary", "index3.txt", "CCCCCC", "text/plain"), + xmldb:create-collection("/db/morebinary", "shakespeare"), + xmldb:store("/db/morebinary/shakespeare", "hamlet.xml", $pstor:SAMPLE_PLAY), + xmldb:store("/db/morebinary/shakespeare", "macbeth.xml", $pstor:SAMPLE_PLAY), + xmldb:store("/db/morebinary/shakespeare", "r_and_j.xml", $pstor:SAMPLE_PLAY), + xmldb:create-collection("/db", "morebinary2"), + xmldb:create-collection("/db/morebinary2", "shakespeare"), + xmldb:store("/db/morebinary2/shakespeare", "hamlet.xml", $pstor:SAMPLE_PLAY), + xmldb:store("/db/morebinary2/shakespeare", "macbeth.xml", $pstor:SAMPLE_PLAY), + xmldb:store("/db/morebinary2/shakespeare", "r_and_j.xml", $pstor:SAMPLE_PLAY), + xmldb:create-collection("/db", "morebinary3"), + xmldb:create-collection("/db/morebinary3", "shakespeare"), + xmldb:store("/db/morebinary3/shakespeare", "hamlet.xml", $pstor:SAMPLE_PLAY), + xmldb:store("/db/morebinary3/shakespeare", "macbeth.xml", $pstor:SAMPLE_PLAY), + xmldb:store("/db/morebinary3/shakespeare", "r_and_j.xml", $pstor:SAMPLE_PLAY) ) +}; + +(:~ + : tearDown: remove morebinary, morebinary2, morebinary3 (ignore missing for morebinary3). + :) +declare + %test:tearDown +function pstor:tearDown() { + ( xmldb:remove("/db/morebinary"), + xmldb:remove("/db/morebinary2"), + if (xmldb:collection-available("/db/morebinary3")) then xmldb:remove("/db/morebinary3") else () ) +}; + +(:~ + : Store index document 1. Builds the searchable index for index1.txt; later tests depend on it. + : Named a-* so it runs first. + :) +declare + %test:assertEmpty +function pstor:a-store-index-1() { + ft:index("/db/morebinary/index1.txt", Dannes WesselsSome text for a paragraph) +}; + +(:~ + : Store index document 2. Builds the index for index2.txt. + : Named b-* so it runs after a-store-index-1. + :) +declare + %test:assertEmpty +function pstor:b-store-index-2() { + ft:index("/db/morebinary/index2.txt", Adam RetterSome text for a paragraph Some text for a paragraph Some text for a paragraph.) +}; + +(:~ + : Store index document 3. Builds the index for index3.txt. + : Named c-* so it runs after b-store-index-2. + :) +declare + %test:assertEmpty +function pstor:c-store-index-3() { + ft:index("/db/morebinary/index3.txt", Harry PotterSome blah for a paragraph Some blah for a paragraph Some blah for a paragraph paragraph paragraph.) +}; + +(:~ + : Query for text in para. + :) +declare + %test:assertEquals("/db/morebinary/index1.txt /db/morebinary/index2.txt") +function pstor:query-para-text() { + string-join(for $uri in ft:search("/db/morebinary/", "para:text")//@uri order by $uri return string($uri), ' ') +}; + +(:~ + : Query for text in non-stored field. + :) +declare + %test:assertXPath("//search[@uri = '/db/morebinary/index3.txt']") +function pstor:query-non-stored-field() { + ft:search("/db/morebinary/", "author:potter") +}; + +(:~ + : Query for text in stored field. + :) +declare + %test:assertXPath("//search/field") +function pstor:query-stored-field() { + ft:search("/db/morebinary/", "author:dannes") +}; + +(:~ + : Validate scores. + :) +declare + %test:assertEquals("true true true") +function pstor:validate-scores() { + let $results := ft:search("/db/morebinary/", "para:paragraph"), + $score := for $s in $results//@score order by xs:double($s) descending return xs:double($s) + return string-join(($score[1] > $score[2], $score[2] > $score[3], $score[1] > $score[3]), ' ') +}; + +(:~ + : Get content of stored field. + :) +declare + %test:assertTrue +function pstor:get-content-stored-field() { + let $result := ft:search("/db/morebinary/", "para:blah")//field + return deep-equal($result, Some blah for a paragraph Some blah for a paragraph Some blah for a paragraph paragraph paragraph.) +}; + +(:~ + : Index-data helper for Macbeth SCENE. + :) +declare + %private +function pstor:index-data($scene as element(SCENE)) as element(doc) { + + { $scene/TITLE/text() } + { for $speech in $scene//SPEECH return { string-join($speech/*/text(), ' ') } } + +}; + +(:~ + : Add additional index to XML document. + :) +declare + %test:assertEquals(1) +function pstor:add-index-xml-document() { + let $path := "/db/morebinary/shakespeare/macbeth.xml", + $doc := doc($path), + $index := for $scene in $doc//SCENE return ft:index($path, pstor:index-data($scene)) + return count(ft:search($path, 'speech:"boil and bake"')//search) +}; + +(:~ + : Query on parent collection should include subcollections (previously ignored). + :) +declare + %test:pending("previously ignored; query on parent collection") + %test:assertEquals(1) +function pstor:query-parent-includes-subcollections() { + count(ft:search("/db/morebinary/shakespeare", 'speech:"boil bake"')//field) +}; + +(:~ + : Remove single document. + :) +declare + %test:assertEquals(0) +function pstor:remove-single-document() { + xmldb:remove("/db/morebinary2/shakespeare", "macbeth.xml"), + count(ft:search("/db/morebinary2/shakespeare", 'speech:"boil bake"')//field) +}; + +(:~ + : Remove collection. + :) +declare + %test:assertEmpty +function pstor:remove-collection() { + xmldb:remove("/db/morebinary3"), + ft:search("/db/morebinary3", "para:text")//@uri +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/queries.xml b/extensions/indexes/lucene/src/test/xquery/lucene/queries.xml deleted file mode 100644 index b5d7f8eabf0..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/queries.xml +++ /dev/null @@ -1,1050 +0,0 @@ - - - Lucene indexing tests - - Tests for the Lucene extensions - Wolfgang Meier - Leif-Jöran Olsson - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Eins zwei drei vier zwei fünf sechs.

-

Sieben acht neun zehn acht.

- The stopwords should not be indexed. -

Det är flera ord och fraser i det här stycket - som börjar med det är flera ord och fraser. - Dessutom är stycket något krystat komponerat med - ord och fraser i långa rader, men det är nu dags - att verkligen sluta upprepa ord och fraser.

- Note using different namespace. - - Nested nodes - - A11 -

erste aus haus maus zaus yaus raus qaus leisten

-
-
- - -
- Div1 -

First level

-
- Div2 -

Second level

-
- Div3 -

Third level

-
-
-
-
-
-
- - - - - - Term range query - - declare namespace tei="http://www.tei-c.org/ns/1.0"; - - doc("/db/lucene/text1.xml")//p[ft:query(., 'eins TO zwei')] - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - Case sensitivity - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., 'Eins')] return $hit - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 1: boolean with must, matches - einszwei - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 1a: boolean with optional, matches, minimum of 4 results - einszwei - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - - - - XML query test 1b: boolean with optional, matches, minimum of 2 results - einszwei - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> -

Eins zwei drei vier zwei fünf sechs.

-
- - XML query test 2: boolean with must, no match - einssieben - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - - - - XML query test 3: boolean with should - einssieben - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 4: phrase - einszwei - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 5: phrase, matches too distant - einsdrei - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - - - - XML query test 6: phrase with slop 2 - einsdrei - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 7: phrase, wrong order of terms - zweieins - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - - - - XML query test 8: near - einsvier - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 9: near, wrong slop - einsvier - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - - - - XML query test 10: near, unordered - zweieins - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 11: near, nested - - - einszwei - zweifünf - - - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 12: near, first - - - zweidrei - fünfsechs - - - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 13: wildcard - einssech* - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 14: regex - einssech.* - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - XML query test 15: near with regex - [ei][ei]nss.ch. - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] - return - $hit - ]]> - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - Query test: wildcard context - doc("/db/lucene/text1.xml")/test[ft:query(*, "acht")] - $output/p - - - - Query test: wildcard context - doc("/db/lucene/text1.xml")/test[ft:query(*, "should")] - $output/p - - - Query test: wildcard context - doc("/db/lucene/text1.xml")/test/p[ft:query(*, "neun")] - -

Sieben acht neun zehn acht.

-
-
- - Query test: wildcard context, no match - doc("/db/lucene/text1.xml")/test/p[ft:query(*, "acht")] - - - - Query test: wildcard context, no match in nested - doc("/db/lucene/text1.xml")/test/x[ft:query(*, "nodes")] - - - - Query test: wildcard context, match in nested - doc("/db/lucene/text1.xml")/test//y[ft:query(*, "nodes")] - - Nested nodes - - - - Query test: wildcard context, match on descendant - doc("/db/lucene/text1.xml")/test[ft:query(.//*, "neun")] - $output/p - - - Query test: wildcard context, match on self/child - doc("/db/lucene/text1.xml")//p[ft:query(./*, "neun")] - -

Sieben acht neun zehn acht.

-
-
- - Query test: wildcard context, match descendant - doc("/db/lucene/text1.xml")/x[ft:query(.//*, "nodes")] - - - - Query test: wildcard context, long path - doc("/db/lucene/text1.xml")/x[ft:query(./y/*, "nodes")] - - - - Query test: wildcard context, no match in child - doc("/db/lucene/text1.xml")/x[ft:query(./*, "nodes")] - - - - Query test: wildcard context with prefix wildcard - doc("/db/lucene/text1.xml")/test[ft:query(*:p, "acht")] - $output/*:p - - - Query test: wildcard context with prefix wildcard 2 - doc("/db/lucene/text1.xml")/test[ft:query(*:note, "namespace")] - $output/*:note - - - Query test: wildcard context with namespace - declare namespace tt="urn:test"; doc("/db/lucene/text1.xml")/test[ft:query(tt:*, - "namespace")]/tt:note - - Note using different namespace. - - - - Query test: optimizer test, query on element - doc("/db/lucene/text1.xml")//p[ft:query(b, "neun")] - $output/stats:index[@type eq 'lucene']/@optimization-level eq 'OPTIMIZED' - - - Query test: optimizer test, query on self - doc("/db/lucene/text1.xml")//p[ft:query(., "acht")] - $output/stats:index[@type eq 'lucene']/@optimization-level eq 'OPTIMIZED' - - - Query test: optimizer test, query on wildcard - doc("/db/lucene/text1.xml")/test[ft:query(*, "acht")] - $output/stats:index[@type eq 'lucene']/@optimization-level eq 'OPTIMIZED' - - - Optimizer test: wildcard context, self/descendant - doc("/db/lucene/text1.xml")//x[ft:query(.//*, "nodes")] - $output/stats:index[@type eq 'lucene']/@optimization-level eq 'OPTIMIZED' - - - Optimizer test: wildcard context, long path - doc("/db/lucene/text1.xml")//x[ft:query(./y/*, "nodes")] - $output/stats:index[@type eq 'lucene']/@optimization-level eq 'OPTIMIZED' - - - Phrase highlighting 1 - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"zwei drei"')] return - util:expand($hit) - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - Phrase highlighting 2 - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"eins zwei"')] return - util:expand($hit) - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - Phrase highlighting 3 - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"zwei fünf"')] return - util:expand($hit) - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - Phrase highlighting 4 - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"eins zwei"')] return - util:expand($hit) - -

Eins zwei drei vier zwei fünf sechs.

-
-
- - Phrase highlighting 5 - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"acht neun"')] return - util:expand($hit/b) - - - neun - - - - - Phrase highlighting 6: multiple phrases match - declare namespace exist="http://exist.sourceforge.net/NS/exist"; for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"ord och fraser"')] return util:expand($hit)//exist:match - - ord och fraser - ord och fraser - ord och fraser - ord och fraser - - - - Phrase highlighting 7: phrase with same start token as previously occuring token. - declare namespace exist="http://exist.sourceforge.net/NS/exist"; for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"stycket något krystat"')] return util:expand($hit)//exist:match - - stycket något krystat - - - - Match highlighting: prefix query - for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., 'neu*')] return - util:expand($hit/b) - - - neun - - - - - Match highlighting: prefix query xml syntax - neu)] - return - util:expand($hit/b) - ]]> - - - neun - - - - - Match highlighting: wildcard query - *eu*)] - return - util:expand($hit/b) - ]]> - - - neun - - - - - Match highlighting: wildcard query TEI NS MultiTermQueryRewriteMetod no silent fail due to limits/cutoffs but return all results - {$expr} - return for $hit in doc("/db/lucene/text1.xml")//tei:p[ft:query(., $query)] - return - util:expand($hit)//exist:match - ]]> - count($output) eq 42 - - - Match highlighting: regex query - .?eu.*)] - return - util:expand($hit/b) - ]]> - - - neun - - - - - Match highlighting: fuzzy query - neue)] - return - util:expand($hit/b) - ]]> - - - neun - - - - - Match highlighting: near query - acht neun)] - return - util:expand($hit/b) - ]]> - - - neun - - - - - Match highlighting: near query - achtneun)] - return - util:expand($hit/b) - ]]> - - - neun - - - - - index-keys test 1 - {$key} - }; - - - { - let $callback := util:function(xs:QName("local:key"), 2) - return - util:index-keys-by-qname(xs:QName("p"), (), $callback, 10000, "lucene-index") - } - ]]> - - - acht - att - börjar - dags - dessutom - det - drei - eins - first - flera - fraser - fünf - här - i - komponerat - krystat - level - långa - med - men - neun - nu - något - och - ord - rader - sechs - second - sieben - sluta - som - stycket - third - upprepa - verkligen - vier - zehn - zwei - är - - - - - index-keys test 2 - {$key} - }; - - - { - let $callback := util:function(xs:QName("local:key"), 2) - return - util:index-keys-by-qname(xs:QName("p"), "s", $callback, 10000, "lucene-index") - } - ]]> - - - sechs - second - sieben - sluta - som - stycket - - - - - index-keys test 3 - {$key} - }; - - - { - let $callback := util:function(xs:QName("local:key"), 2) - return - collection("/db/does/not/exist")/util:index-keys-by-qname(xs:QName("p"), "s", $callback, 10000, "lucene-index") - } - ]]> - - - - index-keys test 4 - {$key} - }; - - - { - let $callback := util:function(xs:QName("local:key"), 2) - return - util:index-keys(doc("/db/lucene/text1.xml")//p, "s", $callback, 10000, "lucene-index") - } - ]]> - - - sechs - sieben - sluta - som - stycket - - - - - index-keys test 5 - {$key} - }; - - - { - let $callback := util:function(xs:QName("local:key"), 2) - return - util:index-keys(doc("/db/lucene/text1.xml")//p[ft:query(., 'zehn')], "s", $callback, 10000, "lucene-index") - } - ]]> - - - sieben - - - - - index-keys test 6 - {$key} - }; - - { - let $callback := util:function(xs:QName("local:key"), 2) - return - util:index-keys(doc("/db/lucene/text2.xml")//@type, "", $callback, 10000, "lucene-index") - } - ]]> - - - chapter - section - subsection - - - - - - - Analyzer test - for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., '"and indexed"')] return $hit - - The stopwords should not be indexed. - - - - Analyzer test 1: phrase using stopword - andindexed - for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] - return - $hit - ]]> - - The stopwords should not be indexed. - - - - Analyzer test 2: near using stopword - andindexed - for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] - return - $hit - ]]> - - The stopwords should not be indexed. - - - - Analyzer test 3: stopword only - and - for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] - return - $hit - ]]> - - - - Analyzer test 4: stopword only - and - for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] - return - $hit - ]]> - - - - Analyzer test 5: stopword only - and - for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] - return - $hit - ]]> - - - - Analyzer test 6: stopword only - andthe - for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] - return - $hit - ]]> - - - - Analyzer test 7: stopword in boolean - stopwordsand - for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] - return - $hit - ]]> - - The stopwords should not be indexed. - - - - Query test: nested elements 1 - doc("/db/lucene/text2.xml")//div[ft:query(div/p, "second")] - -
- Div1 -

First level

-
- Div2 -

Second level

-
- Div3 -

Third level

-
-
-
-
-
- - Query test: nested elements 2 - doc("/db/lucene/text2.xml")/test/div[ft:query(div/div/p, "third")] - -
- Div1 -

First level

-
- Div2 -

Second level

-
- Div3 -

Third level

-
-
-
-
-
- - Query test: nested elements 3 - doc("/db/lucene/text2.xml")/div[ft:query(div/div/p, "second")] - - - - Query test: nested elements 4 - doc("/db/lucene/text2.xml")//div[ft:query(div/p, "third")] - -
- Div2 -

Second level

-
- Div3 -

Third level

-
-
-
-
- - Query test: nested elements with wildcard 1 - doc("/db/lucene/text2.xml")//div[ft:query(div/*, "third")] - -
- Div2 -

Second level

-
- Div3 -

Third level

-
-
-
-
- - Query test: nested elements with wildcard 2 - doc("/db/lucene/text2.xml")/test/div[ft:query(div/div/*, "third")] - -
- Div1 -

First level

-
- Div2 -

Second level

-
- Div3 -

Third level

-
-
-
-
-
- - Query test: nested elements with wildcard 3 - doc("/db/lucene/text2.xml")/div[ft:query(div/div/*, "second")] - - - - Query test: nested elements with wildcard 4 - doc("/db/lucene/text2.xml")//div[ft:query(div/*, "second")] - -
- Div1 -

First level

-
- Div2 -

Second level

-
- Div3 -

Third level

-
-
-
-
-
- - Query test: nested elements with wildcard 5 - doc("/db/lucene/text2.xml")//div[ft:query(div/*, "third")] - -
- Div2 -

Second level

-
- Div3 -

Third level

-
-
-
-
- - Query test: nested elements with wildcard 6 - doc("/db/lucene/text2.xml")//div[ft:query(./div/*, "third")] - -
- Div2 -

Second level

-
- Div3 -

Third level

-
-
-
-
- - Fields: query duplicate index - doc("/db/lucene/macbeth.xml")//SPEECH[ft:query(LINE, "king")] - count($output) eq 29 - - - Query field test - doc("/db/lucene/macbeth.xml")//SPEECH[ft:query-field("lines", "king")] - count($output) eq 29 - - - Fields: descendant - count(doc("/db/lucene/macbeth.xml")//SCENE[ft:query-field("lines", "king")]) - 10 - - - Query field: wrong parent - doc("/db/lucene/macbeth.xml")//SPEAKER[ft:query-field("lines", "king")] - - - - Fields: keyword analyzer - doc("/db/lucene/text1.xml")/test[ft:query-field("id", "A11")]/id - A11 - - - Fields: keyword analyzer, XML syntax - A11 - return - doc("/db/lucene/text1.xml")/test[ft:query-field("id", $query)]/id - ]]> - A11 - - - Fields: keyword analyzer, no context - ft:query-field("id", "A11") - A11 - - -
diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/queries.xql b/extensions/indexes/lucene/src/test/xquery/lucene/queries.xql new file mode 100644 index 00000000000..101300aa15d --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/queries.xql @@ -0,0 +1,891 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for Lucene indexing and query forms (term, phrase, near, wildcard, regex, etc.). + : Refactored from queries.xml (TestSet). Uses /db/lucene with self-contained sample play + text1/text2. + : + : @author Wolfgang Meier + : @author Leif-Jöran Olsson + :) +module namespace qrys="http://exist-db.org/xquery/lucene/queries/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; +declare namespace tei="http://www.tei-c.org/ns/1.0"; +declare namespace tt="urn:test"; +declare namespace exist="http://exist.sourceforge.net/NS/exist"; +declare namespace stats="http://exist-db.org/xquery/profiling"; + +(:~ + : Collection config: p, tt:p, tei:p, id, para, b, tt:note, z, LINE, @type. + :) +declare variable $qrys:XCONF as element(collection) := + + + + + + + + + + + + + + + + + + + + ; + +(:~ + : text1.xml content. + :) +declare variable $qrys:TEXT1 as element(test) := + +

Eins zwei drei vier zwei fünf sechs.

+

Sieben acht neun zehn acht.

+ The stopwords should not be indexed. +

Det är flera ord och fraser i det här stycket + som börjar med det är flera ord och fraser här. + Dessutom är stycket något krystat komponerat med + ord och fraser i långa rader, men det är nu dags + att verkligen sluta upprepa ord och fraser nu.

+ Note using different namespace. + + Nested nodes + + A11 +

erste aus haus maus zaus yaus raus qaus leisten

+
; + +(:~ + : text2.xml content. + :) +declare variable $qrys:TEXT2 as element(test) := + +
+ Div1 +

First level

+
+ Div2 +

Second level

+
+ Div3 +

Third level

+
+
+
+
; + +(:~ + : Self-contained sample play (PLAY/SCENE/SPEECH/SPEAKER/LINE) for LINE/field tests. + : 10 SCENEs; 29 SPEECHes with LINE containing "king" (matches fields-line-king-count, query-field-lines-king, fields-descendant-scene-count). + : SPEAKER has no LINE child so query-field-wrong-parent returns empty. + :) +declare variable $qrys:SAMPLE_PLAY as document-node() := + document { + + { + for $scene at $s in (3, 3, 3, 3, 3, 3, 3, 3, 2, 3) + return + + Scene { $s } + { for $i in 1 to $scene return Speakerking } + + } + + }; + +declare variable $qrys:COLLECTION_NAME := "lucene"; +declare variable $qrys:COLLECTION := "/db/" || $qrys:COLLECTION_NAME; + +(:~ + : Callback for util:index-keys (returns <t>term</t>). + :) +declare + %private +function qrys:key($key as xs:string, $options as item()*) as element(t) { + { $key } +}; + +(:~ + : setUp: create config hierarchy (/db/system/config/db/lucene), /db/lucene, store sample play + text1, text2, reindex. + :) +declare + %test:setUp +function qrys:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $qrys:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $qrys:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $qrys:COLLECTION_NAME, "collection.xconf", $qrys:XCONF), + xmldb:store($qrys:COLLECTION, "hamlet.xml", $qrys:SAMPLE_PLAY), + xmldb:store($qrys:COLLECTION, "macbeth.xml", $qrys:SAMPLE_PLAY), + xmldb:store($qrys:COLLECTION, "r_and_j.xml", $qrys:SAMPLE_PLAY), + xmldb:store($qrys:COLLECTION, "text1.xml", document { $qrys:TEXT1 }), + xmldb:store($qrys:COLLECTION, "text2.xml", document { $qrys:TEXT2 }), + xmldb:reindex($qrys:COLLECTION) ) +}; + +(:~ + : tearDown: remove /db/lucene and config collection. + :) +declare + %test:tearDown +function qrys:tearDown() { + ( xmldb:remove($qrys:COLLECTION), + xmldb:remove("/db/system/config/db/" || $qrys:COLLECTION_NAME) ) +}; + +(: --- Term / range / boolean / phrase / near / wildcard / regex (XML expected) --- :) + +(:~ Term range query :) +declare + %test:assertTrue +function qrys:term-range-query() { + let $result := doc("/db/lucene/text1.xml")//p[ft:query(., 'eins TO zwei')] + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ Case sensitivity :) +declare + %test:assertTrue +function qrys:case-sensitivity() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., 'Eins')] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 1: boolean with must, matches :) +declare + %test:assertTrue +function qrys:xml-query-bool-must-matches() { + let $qu := einszwei, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 1a: boolean with optional, matches, minimum of 4 results :) +declare + %test:assertEmpty +function qrys:xml-query-bool-optional-min4() { + let $qu := einszwei + return for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit +}; + +(:~ XML query test 1b: boolean with optional, matches, minimum of 2 results :) +declare + %test:assertTrue +function qrys:xml-query-bool-optional-min2() { + let $qu := einszwei, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 2: boolean must, no match :) +declare + %test:assertEmpty +function qrys:xml-query-bool-must-no-match() { + let $qu := einssieben + return for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit +}; + +(:~ XML query test 3: boolean with should :) +declare + %test:assertTrue +function qrys:xml-query-bool-should() { + let $qu := einssieben, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 4: phrase :) +declare + %test:assertTrue +function qrys:xml-query-phrase() { + let $qu := einszwei, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 5: phrase, matches too distant :) +declare + %test:assertEmpty +function qrys:xml-query-phrase-too-distant() { + let $qu := einsdrei + return for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit +}; + +(:~ XML query test 6: phrase with slop 2 :) +declare + %test:assertTrue +function qrys:xml-query-phrase-slop2() { + let $qu := einsdrei, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 7: phrase, wrong order of terms :) +declare + %test:assertEmpty +function qrys:xml-query-phrase-wrong-order() { + let $qu := zweieins + return for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit +}; + +(:~ XML query test 8: near :) +declare + %test:assertTrue +function qrys:xml-query-near() { + let $qu := einsvier, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 9: near, wrong slop :) +declare + %test:assertEmpty +function qrys:xml-query-near-wrong-slop() { + let $qu := einsvier + return for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit +}; + +(:~ XML query test 10: near unordered :) +declare + %test:assertTrue +function qrys:xml-query-near-unordered() { + let $qu := zweieins, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 11: near nested :) +declare + %test:assertTrue +function qrys:xml-query-near-nested() { + let $qu := einszweizweifünf, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 12: near first :) +declare + %test:assertTrue +function qrys:xml-query-near-first() { + let $qu := zweidreifünfsechs, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 13: wildcard :) +declare + %test:assertTrue +function qrys:xml-query-wildcard() { + let $qu := einssech*, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 14: regex :) +declare + %test:assertTrue +function qrys:xml-query-regex() { + let $qu := einssech.*, + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ XML query test 15: near with regex :) +declare + %test:assertTrue +function qrys:xml-query-near-regex() { + let $qu := [ei][ei]nss.ch., + $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., $qu)] return $hit + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(: --- Wildcard context (xpath assertions) --- :) + +(:~ Wildcard context: test[ft:query(*, "acht")] -> result has p :) +declare + %test:assertXPath("exists($result/p)") +function qrys:wildcard-context-acht() { + doc("/db/lucene/text1.xml")/test[ft:query(*, "acht")] +}; + +(:~ Wildcard context: test[ft:query(*, "should")] -> result has p :) +declare + %test:assertXPath("exists($result/p)") +function qrys:wildcard-context-should() { + doc("/db/lucene/text1.xml")/test[ft:query(*, "should")] +}; + +(:~ Wildcard context: p[ft:query(*, "neun")] :) +declare + %test:assertTrue +function qrys:wildcard-context-neun() { + let $result := doc("/db/lucene/text1.xml")/test/p[ft:query(*, "neun")] + return deep-equal($result,

Sieben acht neun zehn acht.

) +}; + +(:~ Wildcard context: p[ft:query(*, "acht")] no match :) +declare + %test:assertEmpty +function qrys:wildcard-context-acht-no-match() { + doc("/db/lucene/text1.xml")/test/p[ft:query(*, "acht")] +}; + +(:~ Wildcard context: x[ft:query(*, "nodes")] no match :) +declare + %test:assertEmpty +function qrys:wildcard-context-nested-no-match() { + doc("/db/lucene/text1.xml")/test/x[ft:query(*, "nodes")] +}; + +(:~ Wildcard context: //y[ft:query(*, "nodes")] match in nested :) +declare + %test:assertTrue +function qrys:wildcard-context-match-in-nested() { + let $result := doc("/db/lucene/text1.xml")/test//y[ft:query(*, "nodes")] + return deep-equal($result, Nested nodes) +}; + +(:~ Wildcard context: test[ft:query(.//*, "neun")] -> result has p :) +declare + %test:assertXPath("exists($result/p)") +function qrys:wildcard-context-descendant-neun() { + doc("/db/lucene/text1.xml")/test[ft:query(.//*, "neun")] +}; + +(:~ Wildcard context: p[ft:query(./*, "neun")] :) +declare + %test:assertTrue +function qrys:wildcard-context-self-child-neun() { + let $result := doc("/db/lucene/text1.xml")//p[ft:query(./*, "neun")] + return deep-equal($result,

Sieben acht neun zehn acht.

) +}; + +(:~ Wildcard context: x[ft:query(.//*, "nodes")] no match (wrong path) :) +declare + %test:assertEmpty +function qrys:wildcard-context-descendant-nodes() { + doc("/db/lucene/text1.xml")/x[ft:query(.//*, "nodes")] +}; + +(:~ Wildcard context: x[ft:query(./y/*, "nodes")] no match :) +declare + %test:assertEmpty +function qrys:wildcard-context-long-path() { + doc("/db/lucene/text1.xml")/x[ft:query(./y/*, "nodes")] +}; + +(:~ Wildcard context: x[ft:query(./*, "nodes")] no match in child :) +declare + %test:assertEmpty +function qrys:wildcard-context-no-match-child() { + doc("/db/lucene/text1.xml")/x[ft:query(./*, "nodes")] +}; + +(:~ Wildcard context with prefix wildcard *:p "acht" -> result has *:p :) +declare + %test:assertXPath("exists($result/*:p)") +function qrys:wildcard-context-prefix-wildcard-acht() { + doc("/db/lucene/text1.xml")/test[ft:query(*:p, "acht")] +}; + +(:~ Wildcard context *:note "namespace" -> result has *:note :) +declare + %test:assertXPath("exists($result/*:note)") +function qrys:wildcard-context-prefix-wildcard-note() { + doc("/db/lucene/text1.xml")/test[ft:query(*:note, "namespace")] +}; + +(:~ Wildcard context with namespace tt:*, "namespace" :) +declare + %test:assertTrue +function qrys:wildcard-context-namespace() { + let $result := doc("/db/lucene/text1.xml")/test[ft:query(tt:*, "namespace")]/tt:note + return deep-equal($result, Note using different namespace.) +}; + +(: --- Optimizer tests (trace / stats) --- :) + +(:~ Optimizer: query on element b "neun" :) +declare + %test:stats + %test:assertXPath("exists($result//stats:index[@type eq 'lucene'][@optimization-level eq 'OPTIMIZED'])") +function qrys:optimizer-query-on-element() { + doc("/db/lucene/text1.xml")//p[ft:query(b, "neun")] +}; + +(:~ Optimizer: query on self "acht" :) +declare + %test:stats + %test:assertXPath("exists($result//stats:index[@type eq 'lucene'][@optimization-level eq 'OPTIMIZED'])") +function qrys:optimizer-query-on-self() { + doc("/db/lucene/text1.xml")//p[ft:query(., "acht")] +}; + +(:~ Optimizer: query on wildcard * "acht" :) +declare + %test:stats + %test:assertXPath("exists($result//stats:index[@type eq 'lucene'][@optimization-level eq 'OPTIMIZED'])") +function qrys:optimizer-query-on-wildcard() { + doc("/db/lucene/text1.xml")/test[ft:query(*, "acht")] +}; + +(:~ Optimizer: wildcard context .//* "nodes" :) +declare + %test:stats + %test:assertXPath("exists($result//stats:index[@type eq 'lucene'][@optimization-level eq 'OPTIMIZED'])") +function qrys:optimizer-wildcard-self-descendant() { + doc("/db/lucene/text1.xml")//x[ft:query(.//*, "nodes")] +}; + +(:~ Optimizer: wildcard context ./y/* "nodes" :) +declare + %test:stats + %test:assertXPath("exists($result//stats:index[@type eq 'lucene'][@optimization-level eq 'OPTIMIZED'])") +function qrys:optimizer-wildcard-long-path() { + doc("/db/lucene/text1.xml")//x[ft:query(./y/*, "nodes")] +}; + +(: --- Phrase highlighting --- :) + +(:~ Phrase highlighting 1: "zwei drei" :) +declare + %test:assertTrue +function qrys:phrase-highlighting-1() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"zwei drei"')] return util:expand($hit) + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ Phrase highlighting 2: "eins zwei" :) +declare + %test:assertTrue +function qrys:phrase-highlighting-2() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"eins zwei"')] return util:expand($hit) + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ Phrase highlighting 3: "zwei fünf" :) +declare + %test:assertTrue +function qrys:phrase-highlighting-3() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"zwei fünf"')] return util:expand($hit) + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ Phrase highlighting 4: "eins zwei" (duplicate of 2) :) +declare + %test:assertTrue +function qrys:phrase-highlighting-4() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"eins zwei"')] return util:expand($hit) + return deep-equal($result,

Eins zwei drei vier zwei fünf sechs.

) +}; + +(:~ Phrase highlighting 5: "acht neun" on b :) +declare + %test:assertTrue +function qrys:phrase-highlighting-5() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"acht neun"')] return util:expand($hit/b) + return deep-equal($result, neun) +}; + +(:~ Phrase highlighting 6: multiple phrases "ord och fraser" (4 matches). Paragraph worded so no occurrence ends with punctuation (avoids highlighter returning 3). :) +declare + %test:assertTrue +function qrys:phrase-highlighting-6() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"ord och fraser"')] return util:expand($hit)//exist:match + return count($result) eq 4 and (every $m in $result satisfies $m/self::exist:match and normalize-space(string($m)) eq "ord och fraser") +}; + +(:~ Phrase highlighting 7: "stycket något krystat" :) +declare + %test:assertTrue +function qrys:phrase-highlighting-7() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., '"stycket något krystat"')] return util:expand($hit)//exist:match + return deep-equal($result, stycket något krystat) +}; + +(: --- Match highlighting: prefix, wildcard, regex, fuzzy, near --- :) + +(:~ Match highlighting: prefix query neu* :) +declare + %test:assertTrue +function qrys:match-highlight-prefix() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., 'neu*')] return util:expand($hit/b) + return deep-equal($result, neun) +}; + +(:~ Match highlighting: prefix query XML syntax :) +declare + %test:assertTrue +function qrys:match-highlight-prefix-xml() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., neu)] return util:expand($hit/b) + return deep-equal($result, neun) +}; + +(:~ Match highlighting: wildcard *eu* :) +declare + %test:assertTrue +function qrys:match-highlight-wildcard() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., *eu*)] return util:expand($hit/b) + return deep-equal($result, neun) +}; + +(:~ Match highlighting: wildcard TEI NS multi-term count 42. Assert in-function to avoid assertXPath namespace injection (xmlns prefix). :) +declare + %test:assertEquals(42) +function qrys:match-highlight-wildcard-tei-count() { + let $result := for $expr in ("aus", "haus", "maus", "zaus", "yaus", "raus", "qaus", + "a*", "h*", "m*", "z*", "y*", "r*", "q*", + "au*", "ha*", "ma*", "za*", "ya*", "ra*", "qa*", + "aus*", "hau*", "mau*", "zau*", "yau*", "rau*", "qau*", + "a*s", "h*s", "m*s", "z*s", "y*s", "r*s", "q*s", + "au*s", "ha*s", "ma*s", "za*s", "ya*s", "ra*s", "qa*s") + let $query := { $expr } + return for $hit in doc("/db/lucene/text1.xml")//tei:p[ft:query(., $query)] return util:expand($hit)//exist:match + return count($result) +}; + +(:~ Match highlighting: regex .?eu.* :) +declare + %test:assertTrue +function qrys:match-highlight-regex() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., .?eu.*)] return util:expand($hit/b) + return deep-equal($result, neun) +}; + +(:~ Match highlighting: fuzzy neue :) +declare + %test:assertTrue +function qrys:match-highlight-fuzzy() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., neue)] return util:expand($hit/b) + return deep-equal($result, neun) +}; + +(:~ Match highlighting: near "acht neun" :) +declare + %test:assertTrue +function qrys:match-highlight-near-string() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., acht neun)] return util:expand($hit/b) + return deep-equal($result, neun) +}; + +(:~ Match highlighting: near XML (term + near) :) +declare + %test:assertTrue +function qrys:match-highlight-near-xml() { + let $result := for $hit in doc("/db/lucene/text1.xml")//p[ft:query(., achtneun)] return util:expand($hit/b) + return deep-equal($result, neun) +}; + +(: --- index-keys (callback) --- :) + +(:~ index-keys test 1: by-qname p, no start :) +declare + %test:assertTrue +function qrys:index-keys-by-qname-all() { + let $callback := util:function(xs:QName("qrys:key"), 2), + $result := { util:index-keys-by-qname(xs:QName("p"), (), $callback, 10000, "lucene-index") } + return deep-equal($result, + achtattbörjardagsdessutomdetdreieinsfirstflera + fraserfünfhärikomponeratkrystatlevellångamedmen + neunnunågotochordradersechssecondsiebenslutasom + stycketthirdupprepaverkligenvierzehnzweiär + ) +}; + +(:~ index-keys test 2: by-qname p, start "s" :) +declare + %test:assertTrue +function qrys:index-keys-by-qname-s() { + let $callback := util:function(xs:QName("qrys:key"), 2), + $result := { util:index-keys-by-qname(xs:QName("p"), "s", $callback, 10000, "lucene-index") } + return deep-equal($result, sechssecondsiebenslutasomstycket) +}; + +(:~ index-keys test 3: non-existent collection :) +declare + %test:assertTrue +function qrys:index-keys-nonexistent-collection() { + let $callback := util:function(xs:QName("qrys:key"), 2), + $result := { collection("/db/does/not/exist")/util:index-keys-by-qname(xs:QName("p"), "s", $callback, 10000, "lucene-index") } + return deep-equal($result, ) +}; + +(:~ index-keys test 4: index-keys on nodes p, start "s" :) +declare + %test:assertTrue +function qrys:index-keys-on-nodes-s() { + let $callback := util:function(xs:QName("qrys:key"), 2), + $result := { util:index-keys(doc("/db/lucene/text1.xml")//p, "s", $callback, 10000, "lucene-index") } + return deep-equal($result, sechssiebenslutasomstycket) +}; + +(:~ index-keys test 5: index-keys on ft:query result "zehn" -> "s" :) +declare + %test:assertTrue +function qrys:index-keys-on-query-result() { + let $callback := util:function(xs:QName("qrys:key"), 2), + $result := { util:index-keys(doc("/db/lucene/text1.xml")//p[ft:query(., 'zehn')], "s", $callback, 10000, "lucene-index") } + return deep-equal($result, sieben) +}; + +(:~ index-keys test 6: index-keys on @type :) +declare + %test:assertTrue +function qrys:index-keys-attr-type() { + let $callback := util:function(xs:QName("qrys:key"), 2), + $result := { util:index-keys(doc("/db/lucene/text2.xml")//@type, "", $callback, 10000, "lucene-index") } + return deep-equal($result, chaptersectionsubsection) +}; + +(:~ index-keys test 7: by-qname @type (previously commented out in XML). :) +declare + %test:pending("previously commented out; index-keys-by-qname with @type") + %test:assertTrue +function qrys:index-keys-by-qname-attr-type() { + let $callback := util:function(xs:QName("qrys:key"), 2), + $result := { util:index-keys-by-qname(xs:QName("@type"), "", $callback, 10000, "lucene-index") } + return deep-equal($result, chaptersectionsubsection) +}; + +(: --- Analyzer (stopword) tests --- :) + +(:~ Analyzer test: phrase "and indexed" on para :) +declare + %test:assertTrue +function qrys:analyzer-phrase-stopword() { + let $result := for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., '"and indexed"')] return $hit + return deep-equal($result, The stopwords should not be indexed.) +}; + +(:~ Analyzer test 1: phrase XML and+indexed :) +declare + %test:assertTrue +function qrys:analyzer-phrase-stopword-xml() { + let $qu := andindexed, + $result := for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] return $hit + return deep-equal($result, The stopwords should not be indexed.) +}; + +(:~ Analyzer test 2: near and+indexed :) +declare + %test:assertTrue +function qrys:analyzer-near-stopword() { + let $qu := andindexed, + $result := for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] return $hit + return deep-equal($result, The stopwords should not be indexed.) +}; + +(:~ Analyzer test 3: term "and" only -> no match :) +declare + %test:assertEmpty +function qrys:analyzer-term-stopword-only() { + let $qu := and + return for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] return $hit +}; + +(:~ Analyzer test 4: near "and" only -> no match :) +declare + %test:assertEmpty +function qrys:analyzer-near-stopword-only() { + let $qu := and + return for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] return $hit +}; + +(:~ Analyzer test 5: phrase "and" only -> no match :) +declare + %test:assertEmpty +function qrys:analyzer-phrase-stopword-only() { + let $qu := and + return for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] return $hit +}; + +(:~ Analyzer test 6: bool must and+the -> no match :) +declare + %test:assertEmpty +function qrys:analyzer-bool-stopword-only() { + let $qu := andthe + return for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] return $hit +}; + +(:~ Analyzer test 7: bool stopwords+and matches :) +declare + %test:assertTrue +function qrys:analyzer-bool-with-stopword() { + let $qu := stopwordsand, + $result := for $hit in doc("/db/lucene/text1.xml")//para[ft:query(., $qu)] return $hit + return deep-equal($result, The stopwords should not be indexed.) +}; + +(: --- Nested elements (text2) --- :) + +(:~ Nested elements 1: div[ft:query(div/p, "second")] :) +declare + %test:assertTrue +function qrys:nested-elements-1() { + let $result := doc("/db/lucene/text2.xml")//div[ft:query(div/p, "second")] + return deep-equal($result,
Div1

First level

Div2

Second level

Div3

Third level

) +}; + +(:~ Nested elements 2: div[ft:query(div/div/p, "third")] :) +declare + %test:assertTrue +function qrys:nested-elements-2() { + let $result := doc("/db/lucene/text2.xml")/test/div[ft:query(div/div/p, "third")] + return deep-equal($result,
Div1

First level

Div2

Second level

Div3

Third level

) +}; + +(:~ Nested elements 3: div[ft:query(div/div/p, "second")] no match :) +declare + %test:assertEmpty +function qrys:nested-elements-3() { + doc("/db/lucene/text2.xml")/div[ft:query(div/div/p, "second")] +}; + +(:~ Nested elements 4: //div[ft:query(div/p, "third")] :) +declare + %test:assertTrue +function qrys:nested-elements-4() { + let $result := doc("/db/lucene/text2.xml")//div[ft:query(div/p, "third")] + return deep-equal($result,
Div2

Second level

Div3

Third level

) +}; + +(:~ Nested elements wildcard 1: div[ft:query(div/*, "third")] :) +declare + %test:assertTrue +function qrys:nested-wildcard-1() { + let $result := doc("/db/lucene/text2.xml")//div[ft:query(div/*, "third")] + return deep-equal($result,
Div2

Second level

Div3

Third level

) +}; + +(:~ Nested elements wildcard 2: test/div[ft:query(div/div/*, "third")] :) +declare + %test:assertTrue +function qrys:nested-wildcard-2() { + let $result := doc("/db/lucene/text2.xml")/test/div[ft:query(div/div/*, "third")] + return deep-equal($result,
Div1

First level

Div2

Second level

Div3

Third level

) +}; + +(:~ Nested elements wildcard 3: div[ft:query(div/div/*, "second")] no match :) +declare + %test:assertEmpty +function qrys:nested-wildcard-3() { + doc("/db/lucene/text2.xml")/div[ft:query(div/div/*, "second")] +}; + +(:~ Nested elements wildcard 4: //div[ft:query(div/*, "second")] :) +declare + %test:assertTrue +function qrys:nested-wildcard-4() { + let $result := doc("/db/lucene/text2.xml")//div[ft:query(div/*, "second")] + return deep-equal($result,
Div1

First level

Div2

Second level

Div3

Third level

) +}; + +(:~ Nested elements wildcard 5: //div[ft:query(div/*, "third")] :) +declare + %test:assertTrue +function qrys:nested-wildcard-5() { + let $result := doc("/db/lucene/text2.xml")//div[ft:query(div/*, "third")] + return deep-equal($result,
Div2

Second level

Div3

Third level

) +}; + +(:~ Nested elements wildcard 6: //div[ft:query(./div/*, "third")] :) +declare + %test:assertTrue +function qrys:nested-wildcard-6() { + let $result := doc("/db/lucene/text2.xml")//div[ft:query(./div/*, "third")] + return deep-equal($result,
Div2

Second level

Div3

Third level

) +}; + +(: --- Fields (LINE, ft:query-field, keyword id) --- :) + +(:~ Fields: duplicate index LINE "king" count 29 :) +declare + %test:assertXPath("count($result) eq 29") +function qrys:fields-line-king-count() { + doc("/db/lucene/macbeth.xml")//SPEECH[ft:query(LINE, "king")] +}; + +(:~ Query field test: lines "king" count 29 :) +declare + %test:assertXPath("count($result) eq 29") +function qrys:query-field-lines-king() { + doc("/db/lucene/macbeth.xml")//SPEECH[ft:query-field("lines", "king")] +}; + +(:~ Fields: descendant SCENE ft:query-field lines "king" count 10 :) +declare + %test:assertEquals(10) +function qrys:fields-descendant-scene-count() { + count(doc("/db/lucene/macbeth.xml")//SCENE[ft:query-field("lines", "king")]) +}; + +(:~ Query field wrong parent: SPEAKER[ft:query-field("lines", "king")] -> empty :) +declare + %test:assertEmpty +function qrys:query-field-wrong-parent() { + doc("/db/lucene/macbeth.xml")//SPEAKER[ft:query-field("lines", "king")] +}; + +(:~ Fields: keyword analyzer id "A11" :) +declare + %test:assertTrue +function qrys:fields-keyword-id() { + let $result := doc("/db/lucene/text1.xml")/test[ft:query-field("id", "A11")]/id + return deep-equal($result, A11) +}; + +(:~ Fields: keyword analyzer XML syntax :) +declare + %test:assertTrue +function qrys:fields-keyword-xml() { + let $query := A11, + $result := doc("/db/lucene/text1.xml")/test[ft:query-field("id", $query)]/id + return deep-equal($result, A11) +}; + +(:~ Fields: keyword analyzer (ft:query-field "id" "A11"); doc context so index sees our docs. :) +declare + %test:assertTrue +function qrys:fields-keyword-no-context() { + let $result := doc("/db/lucene/text1.xml")/test[ft:query-field("id", "A11")]/id, + $expected := doc("/db/lucene/text1.xml")/test/id[. = "A11"] + return count($result) eq 1 and deep-equal($result, $expected) +}; + +(:~ Fields: remove document then query-field (previously commented out in XML). Restores text1.xml so later tests are not broken. :) +declare + %test:pending("previously commented out; remove document then ft:query-field") + %test:assertEmpty +function qrys:fields-remove-document() { + xmldb:remove($qrys:COLLECTION, "text1.xml"), + let $result := ft:query-field("id", "a11.b22.c33.d44") + return ( xmldb:store($qrys:COLLECTION, "text1.xml", document { $qrys:TEXT1 }), $result ) +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/query-field.xql b/extensions/indexes/lucene/src/test/xquery/lucene/query-field.xql index c3b1915f607..3afe46ec6fd 100644 --- a/extensions/indexes/lucene/src/test/xquery/lucene/query-field.xql +++ b/extensions/indexes/lucene/src/test/xquery/lucene/query-field.xql @@ -34,6 +34,17 @@ declare variable $qf:XCONF1 := ; +declare variable $qf:XML as document-node() := + document { + +

Rüsselsheim

+

Russelsheim

+

Māori

+

Maori

+
+ }; + +declare variable $qf:_ := (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")); declare variable $qf:testCol := xmldb:create-collection("/db", "queryfieldtest"); declare variable $qf:confCol := xmldb:create-collection("/db/system/config/db", "queryfieldtest"); @@ -43,22 +54,8 @@ function qf:setup() { ( xmldb:store($qf:confCol, "collection.xconf", $qf:XCONF1), - xmldb:store($qf:testCol, "test1.xml", - -

Rüsselsheim

-

Russelsheim

-

Māori

-

Maori

-
- ), - xmldb:store($qf:testCol, "test2.xml", - -

Rüsselsheim

-

Russelsheim

-

Māori

-

Maori

-
- ) + xmldb:store($qf:testCol, "test1.xml", $qf:XML), + xmldb:store($qf:testCol, "test2.xml", $qf:XML) ) }; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/start-offset.xql b/extensions/indexes/lucene/src/test/xquery/lucene/start-offset.xql new file mode 100644 index 00000000000..d94ad1e1908 --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/start-offset.xql @@ -0,0 +1,181 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for correct offset calculation of util:expand (start offsets). + : Refactored from startOffset.xml (TestSet). + : Tests whether util:expand() calculates correct start offsets. Since there is a problem with + : first matching strings of certain nodes, tests come in pairs: one matching the first word, + : the other matching the second word of a node. + : + : @author Ron Van den Branden + :) +module namespace stof="http://exist-db.org/xquery/lucene/start-offset/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : Collection config: text qname el. + :) +declare variable $stof:XCONF as element(collection) := + + + + + + + + + ; + +declare variable $stof:COLLECTION_NAME := "start-offset"; +declare variable $stof:COLLECTION := "/db/" || $stof:COLLECTION_NAME; + +(:~ + : setUp: create collection, config, store five test docs, reindex. + :) +declare + %test:setUp +function stof:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $stof:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $stof:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $stof:COLLECTION_NAME, "collection.xconf", $stof:XCONF), + xmldb:store($stof:COLLECTION, "test1.xml", document { wordstrong string }), + xmldb:store($stof:COLLECTION, "test2.xml", document { wordstrong string }), + xmldb:store($stof:COLLECTION, "test3.xml", document { wordstrong string }), + xmldb:store($stof:COLLECTION, "test4.xml", document { strong string }), + xmldb:store($stof:COLLECTION, "test5.xml", document { strong string }), + xmldb:reindex($stof:COLLECTION) ) +}; + +(:~ + : tearDown: remove data and config collections. + :) +declare + %test:tearDown +function stof:tearDown() { + xmldb:remove($stof:COLLECTION), + xmldb:remove("/db/system/config/db/" || $stof:COLLECTION_NAME) +}; + +(:~ + : atomic match preceded by complex element, first word. + :) +declare + %test:assertTrue +function stof:atomic-complex-first-word() { + let $result := doc($stof:COLLECTION || "/test1.xml")//el[ft:query(., 'strong')]/util:expand(.) + return deep-equal($result, strong string) +}; + +(:~ + : atomic match preceded by complex element, second word. + :) +declare + %test:assertTrue +function stof:atomic-complex-second-word() { + let $result := doc($stof:COLLECTION || "/test1.xml")//el[ft:query(., 'string')]/util:expand(.) + return deep-equal($result, strong string) +}; + +(:~ + : nested match preceded by simple element, first word. + :) +declare + %test:assertTrue +function stof:nested-simple-first-word() { + let $result := doc($stof:COLLECTION || "/test3.xml")//el[ft:query(., 'strong')]/util:expand(.) + return deep-equal($result, wordstrong string) +}; + +(:~ + : nested match preceded by simple element, second word. + :) +declare + %test:assertTrue +function stof:nested-simple-second-word() { + let $result := doc($stof:COLLECTION || "/test3.xml")//el[ft:query(., 'string')]/util:expand(.) + return deep-equal($result, wordstrong string) +}; + +(:~ + : nested match preceded by empty element, first word. + :) +declare + %test:assertTrue +function stof:nested-empty-first-word() { + let $result := doc($stof:COLLECTION || "/test5.xml")//el[ft:query(., 'strong')]/util:expand(.) + return deep-equal($result, strong string) +}; + +(:~ + : nested match preceded by empty element, second word. + :) +declare + %test:assertTrue +function stof:nested-empty-second-word() { + let $result := doc($stof:COLLECTION || "/test5.xml")//el[ft:query(., 'string')]/util:expand(.) + return deep-equal($result, strong string) +}; + +(:~ + : nested match preceded by complex element, first word. + :) +declare + %test:assertTrue +function stof:nested-complex-first-word() { + let $result := doc($stof:COLLECTION || "/test2.xml")//el[ft:query(., 'strong')]/util:expand(.) + return deep-equal($result, wordstrong string) +}; + +(:~ + : nested match preceded by complex element, second word. + :) +declare + %test:assertTrue +function stof:nested-complex-second-word() { + let $result := doc($stof:COLLECTION || "/test2.xml")//el[ft:query(., 'string')]/util:expand(.) + return deep-equal($result, wordstrong string) +}; + +(:~ + : nested match preceded by complex element (with empty child), first word. + :) +declare + %test:assertTrue +function stof:nested-complex-empty-child-first-word() { + let $result := doc($stof:COLLECTION || "/test4.xml")//el[ft:query(., 'strong')]/util:expand(.) + return deep-equal($result, strong string) +}; + +(:~ + : nested match preceded by complex element (with empty child), second word. + :) +declare + %test:assertTrue +function stof:nested-complex-empty-child-second-word() { + let $result := doc($stof:COLLECTION || "/test4.xml")//el[ft:query(., 'string')]/util:expand(.) + return deep-equal($result, strong string) +}; diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/startOffset.xml b/extensions/indexes/lucene/src/test/xquery/lucene/startOffset.xml deleted file mode 100644 index dfe1eb80391..00000000000 --- a/extensions/indexes/lucene/src/test/xquery/lucene/startOffset.xml +++ /dev/null @@ -1,184 +0,0 @@ - - - tests for correct offset calculation of util:expand - -

These tests whether util:expand() calculates correct start offsets. Since there seems to be a - problem with first matching strings of certain nodes, tests come in pairs: one matching the first word, - the other matching the second word of a node.

- Ron Van den Branden -
- - - - - - - - - - - - - - - - - - - wordstrong string - - - - - wordstrong string - - - - - wordstrong string - - - - - strong string - - - - - strong string - - - - - - - - - atomic match preceded by complex element, first word - - - strong string - - - - atomic match preceded by complex element, second word - - - strong string - - - - nested match preceded by simple element, first word - - - - wordstrong string - - - - - nested match preceded by simple element, second word - - - - wordstrong string - - - - - nested match preceded by empty element, first word - - - - strong string - - - - - nested match preceded by empty element, second word - - - - strong string - - - - - nested match preceded by complex element, first word - - - - wordstrong string - - - - - nested match preceded by complex element, second word - - - - wordstrong string - - - - - nested match preceded by complex element (with empty child), first word - - - - strong string - - - - - nested match preceded by complex element (with empty child), second word - - - - strong string - - - -
diff --git a/extensions/indexes/lucene/src/test/xquery/lucene/unicode-supplementary-lucene.xql b/extensions/indexes/lucene/src/test/xquery/lucene/unicode-supplementary-lucene.xql new file mode 100644 index 00000000000..5b02b3f0ffc --- /dev/null +++ b/extensions/indexes/lucene/src/test/xquery/lucene/unicode-supplementary-lucene.xql @@ -0,0 +1,184 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; +(:~ + : XQsuite tests for Lucene index handling of Supplementary Multilingual Plane (SMP) + : and Supplementary Ideographic Plane (SIP) characters. + : + : Verifies that the Lucene full-text index indexes and finds all 20 SMP/SIP + : code points from issue #787; the issue reports that some are dropped. + : + : @see https://github.com/eXist-db/exist/issues/787 + : @see https://www.unicode.org/roadmaps/smp/ + :) + +module namespace unic-smp-l="http://exist-db.org/xquery/lucene/test/unic-smp-supplementary"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : All 20 SMP/SIP code points from issue #787, grouped as in the issue report. + : @return map with keys smp-indexed, smp-dropped, sip-indexed, sip-dropped; values are sequences of xs:integer codepoints + :) +declare variable $unic-smp-l:CODEPOINTS := map { + "smp-indexed": (65536, 66321, 66661, 68200, 68608), + "smp-dropped": (65797, 65930, 128336, 128512, 119558, 128267), + "sip-indexed": (131072, 131369, 145429, 170811, 178084), + "sip-dropped": (183618, 178231, 178671, 183785) +}; + +(:~ + : Flattened sequence of all codepoints in issue order (smp-indexed, smp-dropped, sip-indexed, sip-dropped). + : @return xs:integer* all 20 codepoints + :) +declare variable $unic-smp-l:ALL_CODEPOINTS := ( + $unic-smp-l:CODEPOINTS("smp-indexed"), + $unic-smp-l:CODEPOINTS("smp-dropped"), + $unic-smp-l:CODEPOINTS("sip-indexed"), + $unic-smp-l:CODEPOINTS("sip-dropped") +); + +(:~ + : Map from codepoint (xs:integer) to group name for informative test output and document attributes. + : @return map(xs:integer, xs:string) codepoint to "smp-indexed" | "smp-dropped" | "sip-indexed" | "sip-dropped" + :) +declare variable $unic-smp-l:CP_TO_GROUP := map:merge( + for $k in map:keys($unic-smp-l:CODEPOINTS) + return for $cp in $unic-smp-l:CODEPOINTS($k) return map:entry($cp, $k) +); + +(:~ + : Test document: one p per supplementary codepoint, with group attribute retained. + : @return document-node() root with 20 p children, each p has @group and one supplementary character + :) +declare variable $unic-smp-l:XML as document-node() := document { + { + for $cp in $unic-smp-l:ALL_CODEPOINTS + return

{ codepoints-to-string($cp) }

+ }
+}; + +(:~ + : Collection configuration with Lucene full-text index on element p. + : @return element(collection) eXist collection config + :) +declare variable $unic-smp-l:xconf := + + + + + + + ; + +(:~ Name of the test collection (no path). :) +declare variable $unic-smp-l:COLLECTION_NAME := "unicode-supplementary-lucene"; + +(:~ Full path of the test collection. :) +declare variable $unic-smp-l:COLLECTION := "/db/" || $unic-smp-l:COLLECTION_NAME; + +(:~ + : XQsuite setUp: create test and config collections, store document and xconf, reindex. + :) +declare + %test:setUp +function unic-smp-l:setup() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $unic-smp-l:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $unic-smp-l:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $unic-smp-l:COLLECTION_NAME, "collection.xconf", $unic-smp-l:xconf), + xmldb:store($unic-smp-l:COLLECTION, "test.xml", $unic-smp-l:XML), + xmldb:reindex($unic-smp-l:COLLECTION) ) +}; + +(:~ + : XQsuite tearDown: remove test collection and its config collection. + :) +declare + %test:tearDown +function unic-smp-l:tearDown() { + xmldb:remove($unic-smp-l:COLLECTION), + xmldb:remove("/db/system/config/db/" || $unic-smp-l:COLLECTION_NAME) +}; + +(:~ + : Counts how many codepoints in the given group Lucene finds (ft:query). + : + : @param $group group name: smp-indexed | smp-dropped | sip-indexed | sip-dropped + : @return xs:string "group: count" e.g. "smp-indexed: 5" + :) +declare function unic-smp-l:lucene-finds-count($group as xs:string) as xs:string { + let $codepoints := $unic-smp-l:CODEPOINTS($group), + $found := sum( + for $cp in $codepoints + return if (count(collection($unic-smp-l:COLLECTION)//p[ft:query(., codepoints-to-string($cp))]) gt 0) + then 1 else 0 + ) + return $group || ": " || $found +}; + +(:~ + : Asserts that Lucene indexes and finds all supplementary characters in group smp-indexed (5 codepoints). + : @return xs:string "smp-indexed: 5" + :) +declare + %test:assertEquals("smp-indexed: 5") +function unic-smp-l:lucene-finds-supplementary-smp-indexed() { + unic-smp-l:lucene-finds-count("smp-indexed") +}; + +(:~ + : Asserts that Lucene indexes and finds all supplementary characters in group smp-dropped (6 codepoints). + : Pending until Lucene fix for issue #787. + : + : @return xs:string "smp-dropped: 6" + :) +declare + %test:pending("Lucene drops these SMP characters, see #787") + %test:assertEquals("smp-dropped: 6") +function unic-smp-l:lucene-finds-supplementary-smp-dropped() { + unic-smp-l:lucene-finds-count("smp-dropped") +}; + +(:~ + : Asserts that Lucene indexes and finds all supplementary characters in group sip-indexed (5 codepoints). + : @return xs:string "sip-indexed: 5" + :) +declare + %test:assertEquals("sip-indexed: 5") +function unic-smp-l:lucene-finds-supplementary-sip-indexed() { + unic-smp-l:lucene-finds-count("sip-indexed") +}; + +(:~ + : Asserts that Lucene indexes and finds all supplementary characters in group sip-dropped (4 codepoints). + : Pending until Lucene fix for issue #787. + : + : @return xs:string "sip-dropped: 4" + :) +declare + %test:pending("Lucene drops these SIP characters, see #787") + %test:assertEquals("sip-dropped: 4") +function unic-smp-l:lucene-finds-supplementary-sip-dropped() { + unic-smp-l:lucene-finds-count("sip-dropped") +}; diff --git a/extensions/indexes/ngram/src/test/xquery/ngram/match-highlighting-ngram.xql b/extensions/indexes/ngram/src/test/xquery/ngram/match-highlighting-ngram.xql new file mode 100644 index 00000000000..691bffd4cfe --- /dev/null +++ b/extensions/indexes/ngram/src/test/xquery/ngram/match-highlighting-ngram.xql @@ -0,0 +1,174 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +(:~ + : XQSuite tests for match highlighting behaviour on ngram index (util:expand highlight-matches). + : Refactored from matchHighlighting_ngram_Tests.xml (TestSet). + : Tests whether matches are highlighted correctly for ngram:contains. Repeated for matches + : in elements and attributes, and for each setting of highlight-matches: none, attributes, + : elements, both. Only qname-based indexes are used. + : + : @author Ron Van den Branden + :) +module namespace mhng="http://exist-db.org/xquery/ngram/match-highlighting/test"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; +declare namespace exist="http://exist.sourceforge.net/NS/exist"; + +(:~ + : Collection config: ngram on el, @att. + :) +declare variable $mhng:XCONF as element(collection) := + + + + + + ; + +(:~ + : Test document. + :) +declare variable $mhng:XML as document-node() := + document { + + onetwo tree + + }; + +(:~ + : Expected: no highlighting. + :) +declare variable $mhng:EXPECTED_NONE as element(el) := + onetwo tree; + +declare variable $mhng:COLLECTION_NAME := "match-highlighting-ngram"; +declare variable $mhng:COLLECTION := "/db/" || $mhng:COLLECTION_NAME; + +(:~ + : setUp: create config hierarchy, collection, store doc, reindex. + :) +declare + %test:setUp +function mhng:setUp() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $mhng:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $mhng:COLLECTION_NAME), + xmldb:store("/db/system/config/db/" || $mhng:COLLECTION_NAME, "collection.xconf", $mhng:XCONF), + xmldb:store($mhng:COLLECTION, "test.xml", $mhng:XML), + xmldb:reindex($mhng:COLLECTION) ) +}; + +(:~ + : tearDown: remove data and config collections. + :) +declare + %test:tearDown +function mhng:tearDown() { + xmldb:remove($mhng:COLLECTION), + xmldb:remove("/db/system/config/db/" || $mhng:COLLECTION_NAME) +}; + +(:~ + : [ngram] element match, match-highlighting=none. + :) +declare + %test:assertTrue +function mhng:element-match-highlight-none() { + let $result := doc($mhng:COLLECTION || "/test.xml")//el[ngram:contains(., 'tree')]/util:expand(., 'highlight-matches=none') + return deep-equal($result, $mhng:EXPECTED_NONE) +}; + +(:~ + : [ngram] element match, match-highlighting=attributes. + :) +declare + %test:pending("previously ignored; match-highlighting=attributes") + %test:assertTrue +function mhng:element-match-highlight-attributes() { + let $result := doc($mhng:COLLECTION || "/test.xml")//el[ngram:contains(., 'tree')]/util:expand(., 'highlight-matches=attributes') + return deep-equal($result, $mhng:EXPECTED_NONE) +}; + +(:~ + : [ngram] element match, match-highlighting=elements. + :) +declare + %test:assertTrue +function mhng:element-match-highlight-elements() { + let $result := doc($mhng:COLLECTION || "/test.xml")//el[ngram:contains(., 'tree')]/util:expand(., 'highlight-matches=elements') + return deep-equal($result, onetwo tree) +}; + +(:~ + : [ngram] element match, match-highlighting=both. (Previously ignored in XML; now runs.) + :) +declare + %test:assertTrue +function mhng:element-match-highlight-both() { + let $result := doc($mhng:COLLECTION || "/test.xml")//el[ngram:contains(., 'tree')]/util:expand(., 'highlight-matches=both') + return deep-equal($result, onetwo tree) +}; + +(:~ + : [ngram] attribute match, match-highlighting=none. + :) +declare + %test:assertTrue +function mhng:attribute-match-highlight-none() { + let $result := doc($mhng:COLLECTION || "/test.xml")//el[ngram:contains(@att, 'val')]/util:expand(., 'highlight-matches=none') + return deep-equal($result, $mhng:EXPECTED_NONE) +}; + +(:~ + : [ngram] attribute match, match-highlighting=attributes. + :) +declare + %test:pending("previously ignored; match-highlighting=attributes") + %test:assertTrue +function mhng:attribute-match-highlight-attributes() { + let $result := doc($mhng:COLLECTION || "/test.xml")//el[ngram:contains(@att, 'val')]/util:expand(., 'highlight-matches=attributes') + return deep-equal($result, onetwo tree) +}; + +(:~ + : [ngram] attribute match, match-highlighting=elements. + :) +declare + %test:assertTrue +function mhng:attribute-match-highlight-elements() { + let $result := doc($mhng:COLLECTION || "/test.xml")//el[ngram:contains(@att, 'val')]/util:expand(., 'highlight-matches=elements') + return deep-equal($result, $mhng:EXPECTED_NONE) +}; + +(:~ + : [ngram] attribute match, match-highlighting=both. + :) +declare + %test:pending("previously ignored; match-highlighting=both") + %test:assertTrue +function mhng:attribute-match-highlight-both() { + let $result := doc($mhng:COLLECTION || "/test.xml")//el[ngram:contains(@att, 'val')]/util:expand(., 'highlight-matches=both') + return deep-equal($result, onetwo tree) +}; diff --git a/extensions/indexes/ngram/src/test/xquery/ngram/matchHighlighting_ngram_Tests.xml b/extensions/indexes/ngram/src/test/xquery/ngram/matchHighlighting_ngram_Tests.xml deleted file mode 100644 index 1238260b018..00000000000 --- a/extensions/indexes/ngram/src/test/xquery/ngram/matchHighlighting_ngram_Tests.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - tests for match highlighting behaviour on different index types - -

These tests test whether matches are highlighted correctly. Tests are grouped - per index type supporting match highlighting (old FT, lucene FT, ngram), and - repeated -

    -
  • for matches in both elements and attributes
  • -
  • for each setting of highlight-matches: none, attributes, elements, both
  • -
- Note: the kind of index definition (qname / path) doesn't seem to effect this - behaviour, so for clarity's sake, only qname-based indexes are included in these tests. -

- Ron Van den Branden -
- - - - - - - - - - - - - - - - onetwo tree - - - - - - - - - [ngram] element match, match-highlighting=none - - - onetwo tree - - - - [ngram] element match, match-highlighting=attributes - - - onetwo tree - - - - [ngram] element match, match-highlighting=elements - - - onetwo tree - - - - [ngram] element match, match-highlighting=both - - - onetwo tree - - - - [ngram] attribute match, match-highlighting=none - - - onetwo tree - - - - [ngram] attribute match, match-highlighting=attributes - - - onetwo tree - - - - [ngram] attribute match, match-highlighting=elements - - - onetwo tree - - - - [ngram] attribute match, match-highlighting=both - - - onetwo tree - - -
diff --git a/extensions/indexes/ngram/src/test/xquery/ngram/unicode-supplementary-ngram.xql b/extensions/indexes/ngram/src/test/xquery/ngram/unicode-supplementary-ngram.xql new file mode 100644 index 00000000000..d23bd97c519 --- /dev/null +++ b/extensions/indexes/ngram/src/test/xquery/ngram/unicode-supplementary-ngram.xql @@ -0,0 +1,208 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; +(:~ + : XQsuite tests for ngram index handling of Supplementary Multilingual Plane (SMP) + : and Supplementary Ideographic Plane (SIP) characters. + : + : Verifies that ngram:contains finds all 20 SMP/SIP code points from issue #787, + : and that ngram:wildcard-contains(., '.') matches one supplementary character (no chopping). + : + : @see https://github.com/eXist-db/exist/issues/787 + : @see https://www.unicode.org/roadmaps/smp/ + :) + +module namespace unic-smp-n="http://exist-db.org/xquery/ngram/test/unic-smp-supplementary"; + +declare namespace test="http://exist-db.org/xquery/xqsuite"; + +(:~ + : All 20 SMP/SIP code points from issue #787, grouped as in the issue report. + : @return map with keys smp-indexed, smp-dropped, sip-indexed, sip-dropped; values are sequences of xs:integer codepoints + :) +declare variable $unic-smp-n:CODEPOINTS := map { + "smp-indexed": (65536, 66321, 66661, 68200, 68608), + "smp-dropped": (65797, 65930, 128336, 128512, 119558, 128267), + "sip-indexed": (131072, 131369, 145429, 170811, 178084), + "sip-dropped": (183618, 178231, 178671, 183785) +}; + +(:~ + : Flattened sequence of all codepoints in issue order (smp-indexed, smp-dropped, sip-indexed, sip-dropped). + : @return xs:integer* all 20 codepoints + :) +declare variable $unic-smp-n:ALL_CODEPOINTS := ( + $unic-smp-n:CODEPOINTS("smp-indexed"), + $unic-smp-n:CODEPOINTS("smp-dropped"), + $unic-smp-n:CODEPOINTS("sip-indexed"), + $unic-smp-n:CODEPOINTS("sip-dropped") +); + +(:~ + : Map from codepoint (xs:integer) to group name for informative test output and document attributes. + : @return map(xs:integer, xs:string) codepoint to "smp-indexed" | "smp-dropped" | "sip-indexed" | "sip-dropped" + :) +declare variable $unic-smp-n:CP_TO_GROUP := map:merge( + for $k in map:keys($unic-smp-n:CODEPOINTS) + return for $cp in $unic-smp-n:CODEPOINTS($k) return map:entry($cp, $k) +); + +(:~ + : Test document: one p per supplementary codepoint (with @group), plus two w elements for wildcard tests (one SMP, one SIP). + : @return document-node() root with 20 p children and 2 w children; each w has @which and one supplementary character + :) +declare variable $unic-smp-n:XML as document-node() := document { + { + for $cp in $unic-smp-n:ALL_CODEPOINTS + return

{ codepoints-to-string($cp) }

, + { codepoints-to-string($unic-smp-n:CODEPOINTS("smp-dropped")[4]) }, + { codepoints-to-string($unic-smp-n:CODEPOINTS("sip-dropped")[1]) } + }
+}; + +(:~ + : Collection configuration with ngram index on elements p and w. + : @return element(collection) eXist collection config + :) +declare variable $unic-smp-n:xconf := + + + + + + ; + +(:~ Name of the test collection (no path). :) +declare variable $unic-smp-n:COLLECTION_NAME := "unicode-supplementary-ngram"; + +(:~ Full path of the test collection. :) +declare variable $unic-smp-n:COLLECTION := "/db/" || $unic-smp-n:COLLECTION_NAME; + +(:~ + : XQsuite setUp: create test and config collections, store document and xconf, reindex. + :) +declare + %test:setUp +function unic-smp-n:setup() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $unic-smp-n:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $unic-smp-n:COLLECTION_NAME), + xmldb:store($unic-smp-n:COLLECTION, "test.xml", $unic-smp-n:XML), + xmldb:store("/db/system/config/db/" || $unic-smp-n:COLLECTION_NAME, "collection.xconf", $unic-smp-n:xconf), + xmldb:reindex($unic-smp-n:COLLECTION) ) +}; + +(:~ + : XQsuite tearDown: remove test collection and its config collection. + :) +declare + %test:tearDown +function unic-smp-n:tearDown() { + xmldb:remove($unic-smp-n:COLLECTION), + xmldb:remove("/db/system/config/db/" || $unic-smp-n:COLLECTION_NAME) +}; + +(:~ + : Counts how many codepoints in the given group ngram:contains finds. + : + : @param $group group name: smp-indexed | smp-dropped | sip-indexed | sip-dropped + : @return xs:string "group: count" e.g. "smp-indexed: 5" + :) +declare function unic-smp-n:ngram-contains-count($group as xs:string) as xs:string { + let $codepoints := $unic-smp-n:CODEPOINTS($group), + $found := sum( + for $cp in $codepoints + return if (count(collection($unic-smp-n:COLLECTION)//p[ngram:contains(., codepoints-to-string($cp))]) gt 0) + then 1 else 0 + ) + return $group || ": " || $found +}; + +(:~ + : Asserts that ngram:contains finds all supplementary characters in group smp-indexed (5 codepoints). + : @return xs:string "smp-indexed: 5" + :) +declare + %test:assertEquals("smp-indexed: 5") +function unic-smp-n:ngram-contains-supplementary-smp-indexed() { + unic-smp-n:ngram-contains-count("smp-indexed") +}; + +(:~ + : Asserts that ngram:contains finds all supplementary characters in group smp-dropped (6 codepoints). + : @return xs:string "smp-dropped: 6" + :) +declare + %test:assertEquals("smp-dropped: 6") +function unic-smp-n:ngram-contains-supplementary-smp-dropped() { + unic-smp-n:ngram-contains-count("smp-dropped") +}; + +(:~ + : Asserts that ngram:contains finds all supplementary characters in group sip-indexed (5 codepoints). + : @return xs:string "sip-indexed: 5" + :) +declare + %test:assertEquals("sip-indexed: 5") +function unic-smp-n:ngram-contains-supplementary-sip-indexed() { + unic-smp-n:ngram-contains-count("sip-indexed") +}; + +(:~ + : Asserts that ngram:contains finds all supplementary characters in group sip-dropped (4 codepoints). + : Pending until ngram fix for sip-dropped in issue #787. + : + : @return xs:string "sip-dropped: 4" + :) +declare + %test:pending("Ngram fails on sip-dropped characters, see #787") + %test:assertEquals("sip-dropped: 4") +function unic-smp-n:ngram-contains-supplementary-sip-dropped() { + unic-smp-n:ngram-contains-count("sip-dropped") +}; + +(:~ + : Asserts that ngram:wildcard-contains(., '.') matches the single w with SMP character (U+1F600). + : Uses the main test document (w elements); pending until ngram wildcard fix for #787. + : + : @return xs:integer 1 if one match + :) +declare + %test:pending("Ngram wildcard chops supplementary characters, see #787") + %test:assertEquals(1) +function unic-smp-n:ngram-wildcard-one-dot-smp() { + count(collection($unic-smp-n:COLLECTION)//w[@which eq "smp"][ngram:wildcard-contains(., '.')]) +}; + +(:~ + : Asserts that ngram:wildcard-contains(., '.') matches the single w with SIP character (U+2CD02). + : Uses the main test document (w elements); pending until ngram wildcard fix for #787. + : + : @return xs:integer 1 if one match + :) +declare + %test:pending("Ngram wildcard chops supplementary characters, see #787") + %test:assertEquals(1) +function unic-smp-n:ngram-wildcard-one-dot-sip() { + count(collection($unic-smp-n:COLLECTION)//w[@which eq "sip"][ngram:wildcard-contains(., '.')]) +}; diff --git a/extensions/indexes/range/src/test/xquery/range/conditions.xql b/extensions/indexes/range/src/test/xquery/range/conditions.xql index a3951eac99f..ad7ddf20baf 100644 --- a/extensions/indexes/range/src/test/xquery/range/conditions.xql +++ b/extensions/indexes/range/src/test/xquery/range/conditions.xql @@ -200,6 +200,7 @@ declare variable $ct:COLLECTION := "/db/" || $ct:COLLECTION_NAME; declare %test:setUp function ct:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", $ct:COLLECTION_NAME), xmldb:store("/db/system/config/db/" || $ct:COLLECTION_NAME, "collection.xconf", $ct:COLLECTION_CONFIG), xmldb:create-collection("/db", $ct:COLLECTION_NAME), diff --git a/extensions/indexes/range/src/test/xquery/range/field-type.xql b/extensions/indexes/range/src/test/xquery/range/field-type.xql index 05a6902dc86..6ba6493a770 100644 --- a/extensions/indexes/range/src/test/xquery/range/field-type.xql +++ b/extensions/indexes/range/src/test/xquery/range/field-type.xql @@ -60,6 +60,7 @@ declare variable $rt:NON_INDEXED_COLLECTION := "/db/" || $rt:NON_INDEXED_COLLECT declare %test:setUp function rt:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", $rt:INDEXED_COLLECTION_NAME), xmldb:store("/db/system/config/db/" || $rt:INDEXED_COLLECTION_NAME, "collection.xconf", $rt:COLLECTION_CONFIG), xmldb:create-collection("/db", $rt:INDEXED_COLLECTION_NAME), diff --git a/extensions/indexes/range/src/test/xquery/range/fields.xql b/extensions/indexes/range/src/test/xquery/range/fields.xql index 781f03448d8..157e86f87ca 100755 --- a/extensions/indexes/range/src/test/xquery/range/fields.xql +++ b/extensions/indexes/range/src/test/xquery/range/fields.xql @@ -84,6 +84,7 @@ declare variable $rt:COLLECTION := "/db/" || $rt:COLLECTION_NAME; declare %test:setUp function rt:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", $rt:COLLECTION_NAME), xmldb:store("/db/system/config/db/" || $rt:COLLECTION_NAME, "collection.xconf", $rt:COLLECTION_CONFIG), xmldb:create-collection("/db", $rt:COLLECTION_NAME), diff --git a/extensions/indexes/range/src/test/xquery/range/index-keys.xql b/extensions/indexes/range/src/test/xquery/range/index-keys.xql index b32d063d7e0..c4776f30a35 100644 --- a/extensions/indexes/range/src/test/xquery/range/index-keys.xql +++ b/extensions/indexes/range/src/test/xquery/range/index-keys.xql @@ -77,6 +77,7 @@ declare variable $rtik:COLLECTION := "/db/" || $rtik:COLLECTION_NAME; declare %test:setUp function rtik:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", $rtik:COLLECTION_NAME), xmldb:store("/db/system/config/db/" || $rtik:COLLECTION_NAME, "collection.xconf", $rtik:COLLECTION_CONFIG), xmldb:create-collection("/db", $rtik:COLLECTION_NAME), diff --git a/extensions/indexes/range/src/test/xquery/range/optimizer.xql b/extensions/indexes/range/src/test/xquery/range/optimizer.xql index ab6fa75b9f9..ba6ecd9255b 100644 --- a/extensions/indexes/range/src/test/xquery/range/optimizer.xql +++ b/extensions/indexes/range/src/test/xquery/range/optimizer.xql @@ -162,6 +162,7 @@ declare variable $ot:COLLECTION := "/db/" || $ot:COLLECTION_NAME; declare %test:setUp function ot:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", $ot:COLLECTION_NAME), xmldb:store("/db/system/config/db/" || $ot:COLLECTION_NAME, "collection.xconf", $ot:COLLECTION_CONFIG), xmldb:create-collection("/db", $ot:COLLECTION_NAME), diff --git a/extensions/indexes/range/src/test/xquery/range/range.xql b/extensions/indexes/range/src/test/xquery/range/range.xql index 38b4489bbc0..5313f7f4a27 100644 --- a/extensions/indexes/range/src/test/xquery/range/range.xql +++ b/extensions/indexes/range/src/test/xquery/range/range.xql @@ -107,6 +107,7 @@ declare variable $rt:DATA2 := declare %test:setUp function rt:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", "rangetest"), xmldb:store("/db/system/config/db/rangetest", "collection.xconf", $rt:COLLECTION_CONFIG), xmldb:create-collection("/db", "rangetest"), diff --git a/extensions/indexes/range/src/test/xquery/range/types.xql b/extensions/indexes/range/src/test/xquery/range/types.xql index d13c7c64872..32d3d815fbd 100644 --- a/extensions/indexes/range/src/test/xquery/range/types.xql +++ b/extensions/indexes/range/src/test/xquery/range/types.xql @@ -109,6 +109,7 @@ declare variable $tt:COLLECTION := "/db/" || $tt:COLLECTION_NAME; declare %test:setUp function tt:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", $tt:COLLECTION_NAME), xmldb:store("/db/system/config/db/" || $tt:COLLECTION_NAME, "collection.xconf", $tt:COLLECTION_CONFIG), xmldb:create-collection("/db", $tt:COLLECTION_NAME), diff --git a/extensions/indexes/range/src/test/xquery/range/unicode-supplementary-range.xql b/extensions/indexes/range/src/test/xquery/range/unicode-supplementary-range.xql new file mode 100644 index 00000000000..85d982b0fac --- /dev/null +++ b/extensions/indexes/range/src/test/xquery/range/unicode-supplementary-range.xql @@ -0,0 +1,179 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; +(:~ + : XQsuite tests for Range index handling of Supplementary Multilingual Plane (SMP) + : and Supplementary Ideographic Plane (SIP) characters. + : + : Verifies that the range index finds all 20 SMP/SIP code points from issue #787 + : (regression test; range is reported to work correctly with supplementary characters). + : + : @see https://github.com/eXist-db/exist/issues/787 + : @see https://www.unicode.org/roadmaps/smp/ + :) + +module namespace unic-smp-r="http://exist-db.org/xquery/range/test/unic-smp-supplementary"; + +import module namespace range="http://exist-db.org/xquery/range" at "java:org.exist.xquery.modules.range.RangeIndexModule"; +import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql"; + +(:~ + : All 20 SMP/SIP code points from issue #787, grouped as in the issue report. + : @return map with keys smp-indexed, smp-dropped, sip-indexed, sip-dropped; values are sequences of xs:integer codepoints + :) +declare variable $unic-smp-r:CODEPOINTS := map { + "smp-indexed": (65536, 66321, 66661, 68200, 68608), + "smp-dropped": (65797, 65930, 128336, 128512, 119558, 128267), + "sip-indexed": (131072, 131369, 145429, 170811, 178084), + "sip-dropped": (183618, 178231, 178671, 183785) +}; + +(:~ + : Flattened sequence of all codepoints in issue order (smp-indexed, smp-dropped, sip-indexed, sip-dropped). + : @return xs:integer* all 20 codepoints + :) +declare variable $unic-smp-r:ALL_CODEPOINTS := ( + $unic-smp-r:CODEPOINTS("smp-indexed"), + $unic-smp-r:CODEPOINTS("smp-dropped"), + $unic-smp-r:CODEPOINTS("sip-indexed"), + $unic-smp-r:CODEPOINTS("sip-dropped") +); + +(:~ + : Map from codepoint (xs:integer) to group name for informative test output and document attributes. + : @return map(xs:integer, xs:string) codepoint to "smp-indexed" | "smp-dropped" | "sip-indexed" | "sip-dropped" + :) +declare variable $unic-smp-r:CP_TO_GROUP := map:merge( + for $k in map:keys($unic-smp-r:CODEPOINTS) + return for $cp in $unic-smp-r:CODEPOINTS($k) return map:entry($cp, $k) +); + +(:~ + : Test document: one p per supplementary codepoint, with group attribute retained. + : @return document-node() root with 20 p children, each p has @group and one supplementary character + :) +declare variable $unic-smp-r:XML as document-node() := document { + { + for $cp in $unic-smp-r:ALL_CODEPOINTS + return

{ codepoints-to-string($cp) }

+ }
+}; + +(:~ + : Collection configuration with range index on element p (xs:string). + : @return element(collection) eXist collection config + :) +declare variable $unic-smp-r:xconf := + + + + + + + ; + +(:~ Name of the test collection (no path). :) +declare variable $unic-smp-r:COLLECTION_NAME := "unicode-supplementary-range"; + +(:~ Full path of the test collection. :) +declare variable $unic-smp-r:COLLECTION := "/db/" || $unic-smp-r:COLLECTION_NAME; + +(:~ + : XQsuite setUp: create test and config collections, store document and xconf, reindex. + :) +declare + %test:setUp +function unic-smp-r:setup() { + ( xmldb:create-collection("/db/system", "config"), + xmldb:create-collection("/db/system/config", "db"), + xmldb:create-collection("/db", $unic-smp-r:COLLECTION_NAME), + xmldb:create-collection("/db/system/config/db", $unic-smp-r:COLLECTION_NAME), + xmldb:store($unic-smp-r:COLLECTION, "test.xml", $unic-smp-r:XML), + xmldb:store("/db/system/config/db/" || $unic-smp-r:COLLECTION_NAME, "collection.xconf", $unic-smp-r:xconf), + xmldb:reindex($unic-smp-r:COLLECTION) ) +}; + +(:~ + : XQsuite tearDown: remove test collection and its config collection. + :) +declare + %test:tearDown +function unic-smp-r:tearDown() { + xmldb:remove($unic-smp-r:COLLECTION), + xmldb:remove("/db/system/config/db/" || $unic-smp-r:COLLECTION_NAME) +}; + +(:~ + : Counts how many codepoints in the given group the range index finds (range:eq). + : + : @param $group group name: smp-indexed | smp-dropped | sip-indexed | sip-dropped + : @return xs:string "group: count" e.g. "smp-indexed: 5" + :) +declare function unic-smp-r:range-finds-count($group as xs:string) as xs:string { + let $codepoints := $unic-smp-r:CODEPOINTS($group), + $found := sum( + for $cp in $codepoints + return if (count(collection($unic-smp-r:COLLECTION)//p[range:eq(., codepoints-to-string($cp))]) gt 0) + then 1 else 0 + ) + return $group || ": " || $found +}; + +(:~ + : Asserts that the range index finds all supplementary characters in group smp-indexed (5 codepoints). + : @return xs:string "smp-indexed: 5" + :) +declare + %test:assertEquals("smp-indexed: 5") +function unic-smp-r:range-finds-supplementary-smp-indexed() { + unic-smp-r:range-finds-count("smp-indexed") +}; + +(:~ + : Asserts that the range index finds all supplementary characters in group smp-dropped (6 codepoints). + : @return xs:string "smp-dropped: 6" + :) +declare + %test:assertEquals("smp-dropped: 6") +function unic-smp-r:range-finds-supplementary-smp-dropped() { + unic-smp-r:range-finds-count("smp-dropped") +}; + +(:~ + : Asserts that the range index finds all supplementary characters in group sip-indexed (5 codepoints). + : @return xs:string "sip-indexed: 5" + :) +declare + %test:assertEquals("sip-indexed: 5") +function unic-smp-r:range-finds-supplementary-sip-indexed() { + unic-smp-r:range-finds-count("sip-indexed") +}; + +(:~ + : Asserts that the range index finds all supplementary characters in group sip-dropped (4 codepoints). + : @return xs:string "sip-dropped: 4" + :) +declare + %test:assertEquals("sip-dropped: 4") +function unic-smp-r:range-finds-supplementary-sip-dropped() { + unic-smp-r:range-finds-count("sip-dropped") +}; diff --git a/extensions/indexes/range/src/test/xquery/range/updates.xql b/extensions/indexes/range/src/test/xquery/range/updates.xql index ca2b10e941e..24624a39d36 100644 --- a/extensions/indexes/range/src/test/xquery/range/updates.xql +++ b/extensions/indexes/range/src/test/xquery/range/updates.xql @@ -87,6 +87,7 @@ declare variable $rt:DATA := declare %test:setUp function rt:setup() { + (xmldb:create-collection("/db/system", "config"), xmldb:create-collection("/db/system/config", "db")), xmldb:create-collection("/db/system/config/db", "rangetest"), xmldb:store("/db/system/config/db/rangetest", "collection.xconf", $rt:COLLECTION_CONFIG), xmldb:create-collection("/db", "rangetest"),