From c0e84fa670cdbd7e3c05d923d18fdf84793c12bc Mon Sep 17 00:00:00 2001 From: lukaseder Date: Tue, 15 May 2018 14:09:32 +0200 Subject: [PATCH] [#7171] Support parsing MERGE .. WHERE --- .../resources/org/jooq/web/grammar-3.11.txt | 4 +-- .../main/java/org/jooq/impl/ParserImpl.java | 33 ++++++++++++++++--- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/grammar-3.11.txt b/jOOQ-manual/src/main/resources/org/jooq/web/grammar-3.11.txt index fe31a277c4..dc171ed12b 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/grammar-3.11.txt +++ b/jOOQ-manual/src/main/resources/org/jooq/web/grammar-3.11.txt @@ -248,8 +248,8 @@ mergeStatement = [ with ] 'MERGE' [ 'INTO' ] tableName [ [ 'AS' ] identifier ] 'USING' '(' select ')' [ [ 'AS' ] identifier ] 'ON' condition break { - 'WHEN MATCHED THEN UPDATE' 'SET' setClauses - | 'WHEN NOT MATCHED THEN INSERT' '(' identifiers ')' 'VALUES' '(' fields ')' + 'WHEN' 'MATCHED' [ 'AND' condition ] 'THEN' 'UPDATE' 'SET' setClauses [ 'WHERE' condition ] + | 'WHEN' 'NOT' 'MATCHED' [ 'AND' condition ] 'THEN' 'INSERT' '(' identifiers ')' 'VALUES' '(' fields ')' [ 'WHERE' condition ] } ; diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 22e89fa6e9..a617228e78 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -1559,13 +1559,26 @@ final class ParserImpl implements Parser { boolean insert = false; Field[] insertColumns = null; List> insertValues = null; + Condition insertWhere = null; Map, Object> updateSet = null; + Condition updateWhere = null; for (;;) { - if (!update && (update = parseKeywordIf(ctx, "WHEN MATCHED THEN UPDATE SET"))) { + if (!update && (update = parseKeywordIf(ctx, "WHEN MATCHED"))) { + if (parseKeywordIf(ctx, "AND")) + updateWhere = parseCondition(ctx); + + parseKeyword(ctx, "THEN UPDATE SET"); updateSet = parseSetClauseList(ctx); + + if (updateWhere == null && parseKeywordIf(ctx, "WHERE")) + updateWhere = parseCondition(ctx); } - else if (!insert && (insert = parseKeywordIf(ctx, "WHEN NOT MATCHED THEN INSERT"))) { + else if (!insert && (insert = parseKeywordIf(ctx, "WHEN NOT MATCHED"))) { + if (parseKeywordIf(ctx, "AND")) + insertWhere = parseCondition(ctx); + + parseKeyword(ctx, "THEN INSERT"); parse(ctx, '('); insertColumns = Tools.fieldsByName(parseIdentifiers(ctx).toArray(EMPTY_NAME)); parse(ctx, ')'); @@ -1576,6 +1589,9 @@ final class ParserImpl implements Parser { if (insertColumns.length != insertValues.size()) throw ctx.exception("Insert column size (" + insertColumns.length + ") must match values size (" + insertValues.size() + ")"); + + if (insertWhere == null && parseKeywordIf(ctx, "WHERE")) + insertWhere = parseCondition(ctx); } else break; @@ -1584,14 +1600,21 @@ final class ParserImpl implements Parser { if (!update && !insert) throw ctx.exception("At least one of UPDATE or INSERT clauses is required"); - // TODO support WHERE // TODO support multi clause MERGE // TODO support DELETE MergeUsingStep s1 = (with == null ? ctx.dsl.mergeInto(target) : with.mergeInto(target)); MergeMatchedStep s2 = s1.using(usingTable).on(on); - MergeNotMatchedStep s3 = update ? s2.whenMatchedThenUpdate().set(updateSet) : s2; - MergeFinalStep s4 = insert ? s3.whenNotMatchedThenInsert(insertColumns).values(insertValues) : s3; + MergeNotMatchedStep s3 = update + ? updateWhere != null + ? s2.whenMatchedThenUpdate().set(updateSet).where(updateWhere) + : s2.whenMatchedThenUpdate().set(updateSet) + : s2; + MergeFinalStep s4 = insert + ? insertWhere != null + ? s3.whenNotMatchedThenInsert(insertColumns).values(insertValues).where(insertWhere) + : s3.whenNotMatchedThenInsert(insertColumns).values(insertValues) + : s3; return s4; }