New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MODE-1680 Improves XPath functionality and corrects JCR-SQL2/JQOM when ORDER BY uses columns not in SELECT #738
Conversation
Remove unused commented lines Add more checks at the parsing stage
Improved the behavior of JCR-SQL2 and JCR-QOM queries that use columns not in the SELECT clause. Such columns are necessary within the query processing to evaluate the ordering, but are not to be exposed in the query results. One particular case needed by the recent XPath improvements (to handle order-by clauses that involve a property on the child node) resulted in the ORDER BY column coming from a selector that was not even included in the SELECT. A test case recently added in other MODE-1680 commits was modified to verify the XPath and JCR-SQL2 behavior is as expected. Also added another query test that uses only JCR-SQL2.
@@ -81,8 +82,42 @@ public void visit( ReferenceValue ref ) { | |||
} | |||
|
|||
// Add each of the sort columns to the appropriate PROJECT nodes in the subtrees of this plan ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the optimizer rule that is run after query parsing and planning, but before query execution (when the processor objects are created). This looks for SORT plan nodes to ensure that the sort columns are included in the descendant PROJECT plan nodes. However, to prevent the sort columns from being visible to the rest of the query, it is wrapped with another PROJECT plan node that excludes the recently-added sort columns.
Given the following query:
SELECT y.* FROM [nt:unstructured] AS x INNER JOIN [nt:unstructured] AS y ON x.somethingElse = y.propC ORDER BY x.propC
the resulting query plan will now be:
Project [y] <PROJECT_COLUMNS=[y.[jcr:primaryType] AS [y.jcr:primaryType], y.[jcr:mixinTypes] AS [y.jcr:mixinTypes], y.[jcr:path] AS [y.jcr:path], y.[jcr:name] AS [y.jcr:name], y.[jcr:score] AS [y.jcr:score], y.[mode:localName] AS [y.mode:localName], y.[mode:depth] AS [y.mode:depth]], PROJECT_COLUMN_TYPES=[STRING, STRING, STRING, STRING, DOUBLE, STRING, LONG]>
Sort [x] <SORT_ORDER_BY=[x.propC ASC]>
Project [y] <PROJECT_COLUMNS=[y.[jcr:primaryType] AS [y.jcr:primaryType], y.[jcr:mixinTypes] AS [y.jcr:mixinTypes], y.[jcr:path] AS [y.jcr:path], y.[jcr:name] AS [y.jcr:name], y.[jcr:score] AS [y.jcr:score], y.[mode:localName] AS [y.mode:localName], y.[mode:depth] AS [y.mode:depth], x.propC AS [x.propC]], PROJECT_COLUMN_TYPES=[STRING, STRING, STRING, STRING, DOUBLE, STRING, LONG, STRING]>
Join [y,x] <JOIN_TYPE=INNER JOIN, JOIN_CONDITION=x.somethingElse = y.propC, JOIN_ALGORITHM=NESTED_LOOP>
Access [x]
Project [x] <PROJECT_COLUMNS=[x.[jcr:primaryType], x.[jcr:mixinTypes], x.[jcr:path], x.[jcr:name], x.[jcr:score], x.[mode:localName], x.[mode:depth], x.somethingElse, x.propC AS [x.propC]], PROJECT_COLUMN_TYPES=[STRING, STRING, STRING, STRING, DOUBLE, STRING, LONG, STRING, STRING]>
Select [x] <SELECT_CRITERIA=x.[jcr:primaryType] IN ('fincayra.UnstrUser','car:Car','fincayra.UnstrPost','nt:unstructured','notion:typed')>
Source [x] <SOURCE_COLUMNS=[jcr:frozenUuid(STRING), mode:sharedUuid(REFERENCE), mode:sessionScope(BOOLEAN), car:msrp(STRING), fieldA(STRING), jcr:defaultValues(STRING), mode:projectedNodeKey(STRING), jcr:frozenPrimaryType(STRING), jcr:mixinTypes(STRING), jcr:defaultPrimaryType(STRING), car:wheelbaseInInches(DOUBLE), text(STRING), notion:booleanAutoCreatedPropertyWithDefault(BOOLEAN), car:model(STRING), jcr:statement(STRING), jcr:lastModifiedBy(STRING), jcr:mimeType(STRING), jcr:hasOrderableChildNodes(BOOLEAN), jcr:etag(STRING), jcr:encoding(STRING), jcr:root(REFERENCE), jcr:supertypes(STRING), car:alternateModels(REFERENCE), jcr:successors(REFERENCE), name(STRING), jcr:primaryItemName(STRING), jcr:hold(STRING), jcr:workspace(STRING), jcr:description(STRING), jcr:primaryType(STRING), mode:initializationState(STRING), fieldB(STRING), mode:externalNodeKey(STRING), notion:booleanProperty(BOOLEAN), mode:derivedFrom(STRING), mode:isHeldBySession(BOOLEAN), jcr:baseVersion(REFERENCE), jcr:lastModified(DATE), jcr:mergeFailed(REFERENCE), jcr:requiredPrimaryTypes(STRING), mode:derivedAt(DATE), jcr:multiple(BOOLEAN), mode:generated(BOOLEAN), jcr:activityTitle(STRING), jcr:lifecyclePolicy(REFERENCE), jcr:isMixin(BOOLEAN), notion:multipleReferences(REFERENCE), jcr:availableQueryOperators(STRING), jcr:childVersionHistory(REFERENCE), car:userRating(LONG), user(STRING), jcr:autoCreated(BOOLEAN), jcr:content(REFERENCE), car:mpgHighway(LONG), mode:alias(STRING), notion:booleanProperty2(BOOLEAN), jcr:createdBy(STRING), jcr:isFullTextSearchable(BOOLEAN), jcr:uuid(STRING), jcr:onParentVersion(STRING), notion:longProperty(LONG), mode:expirationDate(DATE), jcr:lockIsDeep(BOOLEAN), notion:stringProperty(STRING), jcr:isDeep(BOOLEAN), jcr:copiedFrom(REFERENCE), car:engine(STRING), jcr:title(STRING), notion:stringAutoCreatedPropertyWithDefault(STRING), notion:stringPropertyWithDefault(STRING), jcr:isAbstract(BOOLEAN), jcr:versionHistory(REFERENCE), jcr:versionableUuid(STRING), jcr:predecessors(REFERENCE), car:maker(STRING), jcr:lockOwner(STRING), car:mpgCity(LONG), mode:sha1(STRING), jcr:repository(STRING), jcr:created(DATE), jcr:frozenMixinTypes(STRING), car:lengthInInches(DOUBLE), mode:lockedKey(STRING), jcr:text(STRING), jcr:host(STRING), jcr:configuration(REFERENCE), jcr:port(STRING), mode:workspace(STRING), notion:singleReference(REFERENCE), car:valueRating(LONG), jcr:nodeTypeName(STRING), email(STRING), jcr:isQueryable(BOOLEAN), jcr:data(BINARY), jcr:language(STRING), jcr:isQueryOrderable(BOOLEAN), jcr:isCheckedOut(BOOLEAN), jcr:mandatory(BOOLEAN), jcr:protected(BOOLEAN), jcr:protocol(STRING), jcr:sameNameSiblings(BOOLEAN), jcr:requiredType(STRING), mode:lockingSession(STRING), notion:booleanCreatedPropertyWithDefault(BOOLEAN), jcr:messageId(STRING), jcr:id(REFERENCE), mode:uri(STRING), jcr:valueConstraints(STRING), car:year(STRING), jcr:retentionPolicy(REFERENCE), jcr:activity(REFERENCE), jcr:currentLifecycleState(STRING), jcr:path(STRING), jcr:name(STRING), jcr:score(DOUBLE), mode:localName(STRING), mode:depth(LONG)], SOURCE_ALIAS=x, SOURCE_NAME=__ALLNODES__>
Access [y]
Project [y] <PROJECT_COLUMNS=[y.[jcr:primaryType], y.[jcr:mixinTypes], y.[jcr:path], y.[jcr:name], y.[jcr:score], y.[mode:localName], y.[mode:depth], y.propC], PROJECT_COLUMN_TYPES=[STRING, STRING, STRING, STRING, DOUBLE, STRING, LONG, STRING]>
Select [y] <SELECT_CRITERIA=y.[jcr:primaryType] IN ('fincayra.UnstrUser','car:Car','fincayra.UnstrPost','nt:unstructured','notion:typed')>
Source [y] <SOURCE_COLUMNS=[jcr:frozenUuid(STRING), mode:sharedUuid(REFERENCE), mode:sessionScope(BOOLEAN), car:msrp(STRING), fieldA(STRING), jcr:defaultValues(STRING), mode:projectedNodeKey(STRING), jcr:frozenPrimaryType(STRING), jcr:mixinTypes(STRING), jcr:defaultPrimaryType(STRING), car:wheelbaseInInches(DOUBLE), text(STRING), notion:booleanAutoCreatedPropertyWithDefault(BOOLEAN), car:model(STRING), jcr:statement(STRING), jcr:lastModifiedBy(STRING), jcr:mimeType(STRING), jcr:hasOrderableChildNodes(BOOLEAN), jcr:etag(STRING), jcr:encoding(STRING), jcr:root(REFERENCE), jcr:supertypes(STRING), car:alternateModels(REFERENCE), jcr:successors(REFERENCE), name(STRING), jcr:primaryItemName(STRING), jcr:hold(STRING), jcr:workspace(STRING), jcr:description(STRING), jcr:primaryType(STRING), mode:initializationState(STRING), fieldB(STRING), mode:externalNodeKey(STRING), notion:booleanProperty(BOOLEAN), mode:derivedFrom(STRING), mode:isHeldBySession(BOOLEAN), jcr:baseVersion(REFERENCE), jcr:lastModified(DATE), jcr:mergeFailed(REFERENCE), jcr:requiredPrimaryTypes(STRING), mode:derivedAt(DATE), jcr:multiple(BOOLEAN), mode:generated(BOOLEAN), jcr:activityTitle(STRING), jcr:lifecyclePolicy(REFERENCE), jcr:isMixin(BOOLEAN), notion:multipleReferences(REFERENCE), jcr:availableQueryOperators(STRING), jcr:childVersionHistory(REFERENCE), car:userRating(LONG), user(STRING), jcr:autoCreated(BOOLEAN), jcr:content(REFERENCE), car:mpgHighway(LONG), mode:alias(STRING), notion:booleanProperty2(BOOLEAN), jcr:createdBy(STRING), jcr:isFullTextSearchable(BOOLEAN), jcr:uuid(STRING), jcr:onParentVersion(STRING), notion:longProperty(LONG), mode:expirationDate(DATE), jcr:lockIsDeep(BOOLEAN), notion:stringProperty(STRING), jcr:isDeep(BOOLEAN), jcr:copiedFrom(REFERENCE), car:engine(STRING), jcr:title(STRING), notion:stringAutoCreatedPropertyWithDefault(STRING), notion:stringPropertyWithDefault(STRING), jcr:isAbstract(BOOLEAN), jcr:versionHistory(REFERENCE), jcr:versionableUuid(STRING), jcr:predecessors(REFERENCE), car:maker(STRING), jcr:lockOwner(STRING), car:mpgCity(LONG), mode:sha1(STRING), jcr:repository(STRING), jcr:created(DATE), jcr:frozenMixinTypes(STRING), car:lengthInInches(DOUBLE), mode:lockedKey(STRING), jcr:text(STRING), jcr:host(STRING), jcr:configuration(REFERENCE), jcr:port(STRING), mode:workspace(STRING), notion:singleReference(REFERENCE), car:valueRating(LONG), jcr:nodeTypeName(STRING), email(STRING), jcr:isQueryable(BOOLEAN), jcr:data(BINARY), jcr:language(STRING), jcr:isQueryOrderable(BOOLEAN), jcr:isCheckedOut(BOOLEAN), jcr:mandatory(BOOLEAN), jcr:protected(BOOLEAN), jcr:protocol(STRING), jcr:sameNameSiblings(BOOLEAN), jcr:requiredType(STRING), mode:lockingSession(STRING), notion:booleanCreatedPropertyWithDefault(BOOLEAN), jcr:messageId(STRING), jcr:id(REFERENCE), mode:uri(STRING), jcr:valueConstraints(STRING), car:year(STRING), jcr:retentionPolicy(REFERENCE), jcr:activity(REFERENCE), jcr:currentLifecycleState(STRING), jcr:path(STRING), jcr:name(STRING), jcr:score(DOUBLE), mode:localName(STRING), mode:depth(LONG)], SOURCE_ALIAS=y, SOURCE_NAME=__ALLNODES__>
Built upon a previously unmerged pull-request submitted by @okulikov that fixes an XPath for parsing error and adds support for the function
fn:name
and use of a child axis inorder by
clause. The latest commit changes improved the behavior of JCR-SQL2 and JCR-QOM queries that use columns not in theSELECT
clause. Such columns are necessary within the query processing to evaluate the ordering, but are not to be exposed in the query results. One particular case needed by the recent XPath improvements (to handle order-by clauses that involve a property on the child node) resulted in theORDER BY
column coming from a selector that was not even included in theSELECT
.A test case added in Oleg's earlier commits was modified to verify the XPath and JCR-SQL2 behavior is as expected. Also added another query test that uses only JCR-SQL2.