From 2dc8720fcd91ccd0879d440bb7303ea3c4ad3598 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 11 Jul 2019 15:41:01 +0200 Subject: [PATCH] [jOOQ/jOOQ#7597] Do generate a check constraint for non-stored enums --- .../java/org/jooq/impl/CreateTableImpl.java | 41 +++++++++++-------- jOOQ/src/main/java/org/jooq/impl/Tools.java | 32 ++++++++++----- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/CreateTableImpl.java b/jOOQ/src/main/java/org/jooq/impl/CreateTableImpl.java index 74a372ab11..d9a3d74552 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CreateTableImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CreateTableImpl.java @@ -97,6 +97,8 @@ import static org.jooq.impl.Tools.begin; import static org.jooq.impl.Tools.beginExecuteImmediate; import static org.jooq.impl.Tools.end; import static org.jooq.impl.Tools.endExecuteImmediate; +import static org.jooq.impl.Tools.enumLiterals; +import static org.jooq.impl.Tools.storedEnumType; import static org.jooq.impl.Tools.BooleanDataKey.DATA_SELECT_NO_DATA; import static org.jooq.impl.Tools.DataKey.DATA_SELECT_INTO_TABLE; @@ -137,16 +139,17 @@ final class CreateTableImpl extends AbstractRowCountQuery implements /** * Generated UID */ - private static final long serialVersionUID = 8904572826501186329L; - private static final EnumSet NO_SUPPORT_IF_NOT_EXISTS = EnumSet.of(DERBY, FIREBIRD); - private static final EnumSet NO_SUPPORT_WITH_DATA = EnumSet.of(H2, MARIADB, MYSQL, SQLITE); - private static final EnumSet NO_SUPPORT_CTAS_COLUMN_NAMES = EnumSet.of(H2); - private static final EnumSet EMULATE_INDEXES_IN_BLOCK = EnumSet.of(POSTGRES); - private static final EnumSet EMULATE_ENUM_TYPES_AS_CHECK = EnumSet.of(CUBRID, DERBY, FIREBIRD, HSQLDB, SQLITE); - private static final EnumSet REQUIRES_WITH_DATA = EnumSet.of(HSQLDB); - private static final EnumSet WRAP_SELECT_IN_PARENS = EnumSet.of(HSQLDB); - private static final EnumSet SUPPORT_TEMPORARY = EnumSet.of(MARIADB, MYSQL, POSTGRES); - private static final EnumSet EMULATE_COMMENT_IN_BLOCK = EnumSet.of(POSTGRES); + private static final long serialVersionUID = 8904572826501186329L; + private static final EnumSet NO_SUPPORT_IF_NOT_EXISTS = EnumSet.of(DERBY, FIREBIRD); + private static final EnumSet NO_SUPPORT_WITH_DATA = EnumSet.of(H2, MARIADB, MYSQL, SQLITE); + private static final EnumSet NO_SUPPORT_CTAS_COLUMN_NAMES = EnumSet.of(H2); + private static final EnumSet EMULATE_INDEXES_IN_BLOCK = EnumSet.of(POSTGRES); + private static final EnumSet EMULATE_SOME_ENUM_TYPES_AS_CHECK = EnumSet.of(CUBRID, DERBY, FIREBIRD, HSQLDB, POSTGRES, SQLITE); + private static final EnumSet EMULATE_STORED_ENUM_TYPES_AS_CHECK = EnumSet.of(CUBRID, DERBY, FIREBIRD, HSQLDB, SQLITE); + private static final EnumSet REQUIRES_WITH_DATA = EnumSet.of(HSQLDB); + private static final EnumSet WRAP_SELECT_IN_PARENS = EnumSet.of(HSQLDB); + private static final EnumSet SUPPORT_TEMPORARY = EnumSet.of(MARIADB, MYSQL, POSTGRES); + private static final EnumSet EMULATE_COMMENT_IN_BLOCK = EnumSet.of(POSTGRES); @@ -495,17 +498,23 @@ final class CreateTableImpl extends AbstractRowCountQuery implements .formatSeparator() .visit(constraint); - if (EMULATE_ENUM_TYPES_AS_CHECK.contains(ctx.family())) { + if (EMULATE_SOME_ENUM_TYPES_AS_CHECK.contains(ctx.family())) { for (int i = 0; i < columnFields.size(); i++) { DataType type = columnTypes.get(i); if (EnumType.class.isAssignableFrom(type.getType())) { - Field field = columnFields.get(i); - ctx.sql(',') - .formatSeparator() - .visit(DSL.constraint(table.getName() + "_" + field.getName() + "_chk") - .check(((Field) field).in(Tools.inline(Tools.enumLiterals((Class) type.getType()))))); + @SuppressWarnings("unchecked") + DataType enumType = (DataType) type; + + if (EMULATE_STORED_ENUM_TYPES_AS_CHECK.contains(ctx.family()) || !storedEnumType(enumType)) { + Field field = columnFields.get(i); + + ctx.sql(',') + .formatSeparator() + .visit(DSL.constraint(table.getName() + "_" + field.getName() + "_chk") + .check(((Field) field).in(Tools.inline(enumLiterals(enumType.getType()))))); + } } } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 7a587c4801..bfa615c4db 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -4682,8 +4682,8 @@ final class Tools { ctx.visit(K_ENUM).sql('('); String separator = ""; - for (Object e : enumConstants(enumType)) { - ctx.sql(separator).visit(DSL.inline(((EnumType) e).getLiteral())); + for (EnumType e : enumConstants(enumType)) { + ctx.sql(separator).visit(DSL.inline(e.getLiteral())); separator = ", "; } @@ -4695,11 +4695,18 @@ final class Tools { - case POSTGRES: + case POSTGRES: { + + // [#7597] but only if the EnumType.getSchema() value is present + // i.e. when it is a known, stored enum type + if (!storedEnumType(enumType)) + type = emulateEnumType(enumType); + break; + } default: { - type = emulateEnumType(enumType, enumConstants(enumType)); + type = emulateEnumType(enumType); break; } } @@ -4761,8 +4768,12 @@ final class Tools { ctx.sql(' ').visit(K_COLLATE).sql(' ').visit(type.collation()); } - private static Object[] enumConstants(DataType type) { - Object[] enums = type.getType().getEnumConstants(); + static boolean storedEnumType(DataType enumType) { + return enumConstants(enumType)[0].getSchema() != null; + } + + private static EnumType[] enumConstants(DataType type) { + EnumType[] enums = type.getType().getEnumConstants(); if (enums == null) throw new DataTypeException("EnumType must be a Java enum"); @@ -4774,11 +4785,12 @@ final class Tools { return emulateEnumType(type, enumConstants(type)); } - static final DataType emulateEnumType(DataType type, Object[] enums) { + @SuppressWarnings({ "unchecked", "rawtypes" }) + private static final DataType emulateEnumType(DataType type, EnumType[] enums) { int length = 0; - for (Object e : enums) - if (((EnumType) e).getLiteral() != null) - length = Math.max(length, ((EnumType) e).getLiteral().length()); + for (EnumType e : enums) + if (e.getLiteral() != null) + length = Math.max(length, e.getLiteral().length()); return VARCHAR(length).nullability(type.nullability()).defaultValue((Field) type.defaultValue()); }