[jOOQ/jOOQ#12691] Support parsing single element IN predicate without

parentheses
This commit is contained in:
Lukas Eder 2021-12-02 15:42:50 +01:00
parent 814bb5b142
commit 4fb10cb442

View File

@ -6330,6 +6330,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
left = parseConcat();
int p = position();
not = parseKeywordIf("NOT");
boolean isField = left instanceof Field;
if (!not && ((outer = parseTSQLOuterJoinComparatorIf()) != null) && requireProEdition()) {
@ -6357,7 +6358,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
// TODO equal degrees
Condition result =
all
? left instanceof Field
? isField
? peekSelectOrWith(true)
? ((Field) left).compare(comp, DSL.all(parseWithOrSelect(1)))
: ((Field) left).compare(comp, DSL.all(parseList(',', c -> c.parseField()).toArray(EMPTY_FIELD)))
@ -6366,7 +6367,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
: new RowSubqueryCondition((Row) left, DSL.all(parseWithOrSelect(((Row) left).size())), comp)
: any
? left instanceof Field
? isField
? peekSelectOrWith(true)
? ((Field) left).compare(comp, DSL.any(parseWithOrSelect(1)))
: ((Field) left).compare(comp, DSL.any(parseList(',', c -> c.parseField()).toArray(EMPTY_FIELD)))
@ -6374,7 +6375,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
// TODO: Support quantifiers also for rows
: new RowSubqueryCondition((Row) left, DSL.any(parseWithOrSelect(((Row) left).size())), comp)
: left instanceof Field
: isField
? ((Field) left).compare(comp, toField(parseConcat()))
: new RowCondition((Row) left, parseRow(((Row) left).size(), true), comp);
@ -6388,17 +6389,17 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
if (parseKeywordIf("NULL"))
return not
? left instanceof Field
? isField
? ((Field) left).isNotNull()
: ((Row) left).isNotNull()
: left instanceof Field
: isField
? ((Field) left).isNull()
: ((Row) left).isNull();
else if (left instanceof Field && parseKeywordIf("JSON"))
else if (isField && parseKeywordIf("JSON"))
return not
? ((Field) left).isNotJson()
: ((Field) left).isJson();
else if (left instanceof Field && parseKeywordIf("DOCUMENT"))
else if (isField && parseKeywordIf("DOCUMENT"))
return not
? ((Field) left).isNotDocument()
: ((Field) left).isDocument();
@ -6418,62 +6419,73 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
}
else if (!forbidden.contains(FK_IN) && parseKeywordIf("IN")) {
Condition result;
parse('(');
if (peek(')'))
result = not
? left instanceof Field
? ((Field) left).notIn(EMPTY_FIELD)
: new RowInCondition((Row) left, new QueryPartList<>(), true)
: left instanceof Field
? ((Field) left).in(EMPTY_FIELD)
: new RowInCondition((Row) left, new QueryPartList<>(), false);
else if (peekSelectOrWith(true))
result = not
? left instanceof Field
? ((Field) left).notIn(parseWithOrSelect(1))
: new RowSubqueryCondition((Row) left, parseWithOrSelect(((Row) left).size()), NOT_IN)
: left instanceof Field
? ((Field) left).in(parseWithOrSelect(1))
: new RowSubqueryCondition((Row) left, parseWithOrSelect(((Row) left).size()), IN);
else
result = not
? left instanceof Field
? ((Field) left).notIn(parseList(',', c -> c.parseField()))
: new RowInCondition((Row) left, new QueryPartList<>(parseList(',', c -> parseRow(((Row) left).size()))), true)
: left instanceof Field
? ((Field) left).in(parseList(',', c -> c.parseField()))
: new RowInCondition((Row) left, new QueryPartList<>(parseList(',', c -> parseRow(((Row) left).size()))), false);
parse(')');
// [#12691] Some dialects support A IN B syntax without parentheses for single element in lists
if (isField && !peek('(')) {
result = not
? ((Field) left).notIn(parseField())
: ((Field) left).in(parseField());
}
else {
parse('(');
if (peek(')'))
result = not
? isField
? ((Field) left).notIn(EMPTY_FIELD)
: new RowInCondition((Row) left, new QueryPartList<>(), true)
: isField
? ((Field) left).in(EMPTY_FIELD)
: new RowInCondition((Row) left, new QueryPartList<>(), false);
else if (peekSelectOrWith(true))
result = not
? isField
? ((Field) left).notIn(parseWithOrSelect(1))
: new RowSubqueryCondition((Row) left, parseWithOrSelect(((Row) left).size()), NOT_IN)
: isField
? ((Field) left).in(parseWithOrSelect(1))
: new RowSubqueryCondition((Row) left, parseWithOrSelect(((Row) left).size()), IN);
else
result = not
? isField
? ((Field) left).notIn(parseList(',', c -> c.parseField()))
: new RowInCondition((Row) left, new QueryPartList<>(parseList(',', c -> parseRow(((Row) left).size()))), true)
: isField
? ((Field) left).in(parseList(',', c -> c.parseField()))
: new RowInCondition((Row) left, new QueryPartList<>(parseList(',', c -> parseRow(((Row) left).size()))), false);
parse(')');
}
return result;
}
else if (parseKeywordIf("BETWEEN")) {
boolean symmetric = !parseKeywordIf("ASYMMETRIC") && parseKeywordIf("SYMMETRIC");
FieldOrRow r1 = left instanceof Field
FieldOrRow r1 = isField
? parseConcat()
: parseRow(((Row) left).size());
parseKeyword("AND");
FieldOrRow r2 = left instanceof Field
FieldOrRow r2 = isField
? parseConcat()
: parseRow(((Row) left).size());
return symmetric
? not
? left instanceof Field
? isField
? ((Field) left).notBetweenSymmetric((Field) r1, (Field) r2)
: new RowBetweenCondition((Row) left, (Row) r1, not, symmetric, (Row) r2)
: left instanceof Field
: isField
? ((Field) left).betweenSymmetric((Field) r1, (Field) r2)
: new RowBetweenCondition((Row) left, (Row) r1, not, symmetric, (Row) r2)
: not
? left instanceof Field
? isField
? ((Field) left).notBetween((Field) r1, (Field) r2)
: new RowBetweenCondition((Row) left, (Row) r1, not, symmetric, (Row) r2)
: left instanceof Field
: isField
? ((Field) left).between((Field) r1, (Field) r2)
: new RowBetweenCondition((Row) left, (Row) r1, not, symmetric, (Row) r2);
}
else if (left instanceof Field && (parseKeywordIf("LIKE") || parseOperatorIf("~~") || (notOp = parseOperatorIf("!~~")))) {
else if (isField && (parseKeywordIf("LIKE") || parseOperatorIf("~~") || (notOp = parseOperatorIf("!~~")))) {
if (parseKeywordIf("ANY")) {
parse('(');
if (peekSelectOrWith(true)) {
@ -6524,12 +6536,12 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
return parseEscapeClauseIf(like);
}
}
else if (left instanceof Field && (parseKeywordIf("ILIKE") || parseOperatorIf("~~*") || (notOp = parseOperatorIf("!~~*")))) {
else if (isField && (parseKeywordIf("ILIKE") || parseOperatorIf("~~*") || (notOp = parseOperatorIf("!~~*")))) {
Field right = toField(parseConcat());
LikeEscapeStep like = (not ^ notOp) ? ((Field) left).notLikeIgnoreCase(right) : ((Field) left).likeIgnoreCase(right);
return parseEscapeClauseIf(like);
}
else if (left instanceof Field && (parseKeywordIf("REGEXP")
else if (isField && (parseKeywordIf("REGEXP")
|| parseKeywordIf("RLIKE")
|| parseKeywordIf("LIKE_REGEX")
|| parseOperatorIf("~")
@ -6539,7 +6551,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
? ((Field) left).notLikeRegex(right)
: ((Field) left).likeRegex(right);
}
else if (left instanceof Field && parseKeywordIf("SIMILAR TO")) {
else if (isField && parseKeywordIf("SIMILAR TO")) {
Field right = toField(parseConcat());
LikeEscapeStep like = not ? ((Field) left).notSimilarTo(right) : ((Field) left).similarTo(right);
return parseEscapeClauseIf(like);