[#7139] Add support for CREATE TABLE AS SELECT .. WITH [ NO ] DATA

This commit is contained in:
lukaseder 2018-02-02 10:42:16 +01:00
parent 95a775a0d6
commit 9def7171d3
10 changed files with 193 additions and 8 deletions

View File

@ -2298,6 +2298,8 @@ public class JavaGenerator extends AbstractGenerator {
@ -6096,7 +6098,6 @@ public class JavaGenerator extends AbstractGenerator {
return result;
}
@SuppressWarnings("unchecked")
private static final <T> List<T> list(T first, List<T> remaining) {
List<T> result = new ArrayList<T>();

View File

@ -116,6 +116,17 @@ package org.jooq;

View File

@ -67,7 +67,7 @@ public interface CreateTableAsStep<R extends Record> {
* Add an <code>AS</code> clause to the <code>CREATE TABLE</code> statement.
*/
@Support({ CUBRID, DERBY, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
CreateTableOnCommitStep as(Select<? extends R> select);
CreateTableWithDataStep as(Select<? extends R> select);
/**
* Add a column to the column list of the <code>CREATE TABLE</code>

View File

@ -0,0 +1,75 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;
// ...
// ...
import static org.jooq.SQLDialect.CUBRID;
// ...
import static org.jooq.SQLDialect.DERBY;
import static org.jooq.SQLDialect.H2;
// ...
import static org.jooq.SQLDialect.HSQLDB;
// ...
import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
import static org.jooq.SQLDialect.POSTGRES;
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
/**
* A {@link Query} that can create tables.
*
* @author Lukas Eder
*/
public interface CreateTableWithDataStep extends CreateTableOnCommitStep {
/**
* Add a <code>WITH DATA</code> clause.
*/
@Support({ CUBRID, DERBY, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
CreateTableCommentStep withData();
/**
* Add a <code>WITH DATA</code> clause.
*/
@Support({ CUBRID, DERBY, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
CreateTableCommentStep withNoData();
}

View File

@ -145,6 +145,8 @@ package org.jooq.impl;

View File

@ -386,6 +386,34 @@ package org.jooq.impl;

View File

@ -37,6 +37,8 @@
*/
package org.jooq.impl;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static org.jooq.Clause.CREATE_TABLE;
import static org.jooq.Clause.CREATE_TABLE_AS;
import static org.jooq.Clause.CREATE_TABLE_COLUMNS;
@ -47,6 +49,7 @@ import static org.jooq.Clause.CREATE_TABLE_NAME;
// ...
import static org.jooq.SQLDialect.DERBY;
import static org.jooq.SQLDialect.FIREBIRD;
import static org.jooq.SQLDialect.H2;
// ...
import static org.jooq.SQLDialect.HSQLDB;
import static org.jooq.SQLDialect.MARIADB;
@ -77,6 +80,7 @@ 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.DataKey.DATA_SELECT_INTO_TABLE;
import static org.jooq.impl.Tools.DataKey.DATA_SELECT_NO_DATA;
import java.util.ArrayList;
import java.util.Arrays;
@ -91,6 +95,7 @@ import org.jooq.Constraint;
import org.jooq.Context;
import org.jooq.CreateTableAsStep;
import org.jooq.CreateTableColumnStep;
import org.jooq.CreateTableWithDataStep;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.Name;
@ -108,6 +113,7 @@ final class CreateTableImpl<R extends Record> extends AbstractQuery implements
// Cascading interface implementations for CREATE TABLE behaviour
CreateTableAsStep<R>,
CreateTableWithDataStep,
CreateTableColumnStep {
/**
@ -115,6 +121,8 @@ final class CreateTableImpl<R extends Record> extends AbstractQuery implements
*/
private static final long serialVersionUID = 8904572826501186329L;
private static final EnumSet<SQLDialect> NO_SUPPORT_IF_NOT_EXISTS = EnumSet.of(DERBY, FIREBIRD);
private static final EnumSet<SQLDialect> NO_SUPPORT_WITH_DATA = EnumSet.of(H2);
private static final EnumSet<SQLDialect> REQUIRES_WITH_DATA = EnumSet.of(HSQLDB);
private static final EnumSet<SQLDialect> WRAP_SELECT_IN_PARENS = EnumSet.of(HSQLDB);
private static final EnumSet<SQLDialect> SUPPORT_TEMPORARY = EnumSet.of(MARIADB, MYSQL, POSTGRES);
@ -123,6 +131,7 @@ final class CreateTableImpl<R extends Record> extends AbstractQuery implements
private final Table<?> table;
private Select<?> select;
private Boolean withData;
private final List<Field<?>> columnFields;
private final List<DataType<?>> columnTypes;
private final List<Constraint> constraints;
@ -153,6 +162,18 @@ final class CreateTableImpl<R extends Record> extends AbstractQuery implements
return this;
}
@Override
public final CreateTableImpl<R> withData() {
withData = true;
return this;
}
@Override
public final CreateTableImpl<R> withNoData() {
withData = false;
return this;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public final CreateTableImpl<R> column(Field<?> field) {
@ -369,19 +390,31 @@ final class CreateTableImpl<R extends Record> extends AbstractQuery implements
else
ctx.formatSeparator();
if (FALSE.equals(withData) && NO_SUPPORT_WITH_DATA.contains(ctx.family()))
ctx.data(DATA_SELECT_NO_DATA, true);
ctx.start(CREATE_TABLE_AS)
.visit(select)
.end(CREATE_TABLE_AS);
if (FALSE.equals(withData) && NO_SUPPORT_WITH_DATA.contains(ctx.family()))
ctx.data().remove(DATA_SELECT_NO_DATA);
if (WRAP_SELECT_IN_PARENS.contains(ctx.family())) {
ctx.formatIndentEnd()
.formatNewLine()
.sql(')');
if (ctx.family() == HSQLDB)
ctx.sql(' ')
.visit(K_WITH_DATA);
}
if (FALSE.equals(withData) && !NO_SUPPORT_WITH_DATA.contains(ctx.family()))
ctx.sql(' ')
.visit(K_WITH_NO_DATA);
else if (TRUE.equals(withData) && !NO_SUPPORT_WITH_DATA.contains(ctx.family()))
ctx.sql(' ')
.visit(K_WITH_DATA);
else if (REQUIRES_WITH_DATA.contains(ctx.family()))
ctx.sql(' ')
.visit(K_WITH_DATA);
}
@ -416,6 +449,10 @@ final class CreateTableImpl<R extends Record> extends AbstractQuery implements
@ -454,9 +491,15 @@ final class CreateTableImpl<R extends Record> extends AbstractQuery implements
}
private final void acceptSelectInto(Context<?> ctx) {
if (FALSE.equals(withData))
ctx.data(DATA_SELECT_NO_DATA, true);
ctx.data(DATA_SELECT_INTO_TABLE, table);
ctx.visit(select);
ctx.data().remove(DATA_SELECT_INTO_TABLE);
if (FALSE.equals(withData))
ctx.data().remove(DATA_SELECT_NO_DATA);
}
@Override

View File

@ -278,6 +278,7 @@ import org.jooq.CreateTableColumnStep;
import org.jooq.CreateTableCommentStep;
import org.jooq.CreateTableConstraintStep;
import org.jooq.CreateTableStorageStep;
import org.jooq.CreateTableWithDataStep;
import org.jooq.DDLQuery;
import org.jooq.DSLContext;
import org.jooq.DataType;
@ -1813,7 +1814,14 @@ final class ParserImpl implements Parser {
? ctx.dsl.createTemporaryTable(tableName)
: ctx.dsl.createTable(tableName);
storageStep = commentStep = s1.as(select);
CreateTableWithDataStep s2 = s1.as(select);
storageStep = commentStep =
parseKeywordIf(ctx, "WITH DATA")
? s2.withData()
: parseKeywordIf(ctx, "WITH NO DATA")
? s2.withNoData()
: s2;
}
else {
List<Field<?>> fields = new ArrayList<Field<?>>();
@ -7260,6 +7268,7 @@ final class ParserImpl implements Parser {
"UNION",
"USING",
"WHERE",
"WITH",
};
private static final String[] PIVOT_KEYWORDS = {

View File

@ -88,6 +88,7 @@ import static org.jooq.impl.CombineOperator.INTERSECT;
import static org.jooq.impl.CombineOperator.INTERSECT_ALL;
import static org.jooq.impl.CombineOperator.UNION;
import static org.jooq.impl.CombineOperator.UNION_ALL;
import static org.jooq.impl.DSL.falseCondition;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.one;
@ -1226,7 +1227,12 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
// ------------
context.start(SELECT_WHERE);
if (!getWhere().hasWhere() && semiAntiJoinPredicates == null)
if (TRUE.equals(context.data().get(DataKey.DATA_SELECT_NO_DATA)))
context.formatSeparator()
.visit(K_WHERE)
.sql(' ')
.visit(falseCondition());
else if (!getWhere().hasWhere() && semiAntiJoinPredicates == null)
;
else {
ConditionProviderImpl where = new ConditionProviderImpl();

View File

@ -405,6 +405,11 @@ final class Tools {
*/
DATA_SELECT_INTO_TABLE,
/**
* [#7139] No data must be selected in the <code>SELECT</code> statement.
*/
DATA_SELECT_NO_DATA,
/**
* [#3381] Omit the {@link Clause#SELECT_INTO}, as it is being emulated.
*/
@ -2445,6 +2450,11 @@ final class Tools {