You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ju...@apache.org on 2013/04/12 18:44:26 UTC
svn commit: r1467342 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/
oak-core/src/main/re...
Author: jukka
Date: Fri Apr 12 16:44:25 2013
New Revision: 1467342
URL: http://svn.apache.org/r1467342
Log:
OAK-323: Column names aren't reported properly for "select * from [nodeType]" queries
Extend query parser to use proper type information to resolve wildcard columns
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeConstants.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditor.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ColumnImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
jackrabbit/oak/trunk/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_explain.txt
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_measure.txt
jackrabbit/oak/trunk/oak-jcr/pom.xml
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/qom/QomTest.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeConstants.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeConstants.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeConstants.java Fri Apr 12 16:44:25 2013
@@ -62,9 +62,10 @@ public interface NodeTypeConstants exten
// Precompiled Oak type information fields
String OAK_SUPERTYPES = "oak:supertypes";
String OAK_SUBTYPES = "oak:subtypes";
- String OAK_NAMED_PROPERTIES = "oak:namedProperties";
String OAK_MANDATORY_PROPERTIES = "oak:mandatoryProperties";
String OAK_MANDATORY_CHILD_NODES = "oak:mandatoryChildNodes";
+ String OAK_NAMED_SINGLE_VALUED_PROPERTIES =
+ "oak:namedSingleValuedProperties";
String OAK_RESIDUAL_CHILD_NODE_DEFINITIONS =
"oak:residualChildNodeDefinitions";
String OAK_NAMED_CHILD_NODE_DEFINITIONS =
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditor.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditor.java Fri Apr 12 16:44:25 2013
@@ -47,7 +47,7 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_MANDATORY_CHILD_NODES;
import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_MANDATORY_PROPERTIES;
import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_CHILD_NODE_DEFINITIONS;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_PROPERTIES;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_SINGLE_VALUED_PROPERTIES;
import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_PROPERTY_DEFINITIONS;
import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_PROPERTY_DEFINITIONS;
import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_RESIDUAL_CHILD_NODE_DEFINITIONS;
@@ -164,9 +164,9 @@ class RegistrationEditor extends Default
supertype.getProperty(JCR_NODETYPENAME).getValue(NAME);
addNameToList(type, OAK_SUPERTYPES, supername);
mergeNameList(type, supertype, OAK_SUPERTYPES);
- mergeNameList(type, supertype, OAK_NAMED_PROPERTIES);
mergeNameList(type, supertype, OAK_MANDATORY_PROPERTIES);
mergeNameList(type, supertype, OAK_MANDATORY_CHILD_NODES);
+ mergeNameList(type, supertype, OAK_NAMED_SINGLE_VALUED_PROPERTIES);
mergeSubtree(type, supertype, OAK_NAMED_PROPERTY_DEFINITIONS, 2);
mergeSubtree(type, supertype, OAK_RESIDUAL_PROPERTY_DEFINITIONS, 1);
mergeSubtree(type, supertype, OAK_NAMED_CHILD_NODE_DEFINITIONS, 2);
@@ -221,9 +221,9 @@ class RegistrationEditor extends Default
type.setProperty(JCR_PRIMARYTYPE, "oak:nodeType", NAME);
type.removeProperty(OAK_SUPERTYPES);
type.setProperty(OAK_SUBTYPES, empty, NAMES);
- type.setProperty(OAK_NAMED_PROPERTIES, empty, NAMES);
type.setProperty(OAK_MANDATORY_PROPERTIES, empty, NAMES);
type.setProperty(OAK_MANDATORY_CHILD_NODES, empty, NAMES);
+ type.setProperty(OAK_NAMED_SINGLE_VALUED_PROPERTIES, empty, NAMES);
type.removeNode(OAK_NAMED_PROPERTY_DEFINITIONS);
type.removeNode(OAK_RESIDUAL_PROPERTY_DEFINITIONS);
type.removeNode(OAK_NAMED_CHILD_NODE_DEFINITIONS);
@@ -258,8 +258,9 @@ class RegistrationEditor extends Default
// - jcr:name (NAME) protected
PropertyState name = definition.getProperty(JCR_NAME);
NodeBuilder definitions;
+ String propertyName = null;
if (name != null) {
- String propertyName = name.getValue(NAME);
+ propertyName = name.getValue(NAME);
String escapedName = propertyName;
if (JCR_PRIMARYTYPE.equals(escapedName)) {
escapedName = "oak:primaryType";
@@ -302,6 +303,8 @@ class RegistrationEditor extends Default
} else {
key = key + "S";
}
+ } else if (propertyName != null) {
+ addNameToList(type, OAK_NAMED_SINGLE_VALUED_PROPERTIES, propertyName);
}
definitions.setNode(key, definition);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java Fri Apr 12 16:44:25 2013
@@ -16,6 +16,10 @@
*/
package org.apache.jackrabbit.oak.query;
+import static com.google.common.collect.ImmutableSet.of;
+import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
+
import java.text.ParseException;
import java.util.List;
import java.util.Map;
@@ -35,8 +39,6 @@ import org.apache.jackrabbit.oak.spi.sta
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.ImmutableSet;
-
/**
* The query engine implementation.
*/
@@ -46,53 +48,19 @@ public abstract class QueryEngineImpl im
static final String SQL = "sql";
static final String XPATH = "xpath";
static final String JQOM = "JCR-JQOM";
-
+
static final String NO_LITERALS = "-noLiterals";
+ private static final Set<String> SUPPORTED_LANGUAGES = of(
+ SQL2, SQL2 + NO_LITERALS,
+ SQL, SQL + NO_LITERALS,
+ XPATH, XPATH + NO_LITERALS,
+ JQOM);
+
static final Logger LOG = LoggerFactory.getLogger(QueryEngineImpl.class);
private final QueryIndexProvider indexProvider;
- // TODO: Turn into a standalone class
- private final QueryParser parser = new QueryParser() {
- @Override
- public Set<String> getSupportedLanguages() {
- return ImmutableSet.of(
- SQL2, SQL, XPATH, JQOM,
- SQL2 + NO_LITERALS,
- SQL + NO_LITERALS,
- XPATH + NO_LITERALS);
- }
- @Override
- public Query parse(String statement, String language)
- throws ParseException {
- LOG.debug("Parsing {} statement: {}", language, statement);
- SQL2Parser parser = new SQL2Parser();
- if (language.endsWith(NO_LITERALS)) {
- language = language.substring(0, language.length() - NO_LITERALS.length());
- parser.setAllowNumberLiterals(false);
- parser.setAllowTextLiterals(false);
- }
- if (SQL2.equals(language) || JQOM.equals(language)) {
- return parser.parse(statement);
- } else if (SQL.equals(language)) {
- parser.setSupportSQL1(true);
- return parser.parse(statement);
- } else if (XPATH.equals(language)) {
- XPathToSQL2Converter converter = new XPathToSQL2Converter();
- String sql2 = converter.convert(statement);
- LOG.debug("XPath > SQL2: {}", sql2);
- try {
- return parser.parse(sql2);
- } catch (ParseException e) {
- throw new ParseException(statement + " converted to SQL-2 " + e.getMessage(), 0);
- }
- } else {
- throw new ParseException("Unsupported language: " + language, 0);
- }
- }
- };
-
public QueryEngineImpl(QueryIndexProvider indexProvider) {
this.indexProvider = indexProvider;
}
@@ -113,7 +81,7 @@ public abstract class QueryEngineImpl im
@Override
public Set<String> getSupportedQueryLanguages() {
- return parser.getSupportedLanguages();
+ return SUPPORTED_LANGUAGES;
}
/**
@@ -131,7 +99,33 @@ public abstract class QueryEngineImpl im
}
private Query parseQuery(String statement, String language) throws ParseException {
- return parser.parse(statement, language);
+ LOG.debug("Parsing {} statement: {}", language, statement);
+ NodeState root = getRootState();
+ NodeState system = root.getChildNode(JCR_SYSTEM);
+ NodeState types = system.getChildNode(JCR_NODE_TYPES);
+ SQL2Parser parser = new SQL2Parser(types);
+ if (language.endsWith(NO_LITERALS)) {
+ language = language.substring(0, language.length() - NO_LITERALS.length());
+ parser.setAllowNumberLiterals(false);
+ parser.setAllowTextLiterals(false);
+ }
+ if (SQL2.equals(language) || JQOM.equals(language)) {
+ return parser.parse(statement);
+ } else if (SQL.equals(language)) {
+ parser.setSupportSQL1(true);
+ return parser.parse(statement);
+ } else if (XPATH.equals(language)) {
+ XPathToSQL2Converter converter = new XPathToSQL2Converter();
+ String sql2 = converter.convert(statement);
+ LOG.debug("XPath > SQL2: {}", sql2);
+ try {
+ return parser.parse(sql2);
+ } catch (ParseException e) {
+ throw new ParseException(statement + " converted to SQL-2 " + e.getMessage(), 0);
+ }
+ } else {
+ throw new ParseException("Unsupported language: " + language, 0);
+ }
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java Fri Apr 12 16:44:25 2013
@@ -16,6 +16,14 @@
*/
package org.apache.jackrabbit.oak.query;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Maps.newHashMap;
+import static org.apache.jackrabbit.JcrConstants.NT_BASE;
+import static org.apache.jackrabbit.oak.api.Type.NAMES;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_SINGLE_VALUED_PROPERTIES;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_SUBTYPES;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
@@ -35,14 +43,20 @@ import org.apache.jackrabbit.oak.query.a
import org.apache.jackrabbit.oak.query.ast.SourceImpl;
import org.apache.jackrabbit.oak.query.ast.StaticOperandImpl;
import org.apache.jackrabbit.oak.spi.query.PropertyValues;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.ImmutableSet;
+
import javax.jcr.PropertyType;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
/**
* The SQL2 parser can convert a JCR-SQL2 query to a query. The 'old' SQL query
@@ -61,6 +75,8 @@ public class SQL2Parser {
private static final int KEYWORD = 1, IDENTIFIER = 2, PARAMETER = 3, END = 4, VALUE = 5;
private static final int MINUS = 12, PLUS = 13, OPEN = 14, CLOSE = 15;
+ private final NodeState types;
+
// The query as an array of characters and character types
private String statement;
private char[] statementChars;
@@ -78,7 +94,7 @@ public class SQL2Parser {
private HashMap<String, BindVariableValueImpl> bindVariables;
// The list of selectors of this query
- private ArrayList<SelectorImpl> selectors;
+ private final Map<String, SelectorImpl> selectors = newHashMap();
// SQL injection protection: if disabled, literals are not allowed
private boolean allowTextLiterals = true;
@@ -92,7 +108,8 @@ public class SQL2Parser {
* Create a new parser. A parser can be re-used, but it is not thread safe.
*
*/
- public SQL2Parser() {
+ public SQL2Parser(NodeState types) {
+ this.types = checkNotNull(types);
}
/**
@@ -107,7 +124,7 @@ public class SQL2Parser {
// http://docs.jboss.org/modeshape/latest/manuals/reference/html/jcr-query-and-search.html
initialize(query);
- selectors = new ArrayList<SelectorImpl>();
+ selectors.clear();
expected = new ArrayList<String>();
bindVariables = new HashMap<String, BindVariableValueImpl>();
read();
@@ -177,11 +194,30 @@ public class SQL2Parser {
private SelectorImpl parseSelector() throws ParseException {
String nodeTypeName = readName();
+
+ Set<String> matchingTypes = null;
+ if (!NT_BASE.equals(nodeTypeName)) {
+ ImmutableSet.Builder<String> builder = ImmutableSet.builder();
+ NodeState type = types.getChildNode(nodeTypeName);
+ if (type.exists()) {
+ builder.add(nodeTypeName);
+ PropertyState subtypes = type.getProperty(OAK_SUBTYPES);
+ if (subtypes != null) {
+ for (String subname : subtypes.getValue(NAMES)) {
+ builder.add(subname);
+ }
+ }
+ } else {
+ throw getSyntaxError("unknown node type");
+ }
+ matchingTypes = builder.build();
+ }
+
if (readIf("AS")) {
String selectorName = readName();
- return factory.selector(nodeTypeName, selectorName);
+ return factory.selector(nodeTypeName, selectorName, matchingTypes);
} else {
- return factory.selector(nodeTypeName, nodeTypeName);
+ return factory.selector(nodeTypeName, nodeTypeName, matchingTypes);
}
}
@@ -201,7 +237,7 @@ public class SQL2Parser {
private SourceImpl parseSource() throws ParseException {
SelectorImpl selector = parseSelector();
- selectors.add(selector);
+ selectors.put(selector.getSelectorName(), selector);
SourceImpl source = selector;
while (true) {
JoinType joinType;
@@ -218,7 +254,7 @@ public class SQL2Parser {
}
read("JOIN");
selector = parseSelector();
- selectors.add(selector);
+ selectors.put(selector.getSelectorName(), selector);
read("ON");
JoinConditionImpl on = parseJoinCondition();
source = factory.join(source, selector, joinType, on);
@@ -709,21 +745,25 @@ public class SQL2Parser {
} else {
do {
ColumnOrWildcard column = new ColumnOrWildcard();
- column.propertyName = readName();
- if (readIf(".")) {
- column.selectorName = column.propertyName;
- if (readIf("*")) {
- column.propertyName = null;
+ if (readIf("*")) {
+ column.propertyName = null;
+ } else {
+ column.propertyName = readName();
+ if (readIf(".")) {
+ column.selectorName = column.propertyName;
+ if (readIf("*")) {
+ column.propertyName = null;
+ } else {
+ column.propertyName = readName();
+ if (readIf("AS")) {
+ column.columnName = readName();
+ }
+ }
} else {
- column.propertyName = readName();
if (readIf("AS")) {
column.columnName = readName();
}
}
- } else {
- if (readIf("AS")) {
- column.columnName = readName();
- }
}
list.add(column);
} while (readIf(","));
@@ -735,25 +775,20 @@ public class SQL2Parser {
ArrayList<ColumnImpl> columns = new ArrayList<ColumnImpl>();
for (ColumnOrWildcard c : list) {
if (c.propertyName == null) {
- for (SelectorImpl selector : selectors) {
- if (c.selectorName == null
- || c.selectorName
- .equals(selector.getSelectorName())) {
- ColumnImpl column = factory.column(selector
- .getSelectorName(), null, null);
- columns.add(column);
- }
- }
+ addWildcardColumns(columns, c.selectorName);
} else {
- ColumnImpl column;
- if (c.selectorName != null) {
- column = factory.column(c.selectorName, c.propertyName, c.columnName);
- } else if (c.columnName != null) {
- column = factory.column(getOnlySelectorName(), c.propertyName, c.columnName);
- } else {
- column = factory.column(getOnlySelectorName(), c.propertyName, c.propertyName);
+ String selectorName = c.selectorName;
+ if (selectorName == null) {
+ selectorName = getOnlySelectorName();
+ }
+
+ String columnName = c.columnName;
+ if (columnName == null) {
+ columnName = c.propertyName;
}
- columns.add(column);
+
+ columns.add(factory.column(
+ selectorName, c.propertyName, columnName));
}
}
ColumnImpl[] array = new ColumnImpl[columns.size()];
@@ -761,6 +796,42 @@ public class SQL2Parser {
return array;
}
+ private void addWildcardColumns(
+ Collection<ColumnImpl> columns, String selectorName)
+ throws ParseException {
+ if (selectorName == null) {
+ for (SelectorImpl selector : selectors.values()) {
+ addWildcardColumns(columns, selector, selectors.size() > 1);
+ }
+ } else {
+ SelectorImpl selector = selectors.get(selectorName);
+ if (selector != null) {
+ addWildcardColumns(columns, selector, true);
+ } else {
+ throw getSyntaxError("Unknown selector: " + selectorName);
+ }
+ }
+ }
+
+ private void addWildcardColumns(
+ Collection<ColumnImpl> columns, SelectorImpl selector,
+ boolean includeSelectorName) {
+ String name = selector.getNodeTypeName();
+
+ PropertyState properties = types.getChildNode(name).getProperty(
+ OAK_NAMED_SINGLE_VALUED_PROPERTIES);
+ if (properties != null) {
+ String selectorName = selector.getSelectorName();
+ for (String property : properties.getValue(NAMES)) {
+ String columnName = property;
+ if (includeSelectorName) {
+ columnName = selectorName + "." + property;
+ }
+ columns.add(factory.column(selectorName, property, columnName));
+ }
+ }
+ }
+
private boolean readIf(String token) throws ParseException {
if (isToken(token)) {
read();
@@ -1152,7 +1223,7 @@ public class SQL2Parser {
if (selectors.size() > 1) {
throw getSyntaxError("Need to specify the selector name because the query contains more than one selector.");
}
- return selectors.get(0).getSelectorName();
+ return selectors.values().iterator().next().getSelectorName();
}
public static String escapeStringLiteral(String value) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java Fri Apr 12 16:44:25 2013
@@ -13,6 +13,8 @@
*/
package org.apache.jackrabbit.oak.query.ast;
+import java.util.Set;
+
import org.apache.jackrabbit.oak.api.PropertyValue;
/**
@@ -128,8 +130,10 @@ public class AstElementFactory {
return new SameNodeJoinConditionImpl(selector1Name, selector2Name, selector2Path);
}
- public SelectorImpl selector(String nodeTypeName, String selectorName) {
- return new SelectorImpl(nodeTypeName, selectorName);
+ public SelectorImpl selector(
+ String nodeTypeName, String selectorName,
+ Set<String> matchingTypes) {
+ return new SelectorImpl(nodeTypeName, selectorName, matchingTypes);
}
public UpperCaseImpl upperCase(DynamicOperandImpl operand) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ColumnImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ColumnImpl.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ColumnImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ColumnImpl.java Fri Apr 12 16:44:25 2013
@@ -18,8 +18,9 @@
*/
package org.apache.jackrabbit.oak.query.ast;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import org.apache.jackrabbit.oak.api.PropertyValue;
-import org.apache.jackrabbit.oak.spi.query.PropertyValues;
/**
* A result column expression.
@@ -30,9 +31,9 @@ public class ColumnImpl extends AstEleme
private SelectorImpl selector;
public ColumnImpl(String selectorName, String propertyName, String columnName) {
- this.selectorName = selectorName;
- this.propertyName = propertyName;
- this.columnName = columnName;
+ this.selectorName = checkNotNull(selectorName);
+ this.propertyName = checkNotNull(propertyName);
+ this.columnName = checkNotNull(columnName);
}
public String getColumnName() {
@@ -46,23 +47,11 @@ public class ColumnImpl extends AstEleme
@Override
public String toString() {
- if (propertyName != null) {
- return quote(selectorName) + '.' + quote(propertyName) +
- " as " + quote(columnName);
- } else {
- return quote(selectorName) + ".*";
- }
+ return quote(selectorName) + '.' + quote(propertyName)
+ + " as " + quote(columnName);
}
public PropertyValue currentProperty() {
- if (propertyName == null || propertyName.equals("*")) {
- // TODO for SELECT * FROM queries, currently return the path (for testing only)
- String p = selector.currentPath();
- if (p == null) {
- return null;
- }
- return PropertyValues.newString(p);
- }
return selector.currentProperty(propertyName);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java Fri Apr 12 16:44:25 2013
@@ -25,6 +25,7 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.query.ast.ComparisonImpl.LikePattern;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
import org.apache.jackrabbit.oak.spi.query.PropertyValues;
@@ -38,14 +39,33 @@ import static org.apache.jackrabbit.oak.
public class FullTextSearchImpl extends ConstraintImpl {
private final String selectorName;
+ private final String relativePath;
private final String propertyName;
private final StaticOperandImpl fullTextSearchExpression;
private SelectorImpl selector;
- public FullTextSearchImpl(String selectorName, String propertyName,
+ public FullTextSearchImpl(
+ String selectorName, String propertyName,
StaticOperandImpl fullTextSearchExpression) {
this.selectorName = selectorName;
- this.propertyName = propertyName;
+
+ int slash = -1;
+ if (propertyName != null) {
+ slash = propertyName.lastIndexOf('/');
+ }
+ if (slash == -1) {
+ this.relativePath = null;
+ } else {
+ this.relativePath = propertyName.substring(0, slash);
+ propertyName = propertyName.substring(slash + 1);
+ }
+
+ if (propertyName == null || "*".equals(propertyName)) {
+ this.propertyName = null;
+ } else {
+ this.propertyName = propertyName;
+ }
+
this.fullTextSearchExpression = fullTextSearchExpression;
}
@@ -63,13 +83,16 @@ public class FullTextSearchImpl extends
StringBuilder builder = new StringBuilder();
builder.append("contains(");
builder.append(quote(selectorName));
- if (propertyName != null) {
- builder.append('.');
- builder.append(quote(propertyName));
- builder.append(", ");
- } else {
- builder.append(".*, ");
+ builder.append('.');
+ String propertyName = this.propertyName;
+ if (propertyName == null) {
+ propertyName = "*";
+ }
+ if (relativePath != null) {
+ propertyName = relativePath + "/" + propertyName;
}
+ builder.append(quote(propertyName));
+ builder.append(", ");
builder.append(getFullTextSearchExpression());
builder.append(')');
return builder.toString();
@@ -78,19 +101,33 @@ public class FullTextSearchImpl extends
@Override
public boolean evaluate() {
StringBuilder buff = new StringBuilder();
- if (propertyName != null) {
+ if (relativePath == null && propertyName != null) {
PropertyValue p = selector.currentProperty(propertyName);
if (p == null) {
return false;
}
appendString(buff, p);
} else {
- Tree tree = getTree(selector.currentPath());
+ String path = selector.currentPath();
+ if (relativePath != null) {
+ path = PathUtils.concat(path, relativePath);
+ }
+
+ Tree tree = getTree(path);
if (tree == null) {
return false;
}
- for (PropertyState p : tree.getProperties()) {
+
+ if (propertyName != null) {
+ PropertyState p = tree.getProperty(propertyName);
+ if (p == null) {
+ return false;
+ }
appendString(buff, PropertyValues.create(p));
+ } else {
+ for (PropertyState p : tree.getProperties()) {
+ appendString(buff, PropertyValues.create(p));
+ }
}
}
// TODO fulltext conditions: need a way to disable evaluation
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java Fri Apr 12 16:44:25 2013
@@ -18,23 +18,19 @@
*/
package org.apache.jackrabbit.oak.query.ast;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.oak.api.Type.NAME;
+import static org.apache.jackrabbit.oak.api.Type.NAMES;
-import javax.annotation.CheckForNull;
-import javax.jcr.RepositoryException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-import javax.jcr.nodetype.NodeTypeManager;
+import java.util.Set;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
-import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
import org.apache.jackrabbit.oak.query.Query;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
import org.apache.jackrabbit.oak.spi.query.Cursor;
@@ -44,9 +40,6 @@ import org.apache.jackrabbit.oak.spi.que
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
import org.apache.jackrabbit.oak.spi.state.NodeState;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-
/**
* A selector within a query.
*/
@@ -55,20 +48,18 @@ public class SelectorImpl extends Source
// TODO possibly support using multiple indexes (using index intersection / index merge)
protected QueryIndex index;
- private final String nodeTypeName, selectorName;
- private Cursor cursor;
- private IndexRow currentRow;
- private int scanCount;
+ private final String nodeTypeName;
+
+ private final String selectorName;
/**
- * Names of all matching node type names encountered so far.
+ * Names of matching node types, or {@code null} if all types match.
*/
private final Set<String> matchingTypes;
- /**
- * Names of all <em>non-matching</em> node type names encountered so far.
- */
- private final Set<String> nonMatchingTypes;
+ private Cursor cursor;
+ private IndexRow currentRow;
+ private int scanCount;
/**
* The selector condition can be evaluated when the given selector is
@@ -79,19 +70,16 @@ public class SelectorImpl extends Source
*/
private ConstraintImpl selectorCondition;
- public SelectorImpl(String nodeTypeName, String selectorName) {
- this.nodeTypeName = nodeTypeName;
- this.selectorName = selectorName;
-
- if (JcrConstants.NT_BASE.equals(nodeTypeName)) {
- matchingTypes = null;
- nonMatchingTypes = null;
- } else {
- matchingTypes = Sets.newHashSet();
- matchingTypes.add(nodeTypeName);
- nonMatchingTypes = Sets.newHashSet();
- nonMatchingTypes.add(JcrConstants.NT_BASE);
- }
+ public SelectorImpl(
+ String nodeTypeName, String selectorName,
+ Set<String> matchingTypes) {
+ this.nodeTypeName = checkNotNull(nodeTypeName);
+ this.selectorName = checkNotNull(selectorName);
+ this.matchingTypes = matchingTypes;
+ }
+
+ public String getNodeTypeName() {
+ return nodeTypeName;
}
public String getSelectorName() {
@@ -151,7 +139,6 @@ public class SelectorImpl extends Source
private Filter createFilter(boolean preparing) {
FilterImpl f = new FilterImpl(this, query.getStatement());
f.setPreparing(preparing);
- validateNodeType();
f.setNodeType(nodeTypeName);
if (joinCondition != null) {
joinCondition.restrict(f);
@@ -172,30 +159,6 @@ public class SelectorImpl extends Source
return f;
}
-
- private void validateNodeType() {
- if (!JcrConstants.NT_BASE.equals(nodeTypeName)) {
- try {
- // Check both the syntactic validity of the type name
- // and the existence of the named type in one call
- getNodeTypeManager().getNodeType(nodeTypeName);
- } catch (NoSuchNodeTypeException e) {
- // TODO: QueryManagerImpl.executeQuery() expects an
- // IllegalArgumentException to signal an invalid query.
- // This is a bit troublesome since any method could throw
- // that exception as a result of some internal programming
- // error or some other inconsistency that has nothing to
- // do with the validity of the query. A better solution
- // would be to use some checked exception or explicit
- // return value to signal whether the query is valid or not.
- throw new IllegalArgumentException(
- "Unknown node type: " + nodeTypeName, e);
- } catch (RepositoryException e) {
- throw new RuntimeException(
- "Unable to evaluate node type constraints", e);
- }
- }
- }
@Override
public boolean next() {
@@ -225,63 +188,30 @@ public class SelectorImpl extends Source
}
private boolean evaluateTypeMatch(Tree tree) {
- if (JcrConstants.NT_BASE.equals(nodeTypeName)) {
+ if (matchingTypes == null) {
return true; // shortcut for a common case
}
- Set<String> types = Sets.newHashSet();
-
- PropertyState primary = tree.getProperty(JcrConstants.JCR_PRIMARYTYPE);
- if (primary != null && primary.getType() == Type.NAME) {
- String name = primary.getValue(Type.NAME);
+ PropertyState primary = tree.getProperty(JCR_PRIMARYTYPE);
+ if (primary != null && primary.getType() == NAME) {
+ String name = primary.getValue(NAME);
if (matchingTypes.contains(name)) {
return true;
- } else if (!nonMatchingTypes.contains(name)) {
- types.add(name);
}
}
- PropertyState mixins = tree.getProperty(JcrConstants.JCR_MIXINTYPES);
- if (mixins != null && mixins.getType() == Type.NAMES) {
- for (String name : mixins.getValue(Type.NAMES)) {
+ PropertyState mixins = tree.getProperty(JCR_MIXINTYPES);
+ if (mixins != null && mixins.getType() == NAMES) {
+ for (String name : mixins.getValue(NAMES)) {
if (matchingTypes.contains(name)) {
return true;
- } else if (!nonMatchingTypes.contains(name)) {
- types.add(name);
- }
- }
- }
-
- if (!types.isEmpty()) {
- try {
- NodeTypeManager manager = getNodeTypeManager();
- for (String type : types) {
- if (manager.getNodeType(type).isNodeType(nodeTypeName)) {
- matchingTypes.add(type);
- return true;
- } else {
- nonMatchingTypes.add(type);
- // continue iterating
- }
}
- } catch (RepositoryException e) {
- throw new RuntimeException(
- "Unable to evaluate node type constraints", e);
}
}
return false; // no matches found
}
- private NodeTypeManager getNodeTypeManager() {
- return new ReadOnlyNodeTypeManager() {
- @Override @CheckForNull
- protected Tree getTypes() {
- return getTree(NodeTypeConstants.NODE_TYPES_PATH);
- }
- };
- }
-
/**
* Get the current absolute path (including workspace name)
*
@@ -333,16 +263,6 @@ public class SelectorImpl extends Source
}
return PropertyValues.newString(local);
}
- if (propertyName.equals("*")) {
- // TODO currently all property values are converted to strings -
- // this doesn't play well with the idea that the types may be different
- List<String> values = new ArrayList<String>();
- for (PropertyState p : t.getProperties()) {
- Iterables.addAll(values, p.getValue(Type.STRINGS));
- }
- // "*"
- return PropertyValues.newString(values);
- }
return PropertyValues.create(t.getProperty(propertyName));
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd Fri Apr 12 16:44:25 2013
@@ -428,9 +428,9 @@
[oak:nodeType] > nt:nodeType
- oak:supertypes (NAME) protected multiple autocreated
- oak:subtypes (NAME) protected multiple autocreated
- - oak:namedProperties (NAME) protected multiple autocreated
- oak:mandatoryProperties (NAME) protected multiple autocreated
- oak:mandatoryChildNodes (NAME) protected multiple autocreated
+ - oak:namedSingleValuedProperties (NAME) protected multiple autocreated
+ oak:namedPropertyDefinitions (oak:namedPropertyDefinitions) = oak:namedPropertyDefinitions protected mandatory
+ oak:residualPropertyDefinitions (oak:propertyDefinitions) = oak:propertyDefinitions protected mandatory
+ oak:namedChildNodeDefinitions (oak:namedChildNodeDefinitions) = oak:namedChildNodeDefinitions protected mandatory
Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt Fri Apr 12 16:44:25 2013
@@ -28,10 +28,10 @@
commit / + "test": { "a": { "x": "1", "yes": { } }, "b": { "yes" : { } }, "c": { "x": "1", "no" : { } }}
xpath test//yes/..[@x]
-/test/a, null, /test/a
+/test/a, null, null
-select b.[jcr:path] as [jcr:path], b.[jcr:score] as [jcr:score], b.* from [nt:base] as a inner join [nt:base] as b on ischildnode(a, b) where name(a) = 'yes' and isdescendantnode(a, '/test') and b.[x] is not null
-/test/a, null, /test/a
+select b.[jcr:path] as [jcr:path], b.[jcr:score] as [jcr:score] from [nt:base] as a inner join [nt:base] as b on ischildnode(a, b) where name(a) = 'yes' and isdescendantnode(a, '/test') and b.[x] is not null
+/test/a, null
commit / - "test"
@@ -39,7 +39,7 @@ commit / - "test"
commit / + "test": { "space space": { "x": "1" }}
-select * from [nt:base] where issamenode([/test/space space])
+select [jcr:path] from [nt:base] where issamenode([/test/space space])
/test/space space
commit / - "test"
@@ -48,44 +48,44 @@ commit / - "test"
commit / + "test": { "a": { "name": ["Hello", "World" ] }, "b": { "name" : "Hello" }}
-select * from [nt:base] where name = 'Hello'
+select [jcr:path] from [nt:base] where name = 'Hello'
/test/a
/test/b
-select * from [nt:base] where name = 'World'
+select [jcr:path] from [nt:base] where name = 'World'
/test/a
-select * from [nt:base] where isdescendantnode('/test') and name = 'World'
+select [jcr:path] from [nt:base] where isdescendantnode('/test') and name = 'World'
/test/a
commit / - "test"
# expected error on two selectors with the same name
-select * from [nt:base] as p inner join [nt:base] as p on ischildnode(p, p) where p.[jcr:path] = '/'
-java.text.ParseException: select * from [nt:base] as p inner join [nt:base] as p on ischildnode(p, p) where p.[jcr:path] = '/': Two selectors with the same name: p
+select [jcr:path] from [nt:base] as p inner join [nt:base] as p on ischildnode(p, p) where p.[jcr:path] = '/'
+java.text.ParseException: select [jcr:path] from [nt:base] as p inner join [nt:base] as p on ischildnode(p, p) where p.[jcr:path] = '/': Two selectors with the same name: p
# combining 'not' and 'and'
commit / + "test": { "a": { "id": "10" }, "b": { "id" : "20" }}
-select * from [nt:base] where id is not null and not id = '100' and id <> '20'
+select [jcr:path] from [nt:base] where id is not null and not id = '100' and id <> '20'
/test/a
-select * from [nt:base] where id < '1000'
+select [jcr:path] from [nt:base] where id < '1000'
/test/a
-select * from [nt:base] where id is not null and not (id = '100' and id <> '20')
+select [jcr:path] from [nt:base] where id is not null and not (id = '100' and id <> '20')
/test/a
/test/b
-select * from [nt:base] where id = '10'
+select [jcr:path] from [nt:base] where id = '10'
/test/a
-select [jcr:path], * from [nt:base] where id = '10'
-/test/a, /test/a
+select [jcr:path], id from [nt:base] where id = '10'
+/test/a, 10
-select * from [nt:base] where id > '10'
+select [jcr:path] from [nt:base] where id > '10'
/test/b
commit / - "test"
@@ -94,10 +94,10 @@ commit / - "test"
commit / + "test": { "name": "hello world" }
-select * from [nt:base] where contains(name, 'hello')
+select [jcr:path] from [nt:base] where contains(name, 'hello')
/test
-select * from [nt:base] where contains(*, 'hello')
+select [jcr:path] from [nt:base] where contains(*, 'hello')
/test
commit / - "test"
@@ -116,29 +116,29 @@ commit / - "test"
commit / + "test": { "jcr:resource": {}, "resource": { "x" : {}}}
-select * from [nt:base] where id = -1
+select [jcr:path] from [nt:base] where id = -1
-select * from [nt:base] as b where isdescendantnode(b, '/test')
+select [jcr:path] from [nt:base] as b where isdescendantnode(b, '/test')
/test/jcr:resource
/test/resource
/test/resource/x
-select * from [nt:base] as b where ischildnode(b, '/test')
+select [jcr:path] from [nt:base] as b where ischildnode(b, '/test')
/test/jcr:resource
/test/resource
-select * from [nt:base] as b where issamenode(b, '/test')
+select [jcr:path] from [nt:base] as b where issamenode(b, '/test')
/test
-select * from [nt:base] where name() = 'resource'
+select [jcr:path] from [nt:base] where name() = 'resource'
/test/resource
-select * from [nt:base] as b where localname(b) = 'resource'
+select [jcr:path] from [nt:base] as b where localname(b) = 'resource'
/jcr:system/jcr:nodeTypes/nt:resource
/test/jcr:resource
/test/resource
-select * from [nt:base] as x where isdescendantnode(x, '/test')
+select [jcr:path] from [nt:base] as x where isdescendantnode(x, '/test')
/test/jcr:resource
/test/resource
/test/resource/x
@@ -149,27 +149,27 @@ commit / + "parents": { "p0": {"id": "0"
commit / + "children": { "c1": {"p": "1"}, "c2": {"p": "1"}, "c3": {"p": "2"}, "c4": {"p": "3"}}
# relative property
-select * from [nt:base] where [c1/p] = '1'
+select [jcr:path] from [nt:base] where [c1/p] = '1'
/children
-select * from [nt:base] as p where p.[jcr:path] = '/parents'
+select [jcr:path] from [nt:base] as p where p.[jcr:path] = '/parents'
/parents
-select * from [nt:base] as [p] where [p].[jcr:path] = '/parents'
+select [jcr:path] from [nt:base] as [p] where [p].[jcr:path] = '/parents'
/parents
-select * from [nt:base] as p inner join [nt:base] as p2 on ischildnode(p2, p) where p.[jcr:path] = '/'
+select p.[jcr:path], p2.[jcr:path] from [nt:base] as p inner join [nt:base] as p2 on ischildnode(p2, p) where p.[jcr:path] = '/'
/, /children
/, /jcr:system
/, /oak:index
/, /parents
-select * from [nt:base] as p inner join [nt:base] as p2 on isdescendantnode(p2, p) where p.[jcr:path] = '/parents'
+select p.[jcr:path], p2.[jcr:path] from [nt:base] as p inner join [nt:base] as p2 on isdescendantnode(p2, p) where p.[jcr:path] = '/parents'
/parents, /parents/p0
/parents, /parents/p1
/parents, /parents/p2
-select * from [nt:base] as p inner join [nt:base] as p2 on issamenode(p2, p) where p.[jcr:path] = '/parents'
+select p.[jcr:path], p2.[jcr:path] from [nt:base] as p inner join [nt:base] as p2 on issamenode(p2, p) where p.[jcr:path] = '/parents'
/parents, /parents
select id from [nt:base] where id is not null
@@ -182,27 +182,27 @@ select id from [nt:base] where id is not
1
0
-select * from [nt:base] as c right outer join [nt:base] as p on p.id = c.p where p.id is not null and not isdescendantnode(p, '/jcr:system')
+select c.[jcr:path], p.[jcr:path] from [nt:base] as c right outer join [nt:base] as p on p.id = c.p where p.id is not null and not isdescendantnode(p, '/jcr:system')
/children/c1, /parents/p1
/children/c2, /parents/p1
/children/c3, /parents/p2
null, /parents/p0
-select * from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null
+select p.[jcr:path], c.[jcr:path] from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null
/parents/p0, null
/parents/p1, /children/c1
/parents/p1, /children/c2
/parents/p2, /children/c3
-select * from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null and c.p is null
+select p.[jcr:path], c.[jcr:path] from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null and c.p is null
/parents/p0, null
-select * from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null and c.p is not null
+select p.[jcr:path], c.[jcr:path] from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null and c.p is not null
/parents/p1, /children/c1
/parents/p1, /children/c2
/parents/p2, /children/c3
-select * from [nt:base] as p inner join [nt:base] as c on p.id = c.p
+select p.[jcr:path], c.[jcr:path] from [nt:base] as p inner join [nt:base] as c on p.id = c.p
/parents/p1, /children/c1
/parents/p1, /children/c2
/parents/p2, /children/c3
@@ -214,27 +214,27 @@ commit / + "testRoot": {}
commit /testRoot + "test": { "hello": { "x": "1" }, "world": { "x": "2" } }
commit /testRoot + "test2": { "id":"1", "x": "2" }
-select * from [nt:base] where isdescendantnode('/testRoot')
+select [jcr:path] from [nt:base] where isdescendantnode('/testRoot')
/testRoot/test
/testRoot/test/hello
/testRoot/test/world
/testRoot/test2
-select * from [nt:base] where id = '1'
+select [jcr:path] from [nt:base] where id = '1'
/testRoot/test2
-select * from [nt:base] where id = '1' and x = '2'
+select [jcr:path] from [nt:base] where id = '1' and x = '2'
/testRoot/test2
-select * from [nt:base] where id = '1' or x = '2'
+select [jcr:path] from [nt:base] where id = '1' or x = '2'
/testRoot/test/world
/testRoot/test2
-select * from [nt:base] where not (id = '1' or x = '2') and isdescendantnode('/testRoot')
+select [jcr:path] from [nt:base] where not (id = '1' or x = '2') and isdescendantnode('/testRoot')
/testRoot/test
/testRoot/test/hello
-select * from [nt:base] where x is null and isdescendantnode('/testRoot')
+select [jcr:path] from [nt:base] where x is null and isdescendantnode('/testRoot')
/testRoot/test
commit /testRoot - "test"
@@ -253,43 +253,43 @@ Hallo
hello
World!
-select * from [nt:base] where length(name) = 5
+select [jcr:path] from [nt:base] where length(name) = 5
/testRoot/test
/testRoot/test3
-select * from [nt:base] where upper(name) = 'HELLO'
+select [jcr:path] from [nt:base] where upper(name) = 'HELLO'
/testRoot/test
-select * from [nt:base] where lower(name) = 'world!'
+select [jcr:path] from [nt:base] where lower(name) = 'world!'
/testRoot/test2
-select * from [nt:base] where name like 'W%'
+select [jcr:path] from [nt:base] where name like 'W%'
/testRoot/test2
-select * from [nt:base] where name like '%o_%'
+select [jcr:path] from [nt:base] where name like '%o_%'
/testRoot/test2
-select * from [nt:base] where name like '__llo'
+select [jcr:path] from [nt:base] where name like '__llo'
/testRoot/test
/testRoot/test3
-select * from [nt:base] where upper(name) like 'H_LLO'
+select [jcr:path] from [nt:base] where upper(name) like 'H_LLO'
/testRoot/test
/testRoot/test3
-select * from [nt:base] where upper(name) like 'H\_LLO'
+select [jcr:path] from [nt:base] where upper(name) like 'H\_LLO'
-select * from [nt:base] where upper(name) like '10%'
+select [jcr:path] from [nt:base] where upper(name) like '10%'
/testRoot/test4
/testRoot/test5
-select * from [nt:base] where upper(name) like '10\%'
+select [jcr:path] from [nt:base] where upper(name) like '10\%'
/testRoot/test4
# errors
-select * from [nt:base] where name =+ 'Hello'
-java.text.ParseException: Query: select * from [nt:base] where name =+ 'Hello(*)'; expected: Illegal operation: + Hello
+select [jcr:path] from [nt:base] where name =+ 'Hello'
+java.text.ParseException: Query: select [jcr:path] from [nt:base] where name =+ 'Hello(*)'; expected: Illegal operation: + Hello
-select * from [nt:base] where name => 'Hello'
-java.text.ParseException: Query: select * from [nt:base] where name =>(*)'Hello'; expected: (, ., =, <>, <, >, <=, >=, LIKE, IS, NOT
+select [jcr:path] from [nt:base] where name => 'Hello'
+java.text.ParseException: Query: select [jcr:path] from [nt:base] where name =>(*)'Hello'; expected: (, ., =, <>, <, >, <=, >=, LIKE, IS, NOT
Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_explain.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_explain.txt?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_explain.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_explain.txt Fri Apr 12 16:44:25 2013
@@ -36,7 +36,7 @@ explain select * from [nt:base] where pr
explain select b.[jcr:path] as [jcr:path], b.[jcr:score] as [jcr:score], b.* from [nt:base] as a inner join [nt:base] as b on ischildnode(a, b) where name(a) = 'yes' and isdescendantnode(a, '/test') and b.[x] is not null
[nt:base] as [a] /* traverse "/test//*" where (name([a]) = cast('yes' as string)) and (isdescendantnode([a], [/test])) */ inner join [nt:base] as [b] /* traverse "/path/from/the/join" where [b].[x] is not null */ on ischildnode([a], [b])
-select * from [nt:base] where property([*], 'REFERENCE') = CAST('123' AS REFERENCE)
+select [jcr:path] from [nt:base] where property([*], 'REFERENCE') = CAST('123' AS REFERENCE)
/test/a
commit /oak:index + "indexes": { "type": "property" }
@@ -48,10 +48,10 @@ explain select * from [nt:base] where pr
explain select * from [nt:base] where property(id, 'REFERENCE') = CAST('123' AS REFERENCE)
[nt:base] as [nt:base] /* prefixIndex "ref:123" where property([nt:base].[id], 'reference') = cast('123' as reference) */
-select * from [nt:base] where property([*], 'REFERENCE') = CAST('123' AS REFERENCE)
+select [jcr:path] from [nt:base] where property([*], 'REFERENCE') = CAST('123' AS REFERENCE)
/test/a
-select * from [nt:base] where property(id, 'REFERENCE') = CAST('123' AS REFERENCE)
+select [jcr:path] from [nt:base] where property(id, 'REFERENCE') = CAST('123' AS REFERENCE)
/test/a
commit / - "test"
@@ -64,21 +64,21 @@ commit /oak:index/indexes + "property@id
# combining 'not' and 'and'
-select * from [nt:base] where id is not null and not id = '100' and id <> '20'
+select [jcr:path] from [nt:base] where id is not null and not id = '100' and id <> '20'
/test/a
-select * from [nt:base] where id is not null and not (id = '100' and id <> '20')
+select [jcr:path] from [nt:base] where id is not null and not (id = '100' and id <> '20')
/test/a
/test/b
explain select * from [nt:base] where id = '10'
[nt:base] as [nt:base] /* propertyIndex "id [10..10]" where [nt:base].[id] = cast('10' as string) */
-select * from [nt:base] where id = '10'
+select [jcr:path] from [nt:base] where id = '10'
/test/a
-select [jcr:path], * from [nt:base] where id = '10'
-/test/a, /test/a
+select [jcr:path] from [nt:base] where id = '10'
+/test/a
explain select * from [nt:base] where id > '10'
[nt:base] as [nt:base] /* traverse "*" where [nt:base].[id] > cast('10' as string) */
Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt Fri Apr 12 16:44:25 2013
@@ -39,11 +39,11 @@ explain select * from [nt:base] as a inn
commit / + "test": { "jcr:uuid": "xyz", "a": { "jcr:uuid": "123" } }
-select * from [nt:base] where [jcr:uuid] is not null
+select [jcr:path] from [nt:base] where [jcr:uuid] is not null
/test
/test/a
-select * from [nt:base] where [jcr:uuid] = 'xyz'
+select [jcr:path] from [nt:base] where [jcr:uuid] = 'xyz'
/test
commit / - "test"
Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_measure.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_measure.txt?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_measure.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_measure.txt Fri Apr 12 16:44:25 2013
@@ -27,7 +27,7 @@ commit / + "testRoot": { }
commit /testRoot + "parents": { "p0": {"id": "0"}, "p1": {"id": "1"}, "p2": {"id": "2"}}
commit /testRoot + "children": { "c1": {"p": "1"}, "c2": {"p": "1"}, "c3": {"p": "2"}, "c4": {"p": "3"}}
-select * from [nt:base] as c right outer join [nt:base] as p on p.id = c.p where p.id is not null and isdescendantnode(p, '/testRoot') and isdescendantnode(c, '/testRoot')
+select c.[jcr:path], p.[jcr:path] from [nt:base] as c right outer join [nt:base] as p on p.id = c.p where p.id is not null and isdescendantnode(p, '/testRoot') and isdescendantnode(c, '/testRoot')
/testRoot/children/c1, /testRoot/parents/p1
/testRoot/children/c2, /testRoot/parents/p1
/testRoot/children/c3, /testRoot/parents/p2
@@ -37,7 +37,7 @@ c, 30
p, 10
query, 3
-select * from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null and isdescendantnode(p, '/testRoot') and isdescendantnode(c, '/testRoot')
+select p.[jcr:path], c.[jcr:path] from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null and isdescendantnode(p, '/testRoot') and isdescendantnode(c, '/testRoot')
/testRoot/parents/p1, /testRoot/children/c1
/testRoot/parents/p1, /testRoot/children/c2
/testRoot/parents/p2, /testRoot/children/c3
Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Fri Apr 12 16:44:25 2013
@@ -222,9 +222,6 @@
org.apache.jackrabbit.test.api.query.SQLJoinTest#testJoinNtBase <!-- OAK-474 -->
org.apache.jackrabbit.test.api.query.SQLJoinTest#testJoinFilterPrimaryType <!-- OAK-474 -->
org.apache.jackrabbit.test.api.query.SQLJoinTest#testJoinSNS <!-- OAK-474 -->
- org.apache.jackrabbit.test.api.query.SimpleSelectionTest#testSingleProperty <!-- OAK-323 -->
- org.apache.jackrabbit.test.api.query.qom.ColumnTest#testExpandColumnsForNodeType <!-- OAK-323 -->
- org.apache.jackrabbit.test.api.query.GetPropertyNamesTest#testGetPropertyNames <!-- OAK-323 -->
org.apache.jackrabbit.test.api.observation.EventTest#testGetUserId
org.apache.jackrabbit.test.api.observation.NodeMovedTest#testMoveNode
org.apache.jackrabbit.test.api.observation.NodeMovedTest#testMoveTree
Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java Fri Apr 12 16:44:25 2013
@@ -18,6 +18,7 @@
*/
package org.apache.jackrabbit.oak.jcr.query;
+import static com.google.common.collect.Sets.newHashSet;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
@@ -46,6 +47,7 @@ import org.apache.jackrabbit.commons.ite
import org.apache.jackrabbit.oak.jcr.AbstractRepositoryTest;
import org.junit.Test;
+
/**
* Tests the query feature.
*/
@@ -108,11 +110,9 @@ public class QueryTest extends AbstractR
q = qm.createQuery("//*[@id=1]", Query.XPATH);
r = q.execute();
- columns = r.getColumnNames();
- assertEquals(3, columns.length);
- assertEquals("jcr:path", columns[0]);
- assertEquals("jcr:score", columns[1]);
- assertEquals("*", columns[2]);
+ assertEquals(
+ newHashSet("jcr:path", "jcr:score", "jcr:primaryType"),
+ newHashSet(r.getColumnNames()));
}
@Test
Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/qom/QomTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/qom/QomTest.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/qom/QomTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/qom/QomTest.java Fri Apr 12 16:44:25 2013
@@ -400,7 +400,7 @@ public class QomTest extends AbstractRep
@Test
public void createQuery() throws RepositoryException {
- Selector s = f.selector("nodeTypeName", "x");
+ Selector s = f.selector("nt:file", "x");
BindVariableValue b = f.bindVariable("var");
Constraint c = f.propertyExistence("x", "c");
PropertyValue p = f.propertyValue("x", "propertyName");
Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java Fri Apr 12 16:44:25 2013
@@ -71,7 +71,7 @@ public class LuceneIndexQueryTest extend
root.commit();
Iterator<String> result = executeQuery(
- "select * from [nt:base] where isdescendantnode('/test')",
+ "select [jcr:path] from [nt:base] where isdescendantnode('/test')",
"JCR-SQL2").iterator();
assertTrue(result.hasNext());
assertEquals("/test/a", result.next());
@@ -87,7 +87,7 @@ public class LuceneIndexQueryTest extend
root.commit();
Iterator<String> result = executeQuery(
- "select * from [nt:base] where isdescendantnode('/test') and name='World'",
+ "select [jcr:path] from [nt:base] where isdescendantnode('/test') and name='World'",
"JCR-SQL2").iterator();
assertTrue(result.hasNext());
assertEquals("/test/a", result.next());
@@ -105,7 +105,7 @@ public class LuceneIndexQueryTest extend
root.commit();
Iterator<String> result = executeQuery(
- "select * from [nt:base] as p inner join [nt:base] as p2 on ischildnode(p2, p) where p.[jcr:path] = '/'",
+ "select p.[jcr:path], p2.[jcr:path] from [nt:base] as p inner join [nt:base] as p2 on ischildnode(p2, p) where p.[jcr:path] = '/'",
"JCR-SQL2").iterator();
assertTrue(result.hasNext());
assertEquals("/, /children", result.next());
Modified: jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java?rev=1467342&r1=1467341&r2=1467342&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java Fri Apr 12 16:44:25 2013
@@ -89,7 +89,7 @@ public class SolrIndexQueryTest extends
root.commit();
Iterator<String> result = executeQuery(
- "select * from [nt:base] where isdescendantnode('/test')",
+ "select [jcr:path] from [nt:base] where isdescendantnode('/test')",
"JCR-SQL2").iterator();
assertTrue(result.hasNext());
assertEquals("/test/a", result.next());
@@ -105,7 +105,7 @@ public class SolrIndexQueryTest extends
root.commit();
Iterator<String> result = executeQuery(
- "select * from [nt:base] where isdescendantnode('/test') and name='World'",
+ "select [jcr:path] from [nt:base] where isdescendantnode('/test') and name='World'",
"JCR-SQL2").iterator();
assertTrue(result.hasNext());
assertEquals("/test/a", result.next());
@@ -123,7 +123,7 @@ public class SolrIndexQueryTest extends
root.commit();
Iterator<String> result = executeQuery(
- "select * from [nt:base] as p inner join [nt:base] as p2 on ischildnode(p2, p) where p.[jcr:path] = '/'",
+ "select p.[jcr:path], p2.[jcr:path] from [nt:base] as p inner join [nt:base] as p2 on ischildnode(p2, p) where p.[jcr:path] = '/'",
"JCR-SQL2").iterator();
assertTrue(result.hasNext());
assertEquals("/, /children", result.next());