use of org.jooq.Context in project jOOQ by jOOQ.
the class RowCondition method accept.
@Override
public final void accept(Context<?> ctx) {
// Regular comparison predicate emulation
if ((comparator == EQUALS || comparator == NOT_EQUALS) && (forceEmulation || EMULATE_EQ_AND_NE.contains(ctx.dialect()))) {
Field<?>[] rightFields = right.fields();
Condition result = DSL.and(map(left.fields(), (f, i) -> f.equal((Field) rightFields[i])));
if (comparator == NOT_EQUALS)
result = result.not();
ctx.visit(result);
} else // Ordering comparison predicate emulation
if ((comparator == GREATER || comparator == GREATER_OR_EQUAL || comparator == LESS || comparator == LESS_OR_EQUAL) && (forceEmulation || EMULATE_RANGES.contains(ctx.dialect()))) {
// The order component of the comparator (stripping the equal component)
Comparator order = (comparator == GREATER) ? GREATER : (comparator == GREATER_OR_EQUAL) ? GREATER : (comparator == LESS) ? LESS : (comparator == LESS_OR_EQUAL) ? LESS : null;
// [#2658] The factored order component of the comparator (enforcing the equal component)
Comparator factoredOrder = (comparator == GREATER) ? GREATER_OR_EQUAL : (comparator == GREATER_OR_EQUAL) ? GREATER_OR_EQUAL : (comparator == LESS) ? LESS_OR_EQUAL : (comparator == LESS_OR_EQUAL) ? LESS_OR_EQUAL : null;
// Whether the comparator has an equal component
boolean equal = (comparator == GREATER_OR_EQUAL) || (comparator == LESS_OR_EQUAL);
Field<?>[] leftFields = left.fields();
Field<?>[] rightFields = right.fields();
// The following algorithm emulates the equivalency of these expressions:
// (A, B, C) > (X, Y, Z)
// (A > X) OR (A = X AND B > Y) OR (A = X AND B = Y AND C > Z)
List<Condition> outer = new ArrayList<>(1 + leftFields.length);
for (int i = 0; i < leftFields.length; i++) {
List<Condition> inner = new ArrayList<>(1 + i);
for (int j = 0; j < i; j++) inner.add(leftFields[j].equal((Field) rightFields[j]));
inner.add(leftFields[i].compare(equal && i == leftFields.length - 1 ? comparator : order, (Field) rightFields[i]));
outer.add(DSL.and(inner));
}
Condition result = DSL.or(outer);
// (A >= X) AND ((A > X) OR (A = X AND B > Y) OR (A = X AND B = Y AND C > Z))
if (leftFields.length > 1)
result = leftFields[0].compare(factoredOrder, (Field) rightFields[0]).and(result);
ctx.visit(result);
} else {
// Some dialects do not support != comparison with rows
{
// Some databases need extra parentheses around the RHS
boolean extraParentheses = false;
ctx.visit(left).sql(' ').sql(comparator.toSQL()).sql(' ').sql(extraParentheses ? "(" : "").visit(right).sql(extraParentheses ? ")" : "");
}
}
}
use of org.jooq.Context in project jOOQ by jOOQ.
the class DefaultParseContext method parseTerm.
private final FieldOrRow parseTerm() {
FieldOrRow field;
Object value;
switch(characterUpper()) {
// [#8821] Known prefixes so far:
case ':':
case '@':
case '?':
if ((field = parseBindVariableIf()) != null)
return field;
break;
case '\'':
return inline(parseStringLiteral());
case '$':
if ((field = parseBindVariableIf()) != null)
return field;
else if ((value = parseDollarQuotedStringLiteralIf()) != null)
return inline((String) value);
break;
case 'A':
if (parseFunctionNameIf("ABS"))
return abs((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("ASC", "ASCII", "ASCII_VAL"))
return ascii((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("ACOS"))
return acos((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("ASIN"))
return asin((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("ATAN", "ATN"))
return atan((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("ATN2", "ATAN2"))
return parseFunctionArgs2(() -> toField(parseNumericOp()), DSL::atan2);
else if (parseFunctionNameIf("ASCII_CHAR"))
return chr((Field) parseFieldParenthesised());
else if ((field = parseArrayValueConstructorIf()) != null)
return field;
else if (parseFunctionNameIf("ADD_YEARS"))
return parseFieldAddDatePart(YEAR);
else if (parseFunctionNameIf("ADD_MONTHS"))
return parseFieldAddDatePart(MONTH);
else if (parseFunctionNameIf("ADD_DAYS"))
return parseFieldAddDatePart(DAY);
else if (parseFunctionNameIf("ADD_HOURS"))
return parseFieldAddDatePart(HOUR);
else if (parseFunctionNameIf("ADD_MINUTES"))
return parseFieldAddDatePart(MINUTE);
else if (parseFunctionNameIf("ADD_SECONDS"))
return parseFieldAddDatePart(SECOND);
else if (parseFunctionNameIf("ARRAY_GET"))
return parseFunctionArgs2((f1, f2) -> arrayGet(f1, f2));
break;
case 'B':
if (parseFunctionNameIf("BIT_LENGTH"))
return bitLength((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("BITCOUNT", "BIT_COUNT"))
return bitCount((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("BYTE_LENGTH"))
return octetLength((Field) parseFieldParenthesised());
else if ((field = parseFieldBitwiseFunctionIf()) != null)
return field;
else if ((value = parseBitLiteralIf()) != null)
return DSL.inline((Boolean) value);
break;
case 'C':
if ((field = parseFieldConcatIf()) != null)
return field;
else if ((parseFunctionNameIf("CURRENT_CATALOG") && parseEmptyParens()))
return currentCatalog();
else if ((parseFunctionNameIf("CURRENT_DATABASE") && parseEmptyParens()))
return currentCatalog();
else if ((parseKeywordIf("CURRENT_SCHEMA", "CURRENT SCHEMA")) && parseEmptyParensIf())
return currentSchema();
else if ((parseKeywordIf("CURRENT_USER", "CURRENT USER", "CURRENTUSER")) && parseEmptyParensIf())
return currentUser();
else if (parseFunctionNameIf("CHR", "CHAR"))
return chr((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("CHARINDEX"))
return parseFunctionArgs3((f1, f2) -> DSL.position(f2, f1), (f1, f2, f3) -> DSL.position(f2, f1, f3));
else if (parseFunctionNameIf("CHAR_LENGTH"))
return charLength((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("CARDINALITY"))
return cardinality((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("CEILING", "CEIL"))
return ceil((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("COSH"))
return cosh((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("COS"))
return cos((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("COTH"))
return coth((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("COT"))
return cot((Field) parseFieldNumericOpParenthesised());
else if ((field = parseNextvalCurrvalIf(SequenceMethod.CURRVAL)) != null)
return field;
else if (parseFunctionNameIf("CENTURY"))
return century(parseFieldParenthesised());
else if ((parseKeywordIf("CURRENT_DATE") || parseKeywordIf("CURRENT DATE")) && parseEmptyParensIf())
return currentDate();
else if (parseKeywordIf("CURRENT_TIMESTAMP") || parseKeywordIf("CURRENT TIMESTAMP")) {
Field<Integer> precision = null;
if (parseIf('('))
if (!parseIf(')')) {
precision = (Field<Integer>) parseField();
parse(')');
}
return precision != null ? currentTimestamp(precision) : currentTimestamp();
} else if ((parseKeywordIf("CURRENT_TIME") || parseKeywordIf("CURRENT TIME")) && parseEmptyParensIf())
return currentTime();
else if (parseFunctionNameIf("CURDATE") && parseEmptyParens())
return currentDate();
else if (parseFunctionNameIf("CURTIME") && parseEmptyParens())
return currentTime();
else if ((field = parseFieldCaseIf()) != null)
return field;
else if ((field = parseFieldCastIf()) != null)
return field;
else if ((field = parseFieldCoalesceIf()) != null)
return field;
else if ((field = parseFieldCumeDistIf()) != null)
return field;
else if ((field = parseFieldConvertIf()) != null)
return field;
else if ((field = parseFieldChooseIf()) != null)
return field;
else if (!ignoreProEdition() && parseKeywordIf("CONNECT_BY_ISCYCLE") && requireProEdition()) {
} else if (!ignoreProEdition() && parseKeywordIf("CONNECT_BY_ISLEAF") && requireProEdition()) {
}
break;
case 'D':
if ((parseFunctionNameIf("DATABASE") && parseEmptyParens()))
return currentCatalog();
else if ((parseFunctionNameIf("DB_NAME") && parseEmptyParens()))
return currentCatalog();
else if ((parseFunctionNameIf("DBINFO") && parse('(') && parseStringLiteral("dbname") != null && parse(')')))
return currentCatalog();
else if (parseFunctionNameIf("DIGITS"))
return digits((Field) parseFieldParenthesised());
else if ((field = parseFieldDateLiteralIf()) != null)
return field;
else if ((field = parseFieldDateTruncIf()) != null)
return field;
else if ((field = parseFieldDateAddIf()) != null)
return field;
else if ((field = parseFieldDateDiffIf()) != null)
return field;
else if ((field = parseFieldDatePartIf()) != null)
return field;
else if ((field = parseFieldDenseRankIf()) != null)
return field;
else if (parseFunctionNameIf("DECADE"))
return decade(parseFieldParenthesised());
else if (parseFunctionNameIf("DAY") || parseFunctionNameIf("DAYOFMONTH"))
return day(parseFieldParenthesised());
else // DB2 and MySQL support the non-ISO version where weeks go from Sunday = 1 to Saturday = 7
if (parseFunctionNameIf("DAYOFWEEK_ISO"))
return isoDayOfWeek(parseFieldParenthesised());
else if (parseFunctionNameIf("DAYOFWEEK") || parseFunctionNameIf("DAY_OF_WEEK"))
return dayOfWeek(parseFieldParenthesised());
else if (parseFunctionNameIf("DAYOFYEAR") || parseFunctionNameIf("DAY_OF_YEAR"))
return dayOfYear(parseFieldParenthesised());
else if (parseFunctionNameIf("DEGREES") || parseFunctionNameIf("DEGREE") || parseFunctionNameIf("DEG"))
return deg((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("DATALENGTH"))
return octetLength((Field) parseFieldParenthesised());
else if ((field = parseFieldDecodeIf()) != null)
return field;
else if (parseKeywordIf("DEFAULT"))
return default_();
break;
case 'E':
// [#6704] PostgreSQL E'...' escaped string literals
if (characterNext() == '\'')
return inline(parseStringLiteral());
else if ((field = parseFieldExtractIf()) != null)
return field;
else if (parseFunctionNameIf("EXP"))
return exp((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("EPOCH"))
return epoch(parseFieldParenthesised());
break;
case 'F':
if (parseFunctionNameIf("FLOOR"))
return floor((Field) parseFieldNumericOpParenthesised());
else if ((field = parseFieldFirstValueIf()) != null)
return field;
else if ((field = parseFieldFieldIf()) != null)
return field;
break;
case 'G':
if (parseKeywordIf("GETDATE") && parseEmptyParens())
return currentTimestamp();
else if (parseFunctionNameIf("GENGUID", "GENERATE_UUID", "GEN_RANDOM_UUID") && parseEmptyParens())
return uuid();
else if ((field = parseFieldGreatestIf()) != null)
return field;
else if (!ignoreProEdition() && parseFunctionNameIf("GROUP_ID") && requireProEdition() && parseEmptyParens()) {
} else if ((field = parseFieldGroupingIdIf()) != null)
return field;
else if (parseFunctionNameIf("GROUPING"))
return grouping(parseFieldParenthesised());
else if (!ignoreProEdition() && (parseFunctionNameIf("GEOMETRY::STGEOMFROMWKB") || parseFunctionNameIf("GEOGRAPHY::STGEOMFROMWKB")) && requireProEdition()) {
} else if (!ignoreProEdition() && (parseFunctionNameIf("GEOMETRY::STGEOMFROMTEXT") || parseFunctionNameIf("GEOGRAPHY::STGEOMFROMTEXT")) && requireProEdition()) {
} else
break;
case 'H':
if (parseFunctionNameIf("HOUR"))
return hour(parseFieldParenthesised());
else if (parseFunctionNameIf("HASH_MD5"))
return md5((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("HEX"))
return toHex((Field) parseFieldParenthesised());
break;
case 'I':
if ((field = parseFieldIntervalLiteralIf()) != null)
return field;
else if (parseFunctionNameIf("ISO_DAY_OF_WEEK"))
return isoDayOfWeek(parseFieldParenthesised());
else if (parseFunctionNameIf("INSTR"))
return parseFunctionArgs3(DSL::position, DSL::position);
else if (parseFunctionNameIf("INSERT"))
return parseFunctionArgs4(DSL::insert);
else if (parseFunctionNameIf("IFNULL"))
return parseFunctionArgs2((f1, f2) -> ifnull((Field<?>) f1, (Field<?>) f2));
else if (parseFunctionNameIf("ISNULL"))
return parseFunctionArgs2(f -> field(f.isNull()), (f1, f2) -> isnull((Field<?>) f1, (Field<?>) f2));
else if ((field = parseFieldIfIf()) != null)
return field;
else
break;
case 'J':
if ((field = parseFieldJSONArrayConstructorIf()) != null)
return field;
else if ((field = parseFieldJSONObjectConstructorIf()) != null)
return field;
else if ((field = parseFieldJSONValueIf()) != null)
return field;
else if ((field = parseFieldJSONLiteralIf()) != null)
return field;
break;
case 'L':
if (parseFunctionNameIf("LOWER", "LCASE"))
return lower((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("LPAD"))
return parseFunctionArgs3(DSL::lpad, DSL::lpad);
else if (parseFunctionNameIf("LTRIM"))
return parseFunctionArgs2(DSL::ltrim, DSL::ltrim);
else if (parseFunctionNameIf("LEFT"))
return parseFunctionArgs2(DSL::left);
else if (parseFunctionNameIf("LENGTH", "LEN"))
return length((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("LENGTHB"))
return octetLength((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("LN", "LOGN"))
return ln((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("LOG10"))
return log10((Field) parseFieldNumericOpParenthesised());
else if ((field = parseFieldLogIf()) != null)
return field;
else if ((field = parseFieldLocateIf()) != null)
return field;
else if (!ignoreProEdition() && parseKeywordIf("LEVEL") && requireProEdition()) {
} else if (parseKeywordIf("LSHIFT"))
return parseFunctionArgs2(() -> toField(parseNumericOp()), (f1, f2) -> shl(f1, f2));
else if ((field = parseFieldLeastIf()) != null)
return field;
else if ((field = parseFieldLeadLagIf()) != null)
return field;
else if ((field = parseFieldLastValueIf()) != null)
return field;
break;
case 'M':
if (parseFunctionNameIf("MOD"))
return parseFunctionArgs2(Field::mod);
else if (parseFunctionNameIf("MICROSECOND"))
return microsecond(parseFieldParenthesised());
else if (parseFunctionNameIf("MILLENNIUM"))
return millennium(parseFieldParenthesised());
else if (parseFunctionNameIf("MILLISECOND"))
return millisecond(parseFieldParenthesised());
else if (parseFunctionNameIf("MINUTE"))
return minute(parseFieldParenthesised());
else if (parseFunctionNameIf("MONTH"))
return month(parseFieldParenthesised());
else if (parseFunctionNameIf("MID"))
return parseFunctionArgs3(DSL::mid);
else if (parseFunctionNameIf("MD5"))
return md5((Field) parseFieldParenthesised());
else if ((field = parseMultisetValueConstructorIf()) != null)
return field;
else if ((field = parseFieldGreatestIf()) != null)
return field;
else if ((field = parseFieldLeastIf()) != null)
return field;
else if ((field = parseFieldDecodeIf()) != null)
return field;
break;
case 'N':
// [#9540] N'...' NVARCHAR literals
if (characterNext() == '\'')
return inline(parseStringLiteral(), NVARCHAR);
else if ((field = parseFieldNewIdIf()) != null)
return field;
else if (parseFunctionNameIf("NVL2"))
return parseFunctionArgs3((f1, f2, f3) -> nvl2((Field<?>) f1, (Field<?>) f2, (Field<?>) f3));
else if (parseFunctionNameIf("NVL"))
return parseFunctionArgs2((f1, f2) -> nvl((Field<?>) f1, (Field<?>) f2));
else if (parseFunctionNameIf("NULLIF"))
return parseFunctionArgs2((f1, f2) -> nullif((Field<?>) f1, (Field<?>) f2));
else if ((field = parseFieldNtileIf()) != null)
return field;
else if ((field = parseFieldNthValueIf()) != null)
return field;
else if ((field = parseNextValueIf()) != null)
return field;
else if ((field = parseNextvalCurrvalIf(SequenceMethod.NEXTVAL)) != null)
return field;
else if (parseFunctionNameIf("NOW") && parse('(')) {
if (parseIf(')'))
return now();
Field<Integer> precision = (Field<Integer>) parseField();
parse(')');
return now(precision);
}
break;
case 'O':
if (parseFunctionNameIf("OREPLACE"))
return parseFunctionArgs3(DSL::replace, DSL::replace);
else if ((field = parseFieldOverlayIf()) != null)
return field;
else if ((field = parseFieldTranslateIf()) != null)
return field;
else if (parseFunctionNameIf("OCTET_LENGTH"))
return octetLength((Field) parseFieldParenthesised());
break;
case 'P':
if ((field = parseFieldPositionIf()) != null)
return field;
else if ((field = parseFieldPercentRankIf()) != null)
return field;
else if (parseFunctionNameIf("POWER", "POW"))
return parseFunctionArgs2(() -> toField(parseNumericOp()), DSL::power);
else if (parseFunctionNameIf("PI") && parseEmptyParens())
return pi();
else if (!ignoreProEdition() && parseKeywordIf("PRIOR") && requireProEdition()) {
}
break;
case 'Q':
if (characterNext() == '\'')
return inline(parseStringLiteral());
else if (parseFunctionNameIf("QUARTER"))
return quarter(parseFieldParenthesised());
case 'R':
if (parseFunctionNameIf("REPLACE"))
return parseFunctionArgs3(DSL::replace, DSL::replace);
else if ((field = parseFieldRegexpReplaceIf()) != null)
return field;
else if (parseFunctionNameIf("REPEAT", "REPLICATE"))
return parseFunctionArgs2(DSL::repeat);
else if (parseFunctionNameIf("REVERSE"))
return reverse((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("RPAD"))
return parseFunctionArgs3(DSL::rpad, DSL::rpad);
else if (parseFunctionNameIf("RTRIM"))
return parseFunctionArgs2(DSL::rtrim, DSL::rtrim);
else if (parseFunctionNameIf("RIGHT"))
return parseFunctionArgs2(DSL::right);
else if (parseFunctionNameIf("RANDOM_UUID") && parseEmptyParens())
return uuid();
else if (parseFunctionNameIf("ROW_NUMBER") && parseEmptyParens())
return parseWindowFunction(null, null, rowNumber());
else if ((field = parseFieldRankIf()) != null)
return field;
else if ((field = parseFieldRoundIf()) != null)
return field;
else if (!ignoreProEdition() && parseKeywordIf("ROWNUM") && requireProEdition()) {
} else if (parseFunctionNameIf("RADIANS") || parseFunctionNameIf("RADIAN") || parseFunctionNameIf("RAD"))
return rad((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("RAND", "RANDOM") && parseEmptyParens())
return rand();
else if (parseFunctionNameIf("RATIO_TO_REPORT"))
return parseFunctionArgs1(f -> parseWindowFunction(null, null, ratioToReport(f)));
else if (parseKeywordIf("RSHIFT"))
return parseFunctionArgs2(() -> toField(parseNumericOp()), (f1, f2) -> shr(f1, f2));
else if (parseFunctionNameIf("ROW"))
return parseTuple();
break;
case 'S':
if ((field = parseFieldSubstringIf()) != null)
return field;
else if (parseFunctionNameIf("SUBSTRING_INDEX"))
return parseFunctionArgs3(DSL::substringIndex);
else if (parseFunctionNameIf("SPACE"))
return space((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("SPLIT_PART"))
return parseFunctionArgs3(DSL::splitPart);
else if (parseFunctionNameIf("STR_REPLACE"))
return parseFunctionArgs3(DSL::replace, DSL::replace);
else if (parseFunctionNameIf("SCHEMA") && parseEmptyParensIf())
return currentSchema();
else if (parseFunctionNameIf("STRREVERSE"))
return reverse((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("SYSUUID") && parseEmptyParensIf())
return uuid();
else if (parseFunctionNameIf("SECOND"))
return second(parseFieldParenthesised());
else if (!ignoreProEdition() && parseFunctionNameIf("SEQ4", "SEQ8") && parseEmptyParens() && requireProEdition()) {
} else if (parseFunctionNameIf("SIGN", "SGN"))
return sign((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("SQRT", "SQR"))
return sqrt((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("SQUARE"))
return square((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("SINH"))
return sinh((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("SIN"))
return sin((Field) parseFieldNumericOpParenthesised());
else if (parseKeywordIf("SHL", "SHIFTLEFT"))
return parseFunctionArgs2(() -> toField(parseNumericOp()), (f1, f2) -> shl(f1, f2));
else if (parseKeywordIf("SHR", "SHIFTRIGHT"))
return parseFunctionArgs2(() -> toField(parseNumericOp()), (f1, f2) -> shr(f1, f2));
else if ((field = parseFieldSysConnectByPathIf()) != null)
return field;
else if (!ignoreProEdition() && parseFunctionNameIf("ST_AREA") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("SDO_GEOM.SDO_AREA") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_ASBINARY") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_ASTEXT") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_CENTROID") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("SDO_GEOM.SDO_CENTROID") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_DIFFERENCE") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("SDO_GEOM.SDO_DIFFERENCE") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_DISTANCE") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("SDO_GEOM.SDO_DISTANCE") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_ENDPOINT") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_EXTERIORRING") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_GEOMETRYN") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_GEOMETRYTYPE") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_GEOMFROMWKB") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_GEOMFROMTEXT", "SDO_GEOMETRY") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_INTERIORRINGN") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_INTERSECTION") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("SDO_GEOM.SDO_INTERSECTION") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_LENGTH") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("SDO_GEOM.SDO_LENGTH") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_NUMINTERIORRING", "ST_NUMINTERIORRINGS") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_NUMGEOMETRIES", "SDO_UTIL.GETNUMELEM") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_NUMPOINTS") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_POINTN") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_SRID") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_STARTPOINT") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_UNION") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("SDO_GEOM.SDO_UNION") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_X") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_Y") && requireProEdition()) {
} else if (!ignoreProEdition() && parseFunctionNameIf("ST_Z") && requireProEdition()) {
}
break;
case 'T':
if ((field = parseBooleanValueExpressionIf()) != null)
return field;
else if ((field = parseFieldTrimIf()) != null)
return field;
else if ((field = parseFieldTranslateIf()) != null)
return field;
else if (parseFunctionNameIf("TO_CHAR"))
return parseFunctionArgs2(DSL::toChar, DSL::toChar);
else if (parseFunctionNameIf("TO_HEX"))
return toHex((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("TANH"))
return tanh((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("TAN"))
return tan((Field) parseFieldNumericOpParenthesised());
else if (parseFunctionNameIf("TO_NUMBER"))
return parseFunctionArgs1(f -> cast(f, NUMERIC));
else if (parseFunctionNameIf("TIMEZONE_HOUR"))
return timezoneHour(parseFieldParenthesised());
else if (parseFunctionNameIf("TIMEZONE_MINUTE"))
return timezoneMinute(parseFieldParenthesised());
else if (parseFunctionNameIf("TIMEZONE"))
return timezone(parseFieldParenthesised());
else if ((field = parseFieldTimestampLiteralIf()) != null)
return field;
else if ((field = parseFieldTimeLiteralIf()) != null)
return field;
else if (parseFunctionNameIf("TO_DATE"))
return parseFunctionArgs2(f1 -> toDate(f1, inline(settings().getParseDateFormat())), DSL::toDate);
else if (parseFunctionNameIf("TO_TIMESTAMP"))
return parseFunctionArgs2(f1 -> toTimestamp(f1, inline(settings().getParseTimestampFormat())), DSL::toTimestamp);
else if (parseFunctionNameIf("TIMESTAMPDIFF"))
return parseFunctionArgs2((f1, f2) -> DSL.timestampDiff(f1, f2));
else if ((field = parseFieldTruncIf()) != null)
return field;
break;
case 'U':
if (parseFunctionNameIf("UPPER", "UCASE"))
return DSL.upper((Field) parseFieldParenthesised());
else if (parseFunctionNameIf("UUID", "UUID_GENERATE", "UUID_STRING") && parseEmptyParens())
return uuid();
else if (parseFunctionNameIf("UNIX_TIMESTAMP"))
return epoch(parseFieldParenthesised());
break;
case 'W':
if (parseFunctionNameIf("WIDTH_BUCKET"))
return parseFunctionArgs4((f1, f2, f3, f4) -> widthBucket(f1, f2, f3, f4));
else if (parseFunctionNameIf("WEEK"))
return week(parseFieldParenthesised());
break;
case 'X':
if ((value = parseBinaryLiteralIf()) != null)
return inline((byte[]) value);
else if (parseFunctionNameIf("XMLCOMMENT"))
return xmlcomment((Field) parseField());
else if ((field = parseFieldXMLConcatIf()) != null)
return field;
else if ((field = parseFieldXMLElementIf()) != null)
return field;
else if ((field = parseFieldXMLPIIf()) != null)
return field;
else if ((field = parseFieldXMLForestIf()) != null)
return field;
else if ((field = parseFieldXMLParseIf()) != null)
return field;
else if ((field = parseFieldXMLDocumentIf()) != null)
return field;
else if ((field = parseFieldXMLQueryIf()) != null)
return field;
else if ((field = parseFieldXMLSerializeIf()) != null)
return field;
break;
case 'Y':
if (parseFunctionNameIf("YEAR"))
return year(parseFieldParenthesised());
break;
case 'Z':
if (parseFunctionNameIf("ZEROIFNULL"))
return coalesce(parseFieldParenthesised(), zero());
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
case '.':
if ((field = parseFieldUnsignedNumericLiteralIf(Sign.NONE)) != null)
return field;
break;
case '{':
parse('{', false);
switch(characterUpper()) {
case 'D':
parseKeyword("D");
field = inline(parseDateLiteral());
break;
case 'F':
parseKeyword("FN");
// TODO: Limit the supported expressions in this context to the ones specified here:
// http://download.oracle.com/otn-pub/jcp/jdbc-4_2-mrel2-eval-spec/jdbc4.2-fr-spec.pdf
field = parseTerm();
break;
case 'T':
if (parseKeywordIf("TS")) {
field = inline(parseTimestampLiteral());
} else {
parseKeyword("T");
field = inline(parseTimeLiteral());
}
break;
default:
throw exception("Unsupported JDBC escape literal");
}
parse('}');
return field;
case '(':
// A term parenthesis can mark the beginning of any of:
// - ROW expression without ROW keyword: E.g. (1, 2)
// - Parenthesised field expression: E.g. (1 + 2)
// - A correlated subquery: E.g. (select 1)
// - A correlated subquery with nested set ops: E.g. ((select 1) except (select 2))
// - A combination of the above: E.g. ((select 1) + 2, ((select 1) except (select 2)) + 2)
int p = position();
EnumSet fk = forbidden;
try {
if (!forbidden.isEmpty())
forbidden = EnumSet.noneOf(FunctionKeyword.class);
FieldOrRow r = parseScalarSubqueryIf();
if (r != null)
return r;
parse('(');
r = parseFieldOrRow();
List<Field<?>> list = null;
if (r instanceof Field) {
Field<?> f = (Field<?>) r;
while (parseIf(',')) {
if (list == null) {
list = new ArrayList<>();
list.add(f);
}
// TODO Allow for nesting ROWs
list.add(parseField());
}
}
parse(')');
return list != null ? row(list) : r;
} finally {
forbidden = fk;
}
}
if ((field = parseAggregateFunctionIf()) != null)
return field;
else if ((field = parseBooleanValueExpressionIf()) != null)
return field;
else
return parseFieldNameOrSequenceExpression();
}
use of org.jooq.Context in project jOOQ by jOOQ.
the class MergeImpl method toSQLStandard.
private final void toSQLStandard(Context<?> ctx) {
ctx.start(MERGE_MERGE_INTO).visit(K_MERGE_INTO).sql(' ').declareTables(true, c -> c.visit(table)).end(MERGE_MERGE_INTO).formatSeparator().start(MERGE_USING).visit(K_USING).sql(' ');
ctx.declareTables(true, c1 -> c1.data(DATA_WRAP_DERIVED_TABLES_IN_PARENTHESES, true, c2 -> {
// in its MERGE statement.
if (usingDual) {
switch(c2.family()) {
case DERBY:
c2.visit(new Dual());
break;
default:
c2.visit(DSL.selectOne());
break;
}
} else
c2.visit(using);
}));
boolean onParentheses = false;
ctx.end(MERGE_USING).formatSeparator().start(MERGE_ON).visit(K_ON).sql(onParentheses ? " (" : " ").visit(on).sql(onParentheses ? ")" : "").end(MERGE_ON).start(MERGE_WHEN_MATCHED_THEN_UPDATE).start(MERGE_SET);
// [#7291] Multi MATCHED emulation
boolean emulate = false;
boolean requireMatchedConditions = false;
// [#10054] TODO: Skip all WHEN MATCHED clauses after a WHEN MATCHED clause with no search condition
if (NO_SUPPORT_CONDITION_AFTER_NO_CONDITION.contains(ctx.dialect())) {
boolean withoutMatchedConditionFound = false;
for (MatchedClause m : matched) {
if (requireMatchedConditions |= withoutMatchedConditionFound)
break;
withoutMatchedConditionFound |= m.condition instanceof NoCondition;
}
}
emulateCheck: if ((NO_SUPPORT_MULTI.contains(ctx.dialect()) && matched.size() > 1)) {
boolean matchUpdate = false;
boolean matchDelete = false;
for (MatchedClause m : matched) {
if (m.delete) {
if (emulate |= matchDelete)
break emulateCheck;
matchDelete = true;
} else {
if (emulate |= matchUpdate)
break emulateCheck;
matchUpdate = true;
}
}
}
if (emulate) {
MatchedClause update = null;
MatchedClause delete = null;
Condition negate = noCondition();
for (MatchedClause m : matched) {
Condition condition = negate.and(m.condition);
if (m.delete) {
if (delete == null)
delete = new MatchedClause(noCondition(), true);
delete.condition = delete.condition.or(condition);
} else {
if (update == null)
update = new MatchedClause(noCondition());
for (Entry<Field<?>, Field<?>> e : m.updateMap.entrySet()) {
Field<?> exp = update.updateMap.get(e.getKey());
if (exp instanceof CaseConditionStepImpl)
((CaseConditionStepImpl) exp).when(negate.and(condition), e.getValue());
else
update.updateMap.put(e.getKey(), when(negate.and(condition), (Field) e.getValue()).else_(e.getKey()));
}
update.condition = update.condition.or(condition);
}
if (REQUIRE_NEGATION.contains(ctx.dialect()))
negate = negate.andNot(m.condition instanceof NoCondition ? trueCondition() : m.condition);
}
{
if (delete != null)
toSQLMatched(ctx, delete, requireMatchedConditions);
if (update != null)
toSQLMatched(ctx, update, requireMatchedConditions);
}
} else // [#7291] Workaround for https://github.com/h2database/h2database/issues/2552
if (REQUIRE_NEGATION.contains(ctx.dialect())) {
Condition negate = noCondition();
for (MatchedClause m : matched) {
toSQLMatched(ctx, new MatchedClause(negate.and(m.condition), m.delete, m.updateMap), requireMatchedConditions);
negate = negate.andNot(m.condition instanceof NoCondition ? trueCondition() : m.condition);
}
} else {
for (MatchedClause m : matched) toSQLMatched(ctx, m, requireMatchedConditions);
}
ctx.end(MERGE_SET).end(MERGE_WHEN_MATCHED_THEN_UPDATE).start(MERGE_WHEN_NOT_MATCHED_THEN_INSERT);
for (NotMatchedClause m : notMatched) toSQLNotMatched(ctx, m);
ctx.end(MERGE_WHEN_NOT_MATCHED_THEN_INSERT);
}
use of org.jooq.Context in project jOOQ by jOOQ.
the class SelectQueryImpl method toSQLReference0.
/**
* This method renders the main part of a query without the LIMIT clause.
* This part is common to any type of limited query
*/
@SuppressWarnings("unchecked")
private final void toSQLReference0(Context<?> context, List<Field<?>> originalFields, List<Field<?>> alternativeFields) {
SQLDialect family = context.family();
boolean qualify = context.qualify();
int unionOpSize = unionOp.size();
boolean unionParensRequired = false;
boolean unionOpNesting = false;
// The SQL standard specifies:
//
// <query expression> ::=
// [ <with clause> ] <query expression body>
// [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
//
// Depending on the dialect and on various syntax elements, parts of the above must be wrapped in
// synthetic parentheses
boolean wrapQueryExpressionInDerivedTable;
boolean wrapQueryExpressionBodyInDerivedTable;
boolean applySeekOnDerivedTable = applySeekOnDerivedTable();
wrapQueryExpressionInDerivedTable = false;
if (wrapQueryExpressionInDerivedTable)
context.visit(K_SELECT).sql(" *").formatSeparator().visit(K_FROM).sql(" (").formatIndentStart().formatNewLine();
wrapQueryExpressionBodyInDerivedTable = false || // predicate must be applied on a derived table, not on the individual subqueries
applySeekOnDerivedTable;
if (wrapQueryExpressionBodyInDerivedTable) {
context.visit(K_SELECT).sql(' ');
context.formatIndentStart().formatNewLine().sql("t.*");
if (alternativeFields != null && originalFields.size() < alternativeFields.size())
context.sql(", ").formatSeparator().declareFields(true, c -> c.visit(alternativeFields.get(alternativeFields.size() - 1)));
context.formatIndentEnd().formatSeparator().visit(K_FROM).sql(" (").formatIndentStart().formatNewLine();
}
// all databases, we need to wrap relevant subqueries in parentheses.
if (unionOpSize > 0) {
if (!TRUE.equals(context.data(DATA_NESTED_SET_OPERATIONS)))
context.data(DATA_NESTED_SET_OPERATIONS, unionOpNesting = unionOpNesting());
for (int i = unionOpSize - 1; i >= 0; i--) {
switch(unionOp.get(i)) {
case EXCEPT:
context.start(SELECT_EXCEPT);
break;
case EXCEPT_ALL:
context.start(SELECT_EXCEPT_ALL);
break;
case INTERSECT:
context.start(SELECT_INTERSECT);
break;
case INTERSECT_ALL:
context.start(SELECT_INTERSECT_ALL);
break;
case UNION:
context.start(SELECT_UNION);
break;
case UNION_ALL:
context.start(SELECT_UNION_ALL);
break;
}
// [#3676] There might be cases where nested set operations do not
// imply required parentheses in some dialects, but better
// play safe than sorry
unionParenthesis(context, '(', alternativeFields != null ? alternativeFields : getSelect(), derivedTableRequired(context, this), unionParensRequired = unionOpNesting || unionParensRequired(context));
}
}
traverseJoins(getFrom(), t -> {
if (t instanceof TableImpl)
context.scopeRegister(t, true);
});
for (Entry<QueryPart, QueryPart> entry : localQueryPartMapping.entrySet()) context.scopeRegister(entry.getKey(), true, entry.getValue());
// SELECT clause
// -------------
context.start(SELECT_SELECT).visit(K_SELECT).separatorRequired(true);
// [#1493] Oracle hints come directly after the SELECT keyword
if (!StringUtils.isBlank(hint))
context.sql(' ').sql(hint).separatorRequired(true);
if (Tools.isNotEmpty(distinctOn))
context.visit(K_DISTINCT_ON).sql(" (").visit(distinctOn).sql(')').separatorRequired(true);
else if (distinct)
context.visit(K_DISTINCT).separatorRequired(true);
if (TRUE.equals(context.data(BooleanDataKey.DATA_RENDERING_DATA_CHANGE_DELTA_TABLE)))
context.qualify(false);
context.declareFields(true);
// non-ambiguous column names as ambiguous column names are not allowed in subqueries
if (alternativeFields != null)
if (wrapQueryExpressionBodyInDerivedTable && originalFields.size() < alternativeFields.size())
context.visit(new SelectFieldList<>(alternativeFields.subList(0, originalFields.size())));
else
context.visit(new SelectFieldList<>(alternativeFields));
else
// The default behaviour
context.visit(getSelectResolveUnsupportedAsterisks(context.configuration()));
if (TRUE.equals(context.data(BooleanDataKey.DATA_RENDERING_DATA_CHANGE_DELTA_TABLE)))
context.qualify(qualify);
context.declareFields(false).end(SELECT_SELECT);
// only in top level SELECTs
if (!context.subquery()) {
context.start(SELECT_INTO);
QueryPart actualIntoTable = (QueryPart) context.data(DATA_SELECT_INTO_TABLE);
if (actualIntoTable == null)
actualIntoTable = intoTable;
if (actualIntoTable != null && !TRUE.equals(context.data(DATA_OMIT_INTO_CLAUSE)) && (SUPPORT_SELECT_INTO_TABLE.contains(context.dialect()) || !(actualIntoTable instanceof Table))) {
context.formatSeparator().visit(K_INTO).sql(' ').visit(actualIntoTable);
}
context.end(SELECT_INTO);
}
// FROM and JOIN clauses
// ---------------------
context.start(SELECT_FROM).declareTables(true);
// [#....] Some SQL dialects do not require a FROM clause. Others do and
// jOOQ generates a "DUAL" table or something equivalent.
// See also org.jooq.impl.Dual for details.
boolean hasFrom = !getFrom().isEmpty() || !OPTIONAL_FROM_CLAUSE.contains(context.dialect());
List<Condition> semiAntiJoinPredicates = null;
ConditionProviderImpl where = getWhere(context);
if (hasFrom) {
Object previousCollect = context.data(DATA_COLLECT_SEMI_ANTI_JOIN, true);
Object previousCollected = context.data(DATA_COLLECTED_SEMI_ANTI_JOIN, null);
TableList tablelist = getFrom();
tablelist = transformInlineDerivedTables(tablelist, where);
context.formatSeparator().visit(K_FROM).separatorRequired(true).visit(tablelist);
semiAntiJoinPredicates = (List<Condition>) context.data(DATA_COLLECTED_SEMI_ANTI_JOIN, previousCollected);
context.data(DATA_COLLECT_SEMI_ANTI_JOIN, previousCollect);
}
context.declareTables(false).end(SELECT_FROM);
// WHERE clause
// ------------
context.start(SELECT_WHERE);
if (TRUE.equals(context.data().get(BooleanDataKey.DATA_SELECT_NO_DATA)))
context.formatSeparator().visit(K_WHERE).sql(' ').visit(falseCondition());
else if (!where.hasWhere() && semiAntiJoinPredicates == null)
;
else {
ConditionProviderImpl actual = new ConditionProviderImpl();
if (semiAntiJoinPredicates != null)
actual.addConditions(semiAntiJoinPredicates);
if (where.hasWhere())
actual.addConditions(where.getWhere());
context.formatSeparator().visit(K_WHERE).sql(' ').visit(actual);
}
context.end(SELECT_WHERE);
// GROUP BY and HAVING clause
// --------------------------
context.start(SELECT_GROUP_BY);
if (!getGroupBy().isEmpty()) {
context.formatSeparator().visit(K_GROUP_BY);
if (groupByDistinct)
context.sql(' ').visit(K_DISTINCT);
context.separatorRequired(true);
context.visit(groupBy);
}
context.end(SELECT_GROUP_BY);
// HAVING clause
// -------------
context.start(SELECT_HAVING);
if (getHaving().hasWhere())
context.formatSeparator().visit(K_HAVING).sql(' ').visit(getHaving());
context.end(SELECT_HAVING);
// WINDOW clause
// -------------
context.start(SELECT_WINDOW);
if (Tools.isNotEmpty(window) && !NO_SUPPORT_WINDOW_CLAUSE.contains(context.dialect()))
context.formatSeparator().visit(K_WINDOW).separatorRequired(true).declareWindows(true, c -> c.visit(window));
context.end(SELECT_WINDOW);
if (getQualify().hasWhere())
context.formatSeparator().visit(K_QUALIFY).sql(' ').visit(getQualify());
// ORDER BY clause for local subselect
// -----------------------------------
toSQLOrderBy(context, originalFields, alternativeFields, false, wrapQueryExpressionBodyInDerivedTable, orderBy, limit);
// --------------------------------------------
if (unionOpSize > 0) {
unionParenthesis(context, ')', null, derivedTableRequired(context, this), unionParensRequired);
for (int i = 0; i < unionOpSize; i++) {
CombineOperator op = unionOp.get(i);
for (Select<?> other : union.get(i)) {
boolean derivedTableRequired = derivedTableRequired(context, other);
context.formatSeparator().visit(op.toKeyword(family));
if (unionParensRequired)
context.sql(' ');
else
context.formatSeparator();
unionParenthesis(context, '(', other.getSelect(), derivedTableRequired, unionParensRequired);
context.visit(other);
unionParenthesis(context, ')', null, derivedTableRequired, unionParensRequired);
}
// [#1658] Close parentheses opened previously
if (i < unionOpSize - 1)
unionParenthesis(context, ')', null, derivedTableRequired(context, this), unionParensRequired);
switch(unionOp.get(i)) {
case EXCEPT:
context.end(SELECT_EXCEPT);
break;
case EXCEPT_ALL:
context.end(SELECT_EXCEPT_ALL);
break;
case INTERSECT:
context.end(SELECT_INTERSECT);
break;
case INTERSECT_ALL:
context.end(SELECT_INTERSECT_ALL);
break;
case UNION:
context.end(SELECT_UNION);
break;
case UNION_ALL:
context.end(SELECT_UNION_ALL);
break;
}
}
if (unionOpNesting)
context.data().remove(DATA_NESTED_SET_OPERATIONS);
}
if (wrapQueryExpressionBodyInDerivedTable) {
context.formatIndentEnd().formatNewLine().sql(") t");
if (applySeekOnDerivedTable) {
context.formatSeparator().visit(K_WHERE).sql(' ').qualify(false, c -> c.visit(getSeekCondition()));
}
}
// ORDER BY clause for UNION
// -------------------------
context.qualify(false, c -> toSQLOrderBy(context, originalFields, alternativeFields, wrapQueryExpressionInDerivedTable, wrapQueryExpressionBodyInDerivedTable, unionOrderBy, unionLimit));
}
use of org.jooq.Context in project jOOQ by jOOQ.
the class FieldMapForUpdate method accept.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public final void accept(Context<?> ctx) {
if (size() > 0) {
String separator = "";
// [#989] Some dialects do not support qualified column references
// in the UPDATE statement's SET clause
// [#2055] Other dialects require qualified column references to
// disambiguated columns in queries like
// UPDATE t1 JOIN t2 .. SET t1.val = ..., t2.val = ...
boolean supportsQualify = !NO_SUPPORT_QUALIFY.contains(ctx.dialect()) && ctx.qualify();
// [#2823] [#10034] Few dialects need bind value casts for UPDATE .. SET
// Some regressions have been observed e.g. in PostgreSQL with JSON types, so let's be careful.
CastMode previous = ctx.castMode();
if (!CASTS_NEEDED.contains(ctx.dialect()))
ctx.castMode(CastMode.NEVER);
for (Entry<Field<?>, Field<?>> entry : removeReadonly(ctx, flattenEntrySet(entrySet(), true))) {
if (!"".equals(separator))
ctx.sql(separator).formatSeparator();
ctx.start(assignmentClause).qualify(supportsQualify, c -> c.visit(entry.getKey())).sql(" = ");
// [#8479] Emulate WHERE clause using CASE
Condition condition = (Condition) ctx.data(DATA_ON_DUPLICATE_KEY_WHERE);
if (condition != null)
ctx.visit(when(condition, (Field) entry.getValue()).else_(entry.getKey()));
else
ctx.visit(entry.getValue());
ctx.end(assignmentClause);
separator = ",";
}
if (!CASTS_NEEDED.contains(ctx.dialect()))
ctx.castMode(previous);
} else
ctx.sql("[ no fields are updated ]");
}
Aggregations