[jOOQ/jOOQ#10243] Add ParserListener SPI to parse custom syntax

This commit is contained in:
Lukas Eder 2021-02-24 19:32:07 +01:00
parent 160d903493
commit 730d15e2e6
12 changed files with 1034 additions and 43 deletions

View File

@ -57,6 +57,7 @@ import org.jooq.impl.DefaultDiagnosticsListenerProvider;
import org.jooq.impl.DefaultExecuteListenerProvider;
import org.jooq.impl.DefaultExecutorProvider;
import org.jooq.impl.DefaultMigrationListenerProvider;
// ...
import org.jooq.impl.DefaultRecordListenerProvider;
import org.jooq.impl.DefaultRecordMapper;
import org.jooq.impl.DefaultRecordMapperProvider;
@ -518,6 +519,18 @@ public interface Configuration extends Serializable {
@NotNull
ConverterProvider converterProvider();
/**
* Retrieve the configured schema mapping.
*
@ -955,6 +968,41 @@ public interface Configuration extends Serializable {
@NotNull
Configuration set(ConverterProvider newConverterProvider);
/**
* Change this configuration to hold a new dialect.
* <p>
@ -1326,6 +1374,33 @@ public interface Configuration extends Serializable {
@NotNull
Configuration derive(ConverterProvider newConverterProvider);
/**
* Create a derived configuration from this one, with a new dialect.
*

View File

@ -10561,7 +10561,7 @@ public interface DSLContext extends Scope {
* @see DSL#dropViewIfExists(String)
*/
@NotNull
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DropViewFinalStep dropViewIfExists(@Stringly.Name String view);
/**
@ -10570,7 +10570,7 @@ public interface DSLContext extends Scope {
* @see DSL#dropViewIfExists(Name)
*/
@NotNull
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DropViewFinalStep dropViewIfExists(Name view);
/**
@ -10579,7 +10579,7 @@ public interface DSLContext extends Scope {
* @see DSL#dropViewIfExists(Table)
*/
@NotNull
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DropViewFinalStep dropViewIfExists(Table<?> view);
/**

View File

@ -0,0 +1,192 @@
/*
* 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;

View File

@ -0,0 +1,95 @@
/*
* 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;

View File

@ -0,0 +1,81 @@
/*
* 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;

View File

@ -9361,7 +9361,7 @@ public class DSL {
* @see DSLContext#dropViewIfExists(String)
*/
@NotNull
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static org.jooq.DropViewFinalStep dropViewIfExists(@Stringly.Name String view) {
return dsl().dropViewIfExists(view);
}
@ -9376,7 +9376,7 @@ public class DSL {
* @see DSLContext#dropViewIfExists(Name)
*/
@NotNull
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static org.jooq.DropViewFinalStep dropViewIfExists(Name view) {
return dsl().dropViewIfExists(view);
}
@ -9391,7 +9391,7 @@ public class DSL {
* @see DSLContext#dropViewIfExists(Table)
*/
@NotNull
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static org.jooq.DropViewFinalStep dropViewIfExists(Table<?> view) {
return dsl().dropViewIfExists(view);
}

View File

@ -67,6 +67,9 @@ import org.jooq.ExecutorProvider;
import org.jooq.MetaProvider;
import org.jooq.MigrationListener;
import org.jooq.MigrationListenerProvider;
// ...
// ...
// ...
import org.jooq.Record;
import org.jooq.RecordListener;
import org.jooq.RecordListenerProvider;
@ -130,6 +133,10 @@ public class DefaultConfiguration implements Configuration {
private transient CharsetProvider charsetProvider;
private transient ConverterProvider converterProvider;
// [#7062] Apart from the possibility of containing user defined objects, the data
// map also contains the reflection cache, which isn't serializable (and
// should not be serialized anyway).
@ -183,6 +190,9 @@ public class DefaultConfiguration implements Configuration {
null,
null,
null,
null,
dialect,
settings,
@ -218,6 +228,9 @@ public class DefaultConfiguration implements Configuration {
configuration.unwrapperProvider,
configuration.charsetProvider,
configuration.converterProvider,
configuration.clock,
configuration.dialect,
configuration.settings,
@ -252,6 +265,9 @@ public class DefaultConfiguration implements Configuration {
UnwrapperProvider unwrapperProvider,
CharsetProvider charsetProvider,
ConverterProvider converterProvider,
Clock clock,
SQLDialect dialect,
Settings settings,
@ -275,6 +291,9 @@ public class DefaultConfiguration implements Configuration {
set(unwrapperProvider);
set(charsetProvider);
set(converterProvider);
set(clock);
set(dialect);
set(settings);
@ -333,6 +352,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -361,6 +383,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -389,6 +414,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -422,6 +450,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -450,6 +481,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -483,6 +517,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -516,6 +553,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -549,6 +589,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -582,6 +625,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -615,6 +661,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -648,6 +697,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -681,6 +733,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -714,6 +769,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -747,6 +805,9 @@ public class DefaultConfiguration implements Configuration {
newUnwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -775,6 +836,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
newCharsetProvider,
converterProvider,
clock,
dialect,
settings,
@ -803,6 +867,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
newConverterProvider,
clock,
dialect,
settings,
@ -810,6 +877,46 @@ public class DefaultConfiguration implements Configuration {
);
}
@Override
public final Configuration derive(Clock newClock) {
return new DefaultConfiguration(
@ -831,6 +938,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
newClock,
dialect,
settings,
@ -859,6 +969,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
newDialect,
settings,
@ -887,6 +1000,9 @@ public class DefaultConfiguration implements Configuration {
unwrapperProvider,
charsetProvider,
converterProvider,
clock,
dialect,
newSettings,
@ -1095,6 +1211,24 @@ public class DefaultConfiguration implements Configuration {
return this;
}
@Override
public final Configuration set(Clock newClock) {
@ -1296,6 +1430,26 @@ public class DefaultConfiguration implements Configuration {
public final void setDiagnosticsListenerProvider(DiagnosticsListenerProvider... newDiagnosticsListenerProviders) {
set(newDiagnosticsListenerProviders);
}
/**
* @see #set(Unwrapper)
@ -1470,6 +1624,15 @@ public class DefaultConfiguration implements Configuration {
: new DefaultConverterProvider();
}
@Override
public final Clock clock() {
return clock;
@ -1561,6 +1724,9 @@ public class DefaultConfiguration implements Configuration {
oos.writeObject(cloneSerializables(transactionListenerProviders));
oos.writeObject(cloneSerializables(diagnosticsListenerProviders));
oos.writeObject(unwrapperProvider instanceof Serializable
? unwrapperProvider
: null);
@ -1614,6 +1780,9 @@ public class DefaultConfiguration implements Configuration {
visitListenerProviders = (VisitListenerProvider[]) ois.readObject();
transactionListenerProviders = (TransactionListenerProvider[]) ois.readObject();
diagnosticsListenerProviders = (DiagnosticsListenerProvider[]) ois.readObject();
unwrapperProvider = (UnwrapperProvider) ois.readObject();
charsetProvider = (CharsetProvider) ois.readObject();
converterProvider = (ConverterProvider) ois.readObject();

View File

@ -0,0 +1,76 @@
/*
* 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.impl;

View File

@ -0,0 +1,103 @@
/*
* 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.impl;

View File

@ -0,0 +1,112 @@
/*
* 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.impl;

View File

@ -528,6 +528,8 @@ import org.jooq.OrderedAggregateFunctionOfDeferredType;
import org.jooq.Param;
import org.jooq.ParamMode;
import org.jooq.Parameter;
// ...
// ...
import org.jooq.Parser;
// ...
// ...
@ -608,6 +610,8 @@ import org.jooq.types.Interval;
import org.jooq.types.YearToMonth;
import org.jooq.types.YearToSecond;
import org.jetbrains.annotations.Nullable;
/**
* @author Lukas Eder
*/
@ -749,7 +753,7 @@ final class ParserImpl implements Parser {
}
@SuppressWarnings({ "rawtypes", "unchecked" })
final class ParserContext {
final class ParserContext extends AbstractScope {
@ -5964,6 +5968,12 @@ final class ParserContext {
// -----------------------------------------------------------------------------------------------------------------
private final Condition parseCondition() {
return toCondition(parseOr());
}
@ -6318,7 +6328,14 @@ final class ParserContext {
}
private final Table<?> parseTable() {
Table<?> result = parseLateral();
Table<?> result;
result = parseLateral();
for (;;) {
Table<?> joined = parseJoinedTableIf(result);
@ -6975,6 +6992,13 @@ final class ParserContext {
}
private final Field<?> parseField() {
Field<?> result;
return parseField(null);
}
@ -8733,7 +8757,7 @@ final class ParserContext {
private final Field<?> parseFieldLogIf() {
if (parseFunctionNameIf("LOG")) {
parse('(');
switch (family()) {
switch (parseFamily()) {
@ -9740,7 +9764,7 @@ final class ParserContext {
Field<String> f2 = (Field) parseField(S);
parse(')');
switch (dialect()) {
switch (parseDialect()) {
@ -9830,7 +9854,7 @@ final class ParserContext {
}
}
if (!all) switch (family()) {
if (!all) switch (parseFamily()) {
@ -11118,7 +11142,8 @@ final class ParserContext {
return characterSet(parseName());
}
private final Name parseName() {
public final Name parseName() {
Name result = parseNameIf();
if (result == null)
@ -11127,7 +11152,8 @@ final class ParserContext {
return result;
}
private final Name parseNameIf() {
public final Name parseNameIf() {
Name identifier = parseIdentifierIf();
if (identifier == null)
@ -12520,7 +12546,8 @@ final class ParserContext {
return true;
}
private final boolean parse(String string) {
public final boolean parse(String string) {
boolean result = parseIf(string);
if (!result)
@ -12529,7 +12556,8 @@ final class ParserContext {
return result;
}
private final boolean parseIf(String string) {
public final boolean parseIf(String string) {
return parseIf(string, true);
}
@ -12546,7 +12574,8 @@ final class ParserContext {
return result;
}
private final boolean parse(char c) {
public final boolean parse(char c) {
return parse(c, true);
}
@ -12557,7 +12586,8 @@ final class ParserContext {
return true;
}
private final boolean parseIf(char c) {
public final boolean parseIf(char c) {
return parseIf(c, true);
}
@ -12649,18 +12679,21 @@ final class ParserContext {
return true;
}
private final boolean parseKeyword(String keyword) {
public final boolean parseKeyword(String keyword) {
if (!parseKeywordIf(keyword))
throw expected("Keyword '" + keyword + "'");
return true;
}
private final boolean parseKeywordIf(String keyword) {
public final boolean parseKeywordIf(String keyword) {
return peekKeyword(keyword, true, false, false);
}
private final boolean parseKeywordIf(String... keywords) {
public final boolean parseKeywordIf(String... keywords) {
for (String keyword : keywords)
if (parseKeywordIf(keyword))
return true;
@ -12668,7 +12701,8 @@ final class ParserContext {
return false;
}
private final boolean parseKeyword(String... keywords) {
public final boolean parseKeyword(String... keywords) {
if (parseKeywordIf(keywords))
return true;
@ -12699,14 +12733,16 @@ final class ParserContext {
return null;
}
private final boolean peek(char c) {
public final boolean peek(char c) {
if (character() != c)
return false;
return true;
}
private final boolean peek(String string) {
public final boolean peek(String string) {
return peek(string, position());
}
@ -12723,7 +12759,8 @@ final class ParserContext {
return true;
}
private final boolean peekKeyword(String... keywords) {
public final boolean peekKeyword(String... keywords) {
for (String keyword : keywords)
if (peekKeyword(keyword))
return true;
@ -12731,7 +12768,8 @@ final class ParserContext {
return false;
}
private final boolean peekKeyword(String keyword) {
public final boolean peekKeyword(String keyword) {
return peekKeyword(keyword, false, false, false);
}
@ -12883,7 +12921,7 @@ final class ParserContext {
case '-':
case '#':
if (sql[i] == '-' && i + 1 < sql.length && sql[i + 1] == '-' ||
sql[i] == '#' && SUPPORTS_HASH_COMMENT_SYNTAX.contains(dialect())) {
sql[i] == '#' && SUPPORTS_HASH_COMMENT_SYNTAX.contains(parseDialect())) {
if (sql[i] == '-')
i = i + 2;
@ -13125,6 +13163,8 @@ final class ParserContext {
ParserContext(
DSLContext dsl,
Meta meta,
@ -13132,6 +13172,8 @@ final class ParserContext {
String sqlString,
Object[] bindings
) {
super(dsl.configuration());
this.dsl = dsl;
this.locale = parseLocale(dsl.settings());
this.meta = meta;
@ -13142,18 +13184,14 @@ final class ParserContext {
// [#8722] This is an undocumented flag that allows for collecting parameters from the parser
// Do not rely on this flag. It will change incompatibly in the future.
this.bindParamListener = (Consumer<Param<?>>) dsl.configuration().data("org.jooq.parser.param-collector");
parseWhitespaceIf();
}
private final Configuration configuration() {
return dsl.configuration();
}
private final Settings settings() {
return configuration().settings();
}
private final SQLDialect dialect() {
public final SQLDialect parseDialect() {
SQLDialect result = settings().getParseDialect();
if (result == null)
@ -13162,8 +13200,9 @@ final class ParserContext {
return result;
}
private final SQLDialect family() {
return dialect().family();
public final SQLDialect parseFamily() {
return parseDialect().family();
}
private final boolean metaLookupsForceIgnore() {
@ -13234,7 +13273,8 @@ final class ParserContext {
return init(new ParserException(mark(), "Unsupported clause"));
}
private final ParserException exception(String message) {
public final ParserException exception(String message) {
return init(new ParserException(mark(), message));
}
@ -13280,11 +13320,13 @@ final class ParserContext {
return Character.toUpperCase(character());
}
private final char character() {
public final char character() {
return character(position);
}
private final char character(int pos) {
public final char character(int pos) {
return pos >= 0 && pos < sql.length ? sql[pos] : ' ';
}
@ -13296,11 +13338,13 @@ final class ParserContext {
return character(position + 1);
}
private final int position() {
public final int position() {
return position;
}
private final boolean position(int newPosition) {
public final boolean position(int newPosition) {
position = newPosition;
return true;
}

View File

@ -58,6 +58,9 @@ import org.jooq.ExecutorProvider;
import org.jooq.MetaProvider;
import org.jooq.MigrationListener;
import org.jooq.MigrationListenerProvider;
// ...
// ...
// ...
import org.jooq.RecordListener;
import org.jooq.RecordListenerProvider;
import org.jooq.RecordMapper;
@ -199,6 +202,16 @@ public class MockConfiguration implements Configuration {
return delegate.diagnosticsListenerProviders();
}
@Override
public UnwrapperProvider unwrapperProvider() {
return delegate.unwrapperProvider();
@ -359,6 +372,22 @@ public class MockConfiguration implements Configuration {
return delegate.set(newDiagnosticsListenerProviders);
}
@Override
public Configuration set(Unwrapper newUnwrapper) {
return delegate.set(newUnwrapper);
@ -519,6 +548,22 @@ public class MockConfiguration implements Configuration {
return delegate.derive(newDiagnosticsListenerProviders);
}
@Override
public Configuration derive(Unwrapper newUnwrapper) {
return delegate.derive(newUnwrapper);
@ -548,5 +593,4 @@ public class MockConfiguration implements Configuration {
public Configuration derive(Settings newSettings) {
return delegate.derive(newSettings);
}
}