From 988979c172f6dd719af889ec0a16a282e81cc512 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 12 Aug 2013 11:26:51 +0200 Subject: [PATCH] [#2665] Implement SPI for RenderContext and BindContext listening to allow for custom SQL transformation * Added INSERT clause implementation draft. --- jOOQ/src/main/java/org/jooq/Clause.java | 65 ++++++++++++++++++- .../java/org/jooq/impl/FieldMapForInsert.java | 6 +- .../org/jooq/impl/FieldMapsForInsert.java | 8 ++- .../java/org/jooq/impl/InsertQueryImpl.java | 8 ++- .../java/org/jooq/test/VisitContextTest.java | 25 +++++++ 5 files changed, 106 insertions(+), 6 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/Clause.java b/jOOQ/src/main/java/org/jooq/Clause.java index e9cfa66381..05a52f9e44 100644 --- a/jOOQ/src/main/java/org/jooq/Clause.java +++ b/jOOQ/src/main/java/org/jooq/Clause.java @@ -320,15 +320,76 @@ public enum Clause { SELECT_ORDER_BY, + // ------------------------------------------------------------------------- + // Clauses that are used in an INSERT statement + // ------------------------------------------------------------------------- + /** + * A complete INSERT statement. + */ INSERT, + + /** + * The INSERT INTO clause within an {@link #INSERT} statement. + *

+ * This clause surrounds + *

+ */ INSERT_INSERT_INTO, + + /** + * The VALUES clause within an {@link #INSERT} statement. + *

+ * This clause surrounds + *

+ */ + INSERT_VALUES, + + /** + * The SELECT clause within an {@link #INSERT} statement. + *

+ * This clause surrounds a {@link #SELECT} clause. + */ + INSERT_SELECT, + + /** + * The ON DUPLICATE KEY UPDATE clause within an {@link #INSERT} + * statement. + *

+ * This clause surrounds several + * {@link #INSERT_ON_DUPLICATE_KEY_UPDATE_ASSIGNMENT} clauses. + *

+ */ INSERT_ON_DUPLICATE_KEY_UPDATE, + + /** + * The ON DUPLICATE KEY UPDATE clause within an {@link #INSERT} + * statement. + *

+ * This clause surrounds two {@link #FIELD} clauses. + */ INSERT_ON_DUPLICATE_KEY_UPDATE_ASSIGNMENT, + + /** + * The RETURNING clause within an {@link #INSERT} statement. + *

+ * This clause surrounds + *

+ */ INSERT_RETURNING, - - // ------------------------------------------------------------------------- // Clauses that are used in an UPDATE statement // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldMapForInsert.java b/jOOQ/src/main/java/org/jooq/impl/FieldMapForInsert.java index 3cdbb4d982..2bcc59678c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FieldMapForInsert.java +++ b/jOOQ/src/main/java/org/jooq/impl/FieldMapForInsert.java @@ -36,6 +36,7 @@ package org.jooq.impl; import static org.jooq.Clause.DUMMY; +import static org.jooq.Clause.INSERT_VALUES; import static org.jooq.impl.Utils.visitAll; import java.util.Collection; @@ -65,8 +66,11 @@ class FieldMapForInsert extends AbstractQueryPartMap, Field> { public final void toSQL(RenderContext context) { toSQLReferenceKeys(context); context.formatSeparator() - .keyword("values "); + .start(INSERT_VALUES) + .keyword("values") + .sql(" "); toSQLReferenceValues(context); + context.end(INSERT_VALUES); } final void toSQLReferenceKeys(RenderContext context) { diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java index fd60850181..04de579624 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java +++ b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java @@ -35,7 +35,7 @@ */ package org.jooq.impl; -import static org.jooq.Clause.DUMMY; +import static org.jooq.Clause.INSERT_SELECT; import static org.jooq.impl.Utils.visitAll; import java.util.ArrayList; @@ -90,11 +90,15 @@ class FieldMapsForInsert extends AbstractQueryPart { case INGRES: case ORACLE: case SQLITE: + context.start(INSERT_SELECT); toSQLInsertSelect(context); + context.end(INSERT_SELECT); + break; default: toSQL92Values(context); + break; } } @@ -142,7 +146,7 @@ class FieldMapsForInsert extends AbstractQueryPart { @Override public final Clause[] clauses(Context ctx) { - return new Clause[] { DUMMY }; + return null; } // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java index b6079f1bad..6094a16771 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java @@ -38,7 +38,9 @@ package org.jooq.impl; import static java.util.Arrays.asList; import static org.jooq.Clause.INSERT; +import static org.jooq.Clause.INSERT_INSERT_INTO; import static org.jooq.Clause.INSERT_ON_DUPLICATE_KEY_UPDATE_ASSIGNMENT; +import static org.jooq.Clause.INSERT_RETURNING; import static org.jooq.SQLDialect.MARIADB; import static org.jooq.SQLDialect.MYSQL; @@ -326,17 +328,21 @@ class InsertQueryImpl extends AbstractStoreQuery implements } private final void toSQLInsert(RenderContext context) { - context.keyword("insert") + context.start(INSERT_INSERT_INTO) + .keyword("insert") .sql(" ") // [#1295] MySQL natively supports the IGNORE keyword .keyword((onDuplicateKeyIgnore && asList(MARIADB, MYSQL).contains(context.configuration().dialect())) ? "ignore " : "") .keyword("into") .sql(" ") .visit(getInto()) + .end(INSERT_INSERT_INTO) .sql(" ") .visit(insertMaps); + context.start(INSERT_RETURNING); toSQLReturning(context); + context.end(INSERT_RETURNING); } private final void bindInsert(BindContext context) { diff --git a/jOOQ/src/test/java/org/jooq/test/VisitContextTest.java b/jOOQ/src/test/java/org/jooq/test/VisitContextTest.java index 7998cc0ad9..12b227998a 100644 --- a/jOOQ/src/test/java/org/jooq/test/VisitContextTest.java +++ b/jOOQ/src/test/java/org/jooq/test/VisitContextTest.java @@ -57,6 +57,9 @@ import static org.jooq.Clause.FIELD; import static org.jooq.Clause.FIELD_REFERENCE; import static org.jooq.Clause.FIELD_ROW; import static org.jooq.Clause.FIELD_VALUE; +import static org.jooq.Clause.INSERT; +import static org.jooq.Clause.INSERT_INSERT_INTO; +import static org.jooq.Clause.INSERT_VALUES; import static org.jooq.Clause.SELECT; import static org.jooq.Clause.SELECT_CONNECT_BY; import static org.jooq.Clause.SELECT_FROM; @@ -201,6 +204,28 @@ public class VisitContextTest extends AbstractTest { } } + @Test + public void test_INSERT_VALUES_simple() { + ctx.insertInto(TABLE1) + .values(1, "value", null) + .getSQL(); + + assertEvents(asList( + asList(INSERT), + asList(INSERT, INSERT_INSERT_INTO), + asList(INSERT, INSERT_INSERT_INTO, TABLE), + asList(INSERT, INSERT_INSERT_INTO, TABLE, TABLE_REFERENCE), + asList(INSERT, INSERT_VALUES), + asList(INSERT, INSERT_VALUES, FIELD_ROW), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE) + )); + } + @Test public void test_UPDATE_SET_simple() { ctx.update(TABLE1)