Class AbstractSqlExpressionConverter<C extends SqlConversionContext>
- Type Parameters:
C-SqlConversionContextor derived type
- All Implemented Interfaces:
de.calamanari.adl.cnv.ExpressionConverter<de.calamanari.adl.irl.CoreExpression,,QueryTemplateWithParameters> de.calamanari.adl.irl.CoreExpressionVisitor
- Direct Known Subclasses:
DefaultSqlExpressionConverter
A couple of common functions have been identified and realized as template methods to be overridden as desired.
In general methods can be found here that are related to preparation steps before composing the final SQL-statement from the prepared data.
The state of a conversion is quite complex. Because I wanted to make instances reusable (so state must be reset to initial settings), I moved all the
variables into the ResettableScpContext. Now, each SqlConversionContext issued by the converter for a particular level of the
expression being converted has the full picture in form of the injected process state of the converter. This allows global state communication
(variables, flags) throughout a conversion process.
- Author:
- Karl Eilebrecht
-
Field Summary
Fields inherited from class de.calamanari.adl.cnv.AbstractExpressionConverter
contextStack -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedAbstractSqlExpressionConverter(Supplier<? extends C> contextSupplier, ResettableScpContext processContext) Creates a new instance of the converter, fully prepared to callAbstractExpressionConverter.convert(Object).protectedAbstractSqlExpressionConverter(Supplier<? extends C> contextSupplier, DataBinding dataBinding) Creates a new instance of the converter, fully prepared to callAbstractExpressionConverter.convert(Object).protectedAbstractSqlExpressionConverter(Supplier<? extends C> contextSupplier, DataBinding dataBinding, Map<String, Serializable> globalVariables, Set<de.calamanari.adl.Flag> flags) Creates a new instance of the converter, fully prepared to callAbstractExpressionConverter.convert(Object). -
Method Summary
Modifier and TypeMethodDescriptionprotected final Set<ExpressionAlias> protected final AliasHelperprotected voidappendAliasExistenceCheckWithExtraNullCheckIfRequired(StringBuilder sb, MatchCondition condition, ExpressionAlias alias) When we query columns with multi-row sensitivity, we perform the condition check within the alias query and perform an alias existence check in the global WHERE clause (we are not attributing the aliases).protected voidappendAliasGroupToBaseQuery(StringBuilder sb, List<ExpressionAlias> aliasGroup) Appends the query related to one alias group (a table or duo of two tables in case of a reference match) to become part of a UNION that shall form the base query.protected voidappendAliasQuery(StringBuilder sb, ExpressionAlias alias) Append an alias query (part of the SQL WITH-section)protected voidappendAliasUnionBaseQuery(StringBuilder sb, List<ExpressionAlias> aliases) Appends a UNION of the given aliases to compose a super set as base query (part if with)protected voidAppends a UNION of all tables defined in the data binding.protected voidappendFilterColumnConditions(StringBuilder sb, String optionalTableOrAliasName, List<ColumnCondition> columnConditions, boolean followUp) Appends the given list of filter column conditions, connected by AND with the previous contentprotected voidappendFullTableQuery(StringBuilder sb, TableMetaInfo table) Appends a select that queries all IDs of the given tableprotected voidappendMatchCondition(StringBuilder sb, MatchCondition condition, boolean qualified) Appends the given condition to WHERE clause (with/sub query).protected voidappendToAliasConditionClause(StringBuilder sb, MatchCondition condition, boolean qualified) Appends the condition to the given alias WHERE-clause or ON-condition.protected voidappendToGlobalWhereClause(StringBuilder sb, MatchCondition condition, ExpressionAlias currentAlias) Appends the condition to the global WHERE-clause.protected final SqlAugmentationListenerprotected final MatchConditionFactoryprotected AliasHelperThis method allows sub-classes to replace the helper with a custom oneprotected CoreExpressionSqlHelpercreateCoreExpressionSqlHelper(de.calamanari.adl.irl.CoreExpression rootExpression) This method allows sub-classes to replace the helper with a custom oneprotected MatchConditionFactoryThis method allows sub-classes to replace the factory with a custom oneprotected final DataBindingvoidenterCombinedExpression(de.calamanari.adl.irl.CombinedExpression expression) voidenterNegationExpression(de.calamanari.adl.irl.NegationExpression expression) voidexitCombinedExpression(de.calamanari.adl.irl.CombinedExpression expression) protected final CoreExpressionSqlHelperprotected final Set<de.calamanari.adl.Flag> flags()final Stringfinal Set<de.calamanari.adl.Flag> Returns the flag configuration passed to the constructorfinal Map<String, Serializable> Returns the variable configuration passed to the constructorprotected final StringResolves the main id-column for joining further tables.final TableMetaInfoThe main table is the table to start the query with.Returns the converter's process context across the levels of a conversion.final QueryTypefinal de.calamanari.adl.FormatStylegetStyle()protected final Map<String, Serializable> voidhandleMatchExpression(de.calamanari.adl.irl.MatchExpression expression) voidhandleSpecialSetExpression(de.calamanari.adl.irl.SpecialSetExpression expression) voidinit()protected de.calamanari.adl.irl.CoreExpressionvoidsetAugmentationListener(SqlAugmentationListener augmentationListener) final voidsetIdColumnName(String idColumnName) protected final voidsetMainTable(TableMetaInfo mainTable) The main table is the table to start the query with.final voidsetQueryType(QueryType queryType) final voidsetStyle(de.calamanari.adl.FormatStyle style) protected final CoreExpressionStatsstats()protected final de.calamanari.adl.FormatStylestyle()protected final Set<TableMetaInfo> protected final StringBuilderMethods inherited from class de.calamanari.adl.cnv.AbstractCoreExpressionConverter
createConversionException, exitNegationExpression, traverse, visit, visit, visit, visitMethods inherited from class de.calamanari.adl.cnv.AbstractExpressionConverter
convert, createNewContext, decreaseNormalizedDepth, finishResult, getContext, getCurrentDepth, getNormalizedDepth, getParentContext, getRootContext, getRootExpression, increaseNormalizedDepth, popContext, pushContext, setContextPreparator
-
Constructor Details
-
AbstractSqlExpressionConverter
protected AbstractSqlExpressionConverter(Supplier<? extends C> contextSupplier, ResettableScpContext processContext) Creates a new instance of the converter, fully prepared to callAbstractExpressionConverter.convert(Object).Meant for sub-classes that want to provide an individual processContext (or a sub-class).
- Parameters:
contextSupplier- to create a context for each level of the expression we visitprocessContext-- See Also:
-
AbstractSqlExpressionConverter
protected AbstractSqlExpressionConverter(Supplier<? extends C> contextSupplier, DataBinding dataBinding, Map<String, Serializable> globalVariables, Set<de.calamanari.adl.Flag> flags) Creates a new instance of the converter, fully prepared to callAbstractExpressionConverter.convert(Object).Important: The set of global variables and flags you specify here act as a template for each subsequent run. A conversion run will never modify the map with the variables and the set with the flags provided at construction time because it will run on independent copies.
- Parameters:
contextSupplier- to create a context for each level of the expression we visitdataBinding-globalVariables- optional global variables (null means empty)flags- directives and dynamic flags (null means empty)- See Also:
-
AbstractSqlExpressionConverter
protected AbstractSqlExpressionConverter(Supplier<? extends C> contextSupplier, DataBinding dataBinding) Creates a new instance of the converter, fully prepared to callAbstractExpressionConverter.convert(Object).- Parameters:
contextSupplier- to create a context for each level of the expression we visitdataBinding-
-
-
Method Details
-
getAugmentationListener
- Returns:
- augmentation listener of this instance or
SqlAugmentationListener.none()if not installed, not null
-
setAugmentationListener
- Parameters:
augmentationListener- null meansSqlAugmentationListener.none()(default)
-
getProcessContext
Returns the converter's process context across the levels of a conversion.While each level of an expression's DAG gets its own level context
AbstractExpressionConverter.getContext(),AbstractExpressionConverter.getParentContext(),AbstractExpressionConverter.getRootContext()), the process context (global variables and general converter state) is common to all of them and allows data exchange.By sharing the process context callers have access to the full data and feature set of the converter without sharing the converter instance itself.
- Returns:
- the current global process context of the converter (variables, flags, etc.), instance of
ResettableScpContext
-
init
public void init()- Overrides:
initin classde.calamanari.adl.cnv.AbstractExpressionConverter<de.calamanari.adl.irl.CoreExpression,QueryTemplateWithParameters, C extends SqlConversionContext>
-
getIdColumnName
- Returns:
- id-column name for joining and the returned result, defaults to
SqlFormatConstants.DEFAULT_ID_COLUMN_NAME
-
setIdColumnName
- Parameters:
idColumnName- id-column name for joining and the returned result, defaults toSqlFormatConstants.DEFAULT_ID_COLUMN_NAME
-
getQueryType
- Returns:
- type of the query to be created, defaults to
QueryType.SELECT_DISTINCT_ID_ORDERED
-
setQueryType
- Parameters:
queryType- type of the query to be created, defaults toQueryType.SELECT_DISTINCT_ID_ORDERED
-
getInitialVariables
Returns the variable configuration passed to the constructorThis configuration acts as a template for all subsequent calls to
AbstractExpressionConverter.convert(Object).You can use this method if you did not specify any variables at construction time but instead want to define them now (before calling
AbstractExpressionConverter.convert(Object)).- Returns:
- mutable map
-
getInitialFlags
Returns the flag configuration passed to the constructorThis configuration acts as a template for all subsequent calls to
AbstractExpressionConverter.convert(Object)You can use this method if you did not specify any flags at construction time but instead want to define them now (before calling
AbstractExpressionConverter.convert(Object)).- Returns:
- mutable set
-
getMainTable
The main table is the table to start the query with. It is initialized withDataTableConfig.primaryTable().Depending on the conversion strategy it can be reasonable to override it with a different table, for example if only a single table is involved without any complex joins.
- Returns:
- the main table or null if not configured
-
setMainTable
The main table is the table to start the query with. It is initialized withDataTableConfig.primaryTable().Depending on the conversion strategy it can be reasonable to override it with a different table, for example if only a single table is involved without any complex joins.
- Parameters:
mainTable- the table to prefer to start the query or null to enforce another query start strategy
-
getStyle
public final de.calamanari.adl.FormatStyle getStyle()- Returns:
- configured formatting style (inline or multi-line)
-
setStyle
public final void setStyle(de.calamanari.adl.FormatStyle style) - Parameters:
style- formatting style (inline or multi-line)
-
stats
- Returns:
- expression statistics from the expression helper
-
aliasHelper
- Returns:
- alias helper for this conversion, initialized during
prepareRootExpression()
-
expressionHelper
- Returns:
- expression helper for the currently processed expression, initialized during
prepareRootExpression()
-
dataBinding
- Returns:
- initially configured data binding (physical data model)
-
whereClause
- Returns:
- WHERE-clause builder
-
conditionFactory
- Returns:
- match condition factory of the current run
-
style
protected final de.calamanari.adl.FormatStyle style()- Returns:
- configured format style (pretty or inline)
-
flags
- Returns:
- process flags (mutable)
-
globalVariables
- Returns:
- global process variables (mutable)
-
tablesInWhereClause
- Returns:
- collection of the tables referenced in the where clause
-
aliasesInWhereClause
- Returns:
- collection of the aliases referenced in the where clause
-
augmentationListener
- Returns:
- the augmentation listener of this converter or
SqlAugmentationListener.none()if not installed, never null
-
getMainIdColumnName
Resolves the main id-column for joining further tables.The effective name of the ID-column can vary if the tables have custom-IDs and there are aliases or a renamed base selection.
This method simply tests if there is a main table (then the result is the column name) or not (then the ID isgetIdColumnName().Note: This is the raw name, of course finally the returned ID-column name is always
getIdColumnName()(renamed if required).- Returns:
- effective main id for joining
-
prepareRootExpression
protected de.calamanari.adl.irl.CoreExpression prepareRootExpression()- Overrides:
prepareRootExpressionin classde.calamanari.adl.cnv.AbstractExpressionConverter<de.calamanari.adl.irl.CoreExpression,QueryTemplateWithParameters, C extends SqlConversionContext>
-
createAliasHelper
This method allows sub-classes to replace the helper with a custom one- Returns:
- new helper instance
-
createCoreExpressionSqlHelper
protected CoreExpressionSqlHelper createCoreExpressionSqlHelper(de.calamanari.adl.irl.CoreExpression rootExpression) This method allows sub-classes to replace the helper with a custom one- Parameters:
rootExpression- the prepared root expression before start- Returns:
- new helper instance, a
CoreExpressionSqlHelperinitialized with the root expression by default
-
createMatchConditionFactory
This method allows sub-classes to replace the factory with a custom one- Returns:
- new match condition factory, instance of
DefaultMatchConditionFactoryby default
-
enterCombinedExpression
public void enterCombinedExpression(de.calamanari.adl.irl.CombinedExpression expression) - Overrides:
enterCombinedExpressionin classde.calamanari.adl.cnv.AbstractCoreExpressionConverter<QueryTemplateWithParameters,C extends SqlConversionContext>
-
exitCombinedExpression
public void exitCombinedExpression(de.calamanari.adl.irl.CombinedExpression expression) - Overrides:
exitCombinedExpressionin classde.calamanari.adl.cnv.AbstractCoreExpressionConverter<QueryTemplateWithParameters,C extends SqlConversionContext>
-
handleMatchExpression
public void handleMatchExpression(de.calamanari.adl.irl.MatchExpression expression) - Overrides:
handleMatchExpressionin classde.calamanari.adl.cnv.AbstractCoreExpressionConverter<QueryTemplateWithParameters,C extends SqlConversionContext>
-
enterNegationExpression
public void enterNegationExpression(de.calamanari.adl.irl.NegationExpression expression) - Overrides:
enterNegationExpressionin classde.calamanari.adl.cnv.AbstractCoreExpressionConverter<QueryTemplateWithParameters,C extends SqlConversionContext>
-
handleSpecialSetExpression
public void handleSpecialSetExpression(de.calamanari.adl.irl.SpecialSetExpression expression) - Overrides:
handleSpecialSetExpressionin classde.calamanari.adl.cnv.AbstractCoreExpressionConverter<QueryTemplateWithParameters,C extends SqlConversionContext>
-
appendAliasUnionBaseQuery
Appends a UNION of the given aliases to compose a super set as base query (part if with)- Parameters:
sb-aliases-
-
appendAllTableUnionBaseQuery
Appends a UNION of all tables defined in the data binding.This "worst-case" scenario happens if no table is marked as primary table nor containing all IDs and the query contains negative or IS UNKNOWN conditions.
- Parameters:
sb-
-
appendFullTableQuery
Appends a select that queries all IDs of the given table- Parameters:
sb-table- to select all IDs from (with respect to optional table filter conditions)
-
appendAliasGroupToBaseQuery
Appends the query related to one alias group (a table or duo of two tables in case of a reference match) to become part of a UNION that shall form the base query.- Parameters:
sb-aliasGroup-
-
appendAliasQuery
Append an alias query (part of the SQL WITH-section)- Parameters:
sb-alias-
-
appendToAliasConditionClause
protected void appendToAliasConditionClause(StringBuilder sb, MatchCondition condition, boolean qualified) Appends the condition to the given alias WHERE-clause or ON-condition.In contrast to the global where clause we don't need extra existence checks in this case (alias is always a simple join).
- Parameters:
sb-condition-qualified-
-
appendToGlobalWhereClause
protected void appendToGlobalWhereClause(StringBuilder sb, MatchCondition condition, ExpressionAlias currentAlias) Appends the condition to the global WHERE-clause.We always try to work with the regular table names. The alias name only comes into play if there is any multi-row sensitivity or IS-NULL-check.
- Parameters:
sb-condition-currentAlias-- See Also:
-
appendMatchCondition
Appends the given condition to WHERE clause (with/sub query).Note: There is special IS NULL handling, instead of IS NULL we query IS NOT NULL which requires a corresponding handling by the global where clause. Only in the edge case
CoreExpressionSqlHelper.isNullQueryingAllowed(String)NULL will be queried directly to simplify the query.- Parameters:
sb- to append the conditioncondition- to be appendedqualified- tells whether the column names must be qualified or not
-
appendAliasExistenceCheckWithExtraNullCheckIfRequired
protected void appendAliasExistenceCheckWithExtraNullCheckIfRequired(StringBuilder sb, MatchCondition condition, ExpressionAlias alias) When we query columns with multi-row sensitivity, we perform the condition check within the alias query and perform an alias existence check in the global WHERE clause (we are not attributing the aliases).An extra is-null-check can be required to avoid accidentally including nulls in the result.
- Parameters:
sb-condition-alias-- See Also:
-
appendFilterColumnConditions
protected void appendFilterColumnConditions(StringBuilder sb, String optionalTableOrAliasName, List<ColumnCondition> columnConditions, boolean followUp) Appends the given list of filter column conditions, connected by AND with the previous content- Parameters:
sb-optionalTableOrAliasName- qualifier for the columns or null (pure column name)columnConditions-followUp- if true then there is some earlier condition (prepend AND)
-