Package org.exist.xquery

Source Code of org.exist.xquery.OptimizerTest

/*
*  eXist Open Source Native XML Database
*  Copyright (C) 2001-07 The eXist Project
*  http://exist-db.org
*
*  This program 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
*  of the License, or (at your option) any later version.
*
*  This program 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 program; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*
*  $Id$
*/
package org.exist.xquery;

import org.exist.TestUtils;
import org.exist.storage.BrokerPool;
import org.exist.util.Configuration;
import org.exist.util.XMLFilenameFilter;
import org.exist.xmldb.DatabaseInstanceManager;
import org.exist.xmldb.IndexQueryService;
import org.exist.xmldb.XmldbURI;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.xmldb.api.DatabaseManager;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.Database;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.CollectionManagementService;
import org.xmldb.api.modules.XMLResource;
import org.xmldb.api.modules.XQueryService;

import java.io.File;
import java.io.IOException;

/**
*
*/
public class OptimizerTest {

    private final static String OPTIMIZE = "declare option exist:optimize 'enable=yes';";
    private final static String NO_OPTIMIZE = "declare option exist:optimize 'enable=no';";
    private final static String NAMESPACES = "declare namespace mods='http://www.loc.gov/mods/v3';";

    private static final String MSG_OPT_ERROR = "Optimized query should return same number of results.";

    private final static String XML =
            "<root>" +
            "   <a><b>one</b></a>" +
            "   <a><c><b>one</b></c></a>" +
            "   <c><a><c><b>two</b></c></a></c>" +
            "</root>";

    private final static String COLLECTION_CONFIG =
        "<collection xmlns=\"http://exist-db.org/collection-config/1.0\">" +
      "  <index xmlns:mods=\"http://www.loc.gov/mods/v3\">" +
      "    <lucene>" +
        "           <text qname=\"LINE\"/>" +
        "           <text qname=\"SPEAKER\"/>" +
        "    </lucene>" +
      "    <create qname=\"b\" type=\"xs:string\"/>" +
        "        <create qname=\"SPEAKER\" type=\"xs:string\"/>" +
        "        <create qname=\"mods:internetMediaType\" type=\"xs:string\"/>" +
        "  </index>" +
      "</collection>";
    private static Collection testCollection;

    @Test
    public void nestedQuery() {
        execute("/root/a[descendant::b = 'one']", true, "Inner b node should be returned.", 2);
        execute("/root/a[b = 'one']", true, "Inner b node should not be returned.", 1);
        execute("/root/a[b = 'one']", false, "Inner b node should not be returned.", 1);
    }

    @Test
    public void simplePredicates() {
        int r = execute("//SPEECH[ft:query(LINE, 'king')]", false);
        execute("//SPEECH[ft:query(LINE, 'king')]", true, MSG_OPT_ERROR, r);

        r = execute("//SPEECH[SPEAKER = 'HAMLET']", false);
        execute("//SPEECH[SPEAKER = 'HAMLET']", true, MSG_OPT_ERROR, r);

        r = execute("//SPEECH[descendant::SPEAKER = 'HAMLET']", false);
        execute("//SPEECH[descendant::SPEAKER = 'HAMLET']", true, MSG_OPT_ERROR, r);
       
        r = execute("//SCENE[ft:query(descendant::LINE, 'king')]", false);
        execute("//SCENE[ft:query(descendant::LINE, 'king')]", true, MSG_OPT_ERROR, r);

        r = execute("//LINE[ft:query(., 'king')]", false);
        execute("//LINE[ft:query(., 'king')]", true, MSG_OPT_ERROR, r);

        r = execute("//SPEAKER[. = 'HAMLET']", false);
        execute("//SPEAKER[. = 'HAMLET']", true, MSG_OPT_ERROR, r);

//        r = execute("//LINE[descendant-or-self::LINE &= 'king']", false);
//        execute("//LINE[descendant-or-self::LINE &= 'king']", true, MSG_OPT_ERROR, r);

        r = execute("//SPEAKER[descendant-or-self::SPEAKER = 'HAMLET']", false);
        execute("//SPEAKER[descendant-or-self::SPEAKER = 'HAMLET']", true, MSG_OPT_ERROR, r);

        r = execute("//SPEECH/LINE[ft:query(., 'king')]", false);
        execute("//SPEECH/LINE[ft:query(., 'king')]", true, MSG_OPT_ERROR, r);
       
        r = execute("//*[ft:query(LINE, 'king')]", false);
        execute("//*[ft:query(LINE, 'king')]", true, MSG_OPT_ERROR, r);

        r = execute("//*[SPEAKER = 'HAMLET']", false);
        execute("//*[SPEAKER = 'HAMLET']", true, MSG_OPT_ERROR, r);
    }

    @Test
    public void simplePredicatesRegex() {
        int r = execute("//SPEECH[matches(SPEAKER, '^HAM.*')]", false);
        execute("//SPEECH[matches(SPEAKER, '^HAM.*')]", true, MSG_OPT_ERROR, r);
        r = execute("//SPEECH[starts-with(SPEAKER, 'HAML')]", false);
        execute("//SPEECH[starts-with(SPEAKER, 'HAML')]", true, MSG_OPT_ERROR, r);
        r = execute("//SPEECH[ends-with(SPEAKER, 'EO')]", false);
        execute("//SPEECH[ends-with(SPEAKER, 'EO')]", true, MSG_OPT_ERROR, r);
        r = execute("//SPEECH[matches(descendant::SPEAKER, 'HAML.*')]", false);
        execute("//SPEECH[matches(descendant::SPEAKER, 'HAML.*')]", true, MSG_OPT_ERROR, r);
    }

    @Test
    public void twoPredicates() {
        int r = execute("//SPEECH[ft:query(LINE, 'king')][SPEAKER='HAMLET']", false);
        execute("//SPEECH[ft:query(LINE, 'king')][SPEAKER='HAMLET']", true, MSG_OPT_ERROR, r);
        r = execute("//SPEECH[SPEAKER='HAMLET'][ft:query(LINE, 'king')]", false);
        execute("//SPEECH[SPEAKER='HAMLET'][ft:query(LINE, 'king')]", true, MSG_OPT_ERROR, r);
    }

    @Test
    public void twoPredicatesNPEBug808() {
        // Bug #808 NPE $docs[ngram:contains(first, "luke")][ngram:contains(last, "sky")]
        int r = execute("let $sps := collection('/db/test')//SPEECH return $sps[ngram:contains(SPEAKER, 'HAMLET')][ngram:contains(LINE, 'king')]", false);
        execute("let $sps := collection('/db/test')//SPEECH return $sps[ngram:contains(SPEAKER, 'HAMLET')][ngram:contains(LINE, 'king')]", true, MSG_OPT_ERROR, r);
    }

    @Test
    public void noOptimization() {
        int r = execute("/root//b[parent::c/b = 'two']", false);
        Assert.assertEquals(1, r);
        execute("/root//b[parent::c/b = 'two']", true, "Parent axis should not be optimized.", r);
       
        r = execute("/root//b[ancestor::a/c/b = 'two']", false);
        Assert.assertEquals(1, r);
        execute("/root//b[ancestor::a/c/b = 'two']", true, "Ancestor axis should not be optimized.", r);

        r = execute("/root//b[ancestor::a/b = 'two']", false);
        Assert.assertEquals(0, r);
        execute("/root//b[ancestor::a/b = 'two']", true, "Ancestor axis should not be optimized.", r);

        r = execute("/root//b[text()/parent::b = 'two']", false);
        Assert.assertEquals(1, r);
        execute("/root//b[text()/parent::b = 'two']", true, "Parent axis should not be optimized.", r);

        r = execute("/root//b[matches(text()/parent::b, 'two')]", false);
        Assert.assertEquals(1, r);
        execute("/root//b[matches(text()/parent::b, 'two')]", true, "Parent axis should not be optimized.", r);
    }

    @Test
    public void reversePaths() {

        int r = execute("/root//b/parent::c[b = 'two']", false);
        Assert.assertEquals(1, r);
        execute("/root//b/parent::c[b = 'two']", true, MSG_OPT_ERROR, r);
    }

    @Test @Ignore
    public void reversePathsWithWildcard() {
        //parent with wildcard
        int r = execute("/root//b/parent::*[b = 'two']", false);
        Assert.assertEquals(1, r);
        execute("/root//b/parent::*[b = 'two']", true, MSG_OPT_ERROR, r);
    }

    @Test
    public void booleanOperator() {
        int r = execute("//SPEECH[ft:query(LINE, 'king')][SPEAKER='HAMLET']", false);
        execute("//SPEECH[ft:query(LINE, 'king') and SPEAKER='HAMLET']", false, MSG_OPT_ERROR, r);
        execute("//SPEECH[ft:query(LINE, 'king') and SPEAKER='HAMLET']", true, MSG_OPT_ERROR, r);
        r = execute("//SPEECH[ft:query(LINE, 'king') or SPEAKER='HAMLET']", false);
        execute("//SPEECH[ft:query(LINE, 'king') or SPEAKER='HAMLET']", true, MSG_OPT_ERROR, r);

        r = execute("//SPEECH[ft:query(LINE, 'love') and ft:query(LINE, \"woman's\") and SPEAKER='HAMLET']", false);
        execute("//SPEECH[ft:query(LINE, 'love') and ft:query(LINE, \"woman's\") and SPEAKER='HAMLET']", true, MSG_OPT_ERROR, r);

        r = execute("//SPEECH[(ft:query(LINE, 'king') or ft:query(LINE, 'love')) and SPEAKER='HAMLET']", false);
        execute("//SPEECH[(ft:query(LINE, 'king') or ft:query(LINE, 'love')) and SPEAKER='HAMLET']", true, MSG_OPT_ERROR, r);

        r = execute("//SPEECH[(ft:query(LINE, 'juliet') and ft:query(LINE, 'romeo')) or SPEAKER='HAMLET']", false);
        Assert.assertEquals(368, r);
        execute("//SPEECH[(ft:query(LINE, 'juliet') and ft:query(LINE, 'romeo')) or SPEAKER='HAMLET']", true, MSG_OPT_ERROR, r);


        execute("//SPEECH[true() and false()]", true, MSG_OPT_ERROR, 0);
        execute("//SPEECH[true() and true()]", true, MSG_OPT_ERROR, 2628);
    }

    private int execute(String query, boolean optimize) {
        try {
            System.out.println("--- Query: " + query + "; Optimize: " + Boolean.toString(optimize));
            XQueryService service = (XQueryService) testCollection.getService("XQueryService", "1.0");
            if (optimize)
                query = OPTIMIZE + query;
            else
                query = NO_OPTIMIZE + query;
            query = NAMESPACES + query;
            ResourceSet result = service.query(query);
            System.out.println("-- Found: " + result.getSize());
            return (int) result.getSize();
        } catch (XMLDBException e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
        return 0;
    }

    private void execute(String query, boolean optimize, String message, int expected) {
        try {
            System.out.println("--- Query: " + query + "; Optimize: " + Boolean.toString(optimize));
            XQueryService service = (XQueryService) testCollection.getService("XQueryService", "1.0");
            if (optimize)
                query = NAMESPACES + OPTIMIZE + query;
            else
                query = NAMESPACES + NO_OPTIMIZE + query;
            ResourceSet result = service.query(query);
            System.out.println("-- Found: " + result.getSize());
            Assert.assertEquals(message, expected, result.getSize());
        } catch (XMLDBException e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
    }
   
    @BeforeClass
    public static void initDatabase() {
    try {
      //Since we use the deprecated text:match-all() function, we have to be sure is is enabled
            Configuration config = new Configuration();
            config.setProperty(FunctionFactory.PROPERTY_DISABLE_DEPRECATED_FUNCTIONS, new Boolean(false));
            BrokerPool.configure(1, 5, config);
           
      // initialize driver
      Class<?> cl = Class.forName("org.exist.xmldb.DatabaseImpl");
      Database database = (Database) cl.newInstance();
      database.setProperty("create-database", "true");
      DatabaseManager.registerDatabase(database);

      Collection root = DatabaseManager.getCollection(XmldbURI.LOCAL_DB, "admin", "");
      CollectionManagementService service =
        (CollectionManagementService) root.getService("CollectionManagementService", "1.0");
      testCollection = service.createCollection("test");
      Assert.assertNotNull(testCollection);

            IndexQueryService idxConf = (IndexQueryService) testCollection.getService("IndexQueryService", "1.0");
            idxConf.configureCollection(COLLECTION_CONFIG);
           
            XMLResource resource = (XMLResource) testCollection.createResource("test.xml", "XMLResource");
            resource.setContent(XML);
            testCollection.storeResource(resource);

            String existHome = System.getProperty("exist.home");
            File existDir = existHome==null ? new File(".") : new File(existHome);
            File dir = new File(existDir, "samples/shakespeare");
            if (!dir.canRead())
                throw new IOException("Unable to read samples directory");
            File[] files = dir.listFiles(new XMLFilenameFilter());
            for (File file : files) {
                System.out.println("Create resource from "+file.getAbsolutePath());
                resource = (XMLResource) testCollection.createResource(file.getName(), "XMLResource");
                resource.setContent(file);
                testCollection.storeResource(resource);
            }
        } catch (Exception e) {
      e.printStackTrace();
            Assert.fail(e.getMessage());
        }
  }

    @AfterClass
    public static void shutdownDB() {
        try {
            TestUtils.cleanupDB();
            DatabaseInstanceManager dim =
                (DatabaseInstanceManager) testCollection.getService(
                    "DatabaseInstanceManager", "1.0");
            dim.shutdown();
        } catch (XMLDBException e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
        testCollection = null;

    System.out.println("tearDown PASSED");
  }
}
TOP

Related Classes of org.exist.xquery.OptimizerTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.