[#7171] [#7286] Add CREATE OR REPLACE VIEW

This commit is contained in:
lukaseder 2018-03-13 11:49:03 +01:00
parent d10c251ea4
commit 78f23b24eb
7 changed files with 270 additions and 16 deletions

View File

@ -132,7 +132,7 @@ createSchemaStatement = 'CREATE SCHEMA' [ 'IF NOT EXISTS' ] schemaName
createSequenceStatement = 'CREATE' ( 'SEQUENCE' | 'GENERATOR' ) [ 'IF NOT EXISTS' ] sequenceName
;
createViewStatement = 'CREATE VIEW' [ 'IF NOT EXISTS' ] tableName
createViewStatement = 'CREATE' [ 'OR' ( 'ALTER' | 'REPLACE') ] 'VIEW' [ 'IF NOT EXISTS' ] tableName
[ '(' fieldNames ')' ] 'AS' select
;

View File

@ -8775,6 +8775,104 @@ public interface DSLContext extends Scope , AutoCloseable {
CreateViewAsStep<Record> createView(Table<?> view, BiFunction<? super Field<?>, ? super Integer, ? extends Field<?>> fieldNameFunction);
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
*
* @see DSL#createOrReplaceView(String, String...)
*/
@Support({ H2, POSTGRES })
CreateViewAsStep<Record> createOrReplaceView(String view, String... fields);
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
*
* @see DSL#createOrReplaceView(Name, Name...)
*/
@Support({ H2, POSTGRES })
CreateViewAsStep<Record> createOrReplaceView(Name view, Name... fields);
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
*
* @see DSL#createOrReplaceView(Table, Field...)
*/
@Support({ H2, POSTGRES })
CreateViewAsStep<Record> createOrReplaceView(Table<?> view, Field<?>... fields);
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
* <p>
* This works like {@link #createOrReplaceView(String, String...)} except that the
* view's field names are derived from the view's {@link Select} statement
* using a function.
*
* @see DSL#createOrReplaceView(String, String...)
*/
@Support({ H2, POSTGRES })
CreateViewAsStep<Record> createOrReplaceView(String view, Function<? super Field<?>, ? extends String> fieldNameFunction);
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
* <p>
* This works like {@link #createOrReplaceView(String, String...)} except that the
* view's field names are derived from the view's {@link Select} statement
* using a function.
*
* @see DSL#createOrReplaceView(String, String...)
*/
@Support({ H2, POSTGRES })
CreateViewAsStep<Record> createOrReplaceView(String view, BiFunction<? super Field<?>, ? super Integer, ? extends String> fieldNameFunction);
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
* <p>
* This works like {@link #createOrReplaceView(Name, Name...)} except that the
* view's field names are derived from the view's {@link Select} statement
* using a function.
*
* @see DSL#createOrReplaceView(String, String...)
*/
@Support({ H2, POSTGRES })
CreateViewAsStep<Record> createOrReplaceView(Name view, Function<? super Field<?>, ? extends Name> fieldNameFunction);
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
* <p>
* This works like {@link #createOrReplaceView(Name, Name...)} except that the
* view's field names are derived from the view's {@link Select} statement
* using a function.
*
* @see DSL#createOrReplaceView(String, String...)
*/
@Support({ H2, POSTGRES })
CreateViewAsStep<Record> createOrReplaceView(Name view, BiFunction<? super Field<?>, ? super Integer, ? extends Name> fieldNameFunction);
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
* <p>
* This works like {@link #createOrReplaceView(Table, Field...)} except that the
* view's field names are derived from the view's {@link Select} statement
* using a function.
*
* @see DSL#createOrReplaceView(String, String...)
*/
@Support({ H2, POSTGRES })
CreateViewAsStep<Record> createOrReplaceView(Table<?> view, Function<? super Field<?>, ? extends Field<?>> fieldNameFunction);
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
* <p>
* This works like {@link #createOrReplaceView(Table, Field...)} except that the
* view's field names are derived from the view's {@link Select} statement
* using a function.
*
* @see DSL#createOrReplaceView(String, String...)
*/
@Support({ H2, POSTGRES })
CreateViewAsStep<Record> createOrReplaceView(Table<?> view, BiFunction<? super Field<?>, ? super Integer, ? extends Field<?>> fieldNameFunction);
/**
* Create a new DSL <code>CREATE VIEW</code> statement.
*

View File

@ -45,6 +45,7 @@ import static org.jooq.Clause.CREATE_VIEW_NAME;
// ...
import static org.jooq.SQLDialect.DERBY;
import static org.jooq.SQLDialect.FIREBIRD;
import static org.jooq.SQLDialect.H2;
// ...
// ...
import static org.jooq.SQLDialect.POSTGRES;
@ -54,9 +55,13 @@ import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.selectFrom;
import static org.jooq.impl.DSL.table;
import static org.jooq.impl.Keywords.K_ALTER;
import static org.jooq.impl.Keywords.K_AS;
import static org.jooq.impl.Keywords.K_CREATE_VIEW;
import static org.jooq.impl.Keywords.K_CREATE;
import static org.jooq.impl.Keywords.K_IF_NOT_EXISTS;
import static org.jooq.impl.Keywords.K_OR;
import static org.jooq.impl.Keywords.K_REPLACE;
import static org.jooq.impl.Keywords.K_VIEW;
import java.util.EnumSet;
import java.util.List;
@ -87,11 +92,13 @@ final class CreateViewImpl<R extends Record> extends AbstractQuery implements
/**
* Generated UID
*/
private static final long serialVersionUID = 8904572826501186329L;
private static final Clause[] CLAUSES = { CREATE_VIEW };
private static final long serialVersionUID = 8904572826501186329L;
private static final Clause[] CLAUSES = { CREATE_VIEW };
private static final EnumSet<SQLDialect> NO_SUPPORT_IF_NOT_EXISTS = EnumSet.of(DERBY, FIREBIRD, POSTGRES);
private static final EnumSet<SQLDialect> NO_SUPPORT_OR_REPLACE = EnumSet.of(H2);
private final boolean ifNotExists;
private final boolean orReplace;
private final Table<?> view;
private final BiFunction<? super Field<?>, ? super Integer, ? extends Field<?>> fieldNameFunction;
@ -99,7 +106,7 @@ final class CreateViewImpl<R extends Record> extends AbstractQuery implements
private Field<?>[] fields;
private Select<?> select;
CreateViewImpl(Configuration configuration, Table<?> view, Field<?>[] fields, boolean ifNotExists) {
CreateViewImpl(Configuration configuration, Table<?> view, Field<?>[] fields, boolean ifNotExists, boolean orReplace) {
super(configuration);
this.view = view;
@ -108,16 +115,18 @@ final class CreateViewImpl<R extends Record> extends AbstractQuery implements
this.fieldNameFunction = null;
this.ifNotExists = ifNotExists;
this.orReplace = orReplace;
}
CreateViewImpl(Configuration configuration, Table<?> view, BiFunction<? super Field<?>, ? super Integer, ? extends Field<?>> fieldNameFunction, boolean ifNotExists) {
CreateViewImpl(Configuration configuration, Table<?> view, BiFunction<? super Field<?>, ? super Integer, ? extends Field<?>> fieldNameFunction, boolean ifNotExists, boolean orReplace) {
super(configuration);
this.view = view;
this.fields = null;
this.fieldNameFunction = fieldNameFunction;
this.ifNotExists = ifNotExists;
this.orReplace = orReplace;
}
@ -171,7 +180,25 @@ final class CreateViewImpl<R extends Record> extends AbstractQuery implements
ParamType paramType = ctx.paramType();
ctx.start(CREATE_VIEW_NAME)
.visit(K_CREATE_VIEW)
.visit(K_CREATE);
if (orReplace && !NO_SUPPORT_OR_REPLACE.contains(ctx.family())) {
ctx.sql(' ').visit(K_OR);
switch (ctx.family()) {
default:
ctx.sql(' ').visit(K_REPLACE);
break;
}
}
ctx.sql(' ').visit(K_VIEW)
.sql(' ');
if (ifNotExists && supportsIfNotExists(ctx))

View File

@ -7009,6 +7009,80 @@ public class DSL {
}
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
*
* @see DSLContext#createOrReplaceView(String, String...)
*/
@Support({ H2, POSTGRES })
public static CreateViewAsStep createOrReplaceView(String view, String... fields) {
return dsl().createOrReplaceView(view, fields);
}
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
*
* @see DSLContext#createOrReplaceView(Name, Name...)
*/
@Support({ H2, POSTGRES })
public static CreateViewAsStep createOrReplaceView(Name view, Name... fields) {
return dsl().createOrReplaceView(view, fields);
}
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
*
* @see DSLContext#createOrReplaceView(Table, Field...)
*/
@Support({ H2, POSTGRES })
public static CreateViewAsStep createOrReplaceView(Table<?> view, Field<?>... fields) {
return dsl().createOrReplaceView(view, fields);
}
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
* <p>
* This works like {@link #createOrReplaceView(Table, Field...)} except that the
* view's field names are derived from the view's {@link Select} statement
* using a function.
*
* @see DSLContext#createOrReplaceView(String, String...)
*/
@Support({ H2, POSTGRES })
public static CreateViewAsStep createOrReplaceView(String view, Function<? super Field<?>, ? extends String> fieldNameFunction) {
return dsl().createOrReplaceView(view, fieldNameFunction);
}
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
* <p>
* This works like {@link #createOrReplaceView(Table, Field...)} except that the
* view's field names are derived from the view's {@link Select} statement
* using a function.
*
* @see DSLContext#createOrReplaceView(Name, Name...)
*/
@Support({ H2, POSTGRES })
public static CreateViewAsStep createOrReplaceView(Name view, Function<? super Field<?>, ? extends Name> fieldNameFunction) {
return dsl().createOrReplaceView(view, fieldNameFunction);
}
/**
* Create a new DSL <code>CREATE OR REPLACE VIEW</code> statement.
* <p>
* This works like {@link #createOrReplaceView(Table, Field...)} except that the
* view's field names are derived from the view's {@link Select} statement
* using a function.
*
* @see DSLContext#createOrReplaceView(Table, Field...)
*/
@Support({ H2, POSTGRES })
public static CreateViewAsStep createOrReplaceView(Table<?> view, Function<? super Field<?>, ? extends Field<?>> fieldNameFunction) {
return dsl().createOrReplaceView(view, fieldNameFunction);
}
/**
* Create a new DSL <code>CREATE VIEW IF NOT EXISTS</code> statement.
*

View File

@ -2995,7 +2995,7 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
@Override
public CreateViewAsStep<Record> createView(Table<?> view, Field<?>... fields) {
return new CreateViewImpl<Record>(configuration(), view, fields, false);
return new CreateViewImpl<Record>(configuration(), view, fields, false, false);
}
@ -3026,7 +3026,54 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
@Override
public CreateViewAsStep<Record> createView(Table<?> view, BiFunction<? super Field<?>, ? super Integer, ? extends Field<?>> fieldNameFunction) {
return new CreateViewImpl<Record>(configuration(), view, fieldNameFunction, false);
return new CreateViewImpl<Record>(configuration(), view, fieldNameFunction, false, false);
}
@Override
public CreateViewAsStep<Record> createOrReplaceView(String view, String... fields) {
return createOrReplaceView(table(name(view)), Tools.fieldsByName(view, fields));
}
@Override
public CreateViewAsStep<Record> createOrReplaceView(Name view, Name... fields) {
return createOrReplaceView(table(view), Tools.fieldsByName(fields));
}
@Override
public CreateViewAsStep<Record> createOrReplaceView(Table<?> view, Field<?>... fields) {
return new CreateViewImpl<Record>(configuration(), view, fields, false, true);
}
@Override
public CreateViewAsStep<Record> createOrReplaceView(String view, Function<? super Field<?>, ? extends String> fieldNameFunction) {
return createOrReplaceView(table(name(view)), (f, i) -> field(name(fieldNameFunction.apply(f))));
}
@Override
public CreateViewAsStep<Record> createOrReplaceView(String view, BiFunction<? super Field<?>, ? super Integer, ? extends String> fieldNameFunction) {
return createOrReplaceView(table(name(view)), (f, i) -> field(name(fieldNameFunction.apply(f, i))));
}
@Override
public CreateViewAsStep<Record> createOrReplaceView(Name view, Function<? super Field<?>, ? extends Name> fieldNameFunction) {
return createOrReplaceView(table(view), (f, i) -> field(fieldNameFunction.apply(f)));
}
@Override
public CreateViewAsStep<Record> createOrReplaceView(Name view, BiFunction<? super Field<?>, ? super Integer, ? extends Name> fieldNameFunction) {
return createOrReplaceView(table(view), (f, i) -> field(fieldNameFunction.apply(f, i)));
}
@Override
public CreateViewAsStep<Record> createOrReplaceView(Table<?> view, Function<? super Field<?>, ? extends Field<?>> fieldNameFunction) {
return createOrReplaceView(view, (f, i) -> fieldNameFunction.apply(f));
}
@Override
public CreateViewAsStep<Record> createOrReplaceView(Table<?> view, BiFunction<? super Field<?>, ? super Integer, ? extends Field<?>> fieldNameFunction) {
return new CreateViewImpl<Record>(configuration(), view, fieldNameFunction, false, true);
}
@ -3042,7 +3089,7 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
@Override
public CreateViewAsStep<Record> createViewIfNotExists(Table<?> view, Field<?>... fields) {
return new CreateViewImpl<Record>(configuration(), view, fields, true);
return new CreateViewImpl<Record>(configuration(), view, fields, true, false);
}
@ -3073,7 +3120,7 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
@Override
public CreateViewAsStep<Record> createViewIfNotExists(Table<?> view, BiFunction<? super Field<?>, ? super Integer, ? extends Field<?>> fieldNameFunction) {
return new CreateViewImpl<Record>(configuration(), view, fieldNameFunction, true);
return new CreateViewImpl<Record>(configuration(), view, fieldNameFunction, true, false);
}

View File

@ -87,7 +87,6 @@ final class Keywords {
static final Keyword K_CONTINUE_IDENTITY = keyword("continue identity");
static final Keyword K_CREATE = keyword("create");
static final Keyword K_CREATE_SCHEMA = keyword("create schema");
static final Keyword K_CREATE_VIEW = keyword("create view");
static final Keyword K_CROSS_JOIN_LATERAL = keyword("cross join lateral");
static final Keyword K_CURRENT_SCHEMA = keyword("current_schema");
static final Keyword K_CURRENT_ROW = keyword("current row");
@ -225,6 +224,7 @@ final class Keywords {
static final Keyword K_RENAME_INDEX = keyword("rename index");
static final Keyword K_RENAME_TABLE = keyword("rename table");
static final Keyword K_RENAME_TO = keyword("rename to");
static final Keyword K_REPLACE = keyword("replace");
static final Keyword K_RESPECT_NULLS = keyword("respect nulls");
static final Keyword K_RESTART = keyword("restart");
static final Keyword K_RESTART_IDENTITY = keyword("restart identity");

View File

@ -739,6 +739,8 @@ final class ParserImpl implements Parser {
result = parseSelect(ctx, null, with);
else if (!parseSelect && peekKeyword(ctx, "UPDATE"))
result = parseUpdate(ctx, with);
else if ((parseWhitespaceIf(ctx) || true) && ctx.done())
throw ctx.exception("Missing statement after WITH");
else
throw ctx.exception("Unsupported statement after WITH");
@ -1532,10 +1534,14 @@ final class ParserImpl implements Parser {
return parseCreateSchema(ctx);
else if (parseKeywordIf(ctx, "SEQUENCE"))
return parseCreateSequence(ctx);
else if (parseKeywordIf(ctx, "OR REPLACE VIEW"))
return parseCreateView(ctx, true);
else if (parseKeywordIf(ctx, "OR ALTER VIEW"))
return parseCreateView(ctx, true);
else if (parseKeywordIf(ctx, "VIEW"))
return parseCreateView(ctx);
return parseCreateView(ctx, false);
else
throw ctx.expected("GENERATOR", "GLOBAL TEMPORARY TABLE", "INDEX", "SCHEMA", "SEQUENCE", "TABLE", "TEMPORARY TABLE", "UNIQUE INDEX", "VIEW");
throw ctx.expected("GENERATOR", "GLOBAL TEMPORARY TABLE", "INDEX", "OR ALTER VIEW", "OR REPLACE VIEW", "SCHEMA", "SEQUENCE", "TABLE", "TEMPORARY TABLE", "UNIQUE INDEX", "VIEW");
}
private static final Query parseAlter(ParserContext ctx) {
@ -1778,8 +1784,8 @@ final class ParserImpl implements Parser {
return user(parseName(ctx));
}
private static final DDLQuery parseCreateView(ParserContext ctx) {
boolean ifNotExists = parseKeywordIf(ctx, "IF NOT EXISTS");
private static final DDLQuery parseCreateView(ParserContext ctx, boolean orReplace) {
boolean ifNotExists = !orReplace && parseKeywordIf(ctx, "IF NOT EXISTS");
Table<?> view = parseTableName(ctx);
Field<?>[] fields = EMPTY_FIELD;
@ -1797,6 +1803,8 @@ final class ParserImpl implements Parser {
return ifNotExists
? ctx.dsl.createViewIfNotExists(view, fields).as(select)
: orReplace
? ctx.dsl.createOrReplaceView(view, fields).as(select)
: ctx.dsl.createView(view, fields).as(select);
}