Class NXQLQueryMaker
- java.lang.Object
-
- org.nuxeo.ecm.core.storage.sql.jdbc.NXQLQueryMaker
-
- All Implemented Interfaces:
QueryMaker
- Direct Known Subclasses:
TagQueryMaker
public class NXQLQueryMaker extends Object implements QueryMaker
Transformer of NXQL queries into underlying SQL queries to the actual database.The examples below are using the NXQL statement syntax:
SELECT * FROM File WHERE dc:title = 'abc' AND uid:uid = '123' AND dc:contributors = 'bob' -- multi-valued
If there are no proxies (ecm:isProxy = 0) we get:SELECT hierarchy.id FROM hierarchy LEFT JOIN dublincore ON hierarchy.id = dublincore.id LEFT JOIN uid ON hierarchy.id = uid.id WHERE hierarchy.primarytype IN ('File', 'SubFile') AND dublincore.title = 'abc' AND uid.uid = '123' AND EXISTS (SELECT 1 FROM dc_contributors WHERE hierarchy.id = dc_contributors.id AND dc_contributors.item = 'bob') AND NX_ACCESS_ALLOWED(hierarchy.id, 'user1|user2', 'perm1|perm2')
The data tables (dublincore, uid) are joined using a LEFT JOIN, as the schema may not be present on all documents but this shouldn't prevent the WHERE clause from being evaluated. Complex properties are matched using an EXISTS and a subselect. When proxies are matched (ecm:isProxy = 1) there are two additional FULL JOINs. Security checks, id, name, parents and path use the base hierarchy (_H), but all other data use the joined hierarchy.SELECT _H.id FROM hierarchy _H JOIN proxies ON _H.id = proxies.id -- proxy full join JOIN hierarchy ON hierarchy.id = proxies.targetid -- proxy full join LEFT JOIN dublincore ON hierarchy.id = dublincore.id LEFT JOIN uid ON hierarchy.id = uid.id WHERE hierarchy.primarytype IN ('File', 'SubFile') AND dublincore.title = 'abc' AND uid.uid = '123' AND EXISTS (SELECT 1 FROM dc_contributors WHERE hierarchy.id = dc_contributors.id AND dc_contributors.item = 'bob') AND NX_ACCESS_ALLOWED(_H.id, 'user1|user2', 'perm1|perm2') -- uses _H
When both normal documents and proxies are matched, we UNION ALL the two queries. If an ORDER BY is requested, then columns from the inner SELECTs have to be aliased so that an outer ORDER BY can user their names.- Author:
- Florent Guillaume
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description protected static class
NXQLQueryMaker.ColumnInfo
Info about a column and its property type.static class
NXQLQueryMaker.DocKind
protected class
NXQLQueryMaker.QueryAnalyzer
Collects various info about the query AST, and rewrites the toplevel ANDPredicate
s of the WHERE clause into a singleMultiExpression
for easier analysis.protected class
NXQLQueryMaker.WhereBuilder
Builds the database-level WHERE query from the AST.-
Nested classes/interfaces inherited from interface org.nuxeo.ecm.core.storage.sql.jdbc.QueryMaker
QueryMaker.Query, QueryMaker.QueryCannotMatchException
-
-
Field Summary
-
Constructor Summary
Constructors Constructor Description NXQLQueryMaker()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description boolean
accepts(String queryType)
Checks if this query maker accepts a given query.protected void
addJoin(int kind, String alias, Table table, String column, Table contextTable, String contextColumn, String name, int index, String primaryType)
QueryMaker.Query
buildQuery(SQLInfo sqlInfo, Model model, Session.PathResolver pathResolver, String query, QueryFilter queryFilter, Object... params)
Builds the query.static String
canonicalXPath(String xpath)
Canonicalizes a Nuxeo-xpath.protected static boolean
findFulltextIndexOrField(Model model, String[] nameref)
protected void
fixInitialJoins()
protected void
fixSelect(Select select)
protected void
fixWhatColumns(List<Column> whatColumns)
protected Table
getFragmentTable(int joinKind, Table contextTable, String contextKey, String fragmentName, String fragmentColumn, int index, boolean skipJoin, String primaryType)
Adds a more general JOIN:protected Table
getFragmentTable(Table contextHier, String fragmentName)
Gets the table for the given fragmentName, and maybe adds a join if one is not already done.String
getName()
Gets the name for this query maker.protected String
getSelectColName(Column col)
protected String
getSelectColName(Column col, String key)
key used to extract array index if neededprotected static Serializable
getSerializableLiteral(Literal literal)
protected static List<Serializable>
getSerializableLiterals(LiteralList list)
protected static Set<String>
getStringLiterals(LiteralList list)
boolean
hasFinalWildcardIndex(String xpath)
boolean
hasWildcardIndex(String xpath)
protected static String
keyForPos(String name)
protected NXQLQueryMaker.QueryAnalyzer
newQueryAnalyzer(FacetFilter facetFilter)
protected NXQLQueryMaker.WhereBuilder
newWhereBuilder(boolean isProxies)
static String
simpleXPath(String xpath)
Turns the xpath into one where all indices have been replaced by *.
-
-
-
Field Detail
-
TYPE_DOCUMENT
public static final String TYPE_DOCUMENT
- See Also:
- Constant Field Values
-
TYPE_RELATION
public static final String TYPE_RELATION
- See Also:
- Constant Field Values
-
TYPE_TAGGING
public static final String TYPE_TAGGING
- See Also:
- Constant Field Values
-
RELATION_TABLE
public static final String RELATION_TABLE
- See Also:
- Constant Field Values
-
ECM_SIMPLE_ACP_PRINCIPAL
public static final String ECM_SIMPLE_ACP_PRINCIPAL
- See Also:
- Constant Field Values
-
ECM_SIMPLE_ACP_PERMISSION
public static final String ECM_SIMPLE_ACP_PERMISSION
- See Also:
- Constant Field Values
-
ECM_SIMPLE_ACP_GRANT
public static final String ECM_SIMPLE_ACP_GRANT
- See Also:
- Constant Field Values
-
ECM_SIMPLE_ACP_NAME
public static final String ECM_SIMPLE_ACP_NAME
- See Also:
- Constant Field Values
-
ECM_SIMPLE_ACP_POS
public static final String ECM_SIMPLE_ACP_POS
- See Also:
- Constant Field Values
-
ECM_SIMPLE_ACP_CREATOR
public static final String ECM_SIMPLE_ACP_CREATOR
- Since:
- 7.4
- See Also:
- Constant Field Values
-
ECM_SIMPLE_ACP_BEGIN
public static final String ECM_SIMPLE_ACP_BEGIN
- Since:
- 7.4
- See Also:
- Constant Field Values
-
ECM_SIMPLE_ACP_END
public static final String ECM_SIMPLE_ACP_END
- Since:
- 7.4
- See Also:
- Constant Field Values
-
ECM_SIMPLE_ACP_STATUS
public static final String ECM_SIMPLE_ACP_STATUS
- Since:
- 7.4
- See Also:
- Constant Field Values
-
ECM_TAG_STAR
public static final String ECM_TAG_STAR
- See Also:
- Constant Field Values
-
FACETED_TAG
public static final String FACETED_TAG
- Since:
- 9.3
- See Also:
- Constant Field Values
-
FACETED_TAG_LABEL
public static final String FACETED_TAG_LABEL
- Since:
- 9.3
- See Also:
- Constant Field Values
-
TABLE_HIER_ALIAS
protected static final String TABLE_HIER_ALIAS
- See Also:
- Constant Field Values
-
TABLE_FRAG_ALIAS
protected static final String TABLE_FRAG_ALIAS
- See Also:
- Constant Field Values
-
SUBQUERY_ARRAY_ALIAS
protected static final String SUBQUERY_ARRAY_ALIAS
- See Also:
- Constant Field Values
-
COL_ALIAS_PREFIX
protected static final String COL_ALIAS_PREFIX
- See Also:
- Constant Field Values
-
UNION_ALIAS
protected static final String UNION_ALIAS
- See Also:
- Constant Field Values
-
WITH_ALIAS_PREFIX
protected static final String WITH_ALIAS_PREFIX
- See Also:
- Constant Field Values
-
READ_ACL_ALIAS
protected static final String READ_ACL_ALIAS
- See Also:
- Constant Field Values
-
READ_ACL_USER_MAP_ALIAS
protected static final String READ_ACL_USER_MAP_ALIAS
- See Also:
- Constant Field Values
-
DATE_CAST
protected static final String DATE_CAST
- See Also:
- Constant Field Values
-
COUNT_FUNCTION
protected static final String COUNT_FUNCTION
- See Also:
- Constant Field Values
-
AVG_FUNCTION
protected static final String AVG_FUNCTION
- See Also:
- Constant Field Values
-
sqlInfo
protected SQLInfo sqlInfo
-
database
protected Database database
-
dialect
protected Dialect dialect
-
model
protected Model model
-
pathResolver
protected Session.PathResolver pathResolver
-
selectCollectionNotNull
protected Set<String> selectCollectionNotNull
The select columns which we don't want to be NULL.
-
proxyClause
protected Boolean proxyClause
Whether the query must match only proxies (TRUE), no proxies (FALSE), or not specified (null).
-
proxyClauseReason
protected String proxyClauseReason
The reason why proxyClause was set to non-null.
-
hierTable
protected Table hierTable
-
dataHierTable
protected Table dataHierTable
-
proxyTable
protected Table proxyTable
-
whereParams
protected List<Serializable> whereParams
-
fragJoinCount
protected int fragJoinCount
-
INDEX
protected static final Pattern INDEX
-
HAS_WILDCARD_INDEX
protected static final Pattern HAS_WILDCARD_INDEX
-
HAS_FINAL_WILDCARD_INDEX
protected static final Pattern HAS_FINAL_WILDCARD_INDEX
-
INDEX_SLASH
protected static final Pattern INDEX_SLASH
-
NON_CANON_INDEX
protected static final Pattern NON_CANON_INDEX
-
-
Method Detail
-
getName
public String getName()
Description copied from interface:QueryMaker
Gets the name for this query maker.- Specified by:
getName
in interfaceQueryMaker
-
accepts
public boolean accepts(String queryType)
Description copied from interface:QueryMaker
Checks if this query maker accepts a given query.Called first.
- Specified by:
accepts
in interfaceQueryMaker
- Parameters:
queryType
- the query- Returns:
true
if the query is accepted
-
buildQuery
public QueryMaker.Query buildQuery(SQLInfo sqlInfo, Model model, Session.PathResolver pathResolver, String query, QueryFilter queryFilter, Object... params)
Description copied from interface:QueryMaker
Builds the query.- Specified by:
buildQuery
in interfaceQueryMaker
- Parameters:
sqlInfo
- the sql infomodel
- the modelpathResolver
- the path resolverquery
- the queryqueryFilter
- the query filterparams
- additional parameters, maker-specific
-
addJoin
protected void addJoin(int kind, String alias, Table table, String column, Table contextTable, String contextColumn, String name, int index, String primaryType)
-
getFragmentTable
protected Table getFragmentTable(Table contextHier, String fragmentName)
Gets the table for the given fragmentName, and maybe adds a join if one is not already done.LEFT JOIN fragmentName _F123 ON contextHier.id = _F123.id
-
getFragmentTable
protected Table getFragmentTable(int joinKind, Table contextTable, String contextKey, String fragmentName, String fragmentColumn, int index, boolean skipJoin, String primaryType)
Adds a more general JOIN:(LEFT) JOIN fragmentName _F123 ON contextTable.id = _F123.fragmentColumn
-
fixInitialJoins
protected void fixInitialJoins()
-
getSelectColName
protected String getSelectColName(Column col, String key)
key used to extract array index if needed
-
fixSelect
protected void fixSelect(Select select)
-
findFulltextIndexOrField
protected static boolean findFulltextIndexOrField(Model model, String[] nameref)
-
canonicalXPath
public static String canonicalXPath(String xpath)
Canonicalizes a Nuxeo-xpath.Replaces
a/foo[123]/b
witha/123/b
A star or a star followed by digits can be used instead of just the digits as well.
- Parameters:
xpath
- the xpath- Returns:
- the canonicalized xpath.
-
simpleXPath
public static String simpleXPath(String xpath)
Turns the xpath into one where all indices have been replaced by *.- Parameters:
xpath
- the xpath- Returns:
- the simple xpath
-
hasWildcardIndex
public boolean hasWildcardIndex(String xpath)
-
hasFinalWildcardIndex
public boolean hasFinalWildcardIndex(String xpath)
-
newQueryAnalyzer
protected NXQLQueryMaker.QueryAnalyzer newQueryAnalyzer(FacetFilter facetFilter)
-
getStringLiterals
protected static Set<String> getStringLiterals(LiteralList list)
-
getSerializableLiteral
protected static Serializable getSerializableLiteral(Literal literal)
-
getSerializableLiterals
protected static List<Serializable> getSerializableLiterals(LiteralList list)
-
newWhereBuilder
protected NXQLQueryMaker.WhereBuilder newWhereBuilder(boolean isProxies)
-
-