org.dbflute.cbean.AbstractConditionQuery Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dbflute-runtime Show documentation
Show all versions of dbflute-runtime Show documentation
The runtime library of DBFlute
/*
* Copyright 2014-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.dbflute.cbean;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import org.dbflute.FunCustodial;
import org.dbflute.cbean.chelper.HpCBPurpose;
import org.dbflute.cbean.chelper.HpDerivingSubQueryInfo;
import org.dbflute.cbean.chelper.HpFixedConditionQueryResolver;
import org.dbflute.cbean.chelper.HpInvalidQueryInfo;
import org.dbflute.cbean.chelper.HpQDRFunction;
import org.dbflute.cbean.chelper.HpQDRParameter;
import org.dbflute.cbean.chelper.HpQDRSetupper;
import org.dbflute.cbean.chelper.HpSLCCustomized;
import org.dbflute.cbean.chelper.HpSLCFunction;
import org.dbflute.cbean.cipher.ColumnFunctionCipher;
import org.dbflute.cbean.cipher.GearedCipherManager;
import org.dbflute.cbean.ckey.ConditionKey;
import org.dbflute.cbean.ckey.ConditionKeyInScope;
import org.dbflute.cbean.ckey.ConditionKeyPrepareResult;
import org.dbflute.cbean.coption.ConditionOption;
import org.dbflute.cbean.coption.ConditionOptionCall;
import org.dbflute.cbean.coption.DerivedReferrerOption;
import org.dbflute.cbean.coption.DerivedReferrerOptionFactory;
import org.dbflute.cbean.coption.FromToOption;
import org.dbflute.cbean.coption.LikeSearchOption;
import org.dbflute.cbean.coption.ParameterOption;
import org.dbflute.cbean.coption.RangeOfOption;
import org.dbflute.cbean.coption.ScalarConditionOption;
import org.dbflute.cbean.cvalue.ConditionValue;
import org.dbflute.cbean.cvalue.ConditionValue.QueryModeProvider;
import org.dbflute.cbean.dream.SpecifiedColumn;
import org.dbflute.cbean.exception.ConditionBeanExceptionThrower;
import org.dbflute.cbean.garnish.datefitting.DateConditionAdjuster;
import org.dbflute.cbean.garnish.invoking.InvokingQueryAgent;
import org.dbflute.cbean.ordering.ManualOrderOption;
import org.dbflute.cbean.ordering.ManualOrderOptionCall;
import org.dbflute.cbean.scoping.SubQuery;
import org.dbflute.cbean.sqlclause.SqlClause;
import org.dbflute.cbean.sqlclause.SqlClauseMySql;
import org.dbflute.cbean.sqlclause.SqlClauseOracle;
import org.dbflute.cbean.sqlclause.join.FixedConditionLazyChecker;
import org.dbflute.cbean.sqlclause.join.FixedConditionResolver;
import org.dbflute.cbean.sqlclause.orderby.OrderByElement;
import org.dbflute.cbean.sqlclause.query.QueryClause;
import org.dbflute.cbean.sqlclause.query.QueryClauseArranger;
import org.dbflute.cbean.sqlclause.query.QueryUsedAliasInfo;
import org.dbflute.cbean.sqlclause.subquery.ExistsReferrer;
import org.dbflute.cbean.sqlclause.subquery.InScopeRelation;
import org.dbflute.cbean.sqlclause.subquery.QueryDerivedReferrer;
import org.dbflute.cbean.sqlclause.subquery.ScalarCondition;
import org.dbflute.cbean.sqlclause.subquery.ScalarCondition.PartitionByProvider;
import org.dbflute.cbean.sqlclause.subquery.SpecifyDerivedReferrer;
import org.dbflute.cbean.sqlclause.subquery.SubQueryPath;
import org.dbflute.cbean.sqlclause.union.UnionClauseProvider;
import org.dbflute.dbmeta.DBMeta;
import org.dbflute.dbmeta.DBMetaProvider;
import org.dbflute.dbmeta.info.ColumnInfo;
import org.dbflute.dbmeta.info.ForeignInfo;
import org.dbflute.dbmeta.info.PrimaryInfo;
import org.dbflute.dbmeta.info.ReferrerInfo;
import org.dbflute.dbmeta.info.RelationInfo;
import org.dbflute.dbmeta.name.ColumnRealName;
import org.dbflute.dbmeta.name.ColumnRealNameProvider;
import org.dbflute.dbmeta.name.ColumnSqlName;
import org.dbflute.dbmeta.name.ColumnSqlNameProvider;
import org.dbflute.dbway.WayOfMySQL;
import org.dbflute.dbway.topic.ExtensionOperand;
import org.dbflute.exception.IllegalConditionBeanOperationException;
import org.dbflute.exception.OrScopeQueryAndPartUnsupportedOperationException;
import org.dbflute.helper.function.IndependentProcessor;
import org.dbflute.helper.message.ExceptionMessageBuilder;
import org.dbflute.jdbc.Classification;
import org.dbflute.jdbc.ShortCharHandlingMode;
import org.dbflute.system.DBFluteSystem;
import org.dbflute.twowaysql.pmbean.SimpleMapPmb;
import org.dbflute.util.DfCollectionUtil;
import org.dbflute.util.DfTypeUtil;
import org.dbflute.util.Srl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The abstract class of condition-query.
* @author jflute
*/
public abstract class AbstractConditionQuery implements ConditionQuery {
// ===================================================================================
// Definition
// ==========
private static final Logger _log = LoggerFactory.getLogger(AbstractConditionQuery.class);
protected static final ConditionKey CK_EQ = ConditionKey.CK_EQUAL;
protected static final ConditionKey CK_NES = ConditionKey.CK_NOT_EQUAL_STANDARD;
protected static final ConditionKey CK_NET = ConditionKey.CK_NOT_EQUAL_TRADITION;
protected static final ConditionKey CK_GT = ConditionKey.CK_GREATER_THAN;
protected static final ConditionKey CK_LT = ConditionKey.CK_LESS_THAN;
protected static final ConditionKey CK_GE = ConditionKey.CK_GREATER_EQUAL;
protected static final ConditionKey CK_LE = ConditionKey.CK_LESS_EQUAL;
protected static final ConditionKey CK_INS = ConditionKey.CK_IN_SCOPE;
protected static final ConditionKey CK_NINS = ConditionKey.CK_NOT_IN_SCOPE;
protected static final ConditionKey CK_LS = ConditionKey.CK_LIKE_SEARCH;
protected static final ConditionKey CK_NLS = ConditionKey.CK_NOT_LIKE_SEARCH;
protected static final ConditionKey CK_ISN = ConditionKey.CK_IS_NULL;
protected static final ConditionKey CK_ISNOE = ConditionKey.CK_IS_NULL_OR_EMPTY;
protected static final ConditionKey CK_ISNN = ConditionKey.CK_IS_NOT_NULL;
/** Object for DUMMY. */
protected static final Object DOBJ = new Object();
/** The property of condition-query. */
protected static final String CQ_PROPERTY = "conditionQuery";
// ===================================================================================
// Attribute
// =========
/** SQL clause. (NotNull) */
protected final SqlClause _sqlClause;
/** My alias name. (NotNull) */
protected final String _aliasName;
/** The nest level of relation. */
protected final int _nestLevel;
/** The level of subQuery. */
protected int _subQueryLevel;
/** The base condition-bean of this query. (NotNull: after setting, basically is set) */
protected ConditionBean _baseCB;
// -----------------------------------------------------
// Foreign Info
// ------------
/** The property name of foreign. */
protected String _foreignPropertyName;
/** The path of relation. */
protected String _relationPath;
/** The referrer query. */
protected final ConditionQuery _referrerQuery;
// -----------------------------------------------------
// Inline
// ------
/** Is this query in the in-line. Basically this query is CIQ class if true */
protected boolean _inline;
/** Is this query in the on-clause. Also inline is true if this is true. */
protected boolean _onClause;
// -----------------------------------------------------
// Relation Keeping
// ----------------
/** The map of query-relation condition-query to keep parameters for parameter comment. */
protected Map _queryRelationKeepingMap;
/** The map of sub-query condition-query to keep parameters for parameter comment. */
protected Map> _subQueryKeepingMap;
/** The map of sub-query parameter to keep parameters for parameter comment. */
protected Map> _subQueryParameterKeepingMap;
/** The map of parameter option for parameter comment. */
protected Map _parameterOptionMap;
// ===================================================================================
// Constructor
// ===========
/**
* @param referrerQuery The instance of referrer query. (NullAllowed: If null, this is base query)
* @param sqlClause The instance of SQL clause. (NotNull)
* @param aliasName The alias name for this query. (NotNull)
* @param nestLevel The nest level of this query. (If zero, this is base query)
*/
public AbstractConditionQuery(ConditionQuery referrerQuery, SqlClause sqlClause, String aliasName, int nestLevel) {
_referrerQuery = referrerQuery;
_sqlClause = sqlClause;
_aliasName = aliasName;
_nestLevel = nestLevel;
}
// *constructor can not be changed so set it up later
public void xsetBaseCB(ConditionBean baseCB) {
_baseCB = baseCB;
}
protected CQ xinitRelCQ(CQ cq, ConditionBean baseCB, String foreignPropertyName,
String nestRelationPath) {
cq.xsetBaseCB(_baseCB);
cq.xsetForeignPropertyName(foreignPropertyName);
cq.xsetRelationPath(nestRelationPath);
return cq;
}
// ===================================================================================
// DBMeta Provider
// ===============
/**
* @return The provider of DB meta. (NotNull)
*/
protected abstract DBMetaProvider xgetDBMetaProvider();
/**
* Find the DB meta by table name flexibly.
* @param tableFlexibleName The table flexible name. (NotNull)
* @return The DB meta of the table. (NotNull)
*/
protected DBMeta findDBMeta(String tableFlexibleName) {
return xgetDBMetaProvider().provideDBMetaChecked(tableFlexibleName);
}
/**
* @return The instance of local DB meta. (NotNull)
*/
protected DBMeta xgetLocalDBMeta() {
return findDBMeta(asTableDbName());
}
// ===================================================================================
// Important Accessor
// ==================
/** {@inheritDoc} */
public ConditionBean xgetBaseCB() {
return _baseCB;
}
/** {@inheritDoc} */
public ConditionQuery xgetBaseQuery() {
ConditionQuery currentQuery = this;
while (true) {
final ConditionQuery referrerQuery = currentQuery.xgetReferrerQuery();
if (referrerQuery == null) {
break;
}
currentQuery = referrerQuery;
}
return currentQuery;
}
/** {@inheritDoc} */
public ConditionQuery xgetReferrerQuery() {
return _referrerQuery;
}
/** {@inheritDoc} */
public SqlClause xgetSqlClause() {
return _sqlClause;
}
/** {@inheritDoc} */
public String xgetAliasName() {
return _aliasName;
}
/** {@inheritDoc} */
public int xgetNestLevel() {
return _nestLevel;
}
/** {@inheritDoc} */
public int xgetNextNestLevel() {
return _nestLevel + 1;
}
protected int xgetNNLvl() { // for generated source
return xgetNextNestLevel();
}
/** {@inheritDoc} */
public boolean isBaseQuery() {
return (xgetReferrerQuery() == null);
}
// -----------------------------------------------------
// Real Name
// ---------
/** {@inheritDoc} */
public ColumnRealName toColumnRealName(String columnDbName) { // with finding DBMeta
return ColumnRealName.create(xgetAliasName(), toColumnSqlName(columnDbName));
}
/** {@inheritDoc} */
public ColumnRealName toColumnRealName(ColumnInfo columnInfo) { // without finding DBMeta
return ColumnRealName.create(xgetAliasName(), columnInfo.getColumnSqlName());
}
/** {@inheritDoc} */
public ColumnSqlName toColumnSqlName(String columnDbName) { // with finding DBMeta
return xgetLocalDBMeta().findColumnInfo(columnDbName).getColumnSqlName();
}
// -----------------------------------------------------
// Foreign Info
// ------------
/** {@inheritDoc} */
public String xgetForeignPropertyName() {
return _foreignPropertyName;
}
public void xsetForeignPropertyName(String foreignPropertyName) {
this._foreignPropertyName = foreignPropertyName;
}
/** {@inheritDoc} */
public String xgetRelationPath() {
return _relationPath;
}
public void xsetRelationPath(String relationPath) {
this._relationPath = relationPath;
}
// -----------------------------------------------------
// Inline
// ------
// added to confirm internal state so no interface method for now by jflute (2023/07/16)
public boolean xisInline() { // since 1.2.7
return _inline;
}
public boolean xisOnClause() { // since 1.2.7
return _onClause;
}
public void xsetOnClause(boolean onClause) {
_onClause = onClause;
}
// -----------------------------------------------------
// Location
// --------
/** {@inheritDoc} */
public String xgetLocationBase() {
final StringBuilder sb = new StringBuilder();
ConditionQuery query = this;
while (true) {
if (query.isBaseQuery()) {
sb.insert(0, CQ_PROPERTY + ".");
break;
} else {
final String foreignPropertyName = query.xgetForeignPropertyName();
if (foreignPropertyName == null) {
String msg = "The foreignPropertyName of the query should not be null:";
msg = msg + " query=" + query;
throw new IllegalStateException(msg);
}
sb.insert(0, CQ_PROPERTY + initCap(foreignPropertyName) + ".");
}
query = query.xgetReferrerQuery();
}
return sb.toString();
}
/**
* Get the location of the property.
* @param propertyName The name of property. (NotNull)
* @return The location of the property as path. (NotNull)
*/
protected String xgetLocation(String propertyName) {
return xgetLocationBase() + propertyName;
}
// ===================================================================================
// Nested SetupSelect
// ==================
public void xdoNss(NssCall callback) { // very internal
final String foreignPropertyName = callback.qf().xgetForeignPropertyName();
final String foreignTableAliasName = callback.qf().xgetAliasName();
final String localRelationPath = xgetRelationPath();
final String foreignRelationPath = callback.qf().xgetRelationPath();
xgetSqlClause().registerSelectedRelation(foreignTableAliasName, asTableDbName(), foreignPropertyName, localRelationPath,
foreignRelationPath);
}
@FunctionalInterface
public static interface NssCall { // very internal
public ConditionQuery qf();
}
// ===================================================================================
// Outer Join
// ==========
/**
* Register outer-join.
* Optional info, fixed condition and fixed in-line, are resolved in this method.
* @param foreignCQ The condition-query for foreign table. (NotNull)
* @param joinOnResourceMap The resource map of join condition on on-clause. (NotNull)
* @param foreignPropertyName The property name of foreign relation corresponding to this join. (NotNull)
*/
protected void registerOuterJoin(ConditionQuery foreignCQ, Map joinOnResourceMap, String foreignPropertyName) {
final DBMeta dbmeta = xgetLocalDBMeta();
final ForeignInfo foreignInfo = dbmeta.findForeignInfo(foreignPropertyName);
doRegisterOuterJoin(foreignCQ, joinOnResourceMap, foreignPropertyName, foreignInfo);
}
protected void doRegisterOuterJoin(ConditionQuery foreignCQ, Map joinOnResourceMap, final String foreignPropertyName,
ForeignInfo foreignInfo) {
// translate join-on map using column real name
final Map joinOnMap = newLinkedHashMap();
for (Entry entry : joinOnResourceMap.entrySet()) {
final String local = entry.getKey();
final String foreign = entry.getValue();
joinOnMap.put(toColumnRealName(local), foreignCQ.toColumnRealName(foreign));
}
final String foreignAlias = foreignCQ.xgetAliasName();
final String foreignTable = foreignCQ.asTableDbName();
final String localAlias = xgetAliasName();
final String localTable = asTableDbName();
final String fixedCondition = foreignInfo.getFixedCondition();
final boolean fixedInline = foreignInfo.isFixedInline();
final FixedConditionResolver resolver = createForeignFixedConditionResolver(foreignCQ);
final String relationPath = foreignCQ.xgetRelationPath();
if (fixedInline) {
xgetSqlClause().registerOuterJoinFixedInline(foreignAlias, foreignTable, localAlias, localTable // basic
, joinOnMap, relationPath, foreignInfo // join objects
, fixedCondition, resolver); // fixed condition (to in-line view)
} else { // normally here
xgetSqlClause().registerOuterJoin(foreignAlias, foreignTable, localAlias, localTable // basic
, joinOnMap, relationPath, foreignInfo // join objects
, fixedCondition, resolver); // fixed condition (to on-clause)
}
xprepareFixedConditionDynamicParameterLazyChecker(foreignPropertyName, foreignInfo);
}
protected FixedConditionResolver createForeignFixedConditionResolver(ConditionQuery foreignCQ) {
return newFixedConditionResolver(this, foreignCQ, xgetDBMetaProvider());
}
protected FixedConditionResolver newFixedConditionResolver(ConditionQuery localCQ, ConditionQuery foreignCQ,
DBMetaProvider dbmetaProvider) {
return new HpFixedConditionQueryResolver(localCQ, foreignCQ, dbmetaProvider);
}
protected void xprepareFixedConditionDynamicParameterLazyChecker(final String foreignPropertyName, final ForeignInfo foreignInfo) {
if (!foreignInfo.hasFixedConditionDynamicParameter()) {
return;
}
// lazy check because the following code is allowed:
// e.g. ColumnQuery
// cb.columnQuery(new ... {
// }).lessThan(new ... {
// cb.specify().specifyMemberAddressAsValid()... // no dynamic parameter
// });
xgetSqlClause().registerFixedConditionLazyChecker(new FixedConditionLazyChecker() {
public void check() {
xcalbackAssertFixedConditionDynamicParameter(foreignPropertyName, foreignInfo);
}
});
}
protected void xcalbackAssertFixedConditionDynamicParameter(String foreignPropertyName, ForeignInfo foreignInfo) {
// cannot get dynamic parameter map directly in super classes of runtime
// and does not want to add inner class in generated classes,
// so this way...as a last-ditch measure
final Map parameterMap = xfindFixedConditionDynamicParameterMap(foreignPropertyName);
xdoAssertFixedConditionDynamicParameter(foreignPropertyName, foreignInfo, parameterMap);
}
protected abstract Map xfindFixedConditionDynamicParameterMap(String property);
protected void xassertFCDP(String property, Map parameterMap) { // assertFixedConditionDynamicParameter()
final ForeignInfo foreignInfo = xgetLocalDBMeta().findForeignInfo(property);
xdoAssertFixedConditionDynamicParameter(property, foreignInfo, parameterMap);
}
protected void xdoAssertFixedConditionDynamicParameter(String property, ForeignInfo foreignInfo, Map parameterMap) {
if (foreignInfo.isFixedConditionDynamicParameterRequired()) { // required check
boolean notFound = false;
if (parameterMap != null) {
for (Object value : parameterMap.values()) {
if (value == null) {
notFound = true;
break;
}
}
} else { // null treated as not found
notFound = true;
}
if (notFound) {
final String tableDbName = asTableDbName();
final String fixedCondition = foreignInfo.getFixedCondition();
createCBExThrower().throwFixedConditionParameterNotFoundException(tableDbName, property, fixedCondition, parameterMap);
}
}
}
// ===================================================================================
// Union Query
// ===========
/** The map parameter-bean of union query. */
protected SimpleMapPmb _unionQueryMap;
/**
* Get the map parameter-bean of union query. (for parameter comment) {Internal}
* @return The instance of map parameter-bean. (NotNull)
*/
public SimpleMapPmb xdfgetInternalUnionQueryMap() {
if (_unionQueryMap == null) {
_unionQueryMap = xcreateUnionMapPmb();
}
return _unionQueryMap;
}
/**
* Set union query. {Internal}
* @param unionQuery Union query. (NotNull)
*/
public void xsetUnionQuery(ConditionQuery unionQuery) {
xsetupUnion(unionQuery, false, xdfgetInternalUnionQueryMap());
}
/** The map parameter-bean of union all query. */
protected SimpleMapPmb _unionAllQueryMap;
/**
* Get the map parameter-bean of union all query. (for parameter comment) {Internal}
* @return The instance of map parameter-bean. (NotNull)
*/
public SimpleMapPmb xdfgetInternalUnionAllQueryMap() {
if (_unionAllQueryMap == null) {
_unionAllQueryMap = xcreateUnionMapPmb();
}
return _unionAllQueryMap;
}
protected SimpleMapPmb xcreateUnionMapPmb() {
return new SimpleMapPmb();
}
/**
* Set union all query. {Internal}
* @param unionAllQuery Union all query. (NotNull)
*/
public void xsetUnionAllQuery(ConditionQuery unionAllQuery) {
xsetupUnion(unionAllQuery, true, xdfgetInternalUnionAllQueryMap());
}
protected void xsetupUnion(final ConditionQuery unionQuery, boolean unionAll, SimpleMapPmb unionQueryMap) {
if (unionQuery == null) {
String msg = "The argument 'unionQuery' should not be null.";
throw new IllegalArgumentException(msg);
}
// needs to reflect lazily for:
// o SetupSelect(Relation) after Union (however, basically they should be called before union)
// o ManualOrder with Dream Cruise using Specify(Relation) after Union
final ConditionQuery selfCQ = this;
xgetSqlClause().registerClauseLazyReflector(() -> {
reflectRelationOnUnionQuery(selfCQ, unionQuery);
});
final String key = (unionAll ? "unionAllQuery" : "unionQuery") + unionQueryMap.size();
unionQueryMap.addParameter(key, unionQuery);
final String propName = "internalUnion" + (unionAll ? "All" : "") + "QueryMap." + key;
registerUnionQuery(unionQuery, unionAll, propName);
}
/**
* Reflect relation on union query.
* @param baseQueryAsSuper Base query as super. (NotNull)
* @param unionQueryAsSuper Union query as super. (NotNull)
*/
protected abstract void reflectRelationOnUnionQuery(ConditionQuery baseQueryAsSuper, ConditionQuery unionQueryAsSuper);
/**
* Has union query or union all query?
* @return The determination, true or false.
*/
public boolean hasUnionQueryOrUnionAllQuery() {
return (_unionQueryMap != null && !_unionQueryMap.isEmpty()) || (_unionAllQueryMap != null && !_unionAllQueryMap.isEmpty());
}
// ===================================================================================
// Normal Query
// ============
protected void regQ(ConditionKey key, Object value, ConditionValue cvalue, String columnDbName) {
if (prepareQueryChecked(key, value, cvalue, columnDbName).newClause()) {
setupConditionValueAndRegisterWhereClause(key, value, cvalue, columnDbName);
}
}
protected void regQ(ConditionKey key, Object value, ConditionValue cvalue, String columnDbName, ConditionOption option) {
if (prepareQueryChecked(key, value, cvalue, columnDbName).newClause()) {
setupConditionValueAndRegisterWhereClause(key, value, cvalue, columnDbName, option);
}
}
/**
* @param key The condition key for the query. (NotNull)
* @param value The value of the condition. (NotNull)
* @param cvalue The object of condition value to keep the value. (NotNull)
* @param columnDbName The DB name of column for the query. (NotNull)
* @return The result of the preparation for the condition key. (NotNull)
*/
protected ConditionKeyPrepareResult prepareQueryChecked(ConditionKey key, Object value, ConditionValue cvalue, String columnDbName) {
return xdoPrepareQuery(key, value, cvalue, columnDbName, /*invalidChecked*/true);
}
/**
* @param key The condition key for the query. (NotNull)
* @param value The value of the condition. (NotNull)
* @param cvalue The object of condition value to keep the value. (NotNull)
* @param columnDbName The DB name of column for the query. (NotNull)
* @return The result of the preparation for the condition key. (NotNull)
*/
protected ConditionKeyPrepareResult prepareQueryNoCheck(ConditionKey key, Object value, ConditionValue cvalue, String columnDbName) {
return xdoPrepareQuery(key, value, cvalue, columnDbName, /*invalidChecked*/false);
}
protected ConditionKeyPrepareResult xdoPrepareQuery(ConditionKey key, Object value, ConditionValue cvalue, String columnDbName,
boolean invalidChecked) {
final ConditionKeyPrepareResult result = key.prepareQuery(xcreateQueryModeProvider(), cvalue, value);
if (result.overridden()) {
handleOverridingQuery(key, value, cvalue, columnDbName);
}
if (result.duplicate()) {
noticeRegistered(key, value, cvalue, columnDbName);
}
if (invalidChecked && result.invalid()) {
handleInvalidQuery(key, value, cvalue, columnDbName);
}
return result;
}
// ===================================================================================
// Overriding Query
// ================
protected void handleOverridingQuery(ConditionKey key, Object value, ConditionValue cvalue, String columnDbName) {
if (isOverrideQueryAllowed(key, value, cvalue, columnDbName)) {
if (xgetSqlClause().isInvalidQueryAllowedWarning()) { // since 1.2.7
showOverridingQueryAllowedWarning(xgetBaseCB(), key, value, cvalue, columnDbName);
}
return;
}
throwQueryAlreadyRegisteredException(key, value, cvalue, columnDbName);
}
protected boolean isOverrideQueryAllowed(ConditionKey key, Object value, ConditionValue cvalue, String columnDbName) {
return xgetSqlClause().isOverridingQueryAllowed();
}
protected void noticeRegistered(ConditionKey key, Object value, ConditionValue cvalue, String columnDbName) {
if (_log.isDebugEnabled()) {
_log.debug("*Found the duplicate query: target=" + columnDbName + "." + key + ", value=" + value);
}
}
// ===================================================================================
// Invalid Query
// =============
protected void handleInvalidQuery(ConditionKey key, Object value, ConditionValue cvalue, String columnDbName) {
final HpInvalidQueryInfo invalidQueryInfo = xcreateInvalidQueryInfo(key, value, columnDbName);
xdoHandleInvalidQuery(columnDbName, invalidQueryInfo);
}
protected void handleInvalidQueryList(List keyList, List extends Object> valueList, String columnDbName) {
if (keyList.size() != valueList.size()) {
String msg = "The argument 'keyList' should have the same size as 'valueList':";
msg = msg + " keyList=" + keyList + ", valueList=" + valueList;
throw new IllegalArgumentException(msg);
}
final HpInvalidQueryInfo[] invalidQueryInfoAry = new HpInvalidQueryInfo[keyList.size()];
int index = 0;
for (ConditionKey key : keyList) {
final Object value = valueList.get(index);
invalidQueryInfoAry[index] = xcreateInvalidQueryInfo(key, value, columnDbName);
++index;
}
xdoHandleInvalidQuery(columnDbName, invalidQueryInfoAry);
}
protected void xdoHandleInvalidQuery(String columnDbName, HpInvalidQueryInfo... invalidQueryInfoAry) {
if (xgetSqlClause().isNullOrEmptyQueryChecked()) {
throwInvalidQueryRegisteredException(invalidQueryInfoAry);
} else {
if (xgetSqlClause().isInvalidQueryAllowedWarning()) { // since 1.2.7
showNullOrEmptyQueryAllowedWarning(xgetBaseCB(), invalidQueryInfoAry);
}
for (HpInvalidQueryInfo invalidQueryInfo : invalidQueryInfoAry) {
xgetSqlClause().saveInvalidQuery(invalidQueryInfo);
}
}
}
protected HpInvalidQueryInfo xcreateInvalidQueryInfo(ConditionKey key, Object value, String columnDbName) {
final String locationBase = xgetLocationBase();
final ColumnInfo targetColumn = xgetLocalDBMeta().findColumnInfo(columnDbName);
final HpInvalidQueryInfo invalidQueryInfo = new HpInvalidQueryInfo(locationBase, targetColumn, key, value);
if (_inline) {
invalidQueryInfo.inlineView();
}
if (_onClause) { // also inline is true
invalidQueryInfo.onClause();
}
return invalidQueryInfo;
}
protected QueryModeProvider xcreateQueryModeProvider() {
return new QueryModeProvider() {
public boolean isOrScopeQuery() {
return xgetSqlClause().isOrScopeQueryEffective();
}
public boolean isInline() {
return _inline;
}
public boolean isOnClause() {
return _onClause;
}
};
}
protected void throwQueryAlreadyRegisteredException(ConditionKey key, Object value, ConditionValue cvalue, String columnDbName) {
createCBExThrower().throwQueryAlreadyRegisteredException(key, value, cvalue, columnDbName);
}
public void showOverridingQueryAllowedWarning(ConditionBean baseCB, ConditionKey key, Object value, ConditionValue cvalue,
String columnDbName) { // since 1.2.7
createCBExThrower().showOverridingQueryAllowedWarning(baseCB, key, value, cvalue, columnDbName);
}
protected void throwInvalidQueryRegisteredException(HpInvalidQueryInfo... invalidQueryInfoAry) {
createCBExThrower().throwInvalidQueryRegisteredException(invalidQueryInfoAry);
}
public void showNullOrEmptyQueryAllowedWarning(ConditionBean baseCB, HpInvalidQueryInfo... invalidQueryInfoAry) { // since 1.2.7
createCBExThrower().showNullOrEmptyQueryAllowedWarning(baseCB, invalidQueryInfoAry);
}
// ===================================================================================
// LikeSearch Query
// ================
protected void regLSQ(ConditionKey key, String value, ConditionValue cvalue, String columnDbName, LikeSearchOption option) {
registerLikeSearchQuery(key, value, cvalue, columnDbName, option);
}
protected void registerLikeSearchQuery(ConditionKey key, String value, ConditionValue cvalue, String columnDbName,
LikeSearchOption option) {
if (option == null) {
throwLikeSearchOptionNotFoundException(columnDbName, value);
return; // unreachable
}
if (!prepareQueryChecked(key, value, cvalue, columnDbName).newClause()) {
return;
}
if (xsuppressEscape()) {
option.notEscape();
}
// basically for DBMS that has original wild-cards
xgetSqlClause().adjustLikeSearchDBWay(option);
if (value == null || !option.isSplit()) {
if (option.canOptimizeCompoundColumnLikePrefix()) {
// - - - - - - - - - -
// optimized compound
// - - - - - - - - - -
doRegisterLikeSearchQueryCompoundOptimized(value, cvalue, columnDbName, option);
} else {
// - - - - - - - - - - - - -
// normal or normal compound
// - - - - - - - - - - - - -
setupConditionValueAndRegisterWhereClause(key, value, cvalue, columnDbName, option);
}
return;
}
// - - - - - - -
// splitByXxx()
// - - - - - - -
doRegisterLikeSearchQuerySplitBy(key, value, cvalue, columnDbName, option);
}
protected void doRegisterLikeSearchQueryCompoundOptimized(String value, ConditionValue cvalue, String columnDbName,
LikeSearchOption option) {
if (!option.isLikePrefix()) {
String msg = "This optimization is only for LikePrefix: " + option;
throw new IllegalStateException(msg);
}
// *char type only but no checked (cannot check)
final List compoundColumnList = option.getCompoundColumnList();
final List sizeList = option.getCompoundColumnSizeList();
String currentValue = value;
int currentLength = value.length();
String currentColumn = columnDbName;
final boolean needsAndPart = isOrScopeQueryDirectlyUnder();
if (needsAndPart) {
xgetSqlClause().beginOrScopeQueryAndPart();
}
try {
boolean shortLengthBreak = false;
final Iterator compoundColumnIterator = compoundColumnList.iterator();
for (Integer columnSize : sizeList) { // should be less or equal column count (checked in option)
if (currentLength >= columnSize) { // can treat current condition as equal
final String equalValue = currentValue.substring(0, columnSize);
invokeQueryEqual(currentColumn, equalValue);
currentValue = currentValue.substring(columnSize);
currentLength = currentValue.length();
final SpecifiedColumn specifiedColumn;
if (compoundColumnIterator.hasNext()) {
specifiedColumn = compoundColumnIterator.next();
currentColumn = specifiedColumn.getColumnDbName();
} else { // means just size
currentColumn = null; // means end
break; // though basically no need to break because of size loop end
}
} else { // short length condition value
shortLengthBreak = true;
break;
}
}
if (currentValue.length() > 0 && currentColumn != null) { // double check
final LikeSearchOption copyOption = option.createDeepCopy();
copyOption.clearCompoundColumn(); // also fixed sizes cleared
if (!shortLengthBreak) {
while (compoundColumnIterator.hasNext()) {
copyOption.addCompoundColumn(compoundColumnIterator.next());
}
}
invokeQueryLikeSearch(currentColumn, currentValue, copyOption);
}
} finally {
if (needsAndPart) {
xgetSqlClause().endOrScopeQueryAndPart();
}
}
}
protected void doRegisterLikeSearchQuerySplitBy(ConditionKey key, String value, ConditionValue cvalue, String columnDbName,
LikeSearchOption option) {
assertObjectNotNull("option(LikeSearchOption)", option);
// these values should be valid only (already filtered before)
// and invalid values are ignored even at the check mode
// but if all elements are invalid, it is an exception
final String[] strArray = option.generateSplitValueArray(value);
if (strArray.length == 0) {
handleInvalidQuery(key, value, cvalue, columnDbName);
return;
}
if (!option.isAsOrSplit()) {
// as 'and' condition
final boolean needsAndPart = isOrScopeQueryDirectlyUnder();
if (needsAndPart) {
xgetSqlClause().beginOrScopeQueryAndPart();
}
try {
for (int i = 0; i < strArray.length; i++) {
final String currentValue = strArray[i];
setupConditionValueAndRegisterWhereClause(key, currentValue, cvalue, columnDbName, option);
}
} finally {
if (needsAndPart) {
xgetSqlClause().endOrScopeQueryAndPart();
}
}
} else {
// as 'or' condition
if (isOrScopeQueryAndPartEffective()) {
// limit because of so complex
String msg = "The AsOrSplit in and-part is unsupported: " + asTableDbName();
throw new OrScopeQueryAndPartUnsupportedOperationException(msg);
}
final boolean needsNewOrScope = !isOrScopeQueryEffective();
if (needsNewOrScope) {
xgetSqlClause().beginOrScopeQuery();
}
try {
for (int i = 0; i < strArray.length; i++) {
final String currentValue = strArray[i];
if (i == 0) {
setupConditionValueAndRegisterWhereClause(key, currentValue, cvalue, columnDbName, option);
} else {
invokeQueryLikeSearch(columnDbName, currentValue, option);
}
}
} finally {
if (needsNewOrScope) {
xgetSqlClause().endOrScopeQuery();
}
}
}
}
protected void throwLikeSearchOptionNotFoundException(String columnDbName, String value) {
final DBMeta dbmeta = xgetDBMetaProvider().provideDBMeta(asTableDbName());
createCBExThrower().throwLikeSearchOptionNotFoundException(columnDbName, value, dbmeta);
}
protected boolean xsuppressEscape() { // for override
return false; // as default
}
protected void invokeQueryLikeSearch(String columnFlexibleName, Object value, LikeSearchOption option) {
invokeQuery(columnFlexibleName, "likeSearch", value, option);
}
protected boolean isOrScopeQueryDirectlyUnder() {
final boolean orScopeQuery = isOrScopeQueryEffective();
final boolean orScopeQueryAndPart = isOrScopeQueryAndPartEffective();
return orScopeQuery && !orScopeQueryAndPart;
}
protected boolean isOrScopeQueryEffective() {
return xgetSqlClause().isOrScopeQueryEffective();
}
protected boolean isOrScopeQueryAndPartEffective() {
return xgetSqlClause().isOrScopeQueryAndPartEffective();
}
// ===================================================================================
// FromTo Query
// ============
protected void regFTQ(Date fromDate, Date toDate, ConditionValue cvalue, String columnDbName, FromToOption option) {
assertObjectNotNull("option(FromToOption)", option);
filterFromToOption(columnDbName, option); // for fixed option
// this FromTo process is very similar to RangeOf process
final Date filteredFromDate = option.filterFromDate(fromDate);
final ConditionKey fromKey = option.getFromDateConditionKey();
final ConditionKeyPrepareResult fromResult = prepareQueryNoCheck(fromKey, filteredFromDate, cvalue, columnDbName);
final Date filteredToDate = option.filterToDate(toDate);
final ConditionKey toKey = option.getToDateConditionKey();
final ConditionKeyPrepareResult toResult = prepareQueryNoCheck(toKey, filteredToDate, cvalue, columnDbName);
final boolean needsAndPart = isOrScopeQueryDirectlyUnder() && fromResult.newClause() && toResult.newClause();
if (needsAndPart) {
xgetSqlClause().beginOrScopeQueryAndPart();
}
try {
if (fromResult.newClause()) {
final Object registered = filterFromToRegisteredDate(option, filteredFromDate, columnDbName);
setupConditionValueAndRegisterWhereClause(fromKey, registered, cvalue, columnDbName);
}
if (toResult.newClause()) {
final Object registered = filterFromToRegisteredDate(option, filteredToDate, columnDbName);
setupConditionValueAndRegisterWhereClause(toKey, registered, cvalue, columnDbName);
}
if (fromResult.invalid() && toResult.invalid()) {
xhandleFromToBothSideInvalidQuery(fromDate, toDate, columnDbName, option, fromKey, toKey);
} else if (fromResult.invalid() || toResult.invalid()) {
xhandleFromToOneSideInvalidQuery(fromDate, toDate, columnDbName, option, fromKey, toKey);
}
} finally {
if (needsAndPart) {
xgetSqlClause().endOrScopeQueryAndPart();
}
}
}
protected void filterFromToOption(String columnDbName, FromToOption option) {
// do nothing as default, basically for option default
}
protected void xhandleFromToOneSideInvalidQuery(Date fromDate, Date toDate, String columnDbName, FromToOption option,
ConditionKey fromKey, ConditionKey toKey) {
if (!option.isOneSideAllowed()) { // not allowed (if both required)
xdoHandleFromToInvalidQuery(fromDate, toDate, columnDbName, option, fromKey, toKey);
}
}
protected void xhandleFromToBothSideInvalidQuery(Date fromDate, Date toDate, String columnDbName, FromToOption option,
ConditionKey fromKey, ConditionKey toKey) {
xdoHandleFromToInvalidQuery(fromDate, toDate, columnDbName, option, fromKey, toKey);
}
protected void xdoHandleFromToInvalidQuery(Date fromDate, Date toDate, String columnDbName, FromToOption option, ConditionKey fromKey,
ConditionKey toKey) {
final List keyList = newArrayList(fromKey, toKey);
final List valueList = newArrayList(fromDate, toDate);
handleInvalidQueryList(keyList, valueList, columnDbName);
}
// -----------------------------------------------------
// from LocalDate
// --------------
// for conversion
protected Date xfFTHD(Object date, String columnDbName, FromToOption option) { // filterFromToHandlingDate()
final ColumnInfo columnInfo = xgetLocalDBMeta().findColumnInfo(columnDbName);
if (xisNextTimeLocalDate(columnInfo.getObjectNativeType())) {
return xtoFromToUtilDate(date, columnDbName, option);
} else if (xisNextTimeLocalDateTime(columnInfo.getObjectNativeType())) {
return xtoFromToTimestamp(date, columnDbName, option);
}
return xtoFromToUtilDate(date, columnDbName, option); // basically no way (generator controls it)
}
protected Date xtoFromToUtilDate(Object date, String columnDbName, FromToOption option) {
final TimeZone realZone = xchooseFromToRealTimeZone(columnDbName, option);
return DfTypeUtil.toDate(date, realZone);
}
protected Timestamp xtoFromToTimestamp(Object date, String columnDbName, FromToOption option) {
final TimeZone realZone = xchooseFromToRealTimeZone(columnDbName, option);
return DfTypeUtil.toTimestamp(date, realZone);
}
// -----------------------------------------------------
// to LocalDate
// ------------
protected Object filterFromToRegisteredDate(FromToOption option, Date date, String columnDbName) {
final ColumnInfo columnInfo = xgetLocalDBMeta().findColumnInfo(columnDbName);
if (xisNextTimeLocalDate(columnInfo.getObjectNativeType())) {
return xtoFromToLocalDate(date, columnDbName, option);
} else if (xisNextTimeLocalDateTime(columnInfo.getObjectNativeType())) {
return xtoFromToLocalDateTime(date, columnDbName, option);
}
return date;
}
protected Object xtoFromToLocalDate(Object date, String columnDbName, FromToOption option) { // #date_parade
final TimeZone realZone = xchooseFromToRealTimeZone(columnDbName, option);
return DfTypeUtil.toLocalDate(date, realZone);
}
protected Object xtoFromToLocalDateTime(Object date, String columnDbName, FromToOption option) {
final TimeZone realZone = xchooseFromToRealTimeZone(columnDbName, option);
return DfTypeUtil.toLocalDateTime(date, realZone);
}
// -----------------------------------------------------
// LocalDate Assist
// ----------------
protected boolean xisNextTimeLocalDate(Class> nativeType) {
return LocalDate.class.isAssignableFrom(nativeType);
}
protected boolean xisNextTimeLocalDateTime(Class> nativeType) {
return LocalDateTime.class.isAssignableFrom(nativeType);
}
protected TimeZone xchooseFromToRealTimeZone(String columnDbName, FromToOption option) {
final TimeZone opZone = option.getTimeZone();
return opZone != null ? opZone : xgetFromToConversionTimeZone(columnDbName);
}
protected TimeZone xgetFromToConversionTimeZone(String columnDbName) {
return getDBFluteSystemFinalTimeZone();
}
// ===================================================================================
// RangeOf Query
// =============
protected void regROO(Number minNumber, Number maxNumber, ConditionValue cvalue, String columnDbName, RangeOfOption option) {
assertObjectNotNull("option(RangeOfOption)", option);
if (option.hasCalculationRange()) {
final ConditionBean dreamCruiseCB = xgetBaseCB().xcreateDreamCruiseCB();
option.xinitCalculationRange(xgetBaseCB(), dreamCruiseCB);
}
// this RangeOf process is very similar to FromTo process
final ConditionKey minKey = option.getMinNumberConditionKey();
final ConditionKeyPrepareResult minResult = prepareQueryNoCheck(minKey, minNumber, cvalue, columnDbName);
final ConditionKey maxKey = option.getMaxNumberConditionKey();
final ConditionKeyPrepareResult maxResult = prepareQueryNoCheck(maxKey, maxNumber, cvalue, columnDbName);
final boolean needsAndPart = isOrScopeQueryDirectlyUnder() && minResult.newClause() && maxResult.newClause();
if (needsAndPart) {
xgetSqlClause().beginOrScopeQueryAndPart();
}
try {
if (minResult.newClause()) {
setupConditionValueAndRegisterWhereClause(minKey, minNumber, cvalue, columnDbName, option);
}
if (maxResult.newClause()) {
setupConditionValueAndRegisterWhereClause(maxKey, maxNumber, cvalue, columnDbName, option);
}
if (minResult.invalid() && maxResult.invalid()) {
xhandleRangeOfBothSideInvalidQuery(minNumber, maxNumber, columnDbName, option, minKey, maxKey);
} else if (minResult.invalid() || maxResult.invalid()) {
xhandleRangeOfOneSideInvalidQuery(minNumber, maxNumber, columnDbName, option, minKey, maxKey);
}
} finally {
if (needsAndPart) {
xgetSqlClause().endOrScopeQueryAndPart();
}
}
}
protected void xhandleRangeOfOneSideInvalidQuery(Number minNumber, Number maxNumber, String columnDbName, RangeOfOption option,
ConditionKey fromKey, ConditionKey toKey) {
if (!option.isOneSideAllowed()) { // not allowed (if both required)
xdoHandleRangeOfInvalidQuery(minNumber, maxNumber, columnDbName, option, fromKey, toKey);
}
}
protected void xhandleRangeOfBothSideInvalidQuery(Number minNumber, Number maxNumber, String columnDbName, RangeOfOption option,
ConditionKey fromKey, ConditionKey toKey) {
xdoHandleRangeOfInvalidQuery(minNumber, maxNumber, columnDbName, option, fromKey, toKey);
}
protected void xdoHandleRangeOfInvalidQuery(Number minNumber, Number maxNumber, String columnDbName, RangeOfOption option,
ConditionKey fromKey, ConditionKey toKey) {
final List keyList = newArrayList(fromKey, toKey);
final List valueList = newArrayList(minNumber, maxNumber);
handleInvalidQueryList(keyList, valueList, columnDbName);
}
// ===================================================================================
// InScope Query
// =============
protected void regINS(ConditionKey key, List> value, ConditionValue cvalue, String columnDbName) {
if (!prepareQueryChecked(key, value, cvalue, columnDbName).newClause()) {
return;
}
final int inScopeLimit = xgetSqlClause().getInScopeLimit();
if (inScopeLimit > 0 && value.size() > inScopeLimit) {
// if the key is for inScope, it should be split as 'or'
// (if the key is for notInScope, it should be split as 'and')
final boolean orScopeQuery = xgetSqlClause().isOrScopeQueryEffective();
final boolean orScopeQueryAndPart = xgetSqlClause().isOrScopeQueryAndPartEffective();
final boolean needsAndPart = orScopeQuery && !orScopeQueryAndPart;
if (isConditionKeyInScope(key)) {
// if or-scope query has already been effective, create new or-scope
xgetSqlClause().beginOrScopeQuery();
} else {
if (needsAndPart) {
xgetSqlClause().beginOrScopeQueryAndPart();
}
}
try {
// split the condition
@SuppressWarnings("unchecked")
final List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy