jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From thom...@apache.org
Subject svn commit: r1170199 - in /jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src: main/java/org/apache/jackrabbit/spi2microkernel/ test/java/org/apache/jackrabbit/spi2microkernel/ test/resources/
Date Tue, 13 Sep 2011 14:41:43 GMT
Author: thomasm
Date: Tue Sep 13 14:41:42 2011
New Revision: 1170199

URL: http://svn.apache.org/viewvc?rev=1170199&view=rev
Log:
Simple query processor

Added:
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/QueryTest.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/resources/queryPlans.txt
Modified:
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryInfoImpl.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryInfoImpl.java?rev=1170199&r1=1170198&r2=1170199&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryInfoImpl.java
(original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryInfoImpl.java
Tue Sep 13 14:41:42 2011
@@ -18,47 +18,75 @@
  */
 package org.apache.jackrabbit.spi2microkernel;
 
+import java.util.ArrayList;
 import javax.jcr.RangeIterator;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.QValue;
 import org.apache.jackrabbit.spi.QueryInfo;
+import org.apache.jackrabbit.spi.QueryResultRow;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * A query result.
  */
 public class QueryInfoImpl implements QueryInfo {
 
+    static final Logger log = LoggerFactory.getLogger(QueryInfoImpl.class);
+
+    private final String[] columnNames;
+    private final Name[] selectorNames;
+    final ArrayList<QueryResultRow> result = new ArrayList<QueryResultRow>();
+
+    QueryInfoImpl(String[] columnNames, Name[] selectorNames) {
+        this.columnNames = columnNames;
+        this.selectorNames = selectorNames;
+    }
+
+    void addRow(QueryResultRowImpl row) {
+        result.add(row);
+    }
+
     @Override
     public String[] getColumnNames() {
-        return new String[0];
+        return columnNames;
+    }
+
+    @Override
+    public Name[] getSelectorNames() {
+        return selectorNames;
     }
 
     @Override
     public RangeIterator getRows() {
         return new RangeIterator() {
 
+            int pos = 0;
+
             @Override
             public long getPosition() {
-                return 0;
+                return pos;
             }
 
             @Override
             public long getSize() {
-                return 0;
+                return result.size();
             }
 
             @Override
             public void skip(long x) {
-                // ignore
+                pos += x;
             }
 
             @Override
             public boolean hasNext() {
-                return false;
+                return pos < result.size();
             }
 
             @Override
-            public Object next() {
-                return null;
+            public QueryResultRow next() {
+                return result.get(pos++);
             }
 
             @Override
@@ -69,9 +97,34 @@ public class QueryInfoImpl implements Qu
         };
     }
 
-    @Override
-    public Name[] getSelectorNames() {
-        return new Name[0];
+    static class QueryResultRowImpl implements QueryResultRow {
+
+        private final NodeId node;
+        private final QValue[] values;
+
+        QueryResultRowImpl(NodeId node, QValue[] values) {
+            this.node = node;
+            this.values = values;
+        }
+
+        @Override
+        public NodeId getNodeId(Name selectorName) {
+            log.info("getNodeId " + selectorName);
+            return node;
+        }
+
+        @Override
+        public double getScore(Name selectorName) {
+            log.info("getScore " + selectorName);
+            return 0.5;
+        }
+
+        @Override
+        public QValue[] getValues() {
+            log.info("getValues");
+            return values;
+        }
+
     }
 
 }

Added: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java?rev=1170199&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java
(added)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java
Tue Sep 13 14:41:42 2011
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.spi2microkernel;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.mk.index.Indexer;
+import org.apache.jackrabbit.mk.index.PrefixIndex;
+import org.apache.jackrabbit.mk.index.PropertyIndex;
+import org.apache.jackrabbit.mk.util.PathUtils;
+import org.apache.jackrabbit.spi.IdFactory;
+import org.apache.jackrabbit.spi.ItemInfo;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NameFactory;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.PropertyInfo;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.QValueFactory;
+import org.apache.jackrabbit.spi.QueryInfo;
+import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A tool to run a list of hardcoded queries.
+ */
+public class QueryProcessor {
+
+    static final Logger log = LoggerFactory.getLogger(QueryProcessor.class);
+
+    final RepositoryServiceImpl rep;
+    final MicroKernel microKernel;
+    final Indexer indexer;
+    final IdFactory idFactory;
+    final QValueFactory vf;
+
+    private final String QUERY_PLANS = "queryPlans.txt";
+    private long lastModified;
+
+    private ArrayList<QueryPlan> queryPlans = new ArrayList<QueryPlan>();
+    private HashMap<String, Index> indexes = new HashMap<String, Index>();
+
+    public QueryProcessor(MicroKernel microKernel, Indexer indexer, RepositoryServiceImpl
rep) throws RepositoryException {
+        this.rep = rep;
+        this.microKernel = microKernel;
+        this.indexer = indexer;
+        this.idFactory = rep.getIdFactory();
+        this.vf = rep.getQValueFactory();
+    }
+
+    public String[] checkQueryStatement(String language, String statement, Map<String,
String> namespaces) {
+        log.info("checkQueryStatement " + language + " " + statement);
+        loadQueryPlans();
+        return new String[0];
+    }
+
+    public QueryInfo executeQuery(SessionInfo sessionInfo, String statement, String language,
+            Map<String, String> namespaces, long limit, long offset, Map<String,
QValue> values) throws RepositoryException {
+        loadQueryPlans();
+        log.info("executeQuery " + language + " " + statement);
+        for (QueryPlan plan : queryPlans) {
+            if (plan.matches(language, statement)) {
+                log.info("using plan " + plan.toString());
+                return plan.execute(sessionInfo);
+            }
+        }
+        log.warn("unknown query " + language + " " + statement);
+        return new QueryInfoImpl(new String[0], new Name[0]);
+    }
+
+    private void loadQueryPlans() {
+        long last = new File(QUERY_PLANS).lastModified();
+        if (queryPlans.size() != 0 && last == lastModified) {
+            return;
+        }
+        queryPlans.clear();
+        try {
+            lastModified = last;
+            InputStream in;
+            if (new File(QUERY_PLANS).exists()) {
+                in = new FileInputStream(QUERY_PLANS);
+            } else {
+                in = getClass().getClassLoader().getResourceAsStream(QUERY_PLANS);
+            }
+            LineNumberReader r = new LineNumberReader(new InputStreamReader(in));
+            while (true) {
+                String line = r.readLine();
+                if (line == null) {
+                    break;
+                } else if (line.startsWith("#")) {
+                    continue;
+                }
+                if (line.equals("plan")) {
+                    QueryPlan plan = new QueryPlan();
+                    plan.queryPattern = r.readLine().trim();
+                    String indexName = r.readLine().trim();
+                    plan.index = indexes.get(indexName);
+                    plan.propertyValue = r.readLine().trim();
+                    plan.columnNames = r.readLine().trim().split(",");
+                    plan.selectorNames = new Name[plan.columnNames.length];
+                    String[] sel = r.readLine().trim().split(",");
+                    NameFactory f = NameFactoryImpl.getInstance();
+                    for (int i=0; i<sel.length; i++) {
+                        String[] s = sel[i].split(":");
+                        Name n = s.length > 1 ? f.create(s[0], s[1]) : f.create(s[0]);
+                        plan.selectorNames[i] = n;
+                    }
+                    queryPlans.add(plan);
+                    log.info("query plan " + plan.toString());
+                } else if (line.equals("index")) {
+                    Index index = new Index();
+                    index.name = r.readLine().trim();
+                    index.type = r.readLine().trim();
+                    index.unique = r.readLine().trim().equals("unique");
+                    if (!indexes.containsKey(index.name)) {
+                        index.open();
+                        indexes.put(index.name, index);
+                        log.info("index " + index);
+                    }
+                }
+            }
+            r.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+            log.warn("loadQueryPlans", e);
+        }
+    }
+
+    class Index {
+        String name;
+        String type;
+        boolean unique;
+        PropertyIndex propertyIndex;
+        PrefixIndex prefixIndex;
+
+        void open() throws IOException {
+            if (type.equals("propertyIndex")) {
+                propertyIndex = indexer.createPropertyIndex(name, unique);
+            } else if (type.equals("prefixIndex")) {
+                prefixIndex = indexer.createPrefixIndex(name);
+            } else {
+                throw new IOException("Invalid index type: " + type);
+            }
+        }
+
+        public String toString() {
+            return name + " type:" + type + " unique:" + unique;
+        }
+    }
+
+    class QueryPlan {
+        String queryPattern;
+        Index index;
+        String propertyValue;
+        String[] columnNames;
+        Name[] selectorNames;
+
+        boolean matches(String language, String query) {
+            return query.trim().matches(queryPattern.trim());
+        }
+
+        public String toString() {
+            return queryPattern + " index:" + index.name + " columnNames:" + Arrays.toString(columnNames)
+ " propertyNames:" + Arrays.toString(selectorNames) + " propertyValue:" + propertyValue;
+        }
+
+        public QueryInfo execute(SessionInfo sessionInfo) throws RepositoryException {
+            QueryInfoImpl result = new QueryInfoImpl(columnNames, selectorNames);
+            if (index.propertyIndex != null) {
+                String v = propertyValue.length() == 0 ? null : propertyValue;
+                Iterator<String> paths = index.propertyIndex.getPaths(v, microKernel
+                        .getHeadRevision());
+                while (paths.hasNext()) {
+                    String path = paths.next();
+                    path = path.substring(PathUtils.getNextSlash(path, 1));
+                    NodeId node = idFactory.createNodeId((String) null, Paths.stringToPath(path));
+                    log.info("  row: " + path + " " + node);
+                    Iterator<? extends ItemInfo> it = rep.getItemInfos(sessionInfo,
node);
+                    HashMap<String, QValue> values = new HashMap<String, QValue>();
+                    while (it.hasNext()) {
+                        ItemInfo info = it.next();
+                        if (!info.denotesNode()) {
+                            PropertyInfo p = (PropertyInfo) rep.getItemInfos(sessionInfo,
+                                    info.getId()).next();
+                            String propertyName = p.getPath().getLastElement().getName().toString();
+                            values.put(propertyName, p.getValues()[0]);
+                        }
+                    }
+                    QValue[] valueList = new QValue[selectorNames.length];
+                    for (int i = 0; i < selectorNames.length; i++) {
+                        Name selector = selectorNames[i];
+                        valueList[i] = values.get(selector.toString());
+                    }
+                    QueryInfoImpl.QueryResultRowImpl row = new QueryInfoImpl.QueryResultRowImpl(node,
valueList);
+                    result.addRow(row);
+                }
+            }
+            return result;
+        }
+
+    }
+
+}

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java?rev=1170199&r1=1170198&r2=1170199&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java
(original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java
Tue Sep 13 14:41:42 2011
@@ -189,6 +189,7 @@ public class RepositoryServiceImpl exten
     private final NodeTypeStore nodeTypeStore;
     private final String defaultWorkspace;
     private final String systemWorkspace;
+    private final QueryProcessor queryProcessor;
 
     public RepositoryServiceImpl(MicroKernel microKernel, Map<?, ?> parameters) throws
RepositoryException {
         super(DESCRIPTORS, Collections.<String, String>emptyMap(), new QNodeTypeDefinition[0]);
@@ -215,6 +216,7 @@ public class RepositoryServiceImpl exten
             jcrUuidIndex = indexer.createPropertyIndex("{jcr}uuid", true);
             referenceIndex = indexer.createPrefixIndex(Values.typePrefix(PropertyType.REFERENCE));
             weakReferenceIndex = indexer.createPrefixIndex(Values.typePrefix(PropertyType.WEAKREFERENCE));
+            queryProcessor = new QueryProcessor(microKernel, indexer, this);
         }
         catch (MicroKernelException e) {
             throw new RepositoryException(e.getMessage(), e);
@@ -877,17 +879,15 @@ public class RepositoryServiceImpl exten
                                     String language, Map<String, String> namespaces)
throws
             InvalidQueryException, RepositoryException {
         checkSessionInfo(sessionInfo);
-        log.warn("checkQueryStatement " + language + " " + statement);
-        return new String[0];
-        // throw new UnsupportedRepositoryOperationException();
+        return queryProcessor.checkQueryStatement(statement, language, namespaces);
     }
 
     public QueryInfo executeQuery(SessionInfo sessionInfo, String statement,
                                   String language, Map<String, String> namespaces,
long limit,
                                   long offset, Map<String, QValue> values) throws RepositoryException
{
         checkSessionInfo(sessionInfo);
-        log.warn("executeQuery " + language + " " + statement);
-        return new QueryInfoImpl();
+        return queryProcessor.executeQuery(sessionInfo, statement, language, namespaces,
limit,
+                                  offset, values);
     }
 
 }

Added: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/QueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/QueryTest.java?rev=1170199&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/QueryTest.java
(added)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/QueryTest.java
Tue Sep 13 14:41:42 2011
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.apache.jackrabbit.spi2microkernel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import java.util.Collections;
+import java.util.Iterator;
+import javax.imageio.spi.ServiceRegistry;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class QueryTest {
+    private static final String BASE_URL = "fs:target/repository-test/repository";
+    private static long counter = System.currentTimeMillis();
+
+    private Repository repository;
+    private Session session;
+
+    private static String getMkUrl(boolean clean) {
+        // XXX: This is a workaround for the missing dispose of the
+        // microkernel from within the repository.
+        if (clean) {
+            counter++;
+        }
+        return BASE_URL + counter + (clean ? ";clean" : "");
+    }
+
+    @Before
+    public void setup() throws RepositoryException {
+        Session s = getSession();
+        s.getWorkspace().getNamespaceRegistry().registerNamespace("test", "test");
+        s.save();
+    }
+
+    @After
+    public void tearDown() {
+        if (session != null) {
+            session.logout();
+            session = null;
+        }
+    }
+
+    @Test
+    public void queryTest() throws RepositoryException {
+        Session s = getSession();
+        Node test;
+        test = s.getRootNode().addNode("test");
+        test.setProperty("test:vanityPath", "/a");
+        test.setProperty("test:redirect", "/content/a");
+        s.save();
+        test = s.getRootNode().addNode("test2");
+        test.setProperty("test:vanityPath", "/b");
+        test.setProperty("test:redirect", "/content/a");
+        s.save();
+        Query q = s.getWorkspace().getQueryManager().createQuery(
+                "SELECT test:vanityPath, test:redirect FROM test:VanityPath", Query.JCR_SQL2);
+        QueryResult res = q.execute();
+        NodeIterator it = res.getNodes();
+        Node n = it.nextNode();
+        assertEquals("/test", n.getPath());
+        n = it.nextNode();
+        assertEquals("/test2", n.getPath());
+    }
+
+    @Test
+    public void createRepository() throws RepositoryException {
+        Repository repository = getRepository();
+        assertNotNull(repository);
+    }
+
+    private Session getSession() throws RepositoryException {
+        if (session == null) {
+            session = getRepository().login();
+        }
+        return session;
+    }
+
+    private Repository getRepository() throws RepositoryException {
+        if (repository == null) {
+            Iterator<RepositoryFactory> factories = ServiceRegistry.lookupProviders(RepositoryFactory.class);
+            while (repository == null && factories.hasNext()) {
+                RepositoryFactory factory = factories.next();
+                repository = factory.getRepository(Collections.singletonMap(
+                        Spi2MicrokernelRepositoryServiceFactory.PARAM_URL, getMkUrl(false)));
+            }
+        }
+
+        return repository;
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/resources/queryPlans.txt
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/resources/queryPlans.txt?rev=1170199&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/resources/queryPlans.txt
(added)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/resources/queryPlans.txt
Tue Sep 13 14:41:42 2011
@@ -0,0 +1,13 @@
+# vanity urls ======================
+index
+{test}vanityPath
+propertyIndex
+nonUnique
+
+plan
+SELECT test:vanityPath, test:redirect FROM test:VanityPath
+{test}vanityPath
+
+testPath,redirect
+test:vanityPath,test:redirect
+



Mime
View raw message