[jOOQ/jOOQ#9472] Add support for UUID generator functions, such as

NEWID() or GEN_RANDOM_UUID()

This includes:

[jOOQ/jOOQ#11656] Add support for a HEX(number) function for dialects:
- Db2
- MySQL
- Vertica
This commit is contained in:
Lukas Eder 2021-04-28 12:20:18 +02:00
parent f673d0d678
commit 2d8beafd89
3 changed files with 99 additions and 13 deletions

View File

@ -84,6 +84,7 @@ import static org.jooq.SQLDialect.POSTGRES;
// ...
// ...
// ...
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
@ -16979,6 +16980,28 @@ public class DSL {
return new Digits(value);
}
/**
* The <code>HEX</code> function.
* <p>
* Format a number to its hex value.
*/
@NotNull
@Support({ MYSQL })
public static Field<String> hex(Number value) {
return new Hex(Tools.field(value));
}
/**
* The <code>HEX</code> function.
* <p>
* Format a number to its hex value.
*/
@NotNull
@Support({ MYSQL })
public static Field<String> hex(Field<? extends Number> value) {
return new Hex(value);
}
/**
* The <code>LEFT</code> function.
* <p>
@ -18603,6 +18626,17 @@ public class DSL {
return new Upper(string);
}
/**
* The <code>UUID</code> function.
* <p>
* Generate a random UUID.
*/
@NotNull
@Support({ FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE })
public static Field<UUID> uuid() {
return new Uuid();
}
// -------------------------------------------------------------------------
// Date functions
// -------------------------------------------------------------------------

View File

@ -146,7 +146,12 @@ final class Names {
static final Name N_FLOOR = unquotedName("floor");
static final Name N_FUNCTION = unquotedName("function");
static final Name N_GENERATE_SERIES = unquotedName("generate_series");
static final Name N_GENERATE_UNIQUE = unquotedName("generate_unique");
static final Name N_GENERATE_UUID = unquotedName("generate_uuid");
static final Name N_GENGUID = unquotedName("genguid");
static final Name N_GEN_ID = unquotedName("gen_id");
static final Name N_GEN_RANDOM_UUID = unquotedName("gen_random_uuid");
static final Name N_GEN_UUID = unquotedName("gen_uuid");
static final Name N_GETDATE = unquotedName("getdate");
static final Name N_GREATEST = unquotedName("greatest");
static final Name N_GROUP_CONCAT = unquotedName("group_concat");
@ -213,6 +218,7 @@ final class Names {
static final Name N_MODE = unquotedName("mode");
static final Name N_MUL = unquotedName("mul");
static final Name N_NANO100_BETWEEN = unquotedName("nano100_between");
static final Name N_NEWID = unquotedName("newid");
static final Name N_NEXTVAL = unquotedName("nextval");
static final Name N_NOT = unquotedName("not");
static final Name N_NOW = unquotedName("now");
@ -236,6 +242,7 @@ final class Names {
static final Name N_RADIANS = unquotedName("radians");
static final Name N_RAND = unquotedName("rand");
static final Name N_RANDOM = unquotedName("random");
static final Name N_RANDOM_UUID = unquotedName("random_uuid");
static final Name N_RATIO_TO_REPORT = unquotedName("ratio_to_report");
static final Name N_RAWTOHEX = unquotedName("rawtohex");
static final Name N_REGEXP_REPLACE = unquotedName("regexp_replace");
@ -304,7 +311,9 @@ final class Names {
static final Name N_SUBSTRING_INDEX = unquotedName("substring_index");
static final Name N_SYSTEM_RANGE = unquotedName("system_range");
static final Name N_SYSTEM_TIME = unquotedName("system_time");
static final Name N_SYSUUID = unquotedName("sysuuid");
static final Name N_SYS_CONNECT_BY_PATH = unquotedName("sys_connect_by_path");
static final Name N_SYS_GUID = unquotedName("sys_guid");
static final Name N_T = unquotedName("t");
static final Name N_TAN = unquotedName("tan");
static final Name N_TANH = unquotedName("tanh");
@ -314,6 +323,7 @@ final class Names {
static final Name N_TO_CHAR = unquotedName("to_char");
static final Name N_TO_CLOB = unquotedName("to_clob");
static final Name N_TO_DATE = unquotedName("to_date");
static final Name N_TO_HEX = unquotedName("to_hex");
static final Name N_TO_NUMBER = unquotedName("to_number");
static final Name N_TO_TIMESTAMP = unquotedName("to_timestamp");
static final Name N_TRANSLATE = unquotedName("translate");
@ -325,6 +335,10 @@ final class Names {
static final Name N_UPDATING = unquotedName("updating");
static final Name N_UPPER = unquotedName("upper");
static final Name N_USER = unquotedName("user");
static final Name N_UUID = unquotedName("uuid");
static final Name N_UUID_GENERATE = unquotedName("uuid_generate");
static final Name N_UUID_STRING = unquotedName("uuid_string");
static final Name N_UUID_TO_CHAR = unquotedName("uuid_to_char");
static final Name N_VALUE = unquotedName("value");
static final Name N_VALUES = unquotedName("values");
static final Name N_VAR = unquotedName("var");

View File

@ -6843,6 +6843,14 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
return r;
}
private final boolean parseEmptyParens() {
return parse('(') && parse(')');
}
private final boolean parseEmptyParensIf() {
return parseIf('(') && parse(')') || true;
}
// Any numeric operator of low precedence
// See https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-PRECEDENCE
private final FieldOrRow parseNumericOp(Type type) {
@ -7123,13 +7131,13 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
if (S.is(type))
if ((field = parseFieldConcatIf()) != null)
return field;
else if ((parseFunctionNameIf("CURRENT_CATALOG") && parse('(') && parse(')')))
else if ((parseFunctionNameIf("CURRENT_CATALOG") && parseEmptyParens()))
return currentCatalog();
else if ((parseFunctionNameIf("CURRENT_DATABASE") && parse('(') && parse(')')))
else if ((parseFunctionNameIf("CURRENT_DATABASE") && parseEmptyParens()))
return currentCatalog();
else if ((parseKeywordIf("CURRENT_SCHEMA", "CURRENT SCHEMA")) && (parseIf('(') && parse(')') || true))
else if ((parseKeywordIf("CURRENT_SCHEMA", "CURRENT SCHEMA")) && parseEmptyParensIf())
return currentSchema();
else if ((parseKeywordIf("CURRENT_USER", "CURRENT USER", "CURRENTUSER")) && (parseIf('(') && parse(')') || true))
else if ((parseKeywordIf("CURRENT_USER", "CURRENT USER", "CURRENTUSER")) && parseEmptyParensIf())
return currentUser();
else if (parseFunctionNameIf("CHR", "CHAR"))
return chr((Field) parseFieldParenthesised(N));
@ -7157,7 +7165,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
return century(parseFieldParenthesised(D));
if (D.is(type))
if ((parseKeywordIf("CURRENT_DATE") || parseKeywordIf("CURRENT DATE")) && (parseIf('(') && parse(')') || true))
if ((parseKeywordIf("CURRENT_DATE") || parseKeywordIf("CURRENT DATE")) && parseEmptyParensIf())
return currentDate();
else if (parseKeywordIf("CURRENT_TIMESTAMP") || parseKeywordIf("CURRENT TIMESTAMP")) {
Field<Integer> precision = null;
@ -7168,11 +7176,11 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
}
return precision != null ? currentTimestamp(precision) : currentTimestamp();
}
else if ((parseKeywordIf("CURRENT_TIME") || parseKeywordIf("CURRENT TIME")) && (parseIf('(') && parse(')') || true))
else if ((parseKeywordIf("CURRENT_TIME") || parseKeywordIf("CURRENT TIME")) && parseEmptyParensIf())
return currentTime();
else if (parseFunctionNameIf("CURDATE") && parse('(') && parse(')'))
else if (parseFunctionNameIf("CURDATE") && parseEmptyParens())
return currentDate();
else if (parseFunctionNameIf("CURTIME") && parse('(') && parse(')'))
else if (parseFunctionNameIf("CURTIME") && parseEmptyParens())
return currentTime();
if ((field = parseFieldCaseIf()) != null)
@ -7202,7 +7210,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
case 'D':
if (S.is(type))
if ((parseFunctionNameIf("DB_NAME") && parse('(') && parse(')')))
if ((parseFunctionNameIf("DB_NAME") && parseEmptyParens()))
return currentCatalog();
else if ((parseFunctionNameIf("DBINFO") && parse('(') && parseStringLiteral("dbname") != null && parse(')')))
return currentCatalog();
@ -7283,9 +7291,13 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
case 'G':
if (D.is(type))
if (parseKeywordIf("GETDATE") && parse('(') && parse(')'))
if (parseKeywordIf("GETDATE") && parseEmptyParens())
return currentTimestamp();
if (S.is(type))
if (parseFunctionNameIf("GENGUID", "GENERATE_UUID", "GEN_RANDOM_UUID") && parseEmptyParens())
return uuid();
if ((field = parseFieldGreatestIf()) != null)
return field;
else if (N.is(type) && (field = parseFieldGroupIdIf()) != null)
@ -7305,6 +7317,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
if (S.is(type))
if (parseFunctionNameIf("HASH_MD5"))
return md5((Field) parseFieldParenthesised(S));
else if (parseFunctionNameIf("HEX"))
return hex((Field) parseFieldParenthesised(N));
break;
@ -7420,6 +7434,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
if (S.is(type))
if (characterNext() == '\'')
return inline(parseStringLiteral(), NVARCHAR);
else if ((field = parseFieldNewIdIf()) != null)
return field;
if ((field = parseFieldNvl2If()) != null)
return field;
@ -7468,7 +7484,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
return field;
else if ((field = parseFieldPowerIf()) != null)
return field;
else if (parseFunctionNameIf("PI") && parse('(') && parse(')'))
else if (parseFunctionNameIf("PI") && parseEmptyParens())
return pi();
if (parseKeywordIf("PRIOR") && requireProEdition()) {
@ -7504,6 +7520,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
return field;
else if ((field = parseFieldRightIf()) != null)
return field;
else if (parseFunctionNameIf("RANDOM_UUID") && parseEmptyParens())
return uuid();
if (N.is(type))
if ((field = parseFieldRowNumberIf()) != null)
@ -7549,6 +7567,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
return currentSchema();
else if (parseFunctionNameIf("STRREVERSE"))
return reverse((Field) parseFieldParenthesised(S));
else if (parseFunctionNameIf("SYSUUID") && parseEmptyParensIf())
return uuid();
if (N.is(type))
if (parseFunctionNameIf("SECOND"))
@ -7585,6 +7605,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
return field;
else if ((field = parseFieldToCharIf()) != null)
return field;
else if (parseFunctionNameIf("TO_HEX"))
return hex((Field) parseFieldParenthesised(N));
if (N.is(type))
if (parseFunctionNameIf("TANH"))
@ -7620,9 +7642,10 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
case 'U':
if (S.is(type))
if (parseFunctionNameIf("UPPER")
|| parseFunctionNameIf("UCASE"))
if (parseFunctionNameIf("UPPER", "UCASE"))
return DSL.upper((Field) parseFieldParenthesised(S));
else if (parseFunctionNameIf("UUID", "UUID_GENERATE", "UUID_STRING") && parseEmptyParens())
return uuid();
if (D.is(type))
if (parseFunctionNameIf("UNIX_TIMESTAMP"))
@ -7961,6 +7984,21 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
return null;
}
private final Field<?> parseFieldNewIdIf() {
if (parseFunctionNameIf("NEWID")) {
parse('(');
Long l = parseSignedIntegerLiteralIf();
if (l != null && l.longValue() != -1L)
throw expected("No argument or -1 expected");
parse(')');
return uuid();
}
return null;
}
private final Field<?> parseNextValueIf() {
if (parseKeywordIf("NEXT VALUE FOR"))
return sequence(parseName()).nextval();