From 4f29c8db5a2d33d6a07c9938df609a30b50899d2 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 25 Jan 2022 13:18:12 +0100 Subject: [PATCH] [jOOQ/jOOQ#8653] Add support for parsing VALUES , ... --- .../main/java/org/jooq/impl/ParserImpl.java | 72 +++++++++++++------ 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 0a8846132e..874346e274 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -1313,6 +1313,32 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { return result; } + private final Field parseScalarSubqueryIf() { + int p = position(); + + try { + if (peekSelectOrWith(true)) { + parse('('); + SelectQueryImpl select = parseWithOrSelect(); + parse(')'); + if (Tools.degree(select) != 1) + throw exception("Select list must contain exactly one column"); + + return field((Select) select); + } + } + catch (ParserException e) { + + // TODO: Find a better solution than backtracking, here, which doesn't complete in O(N) + if (e.getMessage().contains("Token ')' expected")) + position(p); + else + throw e; + } + + return null; + } + private final SelectQueryImpl parseWithOrSelect() { return parseWithOrSelect(null); } @@ -7113,6 +7139,25 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { + + private final Row parseTableValueConstructorRow(Integer degree) { + if (parseKeywordIf("ROW")) + return parseTuple(degree); + + Field r = null; + + if (degree == null || degree == 1) + r = parseScalarSubqueryIf(); + + if (r != null) + return row(r); + else if (peek('(')) + return parseTuple(degree); + else if (degree == null || degree == 1) + return row(parseField()); + else + throw exception("Expected row of degree: " + degree); + } private final Table parseTableValueConstructor() { parseKeyword("VALUES"); @@ -7120,8 +7165,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { List rows = new ArrayList<>(); Integer degree = null; do { - parseKeywordIf("ROW"); - Row row = parseTuple(degree); + Row row = parseTableValueConstructorRow(degree); rows.add(row); if (degree == null) @@ -8814,28 +8858,12 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { if (!forbidden.isEmpty()) forbidden = EnumSet.noneOf(FunctionKeyword.class); - try { - if (peekSelectOrWith(true)) { - parse('('); - SelectQueryImpl select = parseWithOrSelect(); - parse(')'); - if (Tools.degree(select) != 1) - throw exception("Select list must contain exactly one column"); - - return field((Select) select); - } - } - catch (ParserException e) { - - // TODO: Find a better solution than backtracking, here, which doesn't complete in O(N) - if (e.getMessage().contains("Token ')' expected")) - position(p); - else - throw e; - } + FieldOrRow r = parseScalarSubqueryIf(); + if (r != null) + return r; parse('('); - FieldOrRow r = parseFieldOrRow(); + r = parseFieldOrRow(); List> list = null; if (r instanceof Field) { Field f = (Field) r;