Class SqlQueryContext<S,Q extends FlexibleRelationalPathBase<R>,R>
- java.lang.Object
-
- com.evolveum.midpoint.repo.sqlbase.SqlQueryContext<S,Q,R>
-
- Type Parameters:
S
- schema type, used by encapsulated mappingQ
- type of entity pathR
- row type related to theSqlQueryContext
- All Implemented Interfaces:
FilterProcessor<ObjectFilter>
public abstract class SqlQueryContext<S,Q extends FlexibleRelationalPathBase<R>,R> extends Object implements FilterProcessor<ObjectFilter>
Execution context of the SQL query. Works as a kind of accumulator where information are added as the object query is interpreted. The object has a couple of overlapping responsibilities: * It implementsFilterProcessor
and is used as an entry point for filter processing for the query. * It executes the query, returningPageOf
low-level rows, seeexecuteQuery(com.evolveum.midpoint.repo.sqlbase.JdbcSession)
. * It transforms the row beans to midPoint objects usingtransformToSchemaType(com.evolveum.midpoint.repo.sqlbase.PageOf<com.querydsl.core.Tuple>, com.evolveum.midpoint.repo.sqlbase.JdbcSession)
.QueryTableMapping
is crucial for all these steps and flow of the execution goes a lot between theSqlQueryExecutor
, this class and particular methods of the mapping. Anything specific for a particular type/table should be part of the mapping logic. The mapping contract should cover all the needs of this execution context. It can be extended if needed, but always think whether existing mechanisms are not enough already. E.g. if you need to post-process the low level result, there is a way how to do it and it allows for things like loading all the detail table rows in a single query. SeetransformToSchemaType(com.evolveum.midpoint.repo.sqlbase.PageOf<com.querydsl.core.Tuple>, com.evolveum.midpoint.repo.sqlbase.JdbcSession)
for notes how this allows for inter-row state keeping as well. [NOTE] Implementation note: There was an option to keep this as an information accumulator only and do the execution elsewhere, but it proved more practical to utilize all the contained parameterized types. Methods executing the query and processing the result would need to be parameterized the same way this context already is - so it was better to use the types here. [NOTE] This object does not handle SQL connections or transaction in any way, any connection needed is provided from the outside.
-
-
Field Summary
Fields Modifier and Type Field Description static int
DEFAULT_PAGE_SIZE
Default page size if pagination is requested, that is offset is set, but maxSize is not.protected Q
entityPath
protected QueryTableMapping<S,Q,R>
entityPathMapping
static int
MAX_ID_IN_FOR_TO_MANY_FETCH
Number of values (identifiers) used in the IN clause to-many fetching selects.static long
NO_PAGINATION_LIMIT
If no other limit is used for query this limit will be used for sanity reasons.protected boolean
notFilterUsed
protected Collection<SelectorOptions<GetOperationOptions>>
options
protected com.querydsl.sql.SQLQuery<?>
sqlQuery
-
Constructor Summary
Constructors Modifier Constructor Description protected
SqlQueryContext(Q entityPath, QueryTableMapping<S,Q,R> mapping, SqlQueryContext<?,?,?> parentContext, com.querydsl.sql.SQLQuery<?> sqlQuery)
Constructor for derived context or sub-context, e.g.protected
SqlQueryContext(Q entityPath, QueryTableMapping<S,Q,R> mapping, SqlRepoContext sqlRepoContext, com.querydsl.sql.SQLQuery<?> query)
Constructor for root query context.
-
Method Summary
All Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description void
beforeQuery()
Before-query hook, empty by default, called *before* the JDBC transaction starts.CanonicalItemPath
createCanonicalItemPath(@NotNull ItemPath itemPath)
int
executeCount(JdbcSession jdbcSession)
PageOf<com.querydsl.core.Tuple>
executeQuery(JdbcSession jdbcSession)
Returns page of results with each row represented by aTuple
.boolean
isNotFilterUsed()
<TS,TQ extends FlexibleRelationalPathBase<TR>,TR>
SqlQueryContext<TS,TQ,TR>leftJoin(@NotNull QueryTableMapping<TS,TQ,TR> targetMapping, @NotNull BiFunction<Q,TQ,com.querydsl.core.types.Predicate> joinOnPredicateFunction)
Adds new LEFT JOIN to the query and returnsSqlQueryContext
for this join path.QueryTableMapping<S,Q,R>
mapping()
void
markNotFilterUsage()
protected abstract <TS,TQ extends FlexibleRelationalPathBase<TR>,TR>
SqlQueryContext<TS,TQ,TR>newSubcontext(TQ newPath, QueryTableMapping<TS,TQ,TR> newMapping)
Contract to implement to obtain derived (e.g.protected abstract <TS,TQ extends FlexibleRelationalPathBase<TR>,TR>
SqlQueryContext<TS,TQ,TR>newSubcontext(TQ newPath, QueryTableMapping<TS,TQ,TR> newMapping, com.querydsl.sql.SQLQuery<?> query)
Contract to implement to obtain derived (e.g.@NotNull QName
normalizeRelation(QName qName)
SqlQueryContext<?,?,?>
parentContext()
Q
path()
Returns entity path of this context.<T extends FlexibleRelationalPathBase<?>>
Tpath(Class<T> pathType)
PrismContext
prismContext()
com.querydsl.core.types.Predicate
process(@NotNull ObjectFilter filter)
Implements contract forFilterProcessor
working as a top-level dispatcher to concrete filter types.void
processFilter(ObjectFilter filter)
Processes the object filter and sets the WHERE clause.com.querydsl.core.types.Predicate
processFuzzyFilter(FuzzyStringMatchFilter<?> filter, com.querydsl.core.types.Expression<?> path, ValueFilterValues<?,?> values)
Produces predicate for fuzzy filter with pre-provided expression for the left side.void
processObjectPaging(ObjectPaging paging)
This method takes care ofObjectPaging
which includes ordering.void
processOptions(Collection<SelectorOptions<GetOperationOptions>> options)
<T> Class<? extends T>
qNameToSchemaClass(@NotNull QName qName)
QueryModelMapping<S,Q,R>
queryMapping()
SqlRepoContext
repositoryContext()
Q
root()
<T extends FlexibleRelationalPathBase<?>>
Troot(Class<T> rootType)
com.querydsl.sql.SQLQuery<?>
sqlQuery()
Returns wrapped query if usage of Querydsl API is more convenient.<TS,TQ extends FlexibleRelationalPathBase<TR>,TR>
SqlQueryContext<TS,TQ,TR>subquery(@NotNull QueryTableMapping<TS,TQ,TR> targetMapping)
Creates new subquery and returnsSqlQueryContext
for it, typically for (NOT) EXISTS.<TS,TQ extends FlexibleRelationalPathBase<TR>,TR>
SqlQueryContext<TS,TQ,TR>subquery(@NotNull Class<TQ> subqueryType)
Creates new subquery, seesubquery(QueryTableMapping)
for more.PageOf<S>
transformToSchemaType(PageOf<com.querydsl.core.Tuple> result, JdbcSession jdbcSession)
Transforms result page with (bean + extension columns) tuple to schema type.String
uniqueAliasName(String baseAliasName)
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface com.evolveum.midpoint.repo.sqlbase.filtering.FilterProcessor
process
-
-
-
-
Field Detail
-
DEFAULT_PAGE_SIZE
public static final int DEFAULT_PAGE_SIZE
Default page size if pagination is requested, that is offset is set, but maxSize is not.- See Also:
- Constant Field Values
-
NO_PAGINATION_LIMIT
public static final long NO_PAGINATION_LIMIT
If no other limit is used for query this limit will be used for sanity reasons.- See Also:
- Constant Field Values
-
MAX_ID_IN_FOR_TO_MANY_FETCH
public static final int MAX_ID_IN_FOR_TO_MANY_FETCH
Number of values (identifiers) used in the IN clause to-many fetching selects. This works effectively as factor of how bad N+1 select is, it's at most N/this-limit+1 bad. For obvious reasons, this works only for non-composite PKs (IDs) on the master entity.- See Also:
- Constant Field Values
-
sqlQuery
protected final com.querydsl.sql.SQLQuery<?> sqlQuery
-
entityPath
protected final Q extends FlexibleRelationalPathBase<R> entityPath
-
entityPathMapping
protected final QueryTableMapping<S,Q extends FlexibleRelationalPathBase<R>,R> entityPathMapping
-
notFilterUsed
protected boolean notFilterUsed
-
options
protected Collection<SelectorOptions<GetOperationOptions>> options
-
-
Constructor Detail
-
SqlQueryContext
protected SqlQueryContext(Q entityPath, QueryTableMapping<S,Q,R> mapping, SqlRepoContext sqlRepoContext, com.querydsl.sql.SQLQuery<?> query)
Constructor for root query context.
-
SqlQueryContext
protected SqlQueryContext(Q entityPath, QueryTableMapping<S,Q,R> mapping, SqlQueryContext<?,?,?> parentContext, com.querydsl.sql.SQLQuery<?> sqlQuery)
Constructor for derived context or sub-context, e.g. JOIN, EXISTS, etc.
-
-
Method Detail
-
root
public Q root()
-
root
public <T extends FlexibleRelationalPathBase<?>> T root(Class<T> rootType)
-
processFilter
public void processFilter(ObjectFilter filter) throws RepositoryException
Processes the object filter and sets the WHERE clause. This is different fromprocess(ObjectFilter)
that just creates a predicate. That method is used in this one andQueryBase.where(Predicate)
is called.- Throws:
RepositoryException
-
process
public com.querydsl.core.types.Predicate process(@NotNull @NotNull ObjectFilter filter) throws RepositoryException
Implements contract forFilterProcessor
working as a top-level dispatcher to concrete filter types. This is a universal/generic filter processor that dispatches to the actual filter processor based on the filter type. It is used both as an entry point for the root filter of the query, but also when various structural filters need to resolve their components (e.g. AND uses this for its components). *This only returns the created predicate, compare withprocessFilter(com.evolveum.midpoint.prism.query.ObjectFilter)
.* Some subtypes ofObjectFilter
from Prism API are not supported here, see subclasses.- Specified by:
process
in interfaceFilterProcessor<S>
- Throws:
RepositoryException
-
processObjectPaging
public void processObjectPaging(ObjectPaging paging) throws RepositoryException
This method takes care ofObjectPaging
which includes ordering.- Throws:
RepositoryException
-
executeQuery
public PageOf<com.querydsl.core.Tuple> executeQuery(JdbcSession jdbcSession) throws QueryException
Returns page of results with each row represented by aTuple
. Tuple contains expressions specified byQueryTableMapping.selectExpressions(Q, java.util.Collection<com.evolveum.midpoint.schema.SelectorOptions<com.evolveum.midpoint.schema.GetOperationOptions>>)
, seebuildSelectExpressions(Q, com.querydsl.sql.SQLQuery<?>)
for details. This may for example beSqlQueryContext
(representing the whole entity) and then individual paths for extension columns, seeextensionColumns
inQueryTableMapping
.QueryTableMapping
has many responsibilities in the process: *options
are used to amend the select expression list; the options later enter as a parameter to most methods related to the transformation from row to midPoint object. *QueryTableMapping.createRowTransformer(com.evolveum.midpoint.repo.sqlbase.SqlQueryContext<S, Q, R>, com.evolveum.midpoint.repo.sqlbase.JdbcSession)
(used later bytransformToSchemaType(com.evolveum.midpoint.repo.sqlbase.PageOf<com.querydsl.core.Tuple>, com.evolveum.midpoint.repo.sqlbase.JdbcSession)
) allows for low-level result list processing, e.g. fetching any additional objects efficiently.- Throws:
QueryException
-
executeCount
public int executeCount(JdbcSession jdbcSession)
-
leftJoin
public <TS,TQ extends FlexibleRelationalPathBase<TR>,TR> SqlQueryContext<TS,TQ,TR> leftJoin(@NotNull @NotNull QueryTableMapping<TS,TQ,TR> targetMapping, @NotNull @NotNull BiFunction<Q,TQ,com.querydsl.core.types.Predicate> joinOnPredicateFunction)
Adds new LEFT JOIN to the query and returnsSqlQueryContext
for this join path. The returned context still uses the same SQL query; any further filter processing will add WHERE conditions to the original query, but the conditions use the new alias.- Type Parameters:
TQ
- query type for the JOINed (target) tableTR
- row type related to theSqlQueryContext
- Parameters:
targetMapping
- mapping for the JOIN target query typejoinOnPredicateFunction
- bi-function producing ON predicate for the JOIN
-
subquery
public <TS,TQ extends FlexibleRelationalPathBase<TR>,TR> SqlQueryContext<TS,TQ,TR> subquery(@NotNull @NotNull Class<TQ> subqueryType)
Creates new subquery, seesubquery(QueryTableMapping)
for more.- Parameters:
subqueryType
- entity path type the subquery
-
subquery
public <TS,TQ extends FlexibleRelationalPathBase<TR>,TR> SqlQueryContext<TS,TQ,TR> subquery(@NotNull @NotNull QueryTableMapping<TS,TQ,TR> targetMapping)
Creates new subquery and returnsSqlQueryContext
for it, typically for (NOT) EXISTS. Call toFetchableSubQueryBase.exists()
can't be here, because it's a predicate creating call that we may need to execute when returning the predicate inside the filter processor. See `TypeFilterProcessor` from `repo-sqale` for example.- Type Parameters:
TQ
- query type for the subquery tableTR
- row type related to theSqlQueryContext
- Parameters:
targetMapping
- mapping for the subquery type
-
newSubcontext
protected abstract <TS,TQ extends FlexibleRelationalPathBase<TR>,TR> SqlQueryContext<TS,TQ,TR> newSubcontext(TQ newPath, QueryTableMapping<TS,TQ,TR> newMapping)
Contract to implement to obtain derived (e.g. joined) query context.- Type Parameters:
TQ
- query type for the new (target) tableTR
- row type related to theSqlQueryContext
-
newSubcontext
protected abstract <TS,TQ extends FlexibleRelationalPathBase<TR>,TR> SqlQueryContext<TS,TQ,TR> newSubcontext(TQ newPath, QueryTableMapping<TS,TQ,TR> newMapping, com.querydsl.sql.SQLQuery<?> query)
Contract to implement to obtain derived (e.g. subquery) query context.- Type Parameters:
TQ
- query type for the new (target) tableTR
- row type related to theSqlQueryContext
-
processOptions
public void processOptions(Collection<SelectorOptions<GetOperationOptions>> options)
-
transformToSchemaType
public PageOf<S> transformToSchemaType(PageOf<com.querydsl.core.Tuple> result, JdbcSession jdbcSession) throws SchemaException, QueryException
Transforms result page with (bean + extension columns) tuple to schema type. JDBC session is provided as it may be needed for additional fetches. Instead of calling some transformation method row-by-row, transformer object is provided by the table mapper - which allows for potentially stateful processing.- Throws:
SchemaException
QueryException
-
sqlQuery
public com.querydsl.sql.SQLQuery<?> sqlQuery()
Returns wrapped query if usage of Querydsl API is more convenient.
-
parentContext
public SqlQueryContext<?,?,?> parentContext()
-
path
public Q path()
Returns entity path of this context.
-
path
public <T extends FlexibleRelationalPathBase<?>> T path(Class<T> pathType)
-
mapping
public QueryTableMapping<S,Q,R> mapping()
-
queryMapping
public QueryModelMapping<S,Q,R> queryMapping()
-
markNotFilterUsage
public void markNotFilterUsage()
-
isNotFilterUsed
public boolean isNotFilterUsed()
-
repositoryContext
public SqlRepoContext repositoryContext()
-
prismContext
public PrismContext prismContext()
-
createCanonicalItemPath
public CanonicalItemPath createCanonicalItemPath(@NotNull @NotNull ItemPath itemPath)
-
beforeQuery
public void beforeQuery()
Before-query hook, empty by default, called *before* the JDBC transaction starts.
-
processFuzzyFilter
public com.querydsl.core.types.Predicate processFuzzyFilter(FuzzyStringMatchFilter<?> filter, com.querydsl.core.types.Expression<?> path, ValueFilterValues<?,?> values) throws QueryException
Produces predicate for fuzzy filter with pre-provided expression for the left side. This does not care about single/multi-value definition which must be treated above this method.- Throws:
QueryException
-
-