diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 2e04da0953..1f6e88df6f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -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 data(Object key, Object value, Function function) { + Object previous = data(key, value); + + try { + return function.apply(this); + } + finally { + if (previous == null) + data().remove(key); + else + data(key, previous); + } + } } \ No newline at end of file diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index d8c4ea7fdd..87a3407ed9 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -628,6 +628,13 @@ final class Tools { */ DATA_LOCK_WAIT_TIMEOUT_SET, + /** + * [#13573] We're parsing the ON CONFLICT clause, in which + * the VALUES() function or EXCLUDED pseudo + * table have a special semantics. + */ + DATA_PARSE_ON_CONFLICT, + ; private final boolean resetInSubqueryScope;