From 77d4d004796f4d2c23e43c15d4d95a6a1d167ab2 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 3 Oct 2019 13:18:20 +0200 Subject: [PATCH] [jOOQ/jOOQ#8528] DDL interpretation improvements --- .../java/org/jooq/impl/AlterViewImpl.java | 4 + .../java/org/jooq/impl/CreateViewImpl.java | 6 + .../java/org/jooq/impl/DDLInterpreter.java | 144 +++++++++++++++--- .../main/java/org/jooq/impl/DropViewImpl.java | 15 +- 4 files changed, 144 insertions(+), 25 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/AlterViewImpl.java b/jOOQ/src/main/java/org/jooq/impl/AlterViewImpl.java index 959ee369ca..dbd537bd36 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AlterViewImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/AlterViewImpl.java @@ -108,6 +108,10 @@ final class AlterViewImpl extends AbstractRowCountQuery implements this.ifExists = ifExists; } + final Table $view() { return view; } + final boolean $ifExists() { return ifExists; } + final Table $renameTo() { return renameTo; } + // ------------------------------------------------------------------------ // XXX: DSL API // ------------------------------------------------------------------------ diff --git a/jOOQ/src/main/java/org/jooq/impl/CreateViewImpl.java b/jOOQ/src/main/java/org/jooq/impl/CreateViewImpl.java index 542fe9e4b8..0afeed7de0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CreateViewImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CreateViewImpl.java @@ -138,6 +138,12 @@ final class CreateViewImpl extends AbstractRowCountQuery imple } + final boolean $ifNotExists() { return ifNotExists; } + final boolean $orReplace() { return orReplace; } + final Table $view() { return view; } + final Field[] $fields() { return fields; } + final Select $select() { return parsed(); } + // ------------------------------------------------------------------------ // XXX: DSL API // ------------------------------------------------------------------------ diff --git a/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java b/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java index 366770214e..472658cf54 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java +++ b/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java @@ -41,6 +41,7 @@ import static org.jooq.impl.AbstractName.NO_NAME; import static org.jooq.impl.DSL.unquotedName; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -54,9 +55,11 @@ import org.jooq.Index; import org.jooq.Meta; import org.jooq.Name; import org.jooq.Name.Quoted; +import org.jooq.Named; import org.jooq.Query; import org.jooq.Record; import org.jooq.Schema; +import org.jooq.Select; import org.jooq.SortField; import org.jooq.SortOrder; import org.jooq.Table; @@ -113,6 +116,12 @@ final class DDLInterpreter { accept0((AlterTableImpl) query); else if (query instanceof DropTableImpl) accept0((DropTableImpl) query); + else if (query instanceof CreateViewImpl) + accept0((CreateViewImpl) query); + else if (query instanceof AlterViewImpl) + accept0((AlterViewImpl) query); + else if (query instanceof DropViewImpl) + accept0((DropViewImpl) query); else if (query instanceof CommentOnImpl) accept0((CommentOnImpl) query); else @@ -187,18 +196,7 @@ final class DDLInterpreter { return; } - MutableTable t = new MutableTable((UnqualifiedName) table.getUnqualifiedName(), schema, query.$comment()); - List> columns = query.$columnFields(); - if (!columns.isEmpty()) { - for (int i = 0; i < columns.size(); i++) { - Field column = columns.get(i); - t.fields.add(new MutableField((UnqualifiedName) column.getUnqualifiedName(), t, query.$columnTypes().get(i))); - } - } - else if (query.$select() != null) { - for (Field column : query.$select().fields()) - t.fields.add(new MutableField((UnqualifiedName) column.getUnqualifiedName(), t, column.getDataType())); - } + MutableTable t = newTable(table, schema, query.$columnFields(), query.$columnTypes(), query.$select(), query.$comment(), false); for (Constraint constraint : query.$constraints()) { ConstraintImpl impl = (ConstraintImpl) constraint; @@ -263,7 +261,7 @@ final class DDLInterpreter { MutableSchema schema = getSchema(table.getSchema()); // TODO schema == null - MutableTable existing = schema.dropTable((UnqualifiedName) table.getUnqualifiedName()); + MutableTable existing = schema.drop(table); if (existing == null) { if (!query.$ifExists()) throw tableNotExists(table); @@ -272,6 +270,66 @@ final class DDLInterpreter { } } + private final void accept0(CreateViewImpl query) { + Table table = query.$view(); + MutableSchema schema = getSchema(table.getSchema()); + + MutableTable existing = schema.table(table); + if (existing != null) { + if (!existing.view) + throw objectNotView(table); + else if (query.$orReplace()) + schema.drop(table); + else if (!query.$ifNotExists()) + throw viewAlreadyExists(table); + else + return; + } + + List> columnTypes = new ArrayList<>(); + for (Field f : query.$select().getSelect()) + columnTypes.add(f.getDataType()); + + newTable(table, schema, Arrays.asList(query.$fields()), columnTypes, query.$select(), null, true); + } + + private final void accept0(AlterViewImpl query) { + Table table = query.$view(); + MutableSchema schema = getSchema(table.getSchema()); + + MutableTable existing = schema.table(table); + if (existing == null) { + if (!query.$ifExists()) + throw viewNotExists(table); + + return; + } + else if (!existing.view) + throw objectNotView(table); + + if (query.$renameTo() != null) + existing.name = (UnqualifiedName) query.$renameTo().getUnqualifiedName(); + else + throw unsupportedQuery(query); + } + + private final void accept0(DropViewImpl query) { + Table table = query.$view(); + MutableSchema schema = getSchema(table.getSchema()); + + MutableTable existing = schema.table(table); + if (existing == null) { + if (!query.$ifExists()) + throw viewNotExists(table); + + return; + } + else if (!existing.view) + throw objectNotView(table); + + schema.drop(table); + } + private final void accept0(CommentOnImpl query) { Table table = query.$table(); Field field = query.$field(); @@ -284,7 +342,6 @@ final class DDLInterpreter { throw unsupportedQuery(query); } - // ------------------------------------------------------------------------- // Exceptions // ------------------------------------------------------------------------- @@ -309,10 +366,26 @@ final class DDLInterpreter { return new DataDefinitionException("Table does not exist: " + table.getQualifiedName()); } + private static final DataDefinitionException objectNotTable(Table table) { + return new DataDefinitionException("Object is not a table: " + table.getQualifiedName()); + } + + private static final DataDefinitionException objectNotView(Table table) { + return new DataDefinitionException("Object is not a view: " + table.getQualifiedName()); + } + private static final DataDefinitionException tableAlreadyExists(Table table) { return new DataDefinitionException("Table already exists: " + table.getQualifiedName()); } + private static final DataDefinitionException viewNotExists(Table table) { + return new DataDefinitionException("View does not exist: " + table.getQualifiedName()); + } + + private static final DataDefinitionException viewAlreadyExists(Table table) { + return new DataDefinitionException("View already exists: " + table.getQualifiedName()); + } + private static final DataDefinitionException fieldNotExists(Field field) { return new DataDefinitionException("Field does not exist: " + field.getQualifiedName()); } @@ -348,6 +421,31 @@ final class DDLInterpreter { return schema; } + private static final MutableTable newTable( + Table table, + MutableSchema schema, + List> columns, + List> columnTypes, + Select select, + Comment comment, + boolean view + ) { + MutableTable t = new MutableTable((UnqualifiedName) table.getUnqualifiedName(), schema, comment, view); + + if (!columns.isEmpty()) { + for (int i = 0; i < columns.size(); i++) { + Field column = columns.get(i); + t.fields.add(new MutableField((UnqualifiedName) column.getUnqualifiedName(), t, columnTypes.get(i))); + } + } + else if (select != null) { + for (Field column : select.fields()) + t.fields.add(new MutableField((UnqualifiedName) column.getUnqualifiedName(), t, column.getDataType())); + } + + return t; + } + private final MutableTable table(Table table) { return table(table, true); } @@ -381,7 +479,11 @@ final class DDLInterpreter { return result; } - private static UnqualifiedName normalize(UnqualifiedName name) { + private static final UnqualifiedName normalize(Named named) { + return normalize((UnqualifiedName) named.getUnqualifiedName()); + } + + private static final UnqualifiedName normalize(UnqualifiedName name) { if (name == null) return null; @@ -463,7 +565,7 @@ final class DDLInterpreter { } final MutableTable table(Table t) { - UnqualifiedName n = normalize((UnqualifiedName) t.getUnqualifiedName()); + UnqualifiedName n = normalize(t); for (MutableTable table : tables) if (table.name.equals(n)) @@ -472,11 +574,13 @@ final class DDLInterpreter { return null; } - final MutableTable dropTable(UnqualifiedName n) { - n = normalize(n); + final MutableTable drop(Table t) { + UnqualifiedName n = normalize(t); + for (int i = 0; i < tables.size(); i++) if (tables.get(i).name.equals(n)) return tables.remove(i); + return null; } @@ -503,11 +607,13 @@ final class DDLInterpreter { MutableUniqueKey primaryKey; List uniqueKeys = new ArrayList<>(); List indexes = new ArrayList<>(); + boolean view; - MutableTable(UnqualifiedName name, MutableSchema schema, Comment comment) { + MutableTable(UnqualifiedName name, MutableSchema schema, Comment comment, boolean view) { super(name, comment); this.schema = schema; + this.view = view; schema.tables.add(this); } diff --git a/jOOQ/src/main/java/org/jooq/impl/DropViewImpl.java b/jOOQ/src/main/java/org/jooq/impl/DropViewImpl.java index 1f0a4e4b32..4e14ea35c8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DropViewImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/DropViewImpl.java @@ -76,20 +76,23 @@ final class DropViewImpl extends AbstractRowCountQuery implements private static final Clause[] CLAUSES = { DROP_VIEW }; private static final Set NO_SUPPORT_IF_EXISTS = SQLDialect.supported(DERBY, FIREBIRD); - private final Table table; + private final Table view; private final boolean ifExists; - DropViewImpl(Configuration configuration, Table table) { - this(configuration, table, false); + DropViewImpl(Configuration configuration, Table view) { + this(configuration, view, false); } - DropViewImpl(Configuration configuration, Table table, boolean ifExists) { + DropViewImpl(Configuration configuration, Table view, boolean ifExists) { super(configuration); - this.table = table; + this.view = view; this.ifExists = ifExists; } + final Table $view() { return view; } + final boolean $ifExists() { return ifExists; } + // ------------------------------------------------------------------------ // XXX: QueryPart API // ------------------------------------------------------------------------ @@ -117,7 +120,7 @@ final class DropViewImpl extends AbstractRowCountQuery implements if (ifExists && supportsIfExists(ctx)) ctx.visit(K_IF_EXISTS).sql(' '); - ctx.visit(table); + ctx.visit(view); ctx.end(DROP_VIEW_TABLE); }