[#3805] Emulation of repeatable nullability changes for Oracle

This commit is contained in:
lukaseder 2017-07-31 15:07:15 +02:00
parent fe9cdba3d1
commit 0ec191b973
2 changed files with 158 additions and 26 deletions

View File

@ -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

View File

@ -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 <code>BEGIN</code> 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 <code>END</code> 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 <code>DROP .. IF EXISTS</code> statement with
* <code>BEGIN EXECUTE IMMEDIATE '...' EXCEPTION WHEN ... END;</code>, 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<Object, Object> data, DataKey key) {
/**
* Increment a counter and return true if the counter was zero prior to
* incrementing.
*/
static final boolean increment(Map<Object, Object> 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<Object, Object> 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) {