Author: thomasm
Date: Fri Jan 26 11:00:48 2018
New Revision: 1822272
URL: http://svn.apache.org/viewvc?rev=1822272&view=rev
Log:
OAK-6898 Query: grammar documentation / annotated railroad diagrams
Modified:
jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/grammar-sql2.md
jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/grammar-xpath.md
jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/query-engine.md
Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/grammar-sql2.md
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/grammar-sql2.md?rev=1822272&r1=1822271&r2=1822272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/grammar-sql2.md
(original)
+++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/grammar-sql2.md Fri
Jan 26 11:00:48 2018
@@ -29,6 +29,7 @@
* [Static Operand](#staticOperand)
* [Ordering](#ordering)
* [Dynamic Operand](#dynamicOperand)
+* [Type](#type)
* [Options](#options)
* [Explain](#explain)
* [Measure](#measure)
@@ -45,26 +46,47 @@ SELECT [ DISTINCT ] { * | { <a href="
<br/> [ <a href="#options">queryOptions</a> ]
</h4>
-DISTINCT ensures each row is only returned once.
+All queries should have a path restriction
+(even if it's just, for example, "/content"), as this allows to shrink indexes.
-UNION combines the result of this query with the results of another query,
-where UNION ALL does not remove duplicates.
+"distinct" ensures each row is only returned once.
-ORDER BY may use an index.
+"union" combines the result of this query with the results of another query,
+where "union all" does not remove duplicates.
+
+"order by" may use an index.
If there is no index for the given sort order,
then the result is fully read in memory and sorted before returning the first
row.
+Examples:
+
+ select * from [sling:Folder] as a where [sling:resourceType] = 'x' and
isdescendantnode(a, '/content')
+ select [jcr:path] from [oak:QueryIndexDefinition] as a where [type] =
'lucene' and isdescendantnode(a, '/') order by [reindexCount] desc
+ select [jcr:path], [jcr:score], * from [nt:base] as a where [type] =
'report' and isdescendantnode(a, '/etc') option(traversal fail)
+
<hr />
<h3 id="column">Column</h3>
<h4>
-{ [ selectorName . ] propertyName
-<br/> | selectorName . *
+{ [ selectorName . ] { propertyName | * }
<br/> | EXCERPT([selectorName])
<br/> | rep:spellcheck()
<br/> } [ AS aliasName ]
</h4>
+It is recommended to enclose property names in square brackets.
+
+Not listed above are "special" properties such as "[jcr:path]" (the path),
"[jcr:score]" (the score),
+"[rep:suggest()]".
+
+Examples:
+
+ *
+ [jcr:path]
+ [jcr:score]
+ a.*
+ a.[sling:resourceType]
+
<hr />
<h3 id="selector">Selector</h3>
@@ -73,6 +95,11 @@ nodeTypeName [ AS selectorName ]
</h4>
The nodetype name can be either a primary nodetype or a mixin nodetype.
+It is recommended to specify the nodetype name in square brackes.
+
+Examples:
+
+ [sling:Folder] as a
<hr />
<h3 id="join">Join</h3>
@@ -85,11 +112,22 @@ The nodetype name can be either a primar
<br/> | { ISDESCENDANTNODE( descendantSelectorName , ancestorSelectorName ) }
</h4>
-An inner join only returns entries if nodes are found on both the left and
right selector.
-A left outer join will return entries that don't have matching nodes on the
right selector.
-A right outer join will return entries that don't have matching nodes on the
left selector.
+An "inner join" only returns entries if nodes are found on both the left and
right selector.
+A "left outer join" will return entries that don't have matching nodes on the
right selector.
+A "right outer join" will return entries that don't have matching nodes on the
left selector.
For outer joins, all the properties of the selector that doesn't have a
matching node are null.
+Examples:
+
+All nodes below /oak:index that _don't_ have a child node:
+
+ select a.* from [oak:QueryIndexDefinition] as a
+ left outer join [nt:base] as b on ischildnode(b, a)
+ where isdescendantnode(a, '/oak:index')
+ and b.[jcr:primaryType] is null
+ order by a.[jcr:path]
+
+
<hr />
<h3 id="constraint">Constraint</h3>
@@ -97,15 +135,15 @@ For outer joins, all the properties of t
<a href="#andCondition">andCondition</a> [ { OR <a
href="#andCondition">andCondition</a> } [...] ]
</h4>
-OR conditions of the form "X = 1 OR X = 2" are automatically converted to "X
IN(1, 2)",
+"or" conditions of the form "[x]=1 or [x]=2" are automatically converted to
"[x] in(1, 2)",
and can use the same an index.
-OR conditions of the form "X = 1 OR Y = 2" are more complicated.
-Oak will try two options: first, what is the expected cost to use a UNION query
-(one query with X = 1, and a second query with Y = 2).
-If using UNION results in a lower estimated cost, then UNION is used.
+"or" conditions of the form "[x]=1 or [y]=2" are more complicated.
+Oak will try two options: first, what is the expected cost to use a "union"
query
+(one query with x=1, and a second query with y=2).
+If using "union" results in a lower estimated cost, then "union" is used.
This can be the case, for example, if there are two distinct indexes,
-one on X and another on Y.
+one on x, and another on y.
<hr />
<h3 id="andCondition">And Condition</h3>
@@ -115,7 +153,7 @@ one on X and another on Y.
</h4>
A special case (not found in relational databases) is
-AND conditions of the form "X = 1 AND X = 2".
+"and" conditions of the form "[x]=1 and [x]=2".
They will match nodes with multi-valued properties,
where the property value contains both 1 and 2.
@@ -136,17 +174,25 @@ where the property value contains both 1
<br/> | SUGGEST ( [ selectorName , ] staticOperand )
</h4>
-NOT conditions can not typically use an index.
+"not" conditions can not typically use an index.
-CONTAINS: see <a href="query-engine.html#Full-Text_Queries">Full-Text
Queries</a>.
+"contains": see <a href="query-engine.html#Full-Text_Queries">Full-Text
Queries</a>.
-SIMILAR: see <a href="query-engine.html#Similarity_Queries">Similarity
Queries</a>.
+"similar": see <a href="query-engine.html#Similarity_Queries">Similarity
Queries</a>.
-NATIVE: see <a href="query-engine.html#Native_Queries">Native Queries</a>.
+"native": see <a href="query-engine.html#Native_Queries">Native Queries</a>.
-SPELLCHECK: see <a href="query-engine.html#Spellchecking">Spellchecking</a>.
+"spellcheck": see <a href="query-engine.html#Spellchecking">Spellchecking</a>.
+
+"suggest": see <a href="query-engine.html#Suggestions">Suggestions</a>.
+
+Examples:
+
+ select [jcr:path] from [nt:base] where similar(*, '/test/a')
+ select [jcr:path] from [nt:base] where native('solr', 'name:(Hello OR
World)')
+ select [rep:suggest()] from [nt:base] where suggest('in ') and
issamenode('/')
+ select [rep:spellcheck()] from [nt:base] as a where spellcheck('helo') and
issamenode(a, '/')
-SUGGEST: see <a href="query-engine.html#Suggestions">Suggestions</a>.
<hr />
<h3 id="comparison">Comparison</h3>
@@ -157,13 +203,18 @@ SUGGEST: see <a href="query-engine.html#
<a href="#staticOperand">staticOperand</a>
</h4>
-LIKE: when comparing with LIKE, the wildcards characters are _ (any one
character)
-and % (any characters). An index is used,
+"like": when comparing with LIKE, the wildcards characters are '_' (any one
character)
+and '%' (any characters). An index is used,
except if the operand starts with a wildcard.
-To search for the characters % and _, the characters need to be escaped using
\ (backslash).
+To search for the characters '%' and '_', the characters need to be escaped
using '\' (backslash).
Comparison using <, >, >=, and <= can use an index if the property
in the index is ordered.
+Examples:
+
+ [name] like '%: 100 \%'
+
+
<hr />
<h3 id="inComparison">In Comparison</h3>
@@ -171,25 +222,18 @@ Comparison using <, >, >=, and
<a href="#dynamicOperand">dynamicOperand</a> IN ( <a
href="#staticOperand">staticOperand</a> [, ...] )
</h4>
+Examples:
+
+ [status] in('active', 'inactive')
+
+
<hr />
<h3 id="staticOperand">Static Operand</h3>
<h4>
literal
<br/> | $ bindVariableName
-<br/> | CAST ( literal AS {
-<br/> STRING
-<br/> | BINARY
-<br/> | DATE
-<br/> | LONG
-<br/> | DOUBLE
-<br/> | DECIMAL
-<br/> | BOOLEAN
-<br/> | NAME
-<br/> | PATH
-<br/> | REFERENCE
-<br/> | WEAKREFERENCE
-<br/> | URI } )
+<br/> | CAST ( literal AS <a href="#type">type</a> )
</h4>
A string (text) literal starts and ends with a single quote.
@@ -197,7 +241,10 @@ Two single quotes can be used to create
Example:
-'John''s car'
+ 'John''s car'
+ $uuid
+ cast('2020-12-01T20:00:00.000' as date)
+
<hr />
<h3 id="ordering">Ordering</h3>
@@ -216,6 +263,12 @@ As a special case, sorting by "jcr:score
If for some reason you want to enforce sorting by "jcr:score", then
you can use the workaround to order by "LOWER([jcr:score]) DESC".
+Examples:
+
+ [lastName]
+ [price] desc
+
+
<hr />
<h3 id="dynamicOperand">Dynamic Operand</h3>
@@ -225,20 +278,50 @@ you can use the workaround to order by "
<br/> | { NAME | LOCALNAME | SCORE } ( [ selectorName ] )
<br/> | { LOWER | UPPER } ( dynamicOperand )
<br/> | COALESCE ( dynamicOperand1, dynamicOperand2 )
-<br/> | PROPERTY ( propertyName, type )
+<br/> | PROPERTY ( propertyName, <a href="#type">type</a> )
</h4>
The selector name is only needed if the query contains multiple selectors.
-COALESCE: this returns the first operand if it is not null,
+"coalesce": this returns the first operand if it is not null,
and the second operand otherwise.
`@since Oak 1.8`
-PROPERTY: This feature is rarely used.
+"property": This feature is rarely used.
It allows to filter for all properties with a given type.
-Example: the condition `PROPERTY(*, Reference) = $uuid` will search for any
property of type
+Example: the condition `property(*, Reference) = $uuid` will search for any
property of type
`Reference`.
+"lower", "upper", "length": Indexes on functions are supported `@since Oak
1.6`, see OAK-3574.
+
+Examples:
+
+ lower([firstName])
+ coalesce([lastName], name())
+ length(coalesce([lastName], name()))
+
+
+<hr />
+<h3 id="type">Type</h3>
+
+<h4>
+<br/>STRING
+<br/> | BINARY
+<br/> | DATE
+<br/> | LONG
+<br/> | DOUBLE
+<br/> | DECIMAL
+<br/> | BOOLEAN
+<br/> | NAME
+<br/> | PATH
+<br/> | REFERENCE
+<br/> | WEAKREFERENCE
+<br/> | URI
+</h4>
+
+This is the list of all JCR property types.
+
+
<hr />
<h3 id="options">Options</h3>
@@ -249,18 +332,23 @@ OPTION( {
<br/> } [ , ... ] )
</h4>
-TRAVERSAL: by default, queries without index will log a warning,
+"traversal": by default, queries without index will log a warning,
except if the configuration option `QueryEngineSettings.failTraversal` is
changed
The traversal option can be used to change the behavior of the given query:
-OK to not log a warning,
-WARN to log a warning,
-FAIL to fail the query, and
-DEFAULT to use the default setting.
+"ok" to not log a warning,
+"warn" to log a warning,
+"fail" to fail the query, and
+"default" to use the default setting.
-INDEX TAG: by default, queries will use the index with the lowest expected
cost (as in relational databases).
+"index tag": by default, queries will use the index with the lowest expected
cost (as in relational databases).
To only consider some of the indexes, add tags (a multi-valued String
property) to the index(es) of choice,
and specify this tag in the query.
+Examples:
+
+ option(traversal fail)
+
+
<hr />
<h3 id="explain">Explain Query</h3>
@@ -274,8 +362,8 @@ In both cases, the query result will onl
Examples:
- EXPLAIN MEASURE
- SELECT * FROM [nt:base] WHERE [jcr:uuid] = 1
+ explain measure
+ select * from [nt:base] where [jcr:uuid] = 1
Result:
@@ -286,6 +374,7 @@ Result:
This means the property index named "uuid" is used for this query.
The expected cost (roughly the number of uncached I/O operations) is 2.
+
<hr />
<h3 id="measure">Measure</h3>
@@ -300,8 +389,8 @@ and one per selector used in the query.
Examples:
- MEASURE
- SELECT * FROM [nt:base] WHERE [jcr:uuid] = 1
+ measure
+ select * from [nt:base] where [jcr:uuid] = 1
Result:
Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/grammar-xpath.md
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/grammar-xpath.md?rev=1822272&r1=1822271&r2=1822272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/grammar-xpath.md
(original)
+++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/grammar-xpath.md Fri
Jan 26 11:00:48 2018
@@ -19,6 +19,7 @@
* [Query](#query)
* [Filter](#filter)
+* [Column](#column)
* [Constraint](#constraint)
* [And Condition](#andCondition)
* [Condition](#condition)
@@ -43,6 +44,9 @@
The "/jcr:root" means the root node.
It is recommended that all XPath queries start with this term.
+All queries should have a path restriction
+(even if it's just, for example, "/content"), as this allows to shrink indexes.
+
"order by" may use an index.
If there is no index for the given sort order,
then the result is fully read in memory and sorted before returning the first
row.
@@ -53,15 +57,15 @@ It is only needed if non-standard (compu
Examples:
-Get all nodes of node type sling:Folder with the property sling:resourceType
set to 'x':
+Get all nodes of node type 'sling:Folder' with the property
'sling:resourceType' set to 'x':
- /jcr:root//element(*, sling:Folder)[@sling:resourceType='x']
+ /jcr:root/content//element(*, sling:Folder)[@sling:resourceType='x']
-Get all workflow nodes with status 'active', sorted by starting time:
+Get all index definition nodes of type 'lucene', sorted by reindex count,
descending:
- /jcr:root//element(*, acme:Workflow)[@status='active'] order by @startTime
descending
+ /jcr:root/oak:index/element(*, oak:QueryIndexDefinition)[@type='lucene']
order by @reindexCount descending
-Get all nodes below /etc that have the property type set to 'report'; fail the
query if there is no index:
+Get all nodes below /etc that have the property type set to 'report'; fail the
query if there is no index that can be used:
/jcr:root/etc//*[@type='report'] option(traversal fail)
@@ -76,6 +80,7 @@ Get all nodes below /etc that have the p
<br/> | element( [ * | nodeName ] [, nodeType] )
<br/> | text()
<br/> | '[' <a href="#constraint">constraint</a> ']'
+<br/> | ( filter '|' unionFilter [...] )
</h4>
A single slash means filtering on a specific child node,
@@ -86,35 +91,43 @@ while two slashes means filtering on a d
"text()" is a shortcut for "jcr:xmltext".
It is supported only for compatibility.
+Queries using the construct `(filter1 | filter2)' are converted to union,
+that is, one query is generated for each filter, and the result of both
+queries is combined.
+
Examples:
Only direct child nodes of /content/dam:
- /content/dam/*
+ /jcr:root/content/dam/*
-All descendant nodes of /content/dam:
+All descendant nodes of /content/oak:index:
- /content/dam//*
+ /jcr:root/content/oak:index//*
-All nodes named "profile" that have a parent node which is the direct child
node of /user/home:
+All nodes named "rep:policy" that have a parent node which is the direct child
node of /home/users:
- /user/home/*/profile
+ /jcr:root/home/users/*/rep:policy
-All nodes named "profile" that have a parent node which is a descendant of
/user/home:
+All nodes named "profile" that have a parent node which is a descendant of
/home/users:
- /user/home//*/profile
+ /jcr:root/home/users//*/profile
All descendant nodes of /content that are of type oak:QueryIndexDefinition:
- /content//element(*, oak:QueryIndexDefinition)
+ /jcr:root/content//element(*, oak:QueryIndexDefinition)
All descendant nodes of /content that are of type oak:QueryIndexDefinition and
are named "lucene":
- /content//element(lucene, oak:QueryIndexDefinition)
+ /jcr:root/content//element(lucene, oak:QueryIndexDefinition)
+
+All nodes named "indexRules" that have a parent node with the property "type"
set to "lucene":
-All nodes named "analyzers" that have a parent node with the property "type"
set to "lucene":
+ /jcr:root/oak:index/*[@type = 'lucene']/indexRules
+
+The paths '/libs' and '/etc' should be searched:
- /oak:index/[@type = 'lucene']/analyzers
+ /jcr:root/(libs | etc)//*[@jcr:uuid and @jcr:mimeType = 'text/css']
<hr />
@@ -166,7 +179,6 @@ Include the nodes that have the property
or don't have the property set:
/jcr:root/content/dam/*[@hidden='hidden-folder' or not(@hidden)]
-
<hr />
@@ -183,7 +195,7 @@ where the property value contains both 1
Examples:
- /jcr:root/home//element(*, rep:Authorizable)[@rep:principalName!='Joe' and
@rep:principalName!='Steve']
+ /jcr:root/home//element(*, rep:Authorizable)[@rep:principalName != 'Joe'
and @rep:principalName != 'Steve']
<hr />
@@ -202,7 +214,14 @@ Examples:
<br/> | rep:suggest ( staticOperand )
</h4>
-"fn:not" conditions can not typically use an index.
+"fn:not": this is used for both "is not null", and for nested conditions.
+For example "fn:not(@status)" means nodes where this property is not set.
+In this case, and index can be used, but it is relatively expensive to index
+all nodes that don't have a certain property. It is recommended to only index
+this if there are relatively view nodes with this nodetype. See also
+<a href="lucene.html">nullCheckEnabled</a>.
+Nested conditions, for example "fn:not(@status = 'x' and @color = 'red')",
+can not typically use an index.
"jcr:contains": see <a href="query-engine.html#Full-Text_Queries">Full-Text
Queries</a>.
@@ -301,7 +320,9 @@ Examples:
<br/> | fn:coalesce ( dynamicOperand1, dynamicOperand2 )
</h4>
-The selector name is only needed if the query contains multiple selectors.
+The "*" stands for any property.
+
+"jcr:score()" is the score returned by the index.
"fn:coalesce": this returns the first operand if it is not null,
and the second operand otherwise.
@@ -312,7 +333,7 @@ Examples:
@type
./@jcr:primaryType
items/type/@metaType
- items/type/*
+ indexRules/nt:base/*
fn:string-length(@title)
fn:name()
jcr:score ()
Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/query-engine.md
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/query-engine.md?rev=1822272&r1=1822271&r2=1822272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/query-engine.md
(original)
+++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/query-engine.md Fri
Jan 26 11:00:48 2018
@@ -487,7 +487,7 @@ facets can be retrieved on properties (b
field in Lucene / Solr) using the following snippet:
String sql2 = "select [jcr:path], [rep:facet(tags)] from [nt:base] " +
- "where contains([jcr:title], 'oak');
+ "where contains([jcr:title], 'oak')");
Query q = qm.createQuery(sql2, Query.JCR_SQL2);
QueryResult result = q.execute();
FacetResult facetResult = new FacetResult(result);