diff --git a/jOOQ/src/main/java/org/jooq/impl/AlterTableImpl.java b/jOOQ/src/main/java/org/jooq/impl/AlterTableImpl.java index e64e38d74a..dca3ef3176 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AlterTableImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/AlterTableImpl.java @@ -67,20 +67,24 @@ import static org.jooq.impl.Keywords.K_ALTER; import static org.jooq.impl.Keywords.K_ALTER_COLUMN; import static org.jooq.impl.Keywords.K_ALTER_CONSTRAINT; import static org.jooq.impl.Keywords.K_ALTER_TABLE; -import static org.jooq.impl.Keywords.K_BEGIN; import static org.jooq.impl.Keywords.K_CASCADE; import static org.jooq.impl.Keywords.K_CHANGE_COLUMN; import static org.jooq.impl.Keywords.K_DEFAULT; -import static org.jooq.impl.Keywords.K_DO; import static org.jooq.impl.Keywords.K_DROP; import static org.jooq.impl.Keywords.K_DROP_COLUMN; import static org.jooq.impl.Keywords.K_DROP_CONSTRAINT; -import static org.jooq.impl.Keywords.K_END; +import static org.jooq.impl.Keywords.K_ELSE; +import static org.jooq.impl.Keywords.K_END_IF; +import static org.jooq.impl.Keywords.K_EXCEPTION; import static org.jooq.impl.Keywords.K_EXEC; +import static org.jooq.impl.Keywords.K_EXECUTE_IMMEDIATE; +import static org.jooq.impl.Keywords.K_IF; import static org.jooq.impl.Keywords.K_IF_EXISTS; +import static org.jooq.impl.Keywords.K_LIKE; import static org.jooq.impl.Keywords.K_MODIFY; import static org.jooq.impl.Keywords.K_NOT_NULL; import static org.jooq.impl.Keywords.K_NULL; +import static org.jooq.impl.Keywords.K_RAISE; import static org.jooq.impl.Keywords.K_RENAME_COLUMN; import static org.jooq.impl.Keywords.K_RENAME_CONSTRAINT; import static org.jooq.impl.Keywords.K_RENAME_INDEX; @@ -89,9 +93,13 @@ import static org.jooq.impl.Keywords.K_RENAME_TO; import static org.jooq.impl.Keywords.K_SET; import static org.jooq.impl.Keywords.K_SET_DATA_TYPE; import static org.jooq.impl.Keywords.K_SET_DEFAULT; +import static org.jooq.impl.Keywords.K_THEN; import static org.jooq.impl.Keywords.K_TO; import static org.jooq.impl.Keywords.K_TYPE; import static org.jooq.impl.Keywords.K_USING_INDEX; +import static org.jooq.impl.Keywords.K_WHEN; +import static org.jooq.impl.Tools.begin; +import static org.jooq.impl.Tools.end; import static org.jooq.impl.Tools.toSQLDDLTypeDeclaration; import static org.jooq.impl.Tools.toSQLDDLTypeDeclarationForAddition; import static org.jooq.impl.Tools.DataKey.DATA_CONSTRAINT_REFERENCE; @@ -114,6 +122,7 @@ import org.jooq.Field; import org.jooq.Index; import org.jooq.Name; import org.jooq.Nullability; +import org.jooq.Query; import org.jooq.SQLDialect; import org.jooq.Table; @@ -904,18 +913,57 @@ final class AlterTableImpl extends AbstractQuery implements private final void alterColumnTypeAndNullabilityInBlock(Context ctx) { boolean qualify = ctx.qualify(); - ctx.visit(K_DO).sql(" $$").formatSeparator() - .visit(K_BEGIN).formatIndentStart().formatSeparator(); + begin(ctx); + + + + + accept1(ctx); - ctx.sql(';').formatSeparator() - .visit(K_ALTER_TABLE).sql(' ').visit(table).formatIndentStart().formatSeparator() - .visit(K_ALTER).sql(' ').qualify(false).visit(alterColumn).qualify(qualify).sql(' ') - .visit(alterColumnType.nullable() ? K_DROP : K_SET).sql(' ').visit(K_NOT_NULL).sql(';') - .formatIndentEnd() - .formatIndentEnd().formatSeparator() - .visit(K_END).sql(" $$"); + + + + + + + ctx.sql(';').formatSeparator(); + + switch (ctx.family()) { + + + + + + + + + + + + + + + + + + + + + + + case POSTGRES: { + + // TODO [#6472] use jOOQ API here, once this is available + ctx.visit(K_ALTER_TABLE).sql(' ').visit(table).formatIndentStart().formatSeparator() + .visit(K_ALTER).sql(' ').qualify(false).visit(alterColumn).qualify(qualify).sql(' ') + .visit(alterColumnType.nullable() ? K_DROP : K_SET).sql(' ').visit(K_NOT_NULL).sql(';') + .formatIndentEnd(); + break; + } + } + end(ctx); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index d5b3c5cfa2..480acdcadf 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -123,6 +123,7 @@ import static org.jooq.impl.Keywords.K_START_WITH; import static org.jooq.impl.Keywords.K_THEN; import static org.jooq.impl.Keywords.K_THROW; import static org.jooq.impl.Keywords.K_WHEN; +import static org.jooq.impl.Tools.DataKey.DATA_BLOCK_NESTING; import static org.jooq.tools.reflect.Reflect.accessible; import java.io.Serializable; @@ -459,6 +460,11 @@ final class Tools { + + /** + * The level of anonymous block nesting, in case we're generating a block. + */ + DATA_BLOCK_NESTING, } /** @@ -3445,6 +3451,67 @@ final class Tools { return result; } + /** + * Generate the BEGIN part of an anonymous procedural block. + */ + static final void begin(Context ctx) { + switch (ctx.family()) { + + + + + + + + + + case FIREBIRD: { + ctx.visit(K_EXECUTE_BLOCK).formatSeparator() + .visit(K_AS).formatSeparator() + .visit(K_BEGIN).formatIndentStart().formatSeparator(); + break; + } + + case POSTGRES: { + if (increment(ctx.data(), DATA_BLOCK_NESTING)) + ctx.visit(K_DO).sql(" $$").formatSeparator(); + + ctx.visit(K_BEGIN).formatIndentStart().formatSeparator(); + } + } + } + + /** + * Generate the END part of an anonymous procedural block. + */ + static final void end(Context ctx) { + switch (ctx.family()) { + + + + + + + + + + case FIREBIRD: { + ctx.formatIndentEnd().formatSeparator() + .visit(K_END); + break; + } + case POSTGRES: { + ctx.formatIndentEnd().formatSeparator() + .visit(K_END); + + if (decrement(ctx.data(), DATA_BLOCK_NESTING)) + ctx.sql(" $$"); + + break; + } + } + } + /** * Wrap a DROP .. IF EXISTS statement with * BEGIN EXECUTE IMMEDIATE '...' EXCEPTION WHEN ... END;, if @@ -3497,17 +3564,11 @@ final class Tools { - - case FIREBIRD: { - ctx.visit(K_EXECUTE_BLOCK).formatSeparator() - .visit(K_AS).formatSeparator() - .visit(K_BEGIN).formatIndentStart().formatSeparator() - .visit(K_EXECUTE_STATEMENT).sql(" '").stringLiteral(true).formatIndentStart().formatSeparator(); - + ctx.visit(K_EXECUTE_STATEMENT).sql(" '").stringLiteral(true).formatIndentStart().formatSeparator(); break; } @@ -3594,17 +3655,14 @@ final class Tools { - - case FIREBIRD: { ctx.formatIndentEnd().formatSeparator().stringLiteral(false).sql("';").formatSeparator() .visit(K_WHEN).sql(" sqlcode -607 ").visit(K_DO).formatIndentStart().formatSeparator() - .visit(K_BEGIN).sql(' ').visit(K_END).formatIndentEnd().formatIndentEnd().formatSeparator() - .visit(K_END); - + .visit(K_BEGIN).sql(' ').visit(K_END).formatIndentEnd(); + end(ctx); break; } @@ -3715,7 +3773,6 @@ final class Tools { - default: executeImmediateEnd(ctx, type); break; @@ -3980,11 +4037,38 @@ final class Tools { return null; } - static final void increment(Map data, DataKey key) { + /** + * Increment a counter and return true if the counter was zero prior to + * incrementing. + */ + static final boolean increment(Map data, DataKey key) { + boolean result = true; Integer updateCounts = (Integer) data.get(key); + if (updateCounts == null) updateCounts = 0; + else + result = false; + data.put(key, updateCounts + 1); + return result; + } + + /** + * Decrement a counter and return true if the counter is zero after + * decrementing. + */ + static final boolean decrement(Map data, DataKey key) { + boolean result = false; + Integer updateCounts = (Integer) data.get(key); + + if (updateCounts == null || updateCounts == 0) + throw new IllegalStateException("Unmatching increment / decrement on key: " + key); + else if (updateCounts == 1) + result = true; + + data.put(key, updateCounts - 1); + return result; } static Field tableField(Table table, Object field) {