You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2010/11/29 13:24:49 UTC
svn commit: r1040084 [1/2] - in /jackrabbit/branches/2.2: ./
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/p...
Author: jukka
Date: Mon Nov 29 12:24:48 2010
New Revision: 1040084
URL: http://svn.apache.org/viewvc?rev=1040084&view=rev
Log:
2.2: Merged revisions from trunk.
Removed:
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/TrackingInputStream.java
Modified:
jackrabbit/branches/2.2/ (props changed)
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactory.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/OperandEvaluator.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ValueComparator.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnection.java
jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnectionFactory.java
jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCARepositoryHandle.java
jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/QueryUtil.java
jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Base64.java
jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/Base64Test.java
jackrabbit/branches/2.2/jackrabbit-jcr-servlet/ (props changed)
jackrabbit/branches/2.2/jackrabbit-webapp/src/main/webapp/search.jsp
jackrabbit/branches/2.2/test/compatibility/create11/ (props changed)
jackrabbit/branches/2.2/test/compatibility/create12/ (props changed)
jackrabbit/branches/2.2/test/compatibility/create13/ (props changed)
jackrabbit/branches/2.2/test/compatibility/create14/ (props changed)
jackrabbit/branches/2.2/test/compatibility/create15/ (props changed)
jackrabbit/branches/2.2/test/compatibility/create16/ (props changed)
jackrabbit/branches/2.2/test/compatibility/create20/ (props changed)
jackrabbit/branches/2.2/test/compatibility/create21/ (props changed)
jackrabbit/branches/2.2/test/performance/parent/pom.xml
Propchange: jackrabbit/branches/2.2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -2,3 +2,4 @@
/jackrabbit/sandbox/JCR-1456:774917-886178
/jackrabbit/sandbox/JCR-2170:812417-816332
/jackrabbit/sandbox/tripod-JCR-2209:795441-795863
+/jackrabbit/trunk:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java Mon Nov 29 12:24:48 2010
@@ -16,11 +16,11 @@
*/
package org.apache.jackrabbit.core.data.db;
+import org.apache.commons.io.input.CountingInputStream;
import org.apache.jackrabbit.core.data.DataIdentifier;
import org.apache.jackrabbit.core.data.DataRecord;
import org.apache.jackrabbit.core.data.DataStore;
import org.apache.jackrabbit.core.data.DataStoreException;
-import org.apache.jackrabbit.core.util.TrackingInputStream;
import org.apache.jackrabbit.core.util.db.CheckSchemaOperation;
import org.apache.jackrabbit.core.util.db.ConnectionFactory;
import org.apache.jackrabbit.core.util.db.ConnectionHelper;
@@ -343,7 +343,7 @@ public class DbDataStore implements Data
temporaryInUse.add(tempId);
MessageDigest digest = getDigest();
DigestInputStream dIn = new DigestInputStream(stream, digest);
- TrackingInputStream in = new TrackingInputStream(dIn);
+ CountingInputStream in = new CountingInputStream(dIn);
StreamWrapper wrapper;
if (STORE_SIZE_MINUS_ONE.equals(storeStream)) {
wrapper = new StreamWrapper(in, -1);
@@ -360,7 +360,7 @@ public class DbDataStore implements Data
// UPDATE DATASTORE SET DATA=? WHERE ID=?
conHelper.exec(updateDataSQL, new Object[]{wrapper, tempId});
now = System.currentTimeMillis();
- long length = in.getPosition();
+ long length = in.getByteCount();
DataIdentifier identifier = new DataIdentifier(digest.digest());
usesIdentifier(identifier);
id = identifier.toString();
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java Mon Nov 29 12:24:48 2010
@@ -74,7 +74,7 @@ public class NodeTypeRegistry implements
"org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd";
private static final String CUSTOM_NODETYPES_RESOURCE_NAME =
- "nodetypes/custom_nodetypes.xml";
+ "/nodetypes/custom_nodetypes.xml";
/**
* resource holding custom node type definitions which are represented as
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java Mon Nov 29 12:24:48 2010
@@ -30,7 +30,6 @@ import org.apache.jackrabbit.core.persis
import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
import org.apache.jackrabbit.core.persistence.util.Serializer;
-import org.apache.jackrabbit.core.util.TrackingInputStream;
import org.apache.jackrabbit.core.id.NodeId;
import org.apache.jackrabbit.core.id.PropertyId;
import org.apache.jackrabbit.core.state.ItemStateException;
@@ -239,10 +238,7 @@ public class BundleFsPersistenceManager
}
InputStream in = itemFs.getInputStream(path);
try {
- TrackingInputStream cin = new TrackingInputStream(in);
- NodePropBundle bundle = binding.readBundle(cin, id);
- bundle.setSize(cin.getPosition());
- return bundle;
+ return binding.readBundle(in, id);
} finally {
IOUtils.closeQuietly(in);
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java Mon Nov 29 12:24:48 2010
@@ -25,8 +25,8 @@ import java.io.InputStream;
import java.sql.Blob;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.sql.Types;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -41,11 +41,11 @@ import org.apache.jackrabbit.core.id.Nod
import org.apache.jackrabbit.core.id.PropertyId;
import org.apache.jackrabbit.core.persistence.PMContext;
import org.apache.jackrabbit.core.persistence.bundle.AbstractBundlePersistenceManager;
+import org.apache.jackrabbit.core.persistence.util.BLOBStore;
import org.apache.jackrabbit.core.persistence.util.BundleBinding;
import org.apache.jackrabbit.core.persistence.util.ErrorHandling;
-import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
+import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
import org.apache.jackrabbit.core.persistence.util.Serializer;
import org.apache.jackrabbit.core.state.ChangeLog;
import org.apache.jackrabbit.core.state.ItemStateException;
@@ -796,27 +796,20 @@ public class BundleDbPersistenceManager
// issuing 2nd statement to circumvent issue JCR-1474
ResultSet bRs = null;
- byte[] data = null;
try {
bRs = conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
if (!bRs.next()) {
throw new SQLException("bundle cannot be retrieved?");
}
- Blob blob = bRs.getBlob(1);
- data = getBytes(blob);
+ // parse and check bundle
+ NodePropBundle bundle = readBundle(id, bRs, 1);
+ checkBundleConsistency(id, bundle, fix, modifications);
+ } catch (SQLException e) {
+ log.error("Unable to parse bundle " + id, e);
} finally {
DbUtility.close(bRs);
}
- try {
- // parse and check bundle
- NodePropBundle bundle = binding.readBundle(
- new ByteArrayInputStream(data), id);
- checkBundleConsistency(id, bundle, fix, modifications);
- } catch (IOException e) {
- log.error("Unable to parse bundle " + id
- + ": " + Arrays.toString(data), e);
- }
count++;
if (count % 1000 == 0) {
log.info(name + ": checked " + count + "/" + total + " bundles...");
@@ -1021,55 +1014,57 @@ public class BundleDbPersistenceManager
/**
* {@inheritDoc}
*/
+ @Override
protected NodePropBundle loadBundle(NodeId id) throws ItemStateException {
- ResultSet rs = null;
try {
- rs = conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
- if (!rs.next()) {
- return null;
- }
- byte[] bytes = getBytes(rs.getBlob(1));
-
+ ResultSet rs =
+ conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
try {
- NodePropBundle bundle =
- binding.readBundle(new ByteArrayInputStream(bytes), id);
- bundle.setSize(bytes.length);
- return bundle;
- } catch (IOException e) {
- log.error("Unable to parse serialization of bundle " + id
- + ": " + Arrays.toString(bytes), e);
- throw e;
+ if (rs.next()) {
+ return readBundle(id, rs, 1);
+ } else {
+ return null;
+ }
+ } finally {
+ rs.close();
}
- } catch (Exception e) {
+ } catch (SQLException e) {
String msg = "failed to read bundle: " + id + ": " + e;
log.error(msg);
throw new ItemStateException(msg, e);
- } finally {
- DbUtility.close(rs);
}
}
/**
- * Reads the blob's bytes and returns it. this is a helper method to
- * circumvent issue JCR-1039 and JCR-1474
- * @param blob blob to read
- * @return bytes of the blob
- * @throws SQLException if an SQL error occurs
- * @throws IOException if an I/O error occurs
+ * Reads and parses a bundle from the BLOB in the given column of the
+ * current row of the given result set. This is a helper method to
+ * circumvent issues JCR-1039 and JCR-1474.
+ *
+ * @param id bundle identifier
+ * @param rs result set
+ * @param column BLOB column
+ * @return parsed bundle
+ * @throws SQLException if the bundle can not be read or parsed
*/
- private byte[] getBytes(Blob blob) throws SQLException, IOException {
- InputStream in = null;
+ private NodePropBundle readBundle(NodeId id, ResultSet rs, int column)
+ throws SQLException {
try {
- long length = blob.length();
- byte[] bytes = new byte[(int) length];
- in = blob.getBinaryStream();
- int read, pos = 0;
- while ((read = in.read(bytes, pos, bytes.length - pos)) > 0) {
- pos += read;
+ InputStream in;
+ if (rs.getMetaData().getColumnType(column) == Types.BLOB) {
+ in = rs.getBlob(column).getBinaryStream();
+ } else {
+ in = rs.getBinaryStream(column);
}
- return bytes;
- } finally {
- IOUtils.closeQuietly(in);
+ try {
+ return binding.readBundle(in, id);
+ } finally {
+ in.close();
+ }
+ } catch (IOException e) {
+ SQLException exception =
+ new SQLException("Failed to parse bundle " + id);
+ exception.initCause(e);
+ throw exception;
}
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java Mon Nov 29 12:24:48 2010
@@ -16,18 +16,9 @@
*/
package org.apache.jackrabbit.core.persistence.pool;
-import java.io.InputStream;
-import java.sql.ResultSet;
import java.sql.SQLException;
-import org.apache.jackrabbit.core.id.NodeId;
import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.util.TrackingInputStream;
-import org.apache.jackrabbit.core.util.db.DbUtility;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Extends the {@link BundleDbPersistenceManager} by PostgreSQL specific code.
@@ -49,12 +40,6 @@ import org.slf4j.LoggerFactory;
public class PostgreSQLPersistenceManager extends BundleDbPersistenceManager {
/**
- * Logger instance.
- */
- private static Logger log =
- LoggerFactory.getLogger(PostgreSQLPersistenceManager.class);
-
- /**
* {@inheritDoc}
*/
public void init(PMContext context) throws Exception {
@@ -85,36 +70,4 @@ public class PostgreSQLPersistenceManage
return SM_LONGLONG_KEYS;
}
- /**
- * PostgreSQL needs slightly different handling of the binary value that is received:
- * rs.getBinaryStream vs rs.getBlob in the super class.
- *
- * {@inheritDoc}
- */
- @Override
- protected NodePropBundle loadBundle(NodeId id) throws ItemStateException {
- ResultSet rs = null;
- try {
- rs = conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
- if (rs.next()) {
- InputStream input = rs.getBinaryStream(1);
- try {
- TrackingInputStream cin = new TrackingInputStream(input);
- NodePropBundle bundle = binding.readBundle(cin, id);
- bundle.setSize(cin.getPosition());
- return bundle;
- } finally {
- input.close();
- }
- } else {
- return null;
- }
- } catch (Exception e) {
- String msg = "failed to read bundle: " + id + ": " + e;
- log.error(msg);
- throw new ItemStateException(msg, e);
- } finally {
- DbUtility.close(rs);
- }
- }
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java Mon Nov 29 12:24:48 2010
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.core.persi
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.commons.io.input.CountingInputStream;
import org.apache.jackrabbit.core.id.NodeId;
import org.apache.jackrabbit.core.id.PropertyId;
import org.apache.jackrabbit.core.value.InternalValue;
@@ -89,6 +90,14 @@ class BundleReader {
private final BundleBinding binding;
+ /**
+ * Counter for the number of bytes read from the input stream.
+ */
+ private final CountingInputStream cin;
+
+ /**
+ * Wrapper for reading structured data from the input stream.
+ */
private final DataInputStream in;
private final int version;
@@ -112,7 +121,8 @@ class BundleReader {
public BundleReader(BundleBinding binding, InputStream stream)
throws IOException {
this.binding = binding;
- this.in = new DataInputStream(stream);
+ this.cin = new CountingInputStream(stream);
+ this.in = new DataInputStream(cin);
this.version = in.readUnsignedByte();
}
@@ -124,12 +134,14 @@ class BundleReader {
* @throws IOException if an I/O error occurs.
*/
public NodePropBundle readBundle(NodeId id) throws IOException {
+ long start = cin.getByteCount();
NodePropBundle bundle = new NodePropBundle(id);
if (version >= BundleBinding.VERSION_3) {
readBundleNew(bundle);
} else {
readBundleOld(bundle);
}
+ bundle.setSize(cin.getByteCount() - start);
return bundle;
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java Mon Nov 29 12:24:48 2010
@@ -16,10 +16,7 @@
*/
package org.apache.jackrabbit.core.query;
-import java.util.Map;
-
import javax.jcr.RepositoryException;
-import javax.jcr.Value;
import javax.jcr.query.QueryResult;
/**
@@ -39,22 +36,4 @@ public interface ExecutableQuery {
*/
QueryResult execute(long offset, long limit) throws RepositoryException;
- /**
- * Binds the given <code>value</code> to the variable named
- * <code>varName</code>.
- *
- * @param varName name of variable in query
- * @param value value to bind
- * @throws RepositoryException if <code>varName</code> is not a
- * valid variable in this query.
- */
- void bindValue(String varName, Value value) throws RepositoryException;
-
- /**
- * Returns the bind variables of this query.
- *
- * @return bind variables
- */
- Map<String, Value> getBindVariables();
-
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java Mon Nov 29 12:24:48 2010
@@ -26,7 +26,6 @@ import org.apache.jackrabbit.core.fs.Fil
import org.apache.jackrabbit.core.id.NodeId;
import org.apache.jackrabbit.core.session.SessionContext;
import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree;
/**
* Defines an interface for the actual node indexing and query execution.
@@ -112,20 +111,6 @@ public interface QueryHandler {
throws InvalidQueryException;
/**
- * Creates a new query by specifying the query object model. If the query
- * object model is considered invalid for the implementing class, an
- * InvalidQueryException is thrown.
- *
- * @param sessionContext component context of the current session
- * @param qomTree query query object model tree.
- * @return A <code>Query</code> object.
- * @throws InvalidQueryException if the query object model tree is invalid.
- */
- ExecutableQuery createExecutableQuery(
- SessionContext sessionContext, QueryObjectModelTree qomTree)
- throws InvalidQueryException;
-
- /**
* @return the name of the query class to use.
*/
String getQueryClass();
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java Mon Nov 29 12:24:48 2010
@@ -21,7 +21,6 @@ import static org.apache.jackrabbit.spi.
import static org.apache.jackrabbit.spi.commons.name.NameConstants.NT_QUERY;
import java.text.NumberFormat;
-import java.util.Set;
import javax.jcr.ItemExistsException;
import javax.jcr.ItemNotFoundException;
@@ -97,7 +96,7 @@ public class QueryImpl extends AbstractQ
/**
* The offset in the total result set
*/
- protected long offset;
+ protected long offset = 0;
/**
* @inheritDoc
@@ -210,29 +209,19 @@ public class QueryImpl extends AbstractQ
/**
* {@inheritDoc}
*/
- public String[] getBindVariableNames() throws RepositoryException {
- Set<String> names = query.getBindVariables().keySet();
- return names.toArray(new String[names.size()]);
+ public String[] getBindVariableNames() {
+ return new String[0];
}
/**
- * Binds the given <code>value</code> to the variable named
- * <code>varName</code>.
+ * Throws an {@link IllegalArgumentException} as XPath and SQL1 queries
+ * have no bind variables.
*
- * @param varName name of variable in query
- * @param value value to bind
- * @throws IllegalArgumentException if <code>varName</code> is not a
- * valid variable in this query.
- * @throws javax.jcr.RepositoryException if an error occurs.
+ * @throws IllegalArgumentException always thrown
*/
public void bindValue(String varName, Value value)
- throws IllegalArgumentException, RepositoryException {
- checkInitialized();
- try {
- query.bindValue(varName, value);
- } catch (NameException e) {
- throw new RepositoryException(e.getMessage());
- }
+ throws IllegalArgumentException {
+ throw new IllegalArgumentException("No such bind variable: " + varName);
}
/**
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java Mon Nov 29 12:24:48 2010
@@ -16,8 +16,6 @@
*/
package org.apache.jackrabbit.core.query;
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_INNER;
-
import java.util.HashMap;
import java.util.Map;
@@ -28,17 +26,17 @@ import javax.jcr.query.InvalidQueryExcep
import javax.jcr.query.QueryResult;
import javax.jcr.query.qom.Column;
import javax.jcr.query.qom.Constraint;
-import javax.jcr.query.qom.EquiJoinCondition;
-import javax.jcr.query.qom.Join;
import javax.jcr.query.qom.Ordering;
import javax.jcr.query.qom.QueryObjectModel;
-import javax.jcr.query.qom.QueryObjectModelConstants;
import javax.jcr.query.qom.Source;
import org.apache.jackrabbit.commons.query.QueryObjectModelBuilderRegistry;
+import org.apache.jackrabbit.core.query.lucene.LuceneQueryFactory;
+import org.apache.jackrabbit.core.query.lucene.SearchIndex;
import org.apache.jackrabbit.core.query.lucene.join.QueryEngine;
import org.apache.jackrabbit.core.session.SessionContext;
-import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.query.qom.BindVariableValueImpl;
+import org.apache.jackrabbit.spi.commons.query.qom.DefaultTraversingQOMTreeVisitor;
import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree;
/**
@@ -51,6 +49,11 @@ public class QueryObjectModelImpl extend
*/
protected QueryObjectModelTree qomTree;
+ /** Bind variables */
+ private final Map<String, Value> variables = new HashMap<String, Value>();
+
+ private LuceneQueryFactory lqf;
+
/**
* {@inheritDoc}
* @throws UnsupportedOperationException always.
@@ -88,24 +91,46 @@ public class QueryObjectModelImpl extend
this.qomTree = qomTree;
this.node = node;
this.statement = QueryObjectModelBuilderRegistry.getQueryObjectModelBuilder(language).toString(this);
- this.query = handler.createExecutableQuery(sessionContext, qomTree);
+
+ try {
+ qomTree.accept(new DefaultTraversingQOMTreeVisitor() {
+ @Override
+ public Object visit(BindVariableValueImpl node, Object data) {
+ variables.put(node.getBindVariableName(), null);
+ return data;
+ }
+ }, null);
+ } catch (Exception ignore) {
+ }
+ this.lqf = new LuceneQueryFactory(
+ sessionContext.getSessionImpl(), (SearchIndex) handler,
+ variables);
setInitialized();
}
public QueryResult execute() throws RepositoryException {
- Source source = getSource();
- if (source instanceof Join) {
- Join join = (Join) source;
- if (JCR_JOIN_TYPE_INNER.equals(join.getJoinType())
- && join.getJoinCondition() instanceof EquiJoinCondition) {
- QueryEngine engine =
- new QueryEngine(sessionContext.getSessionImpl(), query.getBindVariables());
- return engine.execute(
- getColumns(), getSource(), getConstraint(),
- getOrderings(), offset, limit);
- }
+ QueryEngine engine = new QueryEngine(
+ sessionContext.getSessionImpl(), lqf, variables);
+ return engine.execute(
+ getColumns(), getSource(), getConstraint(),
+ getOrderings(), offset, limit);
+ }
+
+
+ @Override
+ public String[] getBindVariableNames() {
+ return variables.keySet().toArray(new String[variables.size()]);
+ }
+
+ @Override
+ public void bindValue(String varName, Value value)
+ throws IllegalArgumentException {
+ if (variables.containsKey(varName)) {
+ variables.put(varName, value);
+ } else {
+ throw new IllegalArgumentException(
+ "No such bind variable: " + varName);
}
- return super.execute();
}
//-------------------------< QueryObjectModel >-----------------------------
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java Mon Nov 29 12:24:48 2010
@@ -16,10 +16,7 @@
*/
package org.apache.jackrabbit.core.query.lucene;
-import java.util.Map;
-
import javax.jcr.RepositoryException;
-import javax.jcr.Value;
import javax.jcr.Workspace;
import javax.jcr.query.qom.QueryObjectModelFactory;
@@ -54,10 +51,6 @@ public abstract class AbstractQueryImpl
*/
private boolean documentOrder = true;
- /** Bind variables of this query */
- private final Map<String, Value> variables;
-
-
/**
* Creates a new query instance from a query string.
*
@@ -67,11 +60,10 @@ public abstract class AbstractQueryImpl
*/
public AbstractQueryImpl(
SessionContext sessionContext, SearchIndex index,
- PropertyTypeRegistry propReg, Map<String, Value> variables) {
+ PropertyTypeRegistry propReg) {
this.sessionContext = sessionContext;
this.index = index;
this.propReg = propReg;
- this.variables = variables;
}
/**
@@ -102,33 +94,6 @@ public abstract class AbstractQueryImpl
}
/**
- * Binds the given <code>value</code> to the variable named
- * <code>varName</code>.
- *
- * @param varName name of variable in query
- * @param value value to bind
- * @throws IllegalArgumentException if <code>varName</code> is not a valid
- * variable in this query.
- * @throws RepositoryException if an error occurs.
- */
- public void bindValue(String varName, Value value)
- throws IllegalArgumentException, RepositoryException {
- if (variables.containsKey(varName)) {
- variables.put(varName, value);
- } else {
- throw new IllegalArgumentException(
- varName + " is not a valid variable in this query");
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public Map<String, Value> getBindVariables() {
- return variables;
- }
-
- /**
* @return the query object model factory.
* @throws RepositoryException if an error occurs.
*/
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactory.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactory.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactory.java Mon Nov 29 12:24:48 2010
@@ -17,9 +17,11 @@
package org.apache.jackrabbit.core.query.lucene;
import static javax.jcr.PropertyType.DATE;
+import static javax.jcr.PropertyType.DECIMAL;
import static javax.jcr.PropertyType.DOUBLE;
import static javax.jcr.PropertyType.LONG;
import static javax.jcr.PropertyType.NAME;
+import static javax.jcr.PropertyType.PATH;
import static javax.jcr.PropertyType.STRING;
import static javax.jcr.PropertyType.UNDEFINED;
import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO;
@@ -29,24 +31,41 @@ import static javax.jcr.query.qom.QueryO
import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO;
import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_LIKE;
import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_NOT_EQUAL_TO;
+import static org.apache.jackrabbit.core.query.lucene.FieldNames.LOCAL_NAME;
+import static org.apache.jackrabbit.core.query.lucene.FieldNames.MVP;
+import static org.apache.jackrabbit.core.query.lucene.FieldNames.NAMESPACE_URI;
+import static org.apache.jackrabbit.core.query.lucene.FieldNames.PARENT;
import static org.apache.jackrabbit.core.query.lucene.FieldNames.PROPERTIES;
+import static org.apache.jackrabbit.core.query.lucene.FieldNames.UUID;
+import static org.apache.jackrabbit.core.query.lucene.TransformConstants.TRANSFORM_LOWER_CASE;
+import static org.apache.jackrabbit.core.query.lucene.TransformConstants.TRANSFORM_NONE;
+import static org.apache.jackrabbit.core.query.lucene.TransformConstants.TRANSFORM_UPPER_CASE;
import static org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_MIXINTYPES;
import static org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_PRIMARYTYPE;
import static org.apache.lucene.search.BooleanClause.Occur.MUST;
+import static org.apache.lucene.search.BooleanClause.Occur.MUST_NOT;
import static org.apache.lucene.search.BooleanClause.Occur.SHOULD;
+import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.PathNotFoundException;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.query.Row;
import javax.jcr.query.qom.And;
import javax.jcr.query.qom.ChildNode;
import javax.jcr.query.qom.Comparison;
@@ -54,26 +73,35 @@ import javax.jcr.query.qom.Constraint;
import javax.jcr.query.qom.DescendantNode;
import javax.jcr.query.qom.DynamicOperand;
import javax.jcr.query.qom.FullTextSearch;
+import javax.jcr.query.qom.FullTextSearchScore;
+import javax.jcr.query.qom.Length;
+import javax.jcr.query.qom.LowerCase;
+import javax.jcr.query.qom.NodeLocalName;
+import javax.jcr.query.qom.NodeName;
import javax.jcr.query.qom.Not;
import javax.jcr.query.qom.Or;
import javax.jcr.query.qom.PropertyExistence;
import javax.jcr.query.qom.PropertyValue;
import javax.jcr.query.qom.SameNode;
+import javax.jcr.query.qom.Selector;
import javax.jcr.query.qom.StaticOperand;
+import javax.jcr.query.qom.UpperCase;
-import org.apache.jackrabbit.core.HierarchyManager;
+import org.apache.jackrabbit.commons.predicate.Predicate;
+import org.apache.jackrabbit.commons.predicate.Predicates;
+import org.apache.jackrabbit.commons.predicate.RowPredicate;
+import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.NodeId;
import org.apache.jackrabbit.core.query.lucene.join.OperandEvaluator;
+import org.apache.jackrabbit.core.query.lucene.join.SelectorRow;
+import org.apache.jackrabbit.core.query.lucene.join.ValueComparator;
import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.commons.query.qom.DefaultQOMTreeVisitor;
import org.apache.jackrabbit.spi.commons.query.qom.FullTextSearchImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.JoinConditionImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.JoinImpl;
import org.apache.jackrabbit.spi.commons.query.qom.PropertyExistenceImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.SelectorImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.SourceImpl;
-import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
@@ -96,10 +124,8 @@ public class LuceneQueryFactory {
*/
private final NodeTypeManager ntManager;
- /**
- * The hierarchy manager.
- */
- private final HierarchyManager hmgr;
+ /** Lucene search index */
+ private final SearchIndex index;
/**
* Namespace mappings to internal prefixes
@@ -111,21 +137,6 @@ public class LuceneQueryFactory {
*/
private final NamePathResolver npResolver;
- /**
- * The analyzer instance to use for contains function query parsing
- */
- private final Analyzer analyzer;
-
- /**
- * The synonym provider or <code>null</code> if none is configured.
- */
- private final SynonymProvider synonymProvider;
-
- /**
- * The index format version.
- */
- private final IndexFormatVersion version;
-
/** Operand evaluator */
private final OperandEvaluator evaluator;
@@ -137,26 +148,16 @@ public class LuceneQueryFactory {
* Creates a new lucene query factory.
*
* @param session the session that executes the query.
- * @param scs the sort comparator source of the index.
- * @param hmgr the hierarchy manager of the workspace.
- * @param nsMappings the index internal namespace mappings.
- * @param analyzer the analyzer of the index.
- * @param synonymProvider the synonym provider of the index.
- * @param version the version of the index format.
+ * @param index the search index
* @param bindVariables the bind variable values of the query
*/
public LuceneQueryFactory(
- SessionImpl session, HierarchyManager hmgr,
- NamespaceMappings nsMappings, Analyzer analyzer,
- SynonymProvider synonymProvider, IndexFormatVersion version,
+ SessionImpl session, SearchIndex index,
Map<String, Value> bindVariables) throws RepositoryException {
this.session = session;
this.ntManager = session.getWorkspace().getNodeTypeManager();
- this.hmgr = hmgr;
- this.nsMappings = nsMappings;
- this.analyzer = analyzer;
- this.synonymProvider = synonymProvider;
- this.version = version;
+ this.index = index;
+ this.nsMappings = index.getNamespaceMappings();
this.npResolver = NamePathResolverImpl.create(nsMappings);
this.evaluator =
new OperandEvaluator(session.getValueFactory(), bindVariables);
@@ -164,6 +165,51 @@ public class LuceneQueryFactory {
this.primaryTypeField = nsMappings.translateName(JCR_PRIMARYTYPE);
}
+ public List<Row> execute(
+ Map<String, PropertyValue> columns, Selector selector,
+ Constraint constraint) throws RepositoryException, IOException {
+ final IndexReader reader = index.getIndexReader(true);
+ try {
+ JackrabbitIndexSearcher searcher = new JackrabbitIndexSearcher(
+ session, reader, index.getContext().getItemStateManager());
+ searcher.setSimilarity(index.getSimilarity());
+
+ Predicate filter = Predicate.TRUE;
+ BooleanQuery query = new BooleanQuery();
+ query.add(create(selector), MUST);
+ if (constraint != null) {
+ String name = selector.getSelectorName();
+ NodeType type =
+ ntManager.getNodeType(selector.getNodeTypeName());
+ filter = mapConstraintToQueryAndFilter(
+ query, constraint, Collections.singletonMap(name, type),
+ searcher, reader);
+ }
+
+ List<Row> rows = new ArrayList<Row>();
+ QueryHits hits = searcher.evaluate(query);
+ ScoreNode node = hits.nextScoreNode();
+ while (node != null) {
+ try {
+ Row row = new SelectorRow(
+ columns, evaluator, selector.getSelectorName(),
+ session.getNodeById(node.getNodeId()),
+ node.getScore());
+ if (filter.evaluate(row)) {
+ rows.add(row);
+ }
+ } catch (ItemNotFoundException e) {
+ // skip the node
+ }
+ node = hits.nextScoreNode();
+ }
+ return rows;
+ } finally {
+ PerQueryCache.getInstance().dispose();
+ Util.closeOrRelease(reader);
+ }
+ }
+
/**
* Creates a lucene query for the given QOM selector.
*
@@ -171,7 +217,7 @@ public class LuceneQueryFactory {
* @return a lucene query for the given selector.
* @throws RepositoryException if an error occurs while creating the query.
*/
- public Query create(SelectorImpl selector) throws RepositoryException {
+ public Query create(Selector selector) throws RepositoryException {
List<Term> terms = new ArrayList<Term>();
String name = selector.getNodeTypeName();
@@ -229,7 +275,7 @@ public class LuceneQueryFactory {
fieldname = tmp.toString();
}
QueryParser parser = new JackrabbitQueryParser(
- fieldname, analyzer, synonymProvider);
+ fieldname, index.getTextAnalyzer(), index.getSynonymProvider());
try {
StaticOperand expr = fts.getFullTextSearchExpression();
return parser.parse(evaluator.getValue(expr).getString());
@@ -247,168 +293,377 @@ public class LuceneQueryFactory {
*/
public Query create(PropertyExistenceImpl prop) throws RepositoryException {
String propName = npResolver.getJCRName(prop.getPropertyQName());
- return Util.createMatchAllQuery(propName, version);
+ return Util.createMatchAllQuery(propName, index.getIndexFormatVersion());
}
- /**
- * Creates a multi column query for the given QOM source.
- *
- * @param source the QOM source.
- * @return a multi column query for the given source.
- * @throws RepositoryException if an error occurs while creating the query.
- */
- public MultiColumnQuery create(SourceImpl source) throws RepositoryException {
- // source is either selector or join
- try {
- return (MultiColumnQuery) source.accept(new DefaultQOMTreeVisitor() {
- public Object visit(JoinImpl node, Object data) throws Exception {
- return create(node);
- }
-
- public Object visit(SelectorImpl node, Object data) throws Exception {
- return MultiColumnQueryAdapter.adapt(
- create(node), node.getSelectorQName());
+ private Predicate mapConstraintToQueryAndFilter(
+ BooleanQuery query, Constraint constraint,
+ Map<String, NodeType> selectorMap,
+ JackrabbitIndexSearcher searcher, IndexReader reader)
+ throws RepositoryException, IOException {
+ Predicate filter = Predicate.TRUE;
+ if (constraint instanceof And) {
+ And and = (And) constraint;
+ filter = mapConstraintToQueryAndFilter(
+ query, and.getConstraint1(), selectorMap, searcher, reader);
+ Predicate other = mapConstraintToQueryAndFilter(
+ query, and.getConstraint2(), selectorMap, searcher, reader);
+ if (filter == Predicate.TRUE) {
+ filter = other;
+ } else if (other != Predicate.TRUE) {
+ filter = Predicates.and(filter, other);
+ }
+ } else if (constraint instanceof Comparison) {
+ Comparison c = (Comparison) constraint;
+ Transform transform = new Transform(c.getOperand1());
+ DynamicOperand left = transform.operand;
+ final String operator = c.getOperator();
+ StaticOperand right = c.getOperand2();
+ if (left instanceof Length
+ || left instanceof FullTextSearchScore
+ || ((!JCR_OPERATOR_EQUAL_TO.equals(operator)
+ || transform.transform != TRANSFORM_NONE)
+ && (left instanceof NodeName
+ || left instanceof NodeLocalName))) {
+ try {
+ int type = PropertyType.UNDEFINED;
+ if (left instanceof Length) {
+ type = PropertyType.LONG;
+ } else if (left instanceof FullTextSearchScore) {
+ type = PropertyType.DOUBLE;
+ }
+ final DynamicOperand operand = c.getOperand1();
+ final Value value = evaluator.getValue(right, type);
+ filter = new RowPredicate() {
+ @Override
+ protected boolean evaluate(Row row)
+ throws RepositoryException {
+ return new ValueComparator().evaluate(
+ operator,
+ evaluator.getValue(operand, row), value);
+ }
+ };
+ } catch (ValueFormatException e) {
+ throw new InvalidQueryException(e);
}
- }, null);
- } catch (RepositoryException e) {
- throw e;
- } catch (Exception e) {
- throw new RepositoryException(e);
+ } else {
+ Query cq = getComparisonQuery(
+ left, transform.transform, operator, right, selectorMap);
+ query.add(cq, MUST);
+ }
+ } else {
+ query.add(create(constraint, selectorMap, searcher), MUST);
}
+ return filter;
}
- /**
- * Creates a multi column query for the given QOM join.
- *
- * @param join the QOM join.
- * @return the multi column query for the given join.
- * @throws RepositoryException if an error occurs while creating the query.
- */
- public MultiColumnQuery create(JoinImpl join) throws RepositoryException {
- MultiColumnQuery left = create((SourceImpl) join.getLeft());
- MultiColumnQuery right = create((SourceImpl) join.getRight());
- return new JoinQuery(left, right, join.getJoinTypeInstance(),
- (JoinConditionImpl) join.getJoinCondition(), nsMappings, hmgr);
- }
-
- public Query create(
- Constraint constraint, Map<String, NodeType> selectorMap)
- throws RepositoryException {
+ private Query create(
+ Constraint constraint, Map<String, NodeType> selectorMap,
+ JackrabbitIndexSearcher searcher)
+ throws RepositoryException, IOException {
if (constraint instanceof And) {
- return getAndQuery((And) constraint, selectorMap);
+ return getAndQuery((And) constraint, selectorMap, searcher);
} else if (constraint instanceof Or) {
- return getOrQuery((Or) constraint, selectorMap);
+ return getOrQuery((Or) constraint, selectorMap, searcher);
} else if (constraint instanceof Not) {
- return getNotQuery((Not) constraint, selectorMap);
+ return getNotQuery((Not) constraint, selectorMap, searcher);
} else if (constraint instanceof PropertyExistence) {
return getPropertyExistenceQuery((PropertyExistence) constraint);
} else if (constraint instanceof Comparison) {
- return getComparisonQuery((Comparison) constraint, selectorMap);
+ Comparison c = (Comparison) constraint;
+ Transform left = new Transform(c.getOperand1());
+ return getComparisonQuery(
+ left.operand, left.transform, c.getOperator(),
+ c.getOperand2(), selectorMap);
} else if (constraint instanceof FullTextSearch) {
- return null; // FIXME
+ return getFullTextSearchQuery((FullTextSearch) constraint);
} else if (constraint instanceof SameNode) {
- return null; // FIXME
+ SameNode sn = (SameNode) constraint;
+ return getNodeIdQuery(UUID, sn.getPath());
} else if (constraint instanceof ChildNode) {
- return null; // FIXME
+ ChildNode cn = (ChildNode) constraint;
+ return getNodeIdQuery(PARENT, cn.getParentPath());
} else if (constraint instanceof DescendantNode) {
- return null; // FIXME
+ DescendantNode dn = (DescendantNode) constraint;
+ return getDescendantNodeQuery(dn, searcher);
} else {
throw new UnsupportedRepositoryOperationException(
"Unknown constraint type: " + constraint);
}
}
- private BooleanQuery getAndQuery(
- And and, Map<String, NodeType> selectorMap)
- throws RepositoryException {
+ private Query getDescendantNodeQuery(
+ DescendantNode dn, JackrabbitIndexSearcher searcher)
+ throws RepositoryException, IOException {
BooleanQuery query = new BooleanQuery();
- addBooleanConstraint(query, and.getConstraint1(), MUST, selectorMap);
- addBooleanConstraint(query, and.getConstraint2(), MUST, selectorMap);
+
+ try {
+ LinkedList<NodeId> ids = new LinkedList<NodeId>();
+ NodeImpl ancestor = (NodeImpl) session.getNode(dn.getAncestorPath());
+ ids.add(ancestor.getNodeId());
+ while (!ids.isEmpty()) {
+ String id = ids.removeFirst().toString();
+ Query q = new JackrabbitTermQuery(new Term(FieldNames.PARENT, id));
+ QueryHits hits = searcher.evaluate(q);
+ ScoreNode sn = hits.nextScoreNode();
+ if (sn != null) {
+ query.add(q, SHOULD);
+ do {
+ ids.add(sn.getNodeId());
+ sn = hits.nextScoreNode();
+ } while (sn != null);
+ }
+ }
+ } catch (PathNotFoundException e) {
+ query.add(new JackrabbitTermQuery(new Term(
+ FieldNames.UUID, "invalid-node-id")), // never matches
+ SHOULD);
+ }
+
return query;
}
- private BooleanQuery getOrQuery(Or or, Map<String, NodeType> selectorMap)
+ private Query getFullTextSearchQuery(FullTextSearch fts)
throws RepositoryException {
+ String field = FieldNames.FULLTEXT;
+ String property = fts.getPropertyName();
+ if (property != null) {
+ Name name = session.getQName(property);
+ field = nsMappings.getPrefix(name.getNamespaceURI()) + ":"
+ + FieldNames.FULLTEXT_PREFIX + name.getLocalName();
+ }
+
+ StaticOperand expression = fts.getFullTextSearchExpression();
+ String query = evaluator.getValue(expression).getString();
+ try {
+ QueryParser parser = new JackrabbitQueryParser(
+ field, index.getTextAnalyzer(), index.getSynonymProvider());
+ return parser.parse(query);
+ } catch (ParseException e) {
+ throw new RepositoryException(
+ "Invalid full text search expression: " + query, e);
+ }
+ }
+
+ private BooleanQuery getAndQuery(
+ And and, Map<String, NodeType> selectorMap,
+ JackrabbitIndexSearcher searcher)
+ throws RepositoryException, IOException {
+ BooleanQuery query = new BooleanQuery();
+ addBooleanConstraint(
+ query, and.getConstraint1(), MUST, selectorMap, searcher);
+ addBooleanConstraint(
+ query, and.getConstraint2(), MUST, selectorMap, searcher);
+ return query;
+ }
+
+ private BooleanQuery getOrQuery(
+ Or or, Map<String, NodeType> selectorMap,
+ JackrabbitIndexSearcher searcher)
+ throws RepositoryException, IOException {
BooleanQuery query = new BooleanQuery();
- addBooleanConstraint(query, or.getConstraint1(), SHOULD, selectorMap);
- addBooleanConstraint(query, or.getConstraint2(), SHOULD, selectorMap);
+ addBooleanConstraint(
+ query, or.getConstraint1(), SHOULD, selectorMap, searcher);
+ addBooleanConstraint(
+ query, or.getConstraint2(), SHOULD, selectorMap, searcher);
return query;
}
private void addBooleanConstraint(
BooleanQuery query, Constraint constraint, Occur occur,
- Map<String, NodeType> selectorMap) throws RepositoryException {
+ Map<String, NodeType> selectorMap, JackrabbitIndexSearcher searcher)
+ throws RepositoryException, IOException {
if (occur == MUST && constraint instanceof And) {
And and = (And) constraint;
- addBooleanConstraint(query, and.getConstraint1(), occur, selectorMap);
- addBooleanConstraint(query, and.getConstraint2(), occur, selectorMap);
+ addBooleanConstraint(
+ query, and.getConstraint1(), occur, selectorMap, searcher);
+ addBooleanConstraint(
+ query, and.getConstraint2(), occur, selectorMap, searcher);
} else if (occur == SHOULD && constraint instanceof Or) {
Or or = (Or) constraint;
- addBooleanConstraint(query, or.getConstraint1(), occur, selectorMap);
- addBooleanConstraint(query, or.getConstraint2(), occur, selectorMap);
+ addBooleanConstraint(
+ query, or.getConstraint1(), occur, selectorMap, searcher);
+ addBooleanConstraint(
+ query, or.getConstraint2(), occur, selectorMap, searcher);
} else {
- query.add(create(constraint, selectorMap), occur);
+ query.add(create(constraint, selectorMap, searcher), occur);
}
}
- private NotQuery getNotQuery(Not not, Map<String, NodeType> selectorMap)
- throws RepositoryException {
- return new NotQuery(create(not.getConstraint(), selectorMap));
+ private NotQuery getNotQuery(
+ Not not, Map<String, NodeType> selectorMap,
+ JackrabbitIndexSearcher searcher)
+ throws RepositoryException, IOException {
+ return new NotQuery(create(not.getConstraint(), selectorMap, searcher));
}
private Query getPropertyExistenceQuery(PropertyExistence property)
throws RepositoryException {
String name = npResolver.getJCRName(session.getQName(
property.getPropertyName()));
- return Util.createMatchAllQuery(name, version);
+ return Util.createMatchAllQuery(name, index.getIndexFormatVersion());
+ }
+
+ private static class Transform {
+
+ private final DynamicOperand operand;
+
+ private final int transform;
+
+ public Transform(DynamicOperand operand) {
+ // Check the transformation type
+ if (operand instanceof UpperCase) {
+ this.transform = TRANSFORM_UPPER_CASE;
+ } else if (operand instanceof LowerCase) {
+ this.transform = TRANSFORM_LOWER_CASE;
+ } else {
+ this.transform = TRANSFORM_NONE;
+ }
+
+ // Unwrap any nested transformations
+ while (true) {
+ if (operand instanceof UpperCase) {
+ operand = ((UpperCase) operand).getOperand();
+ } else if (operand instanceof LowerCase) {
+ operand = ((LowerCase) operand).getOperand();
+ } else {
+ break;
+ }
+ }
+ this.operand = operand;
+ }
}
private Query getComparisonQuery(
- Comparison comparison, Map<String, NodeType> selectorMap)
+ DynamicOperand left, int transform, String operator,
+ StaticOperand rigth, Map<String, NodeType> selectorMap)
throws RepositoryException {
- DynamicOperand operand = comparison.getOperand1();
- if (operand instanceof PropertyValue) {
- PropertyValue property = (PropertyValue) operand;
+ if (left instanceof PropertyValue) {
+ PropertyValue pv = (PropertyValue) left;
String field = npResolver.getJCRName(session.getQName(
- property.getPropertyName()));
+ pv.getPropertyName()));
int type = PropertyType.UNDEFINED;
- NodeType nt = selectorMap.get(property.getSelectorName());
+ NodeType nt = selectorMap.get(pv.getSelectorName());
if (nt != null) {
for (PropertyDefinition pd : nt.getPropertyDefinitions()) {
- if (pd.getName().equals(property.getPropertyName())) {
+ if (pd.getName().equals(pv.getPropertyName())) {
type = pd.getRequiredType();
}
}
}
return getPropertyValueQuery(
- field, comparison.getOperator(),
- evaluator.getValue(comparison.getOperand2()), type);
+ field, operator, evaluator.getValue(rigth), type, transform);
+ } else if (left instanceof NodeName) {
+ return getNodeNameQuery(transform, operator, rigth);
+ } else if (left instanceof NodeLocalName) {
+ return getNodeLocalNameQuery(transform, operator, rigth);
} else {
- throw new UnsupportedRepositoryOperationException(); // FIXME
+ throw new UnsupportedRepositoryOperationException(
+ "Unknown operand type: " + left); // FIXME
}
}
- private Query getPropertyValueQuery(
- String field, String operator, Value value, int type)
+ private Query getNodeNameQuery(
+ int transform, String operator, StaticOperand right)
throws RepositoryException {
- Term term = getTerm(field, getValueString(value, type));
+ if (transform != TRANSFORM_NONE
+ || !JCR_OPERATOR_EQUAL_TO.equals(operator)) {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ Value value = evaluator.getValue(right);
+ int type = value.getType();
+ String string = value.getString();
+ if (type == PropertyType.URI && string.startsWith("./")) {
+ string = string.substring("./".length());
+ } else if (type == PropertyType.DOUBLE
+ || type == PropertyType.DECIMAL
+ || type == PropertyType.LONG
+ || type == PropertyType.BOOLEAN
+ || type == PropertyType.REFERENCE
+ || type == PropertyType.WEAKREFERENCE) {
+ throw new InvalidQueryException("Invalid name value: " + string);
+ }
+
+ try {
+ Name name = session.getQName(string);
+ Term uri = new Term(NAMESPACE_URI, name.getNamespaceURI());
+ Term local = new Term(LOCAL_NAME, name.getLocalName());
+
+ BooleanQuery query = new BooleanQuery();
+ query.add(new JackrabbitTermQuery(uri), MUST);
+ query.add(new JackrabbitTermQuery(local), MUST);
+ return query;
+ } catch (IllegalNameException e) {
+ throw new InvalidQueryException("Illegal name: " + string, e);
+ }
+ }
+
+ private Query getNodeLocalNameQuery(
+ int transform, String operator, StaticOperand right)
+ throws RepositoryException {
+ if (transform != TRANSFORM_NONE
+ || !JCR_OPERATOR_EQUAL_TO.equals(operator)) {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ String name = evaluator.getValue(right).getString();
+ return new JackrabbitTermQuery(new Term(LOCAL_NAME, name));
+ }
+
+ private Query getNodeIdQuery(String field, String path)
+ throws RepositoryException {
+ String value;
+ try {
+ NodeImpl node = (NodeImpl) session.getNode(path);
+ value = node.getNodeId().toString();
+ } catch (PathNotFoundException e) {
+ value = "invalid-node-id"; // can never match a node
+ }
+ return new JackrabbitTermQuery(new Term(field, value));
+ }
+
+ private Query getPropertyValueQuery(
+ String field, String operator, Value value,
+ int type, int transform) throws RepositoryException {
+ String string = getValueString(value, type);
+ if (JCR_OPERATOR_LIKE.equals(operator)) {
+ return new WildcardQuery(PROPERTIES, field, string, transform);
+ }
+
+ Term term = getTerm(field, string);
if (JCR_OPERATOR_EQUAL_TO.equals(operator)) {
- return new JackrabbitTermQuery(term);
+ switch (transform) {
+ case TRANSFORM_UPPER_CASE:
+ return new CaseTermQuery.Upper(term);
+ case TRANSFORM_LOWER_CASE:
+ return new CaseTermQuery.Lower(term);
+ default:
+ return new JackrabbitTermQuery(term);
+ }
} else if (JCR_OPERATOR_GREATER_THAN.equals(operator)) {
- return new RangeQuery(term, getTerm(field, "\uFFFF"), false);
+ return new RangeQuery(term, getTerm(field, "\uFFFF"), false, transform);
} else if (JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO.equals(operator)) {
- return new RangeQuery(term, getTerm(field, "\uFFFF"), true);
+ return new RangeQuery(term, getTerm(field, "\uFFFF"), true, transform);
} else if (JCR_OPERATOR_LESS_THAN.equals(operator)) {
- return new RangeQuery(getTerm(field, ""), term, false);
+ return new RangeQuery(getTerm(field, ""), term, false, transform);
} else if (JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO.equals(operator)) {
- return new RangeQuery(getTerm(field, ""), term, true);
+ return new RangeQuery(getTerm(field, ""), term, true, transform);
} else if (JCR_OPERATOR_NOT_EQUAL_TO.equals(operator)) {
- BooleanQuery or = new BooleanQuery();
- or.add(new RangeQuery(getTerm(field, ""), term, false), SHOULD);
- or.add(new RangeQuery(term, getTerm(field, "\uFFFF"), false), SHOULD);
- return or;
- } else if (JCR_OPERATOR_LIKE.equals(operator)) {
- throw new UnsupportedRepositoryOperationException(); // FIXME
+ BooleanQuery query = new BooleanQuery();
+ query.add(Util.createMatchAllQuery(
+ field, index.getIndexFormatVersion()), SHOULD);
+ switch (transform) {
+ case TRANSFORM_UPPER_CASE:
+ query.add(new CaseTermQuery.Upper(term), MUST_NOT);
+ case TRANSFORM_LOWER_CASE:
+ query.add(new CaseTermQuery.Lower(term), MUST_NOT);
+ default:
+ query.add(new JackrabbitTermQuery(term), MUST_NOT);
+ }
+ // and exclude all nodes where 'field' is multi valued
+ query.add(new JackrabbitTermQuery(new Term(MVP, field)), MUST_NOT);
+ return query;
} else {
throw new UnsupportedRepositoryOperationException(); // FIXME
}
@@ -427,8 +682,12 @@ public class LuceneQueryFactory {
return DoubleField.doubleToString(value.getDouble());
case LONG:
return LongField.longToString(value.getLong());
+ case DECIMAL:
+ return DecimalField.decimalToString(value.getDecimal());
case NAME:
return npResolver.getJCRName(session.getQName(value.getString()));
+ case PATH:
+ return npResolver.getJCRPath(session.getQPath(value.getString()));
default:
String string = value.getString();
if (type != UNDEFINED && type != STRING) {
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java Mon Nov 29 12:24:48 2010
@@ -88,8 +88,7 @@ public class QueryImpl extends AbstractQ
SessionContext sessionContext, SearchIndex index,
PropertyTypeRegistry propReg, String statement, String language,
QueryNodeFactory factory) throws InvalidQueryException {
- super(sessionContext, index, propReg,
- Collections.<String, Value>emptyMap());
+ super(sessionContext, index, propReg);
// parse query according to language
// build query tree using the passed factory
this.root = QueryParser.parse(
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java Mon Nov 29 12:24:48 2010
@@ -16,10 +16,9 @@
*/
package org.apache.jackrabbit.core.query.lucene;
-import java.io.InputStream;
-
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -39,7 +38,6 @@ import javax.xml.parsers.DocumentBuilder
import javax.xml.parsers.ParserConfigurationException;
import org.apache.jackrabbit.core.HierarchyManager;
-import org.apache.jackrabbit.core.ItemManager;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.fs.FileSystem;
import org.apache.jackrabbit.core.fs.FileSystemException;
@@ -60,12 +58,10 @@ import org.apache.jackrabbit.core.state.
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.PathFactory;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
import org.apache.jackrabbit.spi.commons.query.DefaultQueryNodeFactory;
import org.apache.jackrabbit.spi.commons.query.qom.OrderingImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.document.Document;
@@ -683,28 +679,6 @@ public class SearchIndex extends Abstrac
}
/**
- * Creates a new query by specifying the query object model. If the query
- * object model is considered invalid for the implementing class, an
- * InvalidQueryException is thrown.
- *
- * @param sessionContext component context of the current session
- * @param qomTree query query object model tree.
- * @return A <code>Query</code> object.
- * @throws javax.jcr.query.InvalidQueryException
- * if the query object model tree is invalid.
- * @see QueryHandler#createExecutableQuery(SessionImpl, ItemManager, QueryObjectModelTree)
- */
- public ExecutableQuery createExecutableQuery(
- SessionContext sessionContext, QueryObjectModelTree qomTree)
- throws InvalidQueryException {
- QueryObjectModelImpl query = new QueryObjectModelImpl(
- sessionContext, this, getContext().getPropertyTypeRegistry(),
- qomTree);
- query.setRespectDocumentOrder(documentOrder);
- return query;
- }
-
- /**
* {@inheritDoc}
*/
public Iterable<NodeId> getWeaklyReferringNodes(NodeId id)
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java Mon Nov 29 12:24:48 2010
@@ -17,7 +17,6 @@
package org.apache.jackrabbit.core.query.lucene.join;
import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_LEFT_OUTER;
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_RIGHT_OUTER;
import java.util.ArrayList;
import java.util.Collections;
@@ -163,93 +162,47 @@ abstract class JoinMerger {
public QueryResult merge(RowIterator leftRows, RowIterator rightRows)
throws RepositoryException {
RowIterator joinRows;
- if (JCR_JOIN_TYPE_RIGHT_OUTER.equals(type)) {
- Map<String, List<Row>> map = new HashMap<String, List<Row>>();
- for (Row row : new RowIterable(leftRows)) {
- for (String value : getLeftValues(row)) {
- List<Row> rows = map.get(value);
- if (rows == null) {
- rows = new ArrayList<Row>();
- map.put(value, rows);
- }
- rows.add(row);
- }
- }
- joinRows = mergeRight(map, rightRows);
- } else {
- Map<String, List<Row>> map = new HashMap<String, List<Row>>();
- for (Row row : new RowIterable(rightRows)) {
- for (String value : getRightValues(row)) {
- List<Row> rows = map.get(value);
- if (rows == null) {
- rows = new ArrayList<Row>();
- map.put(value, rows);
- }
- rows.add(row);
+
+ Map<String, List<Row>> map = new HashMap<String, List<Row>>();
+ for (Row row : new RowIterable(rightRows)) {
+ for (String value : getRightValues(row)) {
+ List<Row> rows = map.get(value);
+ if (rows == null) {
+ rows = new ArrayList<Row>();
+ map.put(value, rows);
}
+ rows.add(row);
}
- boolean outer = JCR_JOIN_TYPE_LEFT_OUTER.equals(type);
- joinRows = mergeLeft(leftRows, map, outer);
}
- return new SimpleQueryResult(columnNames, selectorNames, joinRows);
- }
- private RowIterator mergeLeft(
- RowIterator leftRows, Map<String, List<Row>> rightRowMap,
- boolean outer) throws RepositoryException {
- if (!rightRowMap.isEmpty()) {
+ if (!map.isEmpty()) {
List<Row> rows = new ArrayList<Row>();
for (Row leftRow : new RowIterable(leftRows)) {
for (String value : getLeftValues(leftRow)) {
- List<Row> rightRows = rightRowMap.get(value);
- if (rightRows != null) {
- for (Row rightRow : rightRows) {
+ List<Row> matchingRows = map.get(value);
+ if (matchingRows != null) {
+ for (Row rightRow : matchingRows) {
rows.add(mergeRow(leftRow, rightRow));
}
- } else if (outer) {
+ } else if (JCR_JOIN_TYPE_LEFT_OUTER.equals(type)) {
+ // No matches in an outer join -> add a null row
rows.add(mergeRow(leftRow, null));
}
}
}
- return new RowIteratorAdapter(rows);
- } else if (outer) {
- return new RowIteratorAdapter(leftRows) {
+ joinRows = new RowIteratorAdapter(rows);
+ } else if (JCR_JOIN_TYPE_LEFT_OUTER.equals(type)) {
+ joinRows = new RowIteratorAdapter(leftRows) {
@Override
public Object next() {
return mergeRow((Row) super.next(), null);
}
};
} else {
- return new RowIteratorAdapter(Collections.emptySet());
+ joinRows = new RowIteratorAdapter(Collections.emptySet());
}
- }
- private RowIterator mergeRight(
- Map<String, List<Row>> leftRowMap, RowIterator rightRows)
- throws RepositoryException {
- if (leftRowMap.isEmpty()) {
- List<Row> rows = new ArrayList<Row>();
- for (Row rightRow : new RowIterable(rightRows)) {
- for (String value : getRightValues(rightRow)) {
- List<Row> leftRows = leftRowMap.get(value);
- if (leftRows != null) {
- for (Row leftRow : leftRows) {
- rows.add(mergeRow(leftRow, rightRow));
- }
- } else {
- rows.add(mergeRow(null, rightRow));
- }
- }
- }
- return new RowIteratorAdapter(rows);
- } else {
- return new RowIteratorAdapter(rightRows) {
- @Override
- public Object next() {
- return mergeRow(null, (Row) super.next());
- }
- };
- }
+ return new SimpleQueryResult(columnNames, selectorNames, joinRows);
}
/**
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/OperandEvaluator.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/OperandEvaluator.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/OperandEvaluator.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/OperandEvaluator.java Mon Nov 29 12:24:48 2010
@@ -24,6 +24,7 @@ import java.util.Map;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
+import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
@@ -67,6 +68,21 @@ public class OperandEvaluator {
this.variables = variables;
}
+ public Value getValue(StaticOperand operand, int type) throws RepositoryException {
+ Value value = getValue(operand);
+ if (type == PropertyType.UNDEFINED || type == value.getType()) {
+ return value;
+ } if (type == PropertyType.LONG) {
+ return factory.createValue(value.getLong());
+ } if (type == PropertyType.DOUBLE) {
+ return factory.createValue(value.getDouble());
+ } if (type == PropertyType.DATE) {
+ return factory.createValue(value.getDate());
+ } else {
+ return factory.createValue(value.getString(), type);
+ }
+ }
+
/**
* Returns the value of the given static operand
* ({@link Literal literal} or {@link BindVariableValue bind variable}).
@@ -280,11 +296,14 @@ public class OperandEvaluator {
*/
private Property getProperty(PropertyValue operand, Row row)
throws RepositoryException {
- try {
- String selector = operand.getSelectorName();
- String property = operand.getPropertyName();
- return row.getNode(selector).getProperty(property);
- } catch (PathNotFoundException e) {
+ Node node = row.getNode(operand.getSelectorName());
+ if (node != null) {
+ try {
+ return node.getProperty(operand.getPropertyName());
+ } catch (PathNotFoundException e) {
+ return null;
+ }
+ } else {
return null;
}
}