[jOOQ/jOOQ#13573] Add parser support for the PostgreSQL EXCLUDED pseudo table and MySQL VALUES() syntax

This commit is contained in:
Lukas Eder 2022-05-23 15:26:41 +02:00
parent 2fa0495ec7
commit 5371c335dd
2 changed files with 35 additions and 4 deletions

View File

@ -156,6 +156,7 @@ import static org.jooq.impl.DSL.digits;
import static org.jooq.impl.DSL.domain;
import static org.jooq.impl.DSL.epoch;
import static org.jooq.impl.DSL.every;
import static org.jooq.impl.DSL.excluded;
// ...
import static org.jooq.impl.DSL.exists;
// ...
@ -462,6 +463,7 @@ import static org.jooq.impl.Tools.deleteQueryImpl;
import static org.jooq.impl.Tools.normaliseNameCase;
import static org.jooq.impl.Tools.selectQueryImpl;
import static org.jooq.impl.Tools.updateQueryImpl;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_PARSE_ON_CONFLICT;
import static org.jooq.impl.Transformations.transformAppendMissingTableReferences;
import static org.jooq.tools.StringUtils.defaultIfNull;
@ -700,6 +702,7 @@ import org.jooq.impl.QOM.JSONOnNull;
import org.jooq.impl.QOM.UEmpty;
import org.jooq.impl.QOM.XMLPassingMechanism;
import org.jooq.impl.ScopeStack.Value;
import org.jooq.impl.Tools.BooleanDataKey;
import org.jooq.tools.StringUtils;
import org.jooq.tools.reflect.Reflect;
import org.jooq.types.DayToSecond;
@ -2308,7 +2311,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
InsertOnConflictWhereStep<?> where = parseKeywordIf("ALL TO EXCLUDED")
? onDuplicate.onDuplicateKeyUpdate().setAllToExcluded()
: onDuplicate.onDuplicateKeyUpdate().set(parseSetClauseList());
: onDuplicate.onDuplicateKeyUpdate().set((Map<?, ?>) data(DATA_PARSE_ON_CONFLICT, true, c -> c.parseSetClauseList()));
if (parseKeywordIf("WHERE"))
returning = where.where(parseCondition());
@ -2343,7 +2346,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
else if (parseKeywordIf("UPDATE SET")) {
InsertOnConflictWhereStep<?> where = parseKeywordIf("ALL TO EXCLUDED")
? doUpdate.doUpdate().setAllToExcluded()
: doUpdate.doUpdate().set(parseSetClauseList());
: doUpdate.doUpdate().set((Map<?, ?>) data(DATA_PARSE_ON_CONFLICT, true, c -> c.parseSetClauseList()));
if (parseKeywordIf("WHERE"))
returning = where.where(parseCondition());
@ -7851,7 +7854,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
return r;
}
private FieldOrRow parseMethodCallIf(FieldOrRow r) {
private final FieldOrRow parseMethodCallIf(FieldOrRow r) {
@ -7863,7 +7866,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
return r;
}
private FieldOrRow parseMethodCallIf0(FieldOrRow r) {
private final FieldOrRow parseMethodCallIf0(FieldOrRow r) {
@ -8779,6 +8782,10 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
break;
case 'V':
if (TRUE.equals(data(DATA_PARSE_ON_CONFLICT)) && (parseFunctionNameIf("VALUES") || parseFunctionNameIf("VALUE")))
return excluded(parseFieldParenthesised());
case 'W':
if (parseFunctionNameIf("WIDTH_BUCKET"))
return parseFunctionArgs4((f1, f2, f3, f4) -> widthBucket(f1, f2, f3, f4));
@ -11684,12 +11691,15 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
Name name = parseName();
if (name.qualified()) {
String first = name.first();
String last = name.last();
if ("NEXTVAL".equalsIgnoreCase(last))
return sequence(name.qualifier()).nextval();
else if ("CURRVAL".equalsIgnoreCase(last))
return sequence(name.qualifier()).currval();
else if (TRUE.equals(data(DATA_PARSE_ON_CONFLICT)) && "EXCLUDED".equalsIgnoreCase(first))
return excluded(field(name.unqualifiedName()));
}
unknownFunctions:
@ -14578,4 +14588,18 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
public String toString() {
return mark();
}
public final <T> T data(Object key, Object value, Function<? super DefaultParseContext, ? extends T> function) {
Object previous = data(key, value);
try {
return function.apply(this);
}
finally {
if (previous == null)
data().remove(key);
else
data(key, previous);
}
}
}

View File

@ -628,6 +628,13 @@ final class Tools {
*/
DATA_LOCK_WAIT_TIMEOUT_SET,
/**
* [#13573] We're parsing the <code>ON CONFLICT</code> clause, in which
* the <code>VALUES()</code> function or <code>EXCLUDED</code> pseudo
* table have a special semantics.
*/
DATA_PARSE_ON_CONFLICT,
;
private final boolean resetInSubqueryScope;