[#7748] Add support for CREATE SEQUENCE flags

This commit is contained in:
Lukas Eder 2018-08-10 17:11:35 +02:00
parent 7820534370
commit 9832681cb4
8 changed files with 387 additions and 24 deletions

View File

@ -131,6 +131,12 @@ createSchemaStatement = 'CREATE SCHEMA' [ 'IF NOT EXISTS' ] schemaName
;
createSequenceStatement = 'CREATE' ( 'SEQUENCE' | 'GENERATOR' ) [ 'IF NOT EXISTS' ] sequenceName
[ START [ WITH ] signedInteger ]
[ INCREMENT [ BY ] signedInteger ]
[ MINVALUE signedInteger | NO MINVALUE ]
[ MAXVALUE signedInteger | NO MAXVALUE ]
[ CYCLE | NO CYCLE ]
[ CACHE unsignedInteger | NO CACHE ]
;
createViewStatement = 'CREATE' [ 'OR' ( 'ALTER' | 'REPLACE') ] 'VIEW' [ 'IF NOT EXISTS' ] tableName

View File

@ -0,0 +1,169 @@
/*
* 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.FIREBIRD;
import static org.jooq.SQLDialect.H2;
// ...
import static org.jooq.SQLDialect.HSQLDB;
// ...
// ...
// ...
import static org.jooq.SQLDialect.POSTGRES;
// ...
// ...
/**
* A {@link Query} that can create sequences.
* <p>
* <h3>Referencing <code>XYZ*Step</code> types directly from client code</h3>
* <p>
* It is usually not recommended to reference any <code>XYZ*Step</code> types
* directly from client code, or assign them to local variables. When writing
* dynamic SQL, creating a statement's components dynamically, and passing them
* to the DSL API statically is usually a better choice. See the manual's
* section about dynamic SQL for details: <a href=
* "https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql">https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql</a>.
* <p>
* Drawbacks of referencing the <code>XYZ*Step</code> types directly:
* <ul>
* <li>They're operating on mutable implementations (as of jOOQ 3.x)</li>
* <li>They're less composable and not easy to get right when dynamic SQL gets
* complex</li>
* <li>They're less readable</li>
* <li>They might have binary incompatible changes between minor releases</li>
* </ul>
*
* @author Lukas Eder
*/
public interface CreateSequenceFlagsStep extends CreateSequenceFinalStep {
/**
* Add a <code>START WITH</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep startWith(Number constant);
/**
* Add a <code>START WITH</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep startWith(Field<? extends Number> constant);
/**
* Add a <code>INCREMENT BY</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep incrementBy(Number constant);
/**
* Add a <code>INCREMENT BY</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep incrementBy(Field<? extends Number> constant);
/**
* Add a <code>MINVALUE</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep minvalue(Number constant);
/**
* Add a <code>MINVALUE</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep minvalue(Field<? extends Number> constant);
/**
* Add a <code>NO MINVALUE</code> clause to the sequence definition.
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES })
CreateSequenceFlagsStep noMinvalue();
/**
* Add a <code>MINVALUE</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep maxvalue(Number constant);
/**
* Add a <code>MINVALUE</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep maxvalue(Field<? extends Number> constant);
/**
* Add a <code>NO MINVALUE</code> clause to the sequence definition.
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES })
CreateSequenceFlagsStep noMaxvalue();
/**
* Add a <code>CYCLE</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep cycle();
/**
* Add a <code>NO CYCLE</code> clause to the sequence definition.
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES })
CreateSequenceFlagsStep noCycle();
/**
* Add a <code>CACHE</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep cache(Number constant);
/**
* Add a <code>CACHE</code> clause to the sequence definition.
*/
@Support({ H2, POSTGRES })
CreateSequenceFlagsStep cache(Field<? extends Number> constant);
/**
* Add a <code>NO CACHE</code> clause to the sequence definition.
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES })
CreateSequenceFlagsStep noCache();
}

View File

@ -83,6 +83,7 @@ import java.util.concurrent.Executor;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Stream;
import javax.sql.DataSource;
import org.jooq.conf.ParamType;
@ -9002,7 +9003,7 @@ public interface DSLContext extends Scope , AutoCloseable {
* @see DSL#createSequence(String)
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES })
CreateSequenceFinalStep createSequence(String sequence);
CreateSequenceFlagsStep createSequence(String sequence);
/**
* Create a new DSL <code>CREATE SEQUENCE</code> statement.
@ -9010,7 +9011,7 @@ public interface DSLContext extends Scope , AutoCloseable {
* @see DSL#createSequence(Name)
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES })
CreateSequenceFinalStep createSequence(Name sequence);
CreateSequenceFlagsStep createSequence(Name sequence);
/**
* Create a new DSL <code>CREATE SEQUENCE</code> statement.
@ -9018,7 +9019,7 @@ public interface DSLContext extends Scope , AutoCloseable {
* @see DSL#createSequence(String)
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES })
CreateSequenceFinalStep createSequence(Sequence<?> sequence);
CreateSequenceFlagsStep createSequence(Sequence<?> sequence);
/**
* Create a new DSL <code>CREATE SEQUENCE</code> statement.
@ -9026,7 +9027,7 @@ public interface DSLContext extends Scope , AutoCloseable {
* @see DSL#createSequenceIfNotExists(String)
*/
@Support({ FIREBIRD, H2, HSQLDB, POSTGRES })
CreateSequenceFinalStep createSequenceIfNotExists(String sequence);
CreateSequenceFlagsStep createSequenceIfNotExists(String sequence);
/**
* Create a new DSL <code>CREATE SEQUENCE</code> statement.
@ -9034,7 +9035,7 @@ public interface DSLContext extends Scope , AutoCloseable {
* @see DSL#createSequenceIfNotExists(Name)
*/
@Support({ FIREBIRD, H2, HSQLDB, POSTGRES })
CreateSequenceFinalStep createSequenceIfNotExists(Name sequence);
CreateSequenceFlagsStep createSequenceIfNotExists(Name sequence);
/**
* Create a new DSL <code>CREATE SEQUENCE</code> statement.
@ -9042,7 +9043,7 @@ public interface DSLContext extends Scope , AutoCloseable {
* @see DSL#createSequenceIfNotExists(String)
*/
@Support({ FIREBIRD, H2, HSQLDB, POSTGRES })
CreateSequenceFinalStep createSequenceIfNotExists(Sequence<?> sequence);
CreateSequenceFlagsStep createSequenceIfNotExists(Sequence<?> sequence);
/**
* Create a new DSL <code>ALTER SEQUENCE</code> statement.

View File

@ -48,8 +48,14 @@ import static org.jooq.SQLDialect.FIREBIRD;
// ...
// ...
// ...
import static org.jooq.impl.Keywords.K_CACHE;
import static org.jooq.impl.Keywords.K_CREATE;
import static org.jooq.impl.Keywords.K_CYCLE;
import static org.jooq.impl.Keywords.K_IF_NOT_EXISTS;
import static org.jooq.impl.Keywords.K_INCREMENT_BY;
import static org.jooq.impl.Keywords.K_MAXVALUE;
import static org.jooq.impl.Keywords.K_MINVALUE;
import static org.jooq.impl.Keywords.K_NO;
import static org.jooq.impl.Keywords.K_SEQUENCE;
import static org.jooq.impl.Keywords.K_SERIAL;
import static org.jooq.impl.Keywords.K_START_WITH;
@ -59,7 +65,8 @@ import java.util.EnumSet;
import org.jooq.Clause;
import org.jooq.Configuration;
import org.jooq.Context;
import org.jooq.CreateSequenceFinalStep;
import org.jooq.CreateSequenceFlagsStep;
import org.jooq.Field;
import org.jooq.SQLDialect;
import org.jooq.Sequence;
@ -69,7 +76,7 @@ import org.jooq.Sequence;
final class CreateSequenceImpl extends AbstractQuery implements
// Cascading interface implementations for CREATE SEQUENCE behaviour
CreateSequenceFinalStep {
CreateSequenceFlagsStep {
/**
* Generated UID
@ -81,6 +88,16 @@ final class CreateSequenceImpl extends AbstractQuery implements
private final Sequence<?> sequence;
private final boolean ifNotExists;
private Field<?> startWith;
private Field<?> incrementBy;
private Field<?> minvalue;
private boolean noMinvalue;
private Field<?> maxvalue;
private boolean noMaxvalue;
private boolean cycle;
private boolean noCycle;
private Field<?> cache;
private boolean noCache;
CreateSequenceImpl(Configuration configuration, Sequence<?> sequence, boolean ifNotExists) {
super(configuration);
@ -89,6 +106,95 @@ final class CreateSequenceImpl extends AbstractQuery implements
this.ifNotExists = ifNotExists;
}
// ------------------------------------------------------------------------
// XXX: Sequence API
// ------------------------------------------------------------------------
@Override
public final CreateSequenceImpl startWith(Number constant) {
return startWith(DSL.val(constant));
}
@Override
public final CreateSequenceImpl startWith(Field<? extends Number> constant) {
this.startWith = constant;
return this;
}
@Override
public final CreateSequenceImpl incrementBy(Number constant) {
return incrementBy(DSL.val(constant));
}
@Override
public final CreateSequenceImpl incrementBy(Field<? extends Number> constant) {
this.incrementBy = constant;
return this;
}
@Override
public final CreateSequenceImpl minvalue(Number constant) {
return minvalue(DSL.val(constant));
}
@Override
public final CreateSequenceImpl minvalue(Field<? extends Number> constant) {
this.minvalue = constant;
return this;
}
@Override
public final CreateSequenceImpl noMinvalue() {
this.noMinvalue = true;
return this;
}
@Override
public final CreateSequenceImpl maxvalue(Number constant) {
return maxvalue(DSL.val(constant));
}
@Override
public final CreateSequenceImpl maxvalue(Field<? extends Number> constant) {
this.maxvalue = constant;
return this;
}
@Override
public final CreateSequenceImpl noMaxvalue() {
this.noMaxvalue = true;
return this;
}
@Override
public final CreateSequenceImpl cycle() {
this.cycle = true;
return this;
}
@Override
public final CreateSequenceImpl noCycle() {
this.noCycle = true;
return this;
}
@Override
public final CreateSequenceImpl cache(Number constant) {
return cache(DSL.val(constant));
}
@Override
public final CreateSequenceImpl cache(Field<? extends Number> constant) {
this.cache = constant;
return this;
}
@Override
public final CreateSequenceImpl noCache() {
this.noCache = true;
return this;
}
// ------------------------------------------------------------------------
// XXX: QueryPart API
// ------------------------------------------------------------------------
@ -123,8 +229,33 @@ final class CreateSequenceImpl extends AbstractQuery implements
ctx.visit(sequence);
// Some databases default to sequences starting with MIN_VALUE
if (REQUIRES_START_WITH.contains(ctx.family()))
if (startWith == null && REQUIRES_START_WITH.contains(ctx.family()))
ctx.sql(' ').visit(K_START_WITH).sql(" 1");
else if (startWith != null)
ctx.sql(' ').visit(K_START_WITH).sql(' ').visit(startWith);
if (incrementBy != null)
ctx.sql(' ').visit(K_INCREMENT_BY).sql(' ').visit(incrementBy);
if (minvalue != null)
ctx.sql(' ').visit(K_MINVALUE).sql(' ').visit(minvalue);
else if (noMinvalue)
ctx.sql(' ').visit(K_NO).sql(' ').visit(K_MINVALUE);
if (maxvalue != null)
ctx.sql(' ').visit(K_MAXVALUE).sql(' ').visit(maxvalue);
else if (noMaxvalue)
ctx.sql(' ').visit(K_NO).sql(' ').visit(K_MAXVALUE);
if (cycle)
ctx.sql(' ').visit(K_CYCLE);
else if (noCycle)
ctx.sql(' ').visit(K_NO).sql(' ').visit(K_CYCLE);
if (cache != null)
ctx.sql(' ').visit(K_CACHE).sql(' ').visit(cache);
else if (noCache)
ctx.sql(' ').visit(K_NO).sql(' ').visit(K_CACHE);
ctx.end(CREATE_SEQUENCE_SEQUENCE);
}

View File

@ -158,7 +158,7 @@ import org.jooq.ConstraintForeignKeyReferencesStepN;
import org.jooq.ConstraintTypeStep;
import org.jooq.CreateIndexStep;
import org.jooq.CreateSchemaFinalStep;
import org.jooq.CreateSequenceFinalStep;
import org.jooq.CreateSequenceFlagsStep;
import org.jooq.CreateTableAsStep;
import org.jooq.CreateViewAsStep;
import org.jooq.DSLContext;
@ -7077,7 +7077,7 @@ public class DSL {
* @see DSLContext#createSequence(String)
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES })
public static CreateSequenceFinalStep createSequence(String sequence) {
public static CreateSequenceFlagsStep createSequence(String sequence) {
return dsl().createSequence(sequence);
}
@ -7087,7 +7087,7 @@ public class DSL {
* @see DSLContext#createSequence(Name)
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES })
public static CreateSequenceFinalStep createSequence(Name sequence) {
public static CreateSequenceFlagsStep createSequence(Name sequence) {
return dsl().createSequence(sequence);
}
@ -7097,7 +7097,7 @@ public class DSL {
* @see DSLContext#createSequence(Sequence)
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES })
public static CreateSequenceFinalStep createSequence(Sequence<?> sequence) {
public static CreateSequenceFlagsStep createSequence(Sequence<?> sequence) {
return dsl().createSequence(sequence);
}
@ -7107,7 +7107,7 @@ public class DSL {
* @see DSLContext#createSequenceIfNotExists(String)
*/
@Support({ FIREBIRD, H2, HSQLDB, POSTGRES })
public static CreateSequenceFinalStep createSequenceIfNotExists(String sequence) {
public static CreateSequenceFlagsStep createSequenceIfNotExists(String sequence) {
return dsl().createSequenceIfNotExists(sequence);
}
@ -7117,7 +7117,7 @@ public class DSL {
* @see DSLContext#createSequenceIfNotExists(Name)
*/
@Support({ FIREBIRD, H2, HSQLDB, POSTGRES })
public static CreateSequenceFinalStep createSequenceIfNotExists(Name sequence) {
public static CreateSequenceFlagsStep createSequenceIfNotExists(Name sequence) {
return dsl().createSequenceIfNotExists(sequence);
}
@ -7127,7 +7127,7 @@ public class DSL {
* @see DSLContext#createSequenceIfNotExists(Sequence)
*/
@Support({ FIREBIRD, H2, HSQLDB, POSTGRES })
public static CreateSequenceFinalStep createSequenceIfNotExists(Sequence<?> sequence) {
public static CreateSequenceFlagsStep createSequenceIfNotExists(Sequence<?> sequence) {
return dsl().createSequenceIfNotExists(sequence);
}

View File

@ -112,7 +112,7 @@ import org.jooq.ContextTransactionalCallable;
import org.jooq.ContextTransactionalRunnable;
import org.jooq.CreateIndexStep;
import org.jooq.CreateSchemaFinalStep;
import org.jooq.CreateSequenceFinalStep;
import org.jooq.CreateSequenceFlagsStep;
import org.jooq.CreateTableAsStep;
import org.jooq.CreateViewAsStep;
import org.jooq.Cursor;
@ -3124,32 +3124,32 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
}
@Override
public CreateSequenceFinalStep createSequence(String sequence) {
public CreateSequenceFlagsStep createSequence(String sequence) {
return createSequence(name(sequence));
}
@Override
public CreateSequenceFinalStep createSequence(Name sequence) {
public CreateSequenceFlagsStep createSequence(Name sequence) {
return createSequence(sequence(sequence));
}
@Override
public CreateSequenceFinalStep createSequence(Sequence<?> sequence) {
public CreateSequenceFlagsStep createSequence(Sequence<?> sequence) {
return new CreateSequenceImpl(configuration(), sequence, false);
}
@Override
public CreateSequenceFinalStep createSequenceIfNotExists(String sequence) {
public CreateSequenceFlagsStep createSequenceIfNotExists(String sequence) {
return createSequenceIfNotExists(name(sequence));
}
@Override
public CreateSequenceFinalStep createSequenceIfNotExists(Name sequence) {
public CreateSequenceFlagsStep createSequenceIfNotExists(Name sequence) {
return createSequenceIfNotExists(sequence(sequence));
}
@Override
public CreateSequenceFinalStep createSequenceIfNotExists(Sequence<?> sequence) {
public CreateSequenceFlagsStep createSequenceIfNotExists(Sequence<?> sequence) {
return new CreateSequenceImpl(configuration(), sequence, true);
}

View File

@ -70,6 +70,7 @@ final class Keywords {
static final Keyword K_BOOLEAN = keyword("boolean");
static final Keyword K_BULK_COLLECT_INTO = keyword("bulk collect into");
static final Keyword K_BY = keyword("by");
static final Keyword K_CACHE = keyword("cache");
static final Keyword K_CASCADE = keyword("cascade");
static final Keyword K_CASE = keyword("case");
static final Keyword K_CAST = keyword("cast");
@ -90,6 +91,7 @@ final class Keywords {
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");
static final Keyword K_CYCLE = keyword("cycle");
static final Keyword K_DATE = keyword("date");
static final Keyword K_DATETIME = keyword("datetime");
static final Keyword K_DATETIMEOFFSET = keyword("datetimeoffset");
@ -159,6 +161,7 @@ final class Keywords {
static final Keyword K_IMMEDIATE = keyword("immediate");
static final Keyword K_IN = keyword("in");
static final Keyword K_INCLUDE = keyword("include");
static final Keyword K_INCREMENT_BY = keyword("increment by");
static final Keyword K_INDEX = keyword("index");
static final Keyword K_INNER_JOIN = keyword("inner join");
static final Keyword K_INSERT = keyword("insert");
@ -178,12 +181,15 @@ final class Keywords {
static final Keyword K_LOCK_IN_SHARE_MODE = keyword("lock in share mode");
static final Keyword K_LOOP = keyword("loop");
static final Keyword K_MATCHED = keyword("matched");
static final Keyword K_MAXVALUE = keyword("maxvalue");
static final Keyword K_MERGE_INTO = keyword("merge into");
static final Keyword K_MINUS = keyword("minus");
static final Keyword K_MINVALUE = keyword("minvalue");
static final Keyword K_MODIFY = keyword("modify");
static final Keyword K_NEW_TABLE = keyword("new table");
static final Keyword K_NOCYCLE = keyword("nocycle");
static final Keyword K_NONCLUSTERED = keyword("nonclustered");
static final Keyword K_NO = keyword("no");
static final Keyword K_NOT = keyword("not");
static final Keyword K_NOT_ENFORCED = keyword("not enforced");
static final Keyword K_NOT_EXISTS = keyword("not exists");

View File

@ -304,6 +304,7 @@ import org.jooq.CreateIndexFinalStep;
import org.jooq.CreateIndexIncludeStep;
import org.jooq.CreateIndexStep;
import org.jooq.CreateIndexWhereStep;
import org.jooq.CreateSequenceFlagsStep;
import org.jooq.CreateTableAsStep;
import org.jooq.CreateTableColumnStep;
import org.jooq.CreateTableCommentStep;
@ -2246,9 +2247,58 @@ final class ParserImpl implements Parser {
boolean ifNotExists = parseKeywordIf(ctx, "IF NOT EXISTS");
Sequence<?> schemaName = parseSequenceName(ctx);
return ifNotExists
CreateSequenceFlagsStep s = ifNotExists
? ctx.dsl.createSequenceIfNotExists(schemaName)
: ctx.dsl.createSequence(schemaName);
for (;;) {
if (parseKeywordIf(ctx, "START")) {
parseKeywordIf(ctx, "WITH");
s = s.startWith(parseUnsignedInteger(ctx));
continue;
}
else if (parseKeywordIf(ctx, "INCREMENT")) {
parseKeywordIf(ctx, "BY");
s = s.incrementBy(parseUnsignedInteger(ctx));
continue;
}
else if (parseKeywordIf(ctx, "MINVALUE")) {
s = s.minvalue(parseUnsignedInteger(ctx));
continue;
}
else if (parseKeywordIf(ctx, "NO MINVALUE")) {
s = s.noMinvalue();
continue;
}
else if (parseKeywordIf(ctx, "MAXVALUE")) {
s = s.maxvalue(parseUnsignedInteger(ctx));
continue;
}
else if (parseKeywordIf(ctx, "NO MAXVALUE")) {
s = s.noMaxvalue();
continue;
}
else if (parseKeywordIf(ctx, "CYCLE")) {
s = s.cycle();
continue;
}
else if (parseKeywordIf(ctx, "NO CYCLE")) {
s = s.noCycle();
continue;
}
else if (parseKeywordIf(ctx, "CACHE")) {
s = s.cache(parseUnsignedInteger(ctx));
continue;
}
else if (parseKeywordIf(ctx, "NO CACHE")) {
s = s.noCache();
continue;
}
break;
}
return s;
}
private static final DDLQuery parseAlterSequence(ParserContext ctx) {