[dna-commits] DNA SVN: r1455 - in trunk: dna-integration-tests/src/test/resources and 2 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Thu Dec 17 20:54:27 EST 2009


Author: rhauch
Date: 2009-12-17 20:54:27 -0500 (Thu, 17 Dec 2009)
New Revision: 1455

Modified:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryEngine.java
   trunk/dna-integration-tests/src/test/resources/log4j.properties
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
Log:
DNA-468 Completed more of the integration, including the addition of the mandatory 'jcr:path' and 'jcr:score' so-called 'pseudo-columns' to the results for XPath queries.  However, there still are issues with the TCK query-related tests, so they are not enabled at the moment.

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryEngine.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryEngine.java	2009-12-18 01:53:48 UTC (rev 1454)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryEngine.java	2009-12-18 01:54:27 UTC (rev 1455)
@@ -33,6 +33,7 @@
 import org.jboss.dna.graph.query.optimize.Optimizer;
 import org.jboss.dna.graph.query.optimize.RuleBasedOptimizer;
 import org.jboss.dna.graph.query.plan.CanonicalPlanner;
+import org.jboss.dna.graph.query.plan.PlanHints;
 import org.jboss.dna.graph.query.plan.PlanNode;
 import org.jboss.dna.graph.query.plan.Planner;
 import org.jboss.dna.graph.query.plan.PlanNode.Property;
@@ -99,7 +100,7 @@
 
             // Find the query result columns ...
             start = System.nanoTime();
-            resultColumns = determineQueryResultColumns(optimizedPlan);
+            resultColumns = determineQueryResultColumns(optimizedPlan, context.getHints());
             duration = System.nanoTime() - start;
             stats = stats.withOptimizationTime(duration);
 
@@ -118,18 +119,21 @@
         return new org.jboss.dna.graph.query.process.QueryResults(resultColumns, stats, context.getProblems());
     }
 
-    protected QueryResultColumns determineQueryResultColumns( PlanNode optimizedPlan ) {
+    protected QueryResultColumns determineQueryResultColumns( PlanNode optimizedPlan,
+                                                              PlanHints hints ) {
         // Look for which columns to include in the results; this will be defined by the highest PROJECT node ...
         PlanNode project = optimizedPlan.findAtOrBelow(Traversal.LEVEL_ORDER, Type.PROJECT);
         if (project != null) {
             List<Column> columns = project.getPropertyAsList(Property.PROJECT_COLUMNS, Column.class);
             // Determine whether to include the full-text search scores in the results ...
-            boolean includeFullTextSearchScores = false;
-            for (PlanNode select : optimizedPlan.findAllAtOrBelow(Type.SELECT)) {
-                Constraint constraint = select.getProperty(Property.SELECT_CRITERIA, Constraint.class);
-                if (QueryResultColumns.includeFullTextScores(constraint)) {
-                    includeFullTextSearchScores = true;
-                    break;
+            boolean includeFullTextSearchScores = hints.hasFullTextSearch;
+            if (!includeFullTextSearchScores) {
+                for (PlanNode select : optimizedPlan.findAllAtOrBelow(Type.SELECT)) {
+                    Constraint constraint = select.getProperty(Property.SELECT_CRITERIA, Constraint.class);
+                    if (QueryResultColumns.includeFullTextScores(constraint)) {
+                        includeFullTextSearchScores = true;
+                        break;
+                    }
                 }
             }
             return new QueryResultColumns(columns, includeFullTextSearchScores);

Modified: trunk/dna-integration-tests/src/test/resources/log4j.properties
===================================================================
--- trunk/dna-integration-tests/src/test/resources/log4j.properties	2009-12-18 01:53:48 UTC (rev 1454)
+++ trunk/dna-integration-tests/src/test/resources/log4j.properties	2009-12-18 01:54:27 UTC (rev 1455)
@@ -18,7 +18,6 @@
 # Set up the default logging to be INFO level, then override specific units
 log4j.logger.org.jboss.dna=WARN
 log4j.logger.org.junit=DEBUG
-# log4j.logger.org.jboss.dna.tests.integration.jackrabbit.JackrabbitMySqlStressTest=DEBUG
 log4j.logger.org.hibernate=WARN
 log4j.logger.org.hibernate.pretty.Printer=WARN
 log4j.logger.org.hibernate.engine.Collections=WARN
@@ -31,10 +30,4 @@
 log4j.logger.org.hibernate.hql.ast=WARN
 log4j.logger.org.hibernate.engine.loading.CollectionLoadContext=WARN
 
-
-# Jackrabbit logging
-log4j.logger.org.apache.jackrabbit=WARN, stdout
-log4j.logger.org.apache.derby=INFO, stdout
-
-
 log4j.logger.org.jboss.dna.connector.store=DEBUG

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java	2009-12-18 01:53:48 UTC (rev 1454)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java	2009-12-18 01:54:27 UTC (rev 1455)
@@ -49,9 +49,13 @@
     public static final Name LOCK_OWNER = new BasicName(Namespace.URI, "lockOwner");
     public static final Name MERGE_FAILED = new BasicName(Namespace.URI, "mergeFailed");
     public static final Name NODE_TYPES = new BasicName(Namespace.URI, "nodeTypes");
+    /** The "jcr:path" pseudo-column used in queries */
+    public static final Name PATH = new BasicName(Namespace.URI, "path");
     public static final Name PREDECESSORS = new BasicName(Namespace.URI, "predecessors");
     public static final Name ROOT = new BasicName(Namespace.URI, "root");
     public static final Name ROOT_VERSION = new BasicName(Namespace.URI, "rootVersion");
+    /** The "jcr:score" pseudo-column used in queries */
+    public static final Name SCORE = new BasicName(Namespace.URI, "score");
     public static final Name STATEMENT = new BasicName(Namespace.URI, "statement");
     public static final Name SUCCESSORS = new BasicName(Namespace.URI, "successors");
     public static final Name SYSTEM = new BasicName(Namespace.URI, "system");

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java	2009-12-18 01:53:48 UTC (rev 1454)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java	2009-12-18 01:54:27 UTC (rev 1455)
@@ -24,7 +24,9 @@
 package org.jboss.dna.jcr;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -32,6 +34,7 @@
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.PathNotFoundException;
+import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.nodetype.ConstraintViolationException;
@@ -48,6 +51,7 @@
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.property.NamespaceRegistry;
 import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFactories;
 import org.jboss.dna.graph.query.QueryResults;
 import org.jboss.dna.graph.query.QueryResults.Columns;
 import org.jboss.dna.graph.query.model.QueryCommand;
@@ -110,7 +114,12 @@
         try {
             // Parsing must be done now ...
             QueryCommand command = parser.parseQuery(expression, typeSystem);
-            return new JcrQuery(this.session, expression, parser.getLanguage(), command, storedAtPath);
+            PlanHints hints = new PlanHints();
+            // If using XPath, we need to add a few hints ...
+            if (Query.XPATH.equals(language)) {
+                hints.hasFullTextSearch = true; // requires 'jcr:score' to exist
+            }
+            return new JcrQuery(this.session, expression, parser.getLanguage(), command, hints, storedAtPath);
         } catch (ParsingException e) {
             // The query is not well-formed and cannot be parsed ...
             String reason = e.getMessage();
@@ -268,17 +277,19 @@
          * @param statement the original statement as supplied by the client; may not be null
          * @param language the language obtained from the {@link QueryParser}; may not be null
          * @param query the parsed query representation; may not be null
+         * @param hints any hints that are to be used; may be null if there are no hints
          * @param storedAtPath the path at which this query was stored, or null if this is not a stored query
          */
         protected JcrQuery( JcrSession session,
                             String statement,
                             String language,
                             QueryCommand query,
+                            PlanHints hints,
                             Path storedAtPath ) {
             super(session, statement, language, storedAtPath);
             assert query != null;
             this.query = query;
-            this.hints = null;
+            this.hints = hints;
             this.variables = null;
         }
 
@@ -295,6 +306,9 @@
                                                                             schemata,
                                                                             hints,
                                                                             variables);
+            if (Query.XPATH.equals(language)) {
+                return new XPathQueryResult(session, result);
+            }
             return new JcrQueryResult(session, result);
         }
 
@@ -336,14 +350,17 @@
         }
     }
 
+    protected static final String JCR_SCORE_COLUMN_NAME = "jcr:score";
+    protected static final String JCR_PATH_COLUMN_NAME = "jcr:path";
+
     /**
      * The results of a query. This is not thread-safe because it relies upon JcrSession, which is not thread-safe. Also, although
      * the results of a query never change, the objects returned by the iterators may vary if the session information changes.
      */
     @NotThreadSafe
     protected static class JcrQueryResult implements QueryResult {
-        private final JcrSession session;
-        private final QueryResults results;
+        protected final JcrSession session;
+        protected final QueryResults results;
 
         protected JcrQueryResult( JcrSession session,
                                   QueryResults graphResults ) {
@@ -357,14 +374,18 @@
             return results;
         }
 
+        public List<String> getColumnNameList() {
+            return results.getColumns().getColumnNames();
+        }
+
         /**
          * {@inheritDoc}
          * 
          * @see javax.jcr.query.QueryResult#getColumnNames()
          */
         public String[] getColumnNames() /*throws RepositoryException*/{
-            List<String> names = results.getColumns().getColumnNames();
-            return names.toArray(new String[names.size()]);
+            List<String> names = getColumnNameList();
+            return names.toArray(new String[names.size()]); // make a defensive copy ...
         }
 
         /**
@@ -491,9 +512,10 @@
      */
     @NotThreadSafe
     protected static class QueryResultRowIterator implements RowIterator {
-        protected final List<String> propertyNames;
+        protected final List<String> columnNames;
         private final Iterator<Object[]> tuples;
         protected final int locationIndex;
+        protected final int scoreIndex;
         protected final JcrSession session;
         private long position = 0L;
         private final long numRows;
@@ -503,9 +525,10 @@
                                           Iterator<Object[]> tuples,
                                           long numRows ) {
             this.tuples = tuples;
-            this.propertyNames = columns.getColumnNames();
+            this.columnNames = columns.getColumnNames();
             String selectorName = columns.getSelectorNames().get(0);
             this.locationIndex = columns.getLocationIndex(selectorName);
+            this.scoreIndex = columns.getFullTextSearchScoreIndexFor(selectorName);
             this.session = session;
             this.numRows = numRows;
         }
@@ -518,49 +541,11 @@
         public Row nextRow() {
             final Object[] tuple = tuples.next();
             ++position;
-            return new Row() {
-                private Node node = null;
-                private Value[] values = null;
+            return createRow(tuple);
+        }
 
-                /**
-                 * {@inheritDoc}
-                 * 
-                 * @see javax.jcr.query.Row#getValue(java.lang.String)
-                 */
-                public Value getValue( String propertyName ) throws ItemNotFoundException, RepositoryException {
-                    return node().getProperty(propertyName).getValue();
-                }
-
-                /**
-                 * {@inheritDoc}
-                 * 
-                 * @see javax.jcr.query.Row#getValues()
-                 */
-                public Value[] getValues() throws RepositoryException {
-                    if (values == null) {
-                        int i = 0;
-                        for (String propertyName : propertyNames) {
-                            values[i++] = node().getProperty(propertyName).getValue();
-                        }
-                    }
-                    return values;
-                }
-
-                /**
-                 * Load the node. The properties are <i>always</i> fetched from the session to ensure that any modifications to
-                 * the nodes within session are always used.
-                 * 
-                 * @return the node
-                 * @throws RepositoryException if the node could not be found
-                 */
-                protected final Node node() throws RepositoryException {
-                    if (node == null) {
-                        Location location = (Location)tuple[locationIndex];
-                        node = session.getNode(location.getPath());
-                    }
-                    return node;
-                }
-            };
+        protected Row createRow( final Object[] tuple ) {
+            return new QueryResultRow(this, tuple);
         }
 
         /**
@@ -620,4 +605,146 @@
             throw new UnsupportedOperationException();
         }
     }
+
+    protected static class QueryResultRow implements Row {
+        protected final QueryResultRowIterator iterator;
+        protected final Object[] tuple;
+        private Node node = null;
+        private Value[] values = null;
+
+        protected QueryResultRow( QueryResultRowIterator iterator,
+                                  Object[] tuple ) {
+            this.iterator = iterator;
+            this.tuple = tuple;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see javax.jcr.query.Row#getValue(java.lang.String)
+         */
+        public Value getValue( String columnName ) throws ItemNotFoundException, RepositoryException {
+            return node().getProperty(columnName).getValue();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see javax.jcr.query.Row#getValues()
+         */
+        public Value[] getValues() throws RepositoryException {
+            if (values == null) {
+                int i = 0;
+                values = new Value[iterator.columnNames.size()];
+                for (String columnName : iterator.columnNames) {
+                    values[i++] = getValue(columnName);
+                }
+            }
+            return values;
+        }
+
+        /**
+         * Load the node. The properties are <i>always</i> fetched from the session to ensure that any modifications to the nodes
+         * within session are always used.
+         * 
+         * @return the node
+         * @throws RepositoryException if the node could not be found
+         */
+        protected final Node node() throws RepositoryException {
+            if (node == null) {
+                Location location = (Location)tuple[iterator.locationIndex];
+                node = iterator.session.getNode(location.getPath());
+            }
+            return node;
+        }
+    }
+
+    protected static class XPathQueryResult extends JcrQueryResult {
+        private final List<String> columnNames;
+
+        protected XPathQueryResult( JcrSession session,
+                                    QueryResults graphResults ) {
+            super(session, graphResults);
+            List<String> columnNames = new LinkedList<String>(graphResults.getColumns().getColumnNames());
+            if (graphResults.getColumns().hasFullTextSearchScores() && !columnNames.contains(JCR_SCORE_COLUMN_NAME)) {
+                columnNames.add(0, JCR_SCORE_COLUMN_NAME);
+            }
+            columnNames.add(0, JCR_PATH_COLUMN_NAME);
+            this.columnNames = Collections.unmodifiableList(columnNames);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.jcr.JcrQueryManager.JcrQueryResult#getColumnNameList()
+         */
+        @Override
+        public List<String> getColumnNameList() {
+            return columnNames;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.jcr.JcrQueryManager.JcrQueryResult#getRows()
+         */
+        @Override
+        public RowIterator getRows() {
+            final int numRows = results.getRowCount();
+            final List<Object[]> tuples = results.getTuples();
+            return new XPathQueryResultRowIterator(session, results.getColumns(), tuples.iterator(), numRows);
+        }
+    }
+
+    protected static class XPathQueryResultRowIterator extends QueryResultRowIterator {
+        private final ValueFactories factories;
+        private final SessionCache cache;
+
+        protected XPathQueryResultRowIterator( JcrSession session,
+                                               Columns columns,
+                                               Iterator<Object[]> tuples,
+                                               long numRows ) {
+            super(session, columns, tuples, numRows);
+            factories = session.executionContext.getValueFactories();
+            cache = session.cache();
+        }
+
+        @Override
+        protected Row createRow( final Object[] tuple ) {
+            return new XPathQueryResultRow(this, tuple);
+        }
+
+        protected Value jcrPath( Path path ) {
+            return new JcrValue(factories, cache, PropertyType.PATH, path);
+        }
+
+        protected Value jcrScore( Float score ) {
+            return new JcrValue(factories, cache, PropertyType.DOUBLE, score);
+        }
+    }
+
+    protected static class XPathQueryResultRow extends QueryResultRow {
+        protected XPathQueryResultRow( XPathQueryResultRowIterator iterator,
+                                       Object[] tuple ) {
+            super(iterator, tuple);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see javax.jcr.query.Row#getValue(java.lang.String)
+         */
+        @Override
+        public Value getValue( String columnName ) throws ItemNotFoundException, RepositoryException {
+            if (JCR_PATH_COLUMN_NAME.equals(columnName)) {
+                Location location = (Location)tuple[iterator.locationIndex];
+                return ((XPathQueryResultRowIterator)iterator).jcrPath(location.getPath());
+            }
+            if (JCR_SCORE_COLUMN_NAME.equals(columnName)) {
+                Float score = (Float)tuple[iterator.scoreIndex];
+                return ((XPathQueryResultRowIterator)iterator).jcrScore(score);
+            }
+            return super.getValue(columnName);
+        }
+    }
 }

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java	2009-12-18 01:53:48 UTC (rev 1454)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java	2009-12-18 01:54:27 UTC (rev 1455)
@@ -180,7 +180,7 @@
             // addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
             // addTestSuite(org.apache.jackrabbit.test.api.query.XPathDocOrderTest.class);
             // addTestSuite(org.apache.jackrabbit.test.api.query.XPathOrderByTest.class);
-            // addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
+            addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
             addTestSuite(org.apache.jackrabbit.test.api.query.DerefQueryLevel1Test.class);
             addTestSuite(org.apache.jackrabbit.test.api.query.GetLanguageTest.class);
             addTestSuite(org.apache.jackrabbit.test.api.query.GetPersistentQueryPathLevel1Test.class);



More information about the dna-commits mailing list