From 48b708dbfc80ce4de68dcdb27d9bde1542a4a9eb Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 25 Mar 2024 13:43:50 +0100 Subject: [PATCH] [jOOQ/jOOQ#16499] Support parsing ARRAY_FILTER() and ARRAY_MAP() --- .../main/java/org/jooq/impl/ParserImpl.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index ca3a4aa615..c331893778 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -81,7 +81,9 @@ import static org.jooq.impl.DSL.arrayAgg; import static org.jooq.impl.DSL.arrayAggDistinct; import static org.jooq.impl.DSL.arrayAppend; import static org.jooq.impl.DSL.arrayConcat; +import static org.jooq.impl.DSL.arrayFilter; import static org.jooq.impl.DSL.arrayGet; +import static org.jooq.impl.DSL.arrayMap; import static org.jooq.impl.DSL.arrayOverlap; import static org.jooq.impl.DSL.arrayPrepend; import static org.jooq.impl.DSL.arrayRemove; @@ -235,6 +237,7 @@ import static org.jooq.impl.DSL.jsonbObjectAgg; import static org.jooq.impl.DSL.key; import static org.jooq.impl.DSL.keyword; import static org.jooq.impl.DSL.lag; +import static org.jooq.impl.DSL.lambda; import static org.jooq.impl.DSL.lastValue; import static org.jooq.impl.DSL.lateral; import static org.jooq.impl.DSL.lead; @@ -647,6 +650,7 @@ import org.jooq.JSONValueOnStep; import org.jooq.JoinType; import org.jooq.Keyword; // ... +import org.jooq.Lambda1; import org.jooq.LanguageContext; import org.jooq.LikeEscapeStep; // ... @@ -8744,6 +8748,10 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { return parseFunctionArgs2((f1, f2) -> arrayConcat(f1, f2)); else if (parseFunctionNameIf("ARRAY_GET", "arrayElement")) return parseFunctionArgs2((f1, f2) -> arrayGet(f1, f2)); + else if ((field = parseFieldArrayFilterIf()) != null) + return field; + else if ((field = parseFieldArrayMapIf()) != null) + return field; else if (parseFunctionNameIf("ARRAY_OVERLAP", "ARRAYS_OVERLAP")) return parseFunctionArgs2((f1, f2) -> arrayOverlap((Field) f1, (Field) f2)); else if (parseFunctionNameIf("ARRAY_PREPEND")) @@ -9553,6 +9561,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { return field; else if ((field = parseFieldCastIf()) != null) return field; + else if ((field = parseFieldArrayMapIf()) != null) + return field; break; @@ -10407,6 +10417,71 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { return null; } + private final Field parseFieldArrayFilterIf() { + if (parseFunctionNameIf("ARRAY_FILTER", "arrayFilter")) { + parse('('); + Field f; + Lambda1 l = parseLambdaIf(c -> c.parseCondition()); + + if (l != null && parse(',')) { + f = parseField(); + } + else { + f = parseField(); + parse(','); + l = parseLambda(c -> c.parseCondition()); + } + + parse(')'); + return arrayFilter(f, l); + } + + return null; + } + + private final Lambda1 parseLambda(Function> field) { + Lambda1 l = parseLambdaIf(field); + + if (l == null) + throw expected("Lambda"); + + return l; + } + + private final Lambda1 parseLambdaIf(Function> field) { + int p = position(); + Name e = parseIdentifierIf(); + + if (e != null && parseIf("->")) + return lambda(field(e), (Field) field.apply(this)); + else + position(p); + + return null; + } + + private final Field parseFieldArrayMapIf() { + if (parseFunctionNameIf("ARRAY_MAP", "arrayMap", "ARRAY_TRANSFORM", "TRANSFORM")) { + parse('('); + Field f; + Lambda1 l = parseLambdaIf(c -> c.parseField()); + + if (l != null && parse(',')) { + f = parseField(); + } + else { + f = parseField(); + parse(','); + l = parseLambda(c -> c.parseField()); + } + + parse(')'); + return arrayMap(f, l); + } + + return null; + } + private final Field parseFieldArrayConstructIf() { boolean absentOnNull = false;