diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index 8205c1bdaa..ed82f615ff 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -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 HEX function. + *

+ * Format a number to its hex value. + */ + @NotNull + @Support({ MYSQL }) + public static Field hex(Number value) { + return new Hex(Tools.field(value)); + } + + /** + * The HEX function. + *

+ * Format a number to its hex value. + */ + @NotNull + @Support({ MYSQL }) + public static Field hex(Field value) { + return new Hex(value); + } + /** * The LEFT function. *

@@ -18603,6 +18626,17 @@ public class DSL { return new Upper(string); } + /** + * The UUID function. + *

+ * Generate a random UUID. + */ + @NotNull + @Support({ FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE }) + public static Field uuid() { + return new Uuid(); + } + // ------------------------------------------------------------------------- // Date functions // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index f2aac5e4c1..1fb38ec290 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -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"); diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 9c0693c9ba..e65594ef97 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -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 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();