From b3e63e510a8cfeaf036295bb5aabaeb5a9829e32 Mon Sep 17 00:00:00 2001 From: John Pentelow Date: Fri, 10 Nov 2023 14:40:38 +0000 Subject: [PATCH 1/2] Legend SQL - add to_char, lpad, rpad 1. add lpad/rpad 2. remove deprecated sql classes 3. added lpad/rpad pure string functions 4. added pure2sql support for month 5. more dialect handling of month/dayofweek --- .../toPureGraph/handlers/Handlers.java | 11 + .../core/legend/test/handlersTest.pure | 4 + .../pure/corefunctions/stringExtension.pure | 30 +++ .../corefunctions/tests/stringExtension.pure | 16 ++ .../pure/router/routing/router_routing.pure | 4 + .../sqlQueryToString/memSQLExtension.pure | 2 + .../sqlQueryToString/postgresExtension.pure | 2 + .../sqlQueryToString/prestoExtension.pure | 2 + .../sqlQueryToString/redshiftExtension.pure | 2 + .../sqlQueryToString/snowflakeExtension.pure | 2 + .../sqlQueryToString/sybaseASEExtension.pure | 1 + .../sqlQueryToString/sybaseIQExtension.pure | 1 + .../pureToSQLQuery/pureToSQLQuery.pure | 40 ++- .../relational/relationalExtension.pure | 40 +++ .../sqlQueryToString/dbExtension.pure | 3 + .../dbSpecific/db2/db2Extension.pure | 2 + .../dbSpecific/h2/h2Extension1_4_200.pure | 5 +- .../dbSpecific/h2/h2Extension2_1_214.pure | 5 +- .../sqlQueryToString/extensionDefaults.pure | 2 + .../testSuite/dynaFunctions/date.pure | 14 + .../testSuite/dynaFunctions/string.pure | 28 ++ .../testSuiteCompletenessTests.pure | 2 +- .../fromPure/tests/testToSQLString.pure | 49 ++++ .../query/sql/api/sources/SQLContext.java | 31 --- .../query/sql/api/sources/SQLSource.java | 42 --- .../sql/api/sources/SQLSourceArgument.java | 29 --- .../sql/api/sources/SQLSourceProvider.java | 25 -- .../api/sources/SQLSourceResolvedContext.java | 59 ----- .../query/sql/api/sources/TableSource.java | 89 ------- .../sql/api/sources/TableSourceArgument.java | 72 ------ .../sql/providers/core/SQLSourceProvider.java | 13 +- .../legend-engine-xt-sql-pure/pom.xml | 17 ++ .../binding/fromPure/fromPure.pure | 239 +++++++++++++++++- .../binding/fromPure/tests/testTranspile.pure | 135 +++++++++- .../engine/query/sql/api/SQLExecutor.java | 10 - .../query/sql/api/TestSQLSourceProvider.java | 2 +- 36 files changed, 634 insertions(+), 396 deletions(-) delete mode 100644 legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLContext.java delete mode 100644 legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSource.java delete mode 100644 legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceArgument.java delete mode 100644 legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceProvider.java delete mode 100644 legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceResolvedContext.java delete mode 100644 legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/TableSource.java delete mode 100644 legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/TableSourceArgument.java diff --git a/legend-engine-core/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/handlers/Handlers.java b/legend-engine-core/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/handlers/Handlers.java index 7f7bdc87b7f..5452ddbba79 100644 --- a/legend-engine-core/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/handlers/Handlers.java +++ b/legend-engine-core/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/handlers/Handlers.java @@ -922,6 +922,11 @@ private void registerStrings() register("meta::pure::functions::string::trim_String_1__String_1_", true, ps -> res("String", "one")); register("meta::pure::functions::string::ltrim_String_1__String_1_", true, ps -> res("String", "one")); register("meta::pure::functions::string::rtrim_String_1__String_1_", true, ps -> res("String", "one")); + register(m(m(h("meta::pure::functions::string::lpad_String_1__Integer_1__String_1_", false, ps -> res("String", "one"), ps -> ps.size() == 2)), + m(h("meta::pure::functions::string::lpad_String_1__Integer_1__String_1__String_1_", false, ps -> res("String", "one"), ps -> true)))); + + register(m(m(h("meta::pure::functions::string::rpad_String_1__Integer_1__String_1_", false, ps -> res("String", "one"), ps -> ps.size() == 2)), + m(h("meta::pure::functions::string::rpad_String_1__Integer_1__String_1__String_1_", false, ps -> res("String", "one"), ps -> true)))); register("meta::pure::functions::string::matches_String_1__String_1__Boolean_1_", true, ps -> res("Boolean", "one")); register("meta::pure::functions::string::isAlphaNumeric_String_1__Boolean_1_", false, ps -> res("Boolean", "one")); register("meta::pure::functions::string::isNoLongerThan_String_$0_1$__Integer_1__Boolean_1_", false, ps -> res("Boolean", "one")); @@ -2052,6 +2057,12 @@ private Map buildDispatch() map.put("meta::pure::functions::string::toString_Any_1__String_1_", (List ps) -> ps.size() == 1 && isOne(ps.get(0)._multiplicity())); map.put("meta::pure::functions::string::toUpper_String_1__String_1_", (List ps) -> ps.size() == 1 && isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "String".equals(ps.get(0)._genericType()._rawType()._name()))); map.put("meta::pure::functions::string::trim_String_1__String_1_", (List ps) -> ps.size() == 1 && isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "String".equals(ps.get(0)._genericType()._rawType()._name()))); + map.put("meta::pure::functions::string::ltrim_String_1__String_1_", (List ps) -> ps.size() == 1 && isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "String".equals(ps.get(0)._genericType()._rawType()._name()))); + map.put("meta::pure::functions::string::rtrim_String_1__String_1_", (List ps) -> ps.size() == 1 && isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "String".equals(ps.get(0)._genericType()._rawType()._name()))); + map.put("meta::pure::functions::string::lpad_String_1__Integer_1__String_1_", (List ps) -> ps.size() == 2 && isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "String".equals(ps.get(0)._genericType()._rawType()._name())) && isOne(ps.get(1)._multiplicity()) && ("Nil".equals(ps.get(1)._genericType()._rawType()._name()) || "Integer".equals(ps.get(1)._genericType()._rawType()._name()))); + map.put("meta::pure::functions::string::lpad_String_1__Integer_1__String_1__String_1_", (List ps) -> ps.size() == 3 && isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "String".equals(ps.get(0)._genericType()._rawType()._name())) && isOne(ps.get(1)._multiplicity()) && ("Nil".equals(ps.get(1)._genericType()._rawType()._name()) || "Integer".equals(ps.get(1)._genericType()._rawType()._name())) && isOne(ps.get(2)._multiplicity()) && ("Nil".equals(ps.get(2)._genericType()._rawType()._name()) || "String".equals(ps.get(2)._genericType()._rawType()._name()))); + map.put("meta::pure::functions::string::rpad_String_1__Integer_1__String_1_", (List ps) -> ps.size() == 2 && isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "String".equals(ps.get(0)._genericType()._rawType()._name())) && isOne(ps.get(1)._multiplicity()) && ("Nil".equals(ps.get(1)._genericType()._rawType()._name()) || "Integer".equals(ps.get(1)._genericType()._rawType()._name()))); + map.put("meta::pure::functions::string::rpad_String_1__Integer_1__String_1__String_1_", (List ps) -> ps.size() == 3 && isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "String".equals(ps.get(0)._genericType()._rawType()._name())) && isOne(ps.get(1)._multiplicity()) && ("Nil".equals(ps.get(1)._genericType()._rawType()._name()) || "Integer".equals(ps.get(1)._genericType()._rawType()._name())) && isOne(ps.get(2)._multiplicity()) && ("Nil".equals(ps.get(2)._genericType()._rawType()._name()) || "String".equals(ps.get(2)._genericType()._rawType()._name()))); map.put("meta::pure::graphFetch::calculateSourceTree_RootGraphFetchTree_1__Mapping_1__Extension_MANY__RootGraphFetchTree_1_", (List ps) -> ps.size() == 3 && isOne(ps.get(0)._multiplicity()) && Sets.immutable.with("Nil", "RootGraphFetchTree", "ExtendedRootGraphFetchTree", "RoutedRootGraphFetchTree", "SerializeTopRootGraphFetchTree").contains(ps.get(0)._genericType()._rawType()._name()) && isOne(ps.get(1)._multiplicity()) && ("Nil".equals(ps.get(1)._genericType()._rawType()._name()) || "Mapping".equals(ps.get(1)._genericType()._rawType()._name())) && ("Nil".equals(ps.get(2)._genericType()._rawType()._name()) || "Extension".equals(ps.get(2)._genericType()._rawType()._name()))); map.put("meta::pure::graphFetch::execution::graphFetchChecked_T_MANY__RootGraphFetchTree_1__Checked_MANY_", (List ps) -> ps.size() == 2 && isOne(ps.get(1)._multiplicity()) && Sets.immutable.with("Nil", "RootGraphFetchTree", "ExtendedRootGraphFetchTree", "RoutedRootGraphFetchTree", "SerializeTopRootGraphFetchTree").contains(ps.get(1)._genericType()._rawType()._name())); map.put("meta::pure::graphFetch::execution::graphFetch_T_MANY__RootGraphFetchTree_1__Integer_1__T_MANY_", (List ps) -> ps.size() == 3 && isOne(ps.get(1)._multiplicity()) && Sets.immutable.with("Nil", "RootGraphFetchTree", "ExtendedRootGraphFetchTree", "RoutedRootGraphFetchTree", "SerializeTopRootGraphFetchTree").contains(ps.get(1)._genericType()._rawType()._name()) && isOne(ps.get(2)._multiplicity()) && ("Nil".equals(ps.get(2)._genericType()._rawType()._name()) || "Integer".equals(ps.get(2)._genericType()._rawType()._name()))); diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/legend/test/handlersTest.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/legend/test/handlersTest.pure index 48d8a454c6e..245903da161 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/legend/test/handlersTest.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/legend/test/handlersTest.pure @@ -372,6 +372,10 @@ Class meta::legend::test::handlers::model::TestString length(){$this.string->length()}:Integer[1]; ltrim(){$this.string->ltrim()}:String[1]; + lpad(){$this.string->lpad(1)}:String[1]; + lpad2(){$this.string->lpad(1, '0')}:String[1]; + rpad(){$this.string->rpad(1)}:String[1]; + rpad2(){$this.string->rpad(1, '0')}:String[1]; parseBoolean(){$this.string->parseBoolean()}:Boolean[1]; parseDate(){$this.string->parseDate()}:Date[1]; diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/corefunctions/stringExtension.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/corefunctions/stringExtension.pure index 2ec81292d02..390c64a9cbd 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/corefunctions/stringExtension.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/corefunctions/stringExtension.pure @@ -167,6 +167,36 @@ function {doc.doc = 'Un-camel case / humanize the provided string using provided ->joinStrings(' '); } +function meta::pure::functions::string::lpad(str:String[1], length:Integer[1]):String[1] +{ + lpad($str, $length, ' ') +} + +function meta::pure::functions::string::lpad(str:String[1], length:Integer[1], char:String[1]):String[1] +{ + pad($str, $length, $char, true) +} + +function meta::pure::functions::string::rpad(str:String[1], length:Integer[1]):String[1] +{ + rpad($str, $length, ' ') +} + +function meta::pure::functions::string::rpad(str:String[1], length:Integer[1], char:String[1]):String[1] +{ + pad($str, $length, $char, false) +} + +function <> meta::pure::functions::string::pad(str:String[1], length:Integer[1], char:String[1], left:Boolean[1]):String[1] +{ + let result = if ($str->length() > $length, + | $str->substring(0, $length), + | range($length - $str->length())->fold({acc, s | if ($left, | $char + $s, | $s + $char)}, $str->toOne()) + ); + + if ($result->length() > $length, | $result->substring(0, $length), | $result); +} + function {doc.doc = 'Split the string and select the part'} meta::pure::functions::string::splitPart(str:String[0..1], token:String[1], part:Integer[1]):String[0..1] { diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/corefunctions/tests/stringExtension.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/corefunctions/tests/stringExtension.pure index 92134809154..8d0324b7bd8 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/corefunctions/tests/stringExtension.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/corefunctions/tests/stringExtension.pure @@ -110,6 +110,22 @@ function <> {test.excludePlatform = 'Java compiled'} meta::pure::func assertEquals('abab', repeatString('ab', 2)); } +function <> meta::pure::functions::string::tests::testLpad():Boolean[1] +{ + assertEquals('abc', lpad('abcd', 3, '_')); + assertEquals('______abcd', lpad('abcd', 10, '_')); + assertEquals(' abcd', lpad('abcd', 10)); + assertEquals('abcd', lpad('abcd', 10, '')); +} + +function <> meta::pure::functions::string::tests::testRpad():Boolean[1] +{ + assertEquals('abc', rpad('abcd', 3, '_')); + assertEquals('abcd______', rpad('abcd', 10, '_')); + assertEquals('abcd ', rpad('abcd', 10)); + assertEquals('abcd', rpad('abcd', 10, '')); +} + function <> meta::pure::functions::string::tests::testSplitPart():Boolean[1] { assertEquals([], splitPart([], 'a', 1)); diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/routing/router_routing.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/routing/router_routing.pure index ecb88e86e68..9fb4a0a45b2 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/routing/router_routing.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/routing/router_routing.pure @@ -730,6 +730,10 @@ function meta::pure::router::routing::shouldStopFunctions(extensions:meta::pure: tdsContains_T_1__Function_MANY__TabularDataSet_1__Boolean_1_, tdsContains_T_1__Function_MANY__String_MANY__TabularDataSet_1__Function_1__Boolean_1_, splitPart_String_$0_1$__String_1__Integer_1__String_$0_1$_, + lpad_String_1__Integer_1__String_1_, + lpad_String_1__Integer_1__String_1__String_1_, + rpad_String_1__Integer_1__String_1_, + rpad_String_1__Integer_1__String_1__String_1_, meta::pure::tds::extensions::firstNotNull_T_MANY__T_$0_1$_, meta::pure::functions::date::calendar::annualized_Date_1__String_1__Date_1__Number_$0_1$__Number_$0_1$_, meta::pure::functions::date::calendar::cme_Date_1__String_1__Date_1__Number_$0_1$__Number_$0_1$_, diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-memsql/legend-engine-xt-relationalStore-memsql-pure/src/main/resources/core_relational_memsql/relational/sqlQueryToString/memSQLExtension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-memsql/legend-engine-xt-relationalStore-memsql-pure/src/main/resources/core_relational_memsql/relational/sqlQueryToString/memSQLExtension.pure index c79014a1a4a..c1f1adda84d 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-memsql/legend-engine-xt-relationalStore-memsql-pure/src/main/resources/core_relational_memsql/relational/sqlQueryToString/memSQLExtension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-memsql/legend-engine-xt-relationalStore-memsql-pure/src/main/resources/core_relational_memsql/relational/sqlQueryToString/memSQLExtension.pure @@ -84,6 +84,7 @@ function <> meta::relational::functions::sqlQueryToString::memsq dynaFnToSql('dateDiff', $allStates, ^ToSql(format='%s', transform={p:String[*]|generateDateDiffExpressionForMemSQL ([$p->at(0), $p->at(1), $p->at(2)->replace('\'', '')])})), dynaFnToSql('datePart', $allStates, ^ToSql(format='date(%s)')), dynaFnToSql('dayOfMonth', $allStates, ^ToSql(format='day(%s)')), + dynaFnToSql('dayOfWeek', $allStates, ^ToSql(format='dayname(%s)')), dynaFnToSql('dayOfWeekNumber', $allStates, ^ToSql(format='dayofweek(%s)')), dynaFnToSql('dayOfYear', $allStates, ^ToSql(format='dayofyear(%s)')), dynaFnToSql('decodeBase64', $allStates, ^ToSql(format='cast(from_base64(%s) as char)')), @@ -103,6 +104,7 @@ function <> meta::relational::functions::sqlQueryToString::memsq dynaFnToSql('minute', $allStates, ^ToSql(format='minute(%s)')), dynaFnToSql('mod', $allStates, ^ToSql(format='mod(%s,%s)')), dynaFnToSql('month', $allStates, ^ToSql(format='month(%s)')), + dynaFnToSql('monthName', $allStates, ^ToSql(format='monthname(%s)')), dynaFnToSql('monthNumber', $allStates, ^ToSql(format='month(%s)')), dynaFnToSql('mostRecentDayOfWeek', $allStates, ^ToSql(format='adddate(%s, INTERVAL case when %s - dayofweek(%s) > 0 then %s - dayofweek(%s) - 7 else %s - dayofweek(%s) end DAY)', transform={p:String[1..2] | $p->formatMostRecentMemSQL('curdate()')}, parametersWithinWhenClause = [false, false])), dynaFnToSql('now', $allStates, ^ToSql(format='now()')), diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-postgres/legend-engine-xt-relationalStore-postgres-pure/src/main/resources/core_relational_postgres/relational/sqlQueryToString/postgresExtension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-postgres/legend-engine-xt-relationalStore-postgres-pure/src/main/resources/core_relational_postgres/relational/sqlQueryToString/postgresExtension.pure index c66d916ebdb..ad39e525cee 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-postgres/legend-engine-xt-relationalStore-postgres-pure/src/main/resources/core_relational_postgres/relational/sqlQueryToString/postgresExtension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-postgres/legend-engine-xt-relationalStore-postgres-pure/src/main/resources/core_relational_postgres/relational/sqlQueryToString/postgresExtension.pure @@ -63,6 +63,7 @@ function <> meta::relational::functions::sqlQueryToString::postg dynaFnToSql('dateDiff', $allStates, ^ToSql(format='%s', transform={p:String[*]|generateDateDiffExpressionForPostgres($p)})), dynaFnToSql('datePart', $allStates, ^ToSql(format='Date(%s)')), dynaFnToSql('dayOfMonth', $allStates, ^ToSql(format='date_part(\'day\', %s)')), + dynaFnToSql('dayOfWeek', $allStates, ^ToSql(format='to_char(%s, \'FMDay\')')), dynaFnToSql('dayOfWeekNumber', $allStates, ^ToSql(format='date_part(\'dow\', %s)')), dynaFnToSql('dayOfYear', $allStates, ^ToSql(format='date_part(\'doy\', %s)')), dynaFnToSql('firstDayOfMonth', $allStates, ^ToSql(format='date_trunc(\'month\', %s)')), @@ -82,6 +83,7 @@ function <> meta::relational::functions::sqlQueryToString::postg dynaFnToSql('length', $allStates, ^ToSql(format='char_length(%s)')), dynaFnToSql('minute', $allStates, ^ToSql(format='date_part(\'minute\', %s)')), dynaFnToSql('mod', $allStates, ^ToSql(format='mod(%s,%s)')), + dynaFnToSql('monthName', $allStates, ^ToSql(format='to_char(%s, \'FMMonth\')')), dynaFnToSql('monthNumber', $allStates, ^ToSql(format='date_part(\'month\', %s)')), dynaFnToSql('now', $allStates, ^ToSql(format='now()')), dynaFnToSql('parseDecimal', $allStates, ^ToSql(format='cast(%s as decimal)')), diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-presto/legend-engine-xt-relationalStore-presto-pure/src/main/resources/core_relational_presto/relational/sqlQueryToString/prestoExtension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-presto/legend-engine-xt-relationalStore-presto-pure/src/main/resources/core_relational_presto/relational/sqlQueryToString/prestoExtension.pure index 5ade44da7fe..92c28c34b4a 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-presto/legend-engine-xt-relationalStore-presto-pure/src/main/resources/core_relational_presto/relational/sqlQueryToString/prestoExtension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-presto/legend-engine-xt-relationalStore-presto-pure/src/main/resources/core_relational_presto/relational/sqlQueryToString/prestoExtension.pure @@ -58,6 +58,7 @@ function <> meta::relational::functions::sqlQueryToString::prest dynaFnToSql('convertVarchar128', $allStates, ^ToSql(format='cast(%s as VARCHAR(128))')), dynaFnToSql('dateDiff', $allStates, ^ToSql(format='date_diff(%s,%s,%s)', transform={p:String[*]|[$p->at(2)->replace('\'', '')->processDateDiffDurationUnitForPresto(),$p->at(0),$p->at(1)]})), dynaFnToSql('datePart', $allStates, ^ToSql(format='Date(%s)')), + dynaFnToSql('dayOfWeek', $allStates, ^ToSql(format='date_format(%s, \'%W\')')), dynaFnToSql('dayOfWeekNumber', $allStates, ^ToSql(format='day_of_week(%s)')), dynaFnToSql('dayOfYear', $allStates, ^ToSql(format='day_of_year(%s)')), dynaFnToSql('firstDayOfMonth', $allStates, ^ToSql(format='date_trunc(\'month\', %s)')), @@ -79,6 +80,7 @@ function <> meta::relational::functions::sqlQueryToString::prest dynaFnToSql('minute', $allStates, ^ToSql(format='minute(%s)')), dynaFnToSql('mod', $allStates, ^ToSql(format='mod(%s,%s)')), dynaFnToSql('month', $allStates, ^ToSql(format='month(%s)')), + dynaFnToSql('monthName', $allStates, ^ToSql(format='date_format(%s, \'%M\')')), dynaFnToSql('monthNumber', $allStates, ^ToSql(format='month(%s)')), dynaFnToSql('mostRecentDayOfWeek', $allStates, ^ToSql(format='date_add(\'day\', case when %s - day_of_week(%s) > 0 then %s - day_of_week(%s) - 7 else %s - day_of_week(%s) end, %s)', transform={p:String[1..2] | $p->formatMostRecentPresto('current_date')}, parametersWithinWhenClause = [false, false])), dynaFnToSql('now', $allStates, ^ToSql(format='current_timestamp')), diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-redshift/legend-engine-xt-relationalStore-redshift-pure/src/main/resources/core_relational_redshift/relational/sqlQueryToString/redshiftExtension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-redshift/legend-engine-xt-relationalStore-redshift-pure/src/main/resources/core_relational_redshift/relational/sqlQueryToString/redshiftExtension.pure index f161fc6ed01..6d03e9c5220 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-redshift/legend-engine-xt-relationalStore-redshift-pure/src/main/resources/core_relational_redshift/relational/sqlQueryToString/redshiftExtension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-redshift/legend-engine-xt-relationalStore-redshift-pure/src/main/resources/core_relational_redshift/relational/sqlQueryToString/redshiftExtension.pure @@ -52,12 +52,14 @@ function <> meta::relational::functions::sqlQueryToString::redsh dynaFnToSql('atan2', $allStates, ^ToSql(format='atan2(%s,%s)')), dynaFnToSql('concat', $allStates, ^ToSql(format='%s', transform={p:String[*]|$p->joinStrings(' + ')})), dynaFnToSql('datePart', $allStates, ^ToSql(format='trunc(%s)')), + dynaFnToSql('dayOfWeek', $allStates, ^ToSql(format='to_char(%s, \'FMDay\')')), dynaFnToSql('hour', $allStates, ^ToSql(format='date_part(hour, %s)')), dynaFnToSql('joinStrings', $allStates, ^ToSql(format='listagg(%s, %s)')), dynaFnToSql('log10', $allStates, ^ToSql(format='log(%s)')), dynaFnToSql('minute', $allStates, ^ToSql(format='extract(minute from %s)')), dynaFnToSql('mod', $allStates, ^ToSql(format='mod(%s,%s)')), dynaFnToSql('month', $allStates, ^ToSql(format='extract(month from %s)')), + dynaFnToSql('monthName', $allStates, ^ToSql(format='to_char(%s, \'FMMonth\')')), dynaFnToSql('monthNumber', $allStates, ^ToSql(format='extract(month from %s)')), dynaFnToSql('now', $allStates, ^ToSql(format='now()')), dynaFnToSql('parseDecimal', $allStates, ^ToSql(format='cast(%s as decimal)')), diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-snowflake/legend-engine-xt-relationalStore-snowflake-pure/src/main/resources/core_relational_snowflake/relational/sqlQueryToString/snowflakeExtension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-snowflake/legend-engine-xt-relationalStore-snowflake-pure/src/main/resources/core_relational_snowflake/relational/sqlQueryToString/snowflakeExtension.pure index f2fb47dbcdf..fdcd0cda345 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-snowflake/legend-engine-xt-relationalStore-snowflake-pure/src/main/resources/core_relational_snowflake/relational/sqlQueryToString/snowflakeExtension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-snowflake/legend-engine-xt-relationalStore-snowflake-pure/src/main/resources/core_relational_snowflake/relational/sqlQueryToString/snowflakeExtension.pure @@ -111,6 +111,7 @@ function <> meta::relational::functions::sqlQueryToString::snowf dynaFnToSql('dateDiff', $allStates, ^ToSql(format='datediff(%s,%s,%s)', transform={p:String[*]|[$p->at(2)->replace('\'', '')->processDateDiffDurationUnitForSnowflake(),$p->at(0),$p->at(1)]})), dynaFnToSql('datePart', $allStates, ^ToSql(format='Date(%s)')), dynaFnToSql('dayOfMonth', $allStates, ^ToSql(format='DAYOFMONTH(%s)')), + dynaFnToSql('dayOfWeek', $allStates, ^ToSql(format='to_char(%s, \'DYDY\')')), dynaFnToSql('dayOfWeekNumber', $allStates, ^ToSql(format='DAYOFWEEKISO(%s)')), dynaFnToSql('dayOfYear', $allStates, ^ToSql(format='DAYOFYEAR(%s)')), dynaFnToSql('extractFromSemiStructured', $allStates, ^ToSql(format='%s', transform={p:String[3]|$p->processExtractFromSemiStructuredParamsForSnowflake()})), @@ -136,6 +137,7 @@ function <> meta::relational::functions::sqlQueryToString::snowf dynaFnToSql('minute', $allStates, ^ToSql(format='minute(%s)')), dynaFnToSql('mod', $allStates, ^ToSql(format='mod(%s,%s)')), dynaFnToSql('month', $allStates, ^ToSql(format='MONTH(%s)')), + dynaFnToSql('monthName', $allStates, ^ToSql(format='to_char(%s, \'MMMM\')')), dynaFnToSql('monthNumber', $allStates, ^ToSql(format='MONTH(%s)')), dynaFnToSql('mostRecentDayOfWeek', $allStates, ^ToSql(format='DATE_TRUNC(\'WEEK\', CURRENT_DATE)%s', transform={p:String[*] | ''})), dynaFnToSql('now', $allStates, ^ToSql(format='current_timestamp')), diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-sybase/legend-engine-xt-relationalStore-sybase-pure/src/main/resources/core_relational_sybase/relational/sqlQueryToString/sybaseASEExtension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-sybase/legend-engine-xt-relationalStore-sybase-pure/src/main/resources/core_relational_sybase/relational/sqlQueryToString/sybaseASEExtension.pure index 8909ba33e73..1cb86366689 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-sybase/legend-engine-xt-relationalStore-sybase-pure/src/main/resources/core_relational_sybase/relational/sqlQueryToString/sybaseASEExtension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-sybase/legend-engine-xt-relationalStore-sybase-pure/src/main/resources/core_relational_sybase/relational/sqlQueryToString/sybaseASEExtension.pure @@ -124,6 +124,7 @@ function meta::relational::functions::sqlQueryToString::sybaseASE::getDynaFuncti dynaFnToSql('minute', $allStates, ^ToSql(format='minute(%s)')), dynaFnToSql('mod', $allStates, ^ToSql(format='mod(%s,%s)')), dynaFnToSql('month', $allStates, ^ToSql(format='month(%s)')), + dynaFnToSql('monthName', $allStates, ^ToSql(format='datename(MONTH, %s)')), dynaFnToSql('monthNumber', $allStates, ^ToSql(format='month(%s)')), dynaFnToSql('mostRecentDayOfWeek', $allStates, ^ToSql(format='dateadd(Day, case when %s - dow(%s) > 0 then %s - dow(%s) - 7 else %s - dow(%s) end, %s)', transform={p:String[1..2] | $p->formatMostRecentSybase('today()')}, parametersWithinWhenClause = [false, false])), dynaFnToSql('now', $allStates, ^ToSql(format='now(%s)', transform={p:String[*] | ''})), diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-sybaseiq/legend-engine-xt-relationalStore-sybaseiq-pure/src/main/resources/core_relational_sybaseiq/relational/sqlQueryToString/sybaseIQExtension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-sybaseiq/legend-engine-xt-relationalStore-sybaseiq-pure/src/main/resources/core_relational_sybaseiq/relational/sqlQueryToString/sybaseIQExtension.pure index 10c33c2e4e6..a167de9a353 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-sybaseiq/legend-engine-xt-relationalStore-sybaseiq-pure/src/main/resources/core_relational_sybaseiq/relational/sqlQueryToString/sybaseIQExtension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-sybaseiq/legend-engine-xt-relationalStore-sybaseiq-pure/src/main/resources/core_relational_sybaseiq/relational/sqlQueryToString/sybaseIQExtension.pure @@ -121,6 +121,7 @@ function meta::relational::functions::sqlQueryToString::sybaseIQ::getDynaFunctio dynaFnToSql('minute', $allStates, ^ToSql(format='minute(%s)')), dynaFnToSql('mod', $allStates, ^ToSql(format='mod(%s,%s)')), dynaFnToSql('month', $allStates, ^ToSql(format='month(%s)')), + dynaFnToSql('monthName', $allStates, ^ToSql(format='monthname(%s)')), dynaFnToSql('monthNumber', $allStates, ^ToSql(format='month(%s)')), dynaFnToSql('mostRecentDayOfWeek', $allStates, ^ToSql(format='dateadd(Day, case when %s - dow(%s) > 0 then %s - dow(%s) - 7 else %s - dow(%s) end, %s)', transform={p:String[1..2] | $p->formatMostRecentSybase('today()')}, parametersWithinWhenClause = [false, false])), dynaFnToSql('now', $allStates, ^ToSql(format='now(%s)', transform={p:String[*] | ''})), diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/pureToSQLQuery/pureToSQLQuery.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/pureToSQLQuery/pureToSQLQuery.pure index 89a0d1341aa..ce76a5a6195 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/pureToSQLQuery/pureToSQLQuery.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/pureToSQLQuery/pureToSQLQuery.pure @@ -2397,11 +2397,14 @@ function meta::relational::functions::pureToSqlQuery::processPlus(f:FunctionExpr function meta::relational::functions::pureToSqlQuery::processParseDate(f:FunctionExpression[1], currentPropertyMapping:PropertyMapping[*], operation:SelectWithCursor[1], vars:Map[1], state:State[1], joinType:JoinType[1], nodeId:String[1], aggFromMap:List[1], context:DebugContext[1], extensions:Extension[*]):RelationalOperationElement[1] { let formatInstance = ^InstanceValue(multiplicity = PureOne, genericType = ^GenericType(rawType=String), values = 'YYYY-MM-DD HH24:MI:SS'); - let dynaFuncName = 'toTimestamp'; - let oldFunc = $f.func; - let newFunc = ^$oldFunc(functionName=$dynaFuncName); - let functionExpression = ^$f(func = $newFunc, parametersValues=$f.parametersValues->concatenate($formatInstance)); - $functionExpression->processDynaFunction($currentPropertyMapping, $operation, $vars, $state, $joinType, $nodeId, $aggFromMap, $context, $extensions); + + processDynafuncWithRename('toTimestamp', ^$f(parametersValues=$f.parametersValues->concatenate($formatInstance)), $currentPropertyMapping, $operation, $vars, $state, $joinType, $nodeId, $aggFromMap, $context, $extensions); +} + +//this is transformed to monthName due to "month" already handled as monthNumber in dialects +function meta::relational::functions::pureToSqlQuery::processMonth(f:FunctionExpression[1], currentPropertyMapping:PropertyMapping[*], operation:SelectWithCursor[1], vars:Map[1], state:State[1], joinType:JoinType[1], nodeId:String[1], aggFromMap:List[1], context:DebugContext[1], extensions:Extension[*]):RelationalOperationElement[1] +{ + processDynafuncWithRename('monthName', $f, $currentPropertyMapping, $operation, $vars, $state, $joinType, $nodeId, $aggFromMap, $context, $extensions) } function meta::relational::functions::pureToSqlQuery::processFirstNotNull(f:FunctionExpression[1], currentPropertyMapping:PropertyMapping[*], operation:SelectWithCursor[1], vars:Map[1], state:State[1], joinType:JoinType[1], nodeId:String[1], aggFromMap:List[1], context:DebugContext[1], extensions:Extension[*]):RelationalOperationElement[1] @@ -2418,8 +2421,13 @@ function meta::relational::functions::pureToSqlQuery::processFirstNotNull(f:Func a:Any[*] | fail($error) ]); + processDynafuncWithRename('coalesce', $f, $currentPropertyMapping, $operation, $vars, $state, $joinType, $nodeId, $aggFromMap, $context, $extensions); +} + +function meta::relational::functions::pureToSqlQuery::processDynafuncWithRename(newName:String[1], f:FunctionExpression[1], currentPropertyMapping:PropertyMapping[*], operation:SelectWithCursor[1], vars:Map[1], state:State[1], joinType:JoinType[1], nodeId:String[1], aggFromMap:List[1], context:DebugContext[1], extensions:Extension[*]):RelationalOperationElement[1] +{ let oldFunc = $f.func; - let newFunc = ^$oldFunc(functionName = 'coalesce'); + let newFunc = ^$oldFunc(functionName = $newName); processDynaFunction(^$f(func = $newFunc), $currentPropertyMapping, $operation, $vars, $state, $joinType, $nodeId, $aggFromMap, $context, $extensions); } @@ -4458,7 +4466,13 @@ function <> meta::relational::functions::pureToSqlQuery::process let select = $mainQuery.select->cast(@TdsSelectSqlQuery); let funcParams = $f->genericType().typeArguments.rawType->cast(@FunctionType).parameters->tail(); let updatedState = if(!$vars->keys()->isEmpty(),|updateFunctionParamScope($state, $funcParams->evaluateAndDeactivate(),$operation),|$state); - let cols = $f->instanceValuesAtParameter(1, $vars, $updatedState.inScopeVars)->cast(@BasicColumnSpecification); + let cols = $f->instanceValuesAtParameter(1, $vars, $updatedState.inScopeVars)->map(col | + $col->match([ + b:BasicColumnSpecification[1] | $b, + s:SimpleFunctionExpression[1] | $s->reactivate()->cast(@BasicColumnSpecification) + ]) + ); + let newCols = $cols->map(cs| let newElement = processTdsLambda($cs.func->cast(@FunctionDefinition).expressionSequence->at(0), $mainQuery.select.columns->cast(@Alias), false, $vars, $updatedState, $currentPropertyMapping, $context)->at(0); let alias = ^Alias(name='"'+$cs.name+'"', relationalElement=$newElement); @@ -5111,6 +5125,9 @@ function meta::relational::functions::pureToSqlQuery::processTdsLambda(mapFn:Val ^PureFunctionTDSToRelationalFunctionPair(first = meta::pure::tds::extensions::firstNotNull_T_MANY__T_$0_1$_, second = {| newDynaFunction('coalesce', $f.parametersValues->at(0)->processTdsLambda($a, $returnColumnName, $vars, $state, $currentPropertyMapping, $context)) }), + ^PureFunctionTDSToRelationalFunctionPair(first = meta::pure::functions::date::month_Date_1__Month_1_, second = {| + newDynaFunction('monthName', $f.parametersValues->at(0)->processTdsLambda($a, $returnColumnName, $vars, $state, $currentPropertyMapping, $context)) + }), ^PureFunctionTDSToRelationalFunctionPair(first = splitPart_String_$0_1$__String_1__Integer_1__String_$0_1$_, second = {| newDynaFunction('splitPart', [ $f.parametersValues->at(0)->processTdsLambda($a, $returnColumnName, $vars, $state, $currentPropertyMapping, $context)->toOne(), @@ -5872,8 +5889,8 @@ function meta::relational::functions::pureToSqlQuery::findBestNodeToIsolate(sele { let joinThreads = ^List(values=$select.data)->buildThreads(); - //For filters having aliases like a.x = 'y' fetch aliases from relationalOperationalElement and for filters without aliases like 'x' = 'x' fetch aliases from the treeNode. - let aliasesWithConstraints = $select.savedFilteringOperation->map(x | let aliasFromFilters = $x.second->extractTableAliasColumns().alias; + //For filters having aliases like a.x = 'y' fetch aliases from relationalOperationalElement and for filters without aliases like 'x' = 'x' fetch aliases from the treeNode. + let aliasesWithConstraints = $select.savedFilteringOperation->map(x | let aliasFromFilters = $x.second->extractTableAliasColumns().alias; if($aliasFromFilters->isNotEmpty(), |$aliasFromFilters, | $x.first.alias); )->removeDuplicates(); @@ -7638,6 +7655,7 @@ function meta::relational::functions::pureToSqlQuery::getSupportedFunctions():Ma ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::date::minute_Date_1__Integer_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::date::second_Date_1__Integer_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::date::monthNumber_Date_1__Integer_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), + ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::date::month_Date_1__Month_1_,second=meta::relational::functions::pureToSqlQuery::processMonth_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::date::quarterNumber_Date_1__Integer_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::date::dateDiff_Date_1__Date_1__DurationUnit_1__Integer_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::date::adjust_Date_1__Integer_1__DurationUnit_1__Date_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), @@ -7677,6 +7695,10 @@ function meta::relational::functions::pureToSqlQuery::getSupportedFunctions():Ma ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::string::trim_String_1__String_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::string::ltrim_String_1__String_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::string::rtrim_String_1__String_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), + ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::string::lpad_String_1__Integer_1__String_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), + ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::string::lpad_String_1__Integer_1__String_1__String_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), + ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::string::rpad_String_1__Integer_1__String_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), + ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::string::rpad_String_1__Integer_1__String_1__String_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::string::toString_Any_1__String_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::string::replace_String_1__String_1__String_1__String_1_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), ^PureFunctionToRelationalFunctionPair(first=meta::pure::functions::string::repeatString_String_$0_1$__Integer_1__String_$0_1$_,second=meta::relational::functions::pureToSqlQuery::processDynaFunction_FunctionExpression_1__PropertyMapping_MANY__SelectWithCursor_1__Map_1__State_1__JoinType_1__String_1__List_1__DebugContext_1__Extension_MANY__RelationalOperationElement_1_), diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/relationalExtension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/relationalExtension.pure index 595ad0f131d..96e257fa526 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/relationalExtension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/relationalExtension.pure @@ -471,6 +471,16 @@ function <> meta::relational::functions::typeInference::getDynaF ]) ), + pair( + 'dayOfMWeek', + list([ + pair( + {params: RelationalOperationElement[*] | true}, + {params: RelationalOperationElement[*] | ^meta::relational::metamodel::datatype::Varchar(size = 9)} + ) + ]) + ), + pair( 'dayOfWeekNumber', list([ @@ -889,6 +899,26 @@ function <> meta::relational::functions::typeInference::getDynaF ]) ), + pair( + 'lpad', + list([ + pair( + {params: RelationalOperationElement[*] | true}, + {params: RelationalOperationElement[*] | ^meta::relational::metamodel::datatype::Varchar(size = $params->at(1)->match([l:Literal[1] | $l.value->match([i:Integer[1] | $i])]))} + ) + ]) + ), + + pair( + 'rpad', + list([ + pair( + {params: RelationalOperationElement[*] | true}, + {params: RelationalOperationElement[*] | ^meta::relational::metamodel::datatype::Varchar(size = $params->at(1)->match([l:Literal[1] | $l.value->match([i:Integer[1] | $i])]))} + ) + ]) + ), + pair( 'max', list([ @@ -967,6 +997,16 @@ function <> meta::relational::functions::typeInference::getDynaF ]) ), + pair( + 'monthName', + list([ + pair( + {params: RelationalOperationElement[*] | true}, + {params: RelationalOperationElement[*] | ^meta::relational::metamodel::datatype::Varchar(size = 9)} + ) + ]) + ), + pair( 'monthNumber', list([ diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbExtension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbExtension.pure index dcac2773f10..deb07bafd16 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbExtension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbExtension.pure @@ -973,6 +973,7 @@ Enum meta::relational::functions::sqlQueryToString::DynaFunctionRegistry lessThanEqual, log, log10, + lpad, ltrim, matches, max, @@ -982,6 +983,7 @@ Enum meta::relational::functions::sqlQueryToString::DynaFunctionRegistry minute, mod, month, + monthName, monthNumber, mostRecentDayOfWeek, not, @@ -1010,6 +1012,7 @@ Enum meta::relational::functions::sqlQueryToString::DynaFunctionRegistry right, round, rowNumber, + rpad, rtrim, second, sha1, diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/db2/db2Extension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/db2/db2Extension.pure index 34468b81f17..c059e176ac7 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/db2/db2Extension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/db2/db2Extension.pure @@ -87,6 +87,7 @@ function <> meta::relational::functions::sqlQueryToString::db2:: dynaFnToSql('convertDateTime', $allStates, ^ToSql(format='%s' , transform={p:String[*] | $p->convertToDateTimeDB2()})), dynaFnToSql('convertVarchar128', $allStates, ^ToSql(format='cast(%s as VARCHAR(128))')), dynaFnToSql('datePart', $allStates, ^ToSql(format='date(%s)')), + dynaFnToSql('dayOfWeek', $allStates, ^ToSql(format='dayname(%s)')), dynaFnToSql('dayOfWeekNumber', $allStates, ^ToSql(format='dayofweek_iso(%s)')), dynaFnToSql('dayOfYear', $allStates, ^ToSql(format='dayofyear(%s)')), dynaFnToSql('firstDayOfMonth', $allStates, ^ToSql(format='date(1) + (year(%s)-1) YEARS + (month(%s)-1) MONTHS', transform={p:String[1] | $p->repeat(2)})), @@ -102,6 +103,7 @@ function <> meta::relational::functions::sqlQueryToString::db2:: dynaFnToSql('md5', $allStates, ^ToSql(format='hash_md5(%s)')), dynaFnToSql('mod', $allStates, ^ToSql(format='mod(%s,%s)')), dynaFnToSql('month', $allStates, ^ToSql(format='month(%s)')), + dynaFnToSql('monthName', $allStates, ^ToSql(format='monthname(%s)')), dynaFnToSql('monthNumber', $allStates, ^ToSql(format='month(%s)')), dynaFnToSql('mostRecentDayOfWeek', $allStates, ^ToSql(format='%s + case when %s - dayofweek(%s) > 0 then %s - dayofweek(%s) - 7 else %s - dayofweek(%s) end DAY', transform={p:String[1..2] | $p->formatMostRecentDb2('current date')}, parametersWithinWhenClause = [false, false])), dynaFnToSql('now', $allStates, ^ToSql(format='current timestamp')), diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/h2/h2Extension1_4_200.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/h2/h2Extension1_4_200.pure index 14e0ce2d648..03f6056e828 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/h2/h2Extension1_4_200.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/h2/h2Extension1_4_200.pure @@ -80,6 +80,7 @@ function <> meta::relational::functions::sqlQueryToString::h2::v dynaFnToSql('dateDiff', $allStates, ^ToSql(format='datediff(%s,%s,%s)', transform={p:String[*]|[$p->at(2)->replace('\'', '')->processDateDiffDurationUnitForH2(),$p->at(0),$p->at(1)]})), dynaFnToSql('datePart', $allStates, ^ToSql(format='cast(truncate(%s) as date)')), dynaFnToSql('dayOfMonth', $allStates, ^ToSql(format='DAY_OF_MONTH(%s)')), + dynaFnToSql('dayOfWeek', $allStates, ^ToSql(format='dayname(%s)')), dynaFnToSql('dayOfWeekNumber', $allStates, ^ToSql(format='%s',transform={p:String[1..2]| if($p->size()==1,| 'DAY_OF_WEEK('+$p->at(0)+')',|$p->dayOfWeekNumberH2());})), dynaFnToSql('dayOfYear', $allStates, ^ToSql(format='DAY_OF_YEAR(%s)')), dynaFnToSql('decodeBase64', $allStates, ^ToSql(format='legend_h2_extension_base64_decode(%s)')), @@ -105,6 +106,7 @@ function <> meta::relational::functions::sqlQueryToString::h2::v dynaFnToSql('mod', $allStates, ^ToSql(format='mod(%s,%s)')), dynaFnToSql('month', $allStates, ^ToSql(format='month(%s)')), dynaFnToSql('monthNumber', $allStates, ^ToSql(format='month(%s)')), + dynaFnToSql('monthName', $allStates, ^ToSql(format='monthname(%s)')), dynaFnToSql('mostRecentDayOfWeek', $allStates, ^ToSql(format='dateadd(DAY, case when %s - DAY_OF_WEEK(%s) > 0 then %s - DAY_OF_WEEK(%s) - 7 else %s - DAY_OF_WEEK(%s) end, %s)', transform={p:String[1..2] | $p->formatMostRecentH2('current_date()')}, parametersWithinWhenClause = [false, false])), dynaFnToSql('now', $allStates, ^ToSql(format='current_timestamp()')), dynaFnToSql('parseDate', $allStates, ^ToSql(format='parsedatetime(%s,%s)')), @@ -133,8 +135,7 @@ function <> meta::relational::functions::sqlQueryToString::h2::v dynaFnToSql('toString', $allStates, ^ToSql(format='cast(%s as varchar)')), dynaFnToSql('toTimestamp', $allStates, ^ToSql(format='%s', transform={p:String[2] | $p->transformToTimestampH2()})), dynaFnToSql('weekOfYear', $allStates, ^ToSql(format='week(%s)')), - dynaFnToSql('year', $allStates, ^ToSql(format='year(%s)')), - dynaFnToSql('dayOfWeek', $allStates, ^ToSql(format='dayname(%s)')) + dynaFnToSql('year', $allStates, ^ToSql(format='year(%s)')) ]; } diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/h2/h2Extension2_1_214.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/h2/h2Extension2_1_214.pure index 57a0b21bdd0..0e9124cb439 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/h2/h2Extension2_1_214.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/dbSpecific/h2/h2Extension2_1_214.pure @@ -189,6 +189,7 @@ function <> meta::relational::functions::sqlQueryToString::h2::v dynaFnToSql('dateDiff', $allStates, ^ToSql(format='datediff(%s,%s,%s)', transform={p:String[*]|[$p->at(2)->replace('\'', '')->processDateDiffDurationUnitForH2(),$p->at(0),$p->at(1)]})), dynaFnToSql('datePart', $allStates, ^ToSql(format='cast(truncate(%s) as date)')), dynaFnToSql('dayOfMonth', $allStates, ^ToSql(format='DAY_OF_MONTH(%s)')), + dynaFnToSql('dayOfWeek', $allStates, ^ToSql(format='dayname(%s)')), dynaFnToSql('dayOfWeekNumber', $allStates, ^ToSql(format='%s',transform={p:String[1..2]| if($p->size()==1,| 'DAY_OF_WEEK('+$p->at(0)+')',|$p->dayOfWeekNumberH2());})), dynaFnToSql('dayOfYear', $allStates, ^ToSql(format='DAY_OF_YEAR(%s)')), dynaFnToSql('decodeBase64', $allStates, ^ToSql(format='legend_h2_extension_base64_decode(%s)')), @@ -218,6 +219,7 @@ function <> meta::relational::functions::sqlQueryToString::h2::v dynaFnToSql('mod', $allStates, ^ToSql(format='mod(%s,%s)')), dynaFnToSql('month', $allStates, ^ToSql(format='month(%s)')), dynaFnToSql('monthNumber', $allStates, ^ToSql(format='month(%s)')), + dynaFnToSql('monthName', $allStates, ^ToSql(format='monthname(%s)')), dynaFnToSql('mostRecentDayOfWeek', $allStates, ^ToSql(format='dateadd(DAY, case when %s - DAY_OF_WEEK(%s) > 0 then %s - DAY_OF_WEEK(%s) - 7 else %s - DAY_OF_WEEK(%s) end, %s)', transform={p:String[1..2] | $p->formatMostRecentH2('current_date()')}, parametersWithinWhenClause = [false, false])), dynaFnToSql('now', $allStates, ^ToSql(format='current_timestamp()')), dynaFnToSql('parseDate', $allStates, ^ToSql(format='cast(parsedatetime(%s,%s) as timestamp)')), @@ -246,8 +248,7 @@ function <> meta::relational::functions::sqlQueryToString::h2::v dynaFnToSql('toFloat', $allStates, ^ToSql(format='cast(%s as double precision)')), dynaFnToSql('toTimestamp', $allStates, ^ToSql(format='%s', transform={p:String[2] | $p->transformToTimestampH2()})), dynaFnToSql('weekOfYear', $allStates, ^ToSql(format='week(%s)')), - dynaFnToSql('year', $allStates, ^ToSql(format='year(%s)')), - dynaFnToSql('dayOfWeek', $allStates, ^ToSql(format='dayname(%s)')) + dynaFnToSql('year', $allStates, ^ToSql(format='year(%s)')) ]; } diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/extensionDefaults.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/extensionDefaults.pure index 737a80b3f26..7a1fabd8994 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/extensionDefaults.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/extensionDefaults.pure @@ -200,6 +200,7 @@ function meta::relational::functions::sqlQueryToString::default::getDynaFunction dynaFnToSql('lessThanEqual', $allStates, ^ToSql(format='%s <= %s')), dynaFnToSql('log', $allStates, ^ToSql(format='ln(%s)')), dynaFnToSql('log10', $allStates, ^ToSql(format='log10(%s)')), + dynaFnToSql('lpad', $allStates, ^ToSql(format='lpad(%s)', transform={p:String[*] | $p->joinStrings(', ')})), dynaFnToSql('ltrim', $allStates, ^ToSql(format='ltrim(%s)')), dynaFnToSql('max', $allStates, ^ToSql(format='max(%s)')), dynaFnToSql('md5', $allStates, ^ToSql(format='md5(%s)')), @@ -215,6 +216,7 @@ function meta::relational::functions::sqlQueryToString::default::getDynaFunction dynaFnToSql('repeatString', $allStates, ^ToSql(format='repeat(%s, %s)')), dynaFnToSql('replace', $allStates, ^ToSql(format='replace(%s, %s, %s)')), dynaFnToSql('reverseString', $allStates, ^ToSql(format='reverse(%s)')), + dynaFnToSql('rpad', $allStates, ^ToSql(format='rpad(%s)', transform={p:String[*] | $p->joinStrings(', ')})), dynaFnToSql('rtrim', $allStates, ^ToSql(format='rtrim(%s)')), dynaFnToSql('rowNumber', $allStates, ^ToSql(format='row_number()')), dynaFnToSql('sha1', $allStates, ^ToSql(format='sha1(%s)')), diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuite/dynaFunctions/date.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuite/dynaFunctions/date.pure index 130c3fa9196..be12499b2c2 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuite/dynaFunctions/date.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuite/dynaFunctions/date.pure @@ -102,6 +102,20 @@ function <> meta::relational::tests::dbSpecificTests::sqlQueryTe runDynaFunctionDatabaseTest($dynaFunc, $expected, $config); } +function <> meta::relational::tests::dbSpecificTests::sqlQueryTests::dynaFunctions::monthName::testMonthName(config:DbTestConfig[1]):Boolean[1] +{ + let dynaFunc = ^DynaFunction(name='monthName', parameters=[^Literal(value=%2014-12-04T15:22:23)]); + let expected = ^Literal(value='December'); + runDynaFunctionDatabaseTest($dynaFunc, $expected, $config); +} + +function <> meta::relational::tests::dbSpecificTests::sqlQueryTests::dynaFunctions::dayOfWeek::testDayOfWeek(config:DbTestConfig[1]):Boolean[1] +{ + let dynaFunc = ^DynaFunction(name='dayOfWeek', parameters=[^Literal(value=%2014-12-04T15:22:23)]); + let expected = ^Literal(value='Thursday'); + runDynaFunctionDatabaseTest($dynaFunc, $expected, $config); +} + function <> meta::relational::tests::dbSpecificTests::sqlQueryTests::dynaFunctions::quarter::testQuarterAsNumber(config:DbTestConfig[1]):Boolean[1] { let dynaFunc = ^DynaFunction(name='quarter', parameters=[^Literal(value=%2014-12-04T15:22:23)]); diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuite/dynaFunctions/string.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuite/dynaFunctions/string.pure index a4b108a63c2..de59320059d 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuite/dynaFunctions/string.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuite/dynaFunctions/string.pure @@ -166,6 +166,34 @@ function <> meta::relational::tests::dbSpecificTests::sqlQueryTe runDynaFunctionDatabaseTest($dynaFunc, $expected, $config); } +function <> meta::relational::tests::dbSpecificTests::sqlQueryTests::dynaFunctions::lpad::testLpad(config:DbTestConfig[1]):Boolean[1] +{ + let dynaFunc = ^DynaFunction(name='lpad', parameters=[^Literal(value='Smith'), ^Literal(value=7)]); + let expected = ^Literal(value=' Smith'); + runDynaFunctionDatabaseTest($dynaFunc, $expected, $config); +} + +function <> meta::relational::tests::dbSpecificTests::sqlQueryTests::dynaFunctions::lpad::testLpadWithChar(config:DbTestConfig[1]):Boolean[1] +{ + let dynaFunc = ^DynaFunction(name='lpad', parameters=[^Literal(value='Smith'), ^Literal(value=7), ^Literal(value='0')]); + let expected = ^Literal(value='00Smith'); + runDynaFunctionDatabaseTest($dynaFunc, $expected, $config); +} + +function <> meta::relational::tests::dbSpecificTests::sqlQueryTests::dynaFunctions::rpad::testRpad(config:DbTestConfig[1]):Boolean[1] +{ + let dynaFunc = ^DynaFunction(name='rpad', parameters=[^Literal(value='Smith'), ^Literal(value=7)]); + let expected = ^Literal(value='Smith '); + runDynaFunctionDatabaseTest($dynaFunc, $expected, $config); +} + +function <> meta::relational::tests::dbSpecificTests::sqlQueryTests::dynaFunctions::rpad::testRpadWithChar(config:DbTestConfig[1]):Boolean[1] +{ + let dynaFunc = ^DynaFunction(name='rpad', parameters=[^Literal(value='Smith'), ^Literal(value=7), ^Literal(value='0')]); + let expected = ^Literal(value='Smith00'); + runDynaFunctionDatabaseTest($dynaFunc, $expected, $config); +} + function <> meta::relational::tests::dbSpecificTests::sqlQueryTests::dynaFunctions::toUpper::test1(config:DbTestConfig[1]):Boolean[1] { let dynaFunc = ^DynaFunction(name='toUpper', parameters=[^Literal(value='Smith')]); diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuiteCompletenessTests.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuiteCompletenessTests.pure index 4af083c0423..96ab9a7eb0d 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuiteCompletenessTests.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/sqlQueryToString/testSuiteCompletenessTests.pure @@ -7,7 +7,7 @@ function <> meta::relational::tests::testSuite::ensureEveryDynaFnIsTe meta::relational::tests::dbSpecificTests::sqlQueryTests::selectSubClauses::aggregationDynaFns ]; let testedDynaFnNames = $packagesContainingDynaFnTests.children->filter(c| $c->instanceOf(Package)).name; - let testingIgnoredDynaFnNames = ['add', 'averageRank', 'cbrt', 'case', 'convertDate', 'convertDateTime', 'convertVarchar128', 'dayOfWeek', 'decodeBase64', 'denseRank', 'distinct', 'divide', 'encodeBase64', 'exists', 'group', 'if', 'isAlphaNumeric', 'isDistinct', 'isNumeric', 'minus', 'not', 'objectReferenceIn', 'parseDate', 'parseDecimal', 'parseFloat', 'parseInteger', 'parseJson', 'percentile', 'plus', 'rank', 'rowNumber', 'sub', 'times', 'toOne', 'toString', 'extractFromSemiStructured', 'explodeSemiStructured']; + let testingIgnoredDynaFnNames = ['add', 'averageRank', 'cbrt', 'case', 'convertDate', 'convertDateTime', 'convertVarchar128', 'decodeBase64', 'denseRank', 'distinct', 'divide', 'encodeBase64', 'exists', 'group', 'if', 'isAlphaNumeric', 'isDistinct', 'isNumeric', 'minus', 'not', 'objectReferenceIn', 'parseDate', 'parseDecimal', 'parseFloat', 'parseInteger', 'parseJson', 'percentile', 'plus', 'rank', 'rowNumber', 'sub', 'times', 'toOne', 'toString', 'extractFromSemiStructured', 'explodeSemiStructured']; let incorrectlyMarkedDynaFnNames = $testingIgnoredDynaFnNames->filter(n| $n->in($testedDynaFnNames)); assert($incorrectlyMarkedDynaFnNames->isEmpty(), |'dyna fns ' + $incorrectlyMarkedDynaFnNames->makeString('[', ', ', ']') + ' are incorrectly marked as ignored even though they are tested in sqlQueryToString/testSuite'); let untestedDynaFnNames = $dynaFnNames->filter(d| !$d->in($testedDynaFnNames) && !$d->in($testingIgnoredDynaFnNames)); diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/transform/fromPure/tests/testToSQLString.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/transform/fromPure/tests/testToSQLString.pure index 206c5d6db81..ce101f8b7fb 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/transform/fromPure/tests/testToSQLString.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/transform/fromPure/tests/testToSQLString.pure @@ -402,6 +402,35 @@ function <> meta::relational::tests::functions::sqlstring::testTrim() )->distinct() == [true]; } +function <> meta::relational::tests::functions::sqlstring::testPad():Boolean[1] +{ + let common = 'select lpad("root".FIRSTNAME, 1) as "lpad", lpad("root".FIRSTNAME, 1, \'0\') as "lpad2", rpad("root".FIRSTNAME, 1) as "rpad", rpad("root".FIRSTNAME, 1, \'0\') as "rpad2" from personTable as "root"'; + + let expected = [ + pair(DatabaseType.DB2, $common), + pair(DatabaseType.H2, $common), + pair(DatabaseType.Composite, $common) + ]; + + $expected->map(p| + let driver = $p.first; + let expectedSql = $p.second; + + let result = toSQLString( + |Person.all()->project([ + a | $a.firstName->lpad(1), + a | $a.firstName->lpad(1, '0'), + a | $a.firstName->rpad(1), + a | $a.firstName->rpad(1, '0') + ], + ['lpad', 'lpad2', 'rpad', 'rpad2']), + simpleRelationalMapping, + $driver, meta::relational::extension::relationalExtensions()); + + assertEquals($expectedSql, $result, '\nSQL not as expected for %s\n\nexpected: %s\nactual: %s', [$driver, $expectedSql, $result]); + )->distinct() == [true]; +} + function <> meta::relational::tests::functions::sqlstring::testCbrt():Boolean[1] { let common = 'select cbrt("root".quantity) as "cbrt" from tradeTable as "root"'; @@ -572,6 +601,26 @@ function <> meta::relational::tests::functions::sqlstring::testToSqlG )->distinct() == [true]; } +function <> meta::relational::tests::functions::sqlstring::testToSqlGenerationMonth():Boolean[1] +{ + let expected = [ + pair(DatabaseType.H2, 'select monthname("root".tradeDate) as "month" from tradeTable as "root"') + ]; + + $expected->map(p| + let driver = $p.first; + let expectedSql = $p.second; + + let result = toSQLString( + |Trade.all() + ->project(col(t|$t.date->month(), 'month')), + simpleRelationalMapping, + $driver, meta::relational::extension::relationalExtensions()); + + assertEquals($expectedSql, $result, '\nSQL not as expected for %s\n\nexpected: %s\nactual: %s', [$driver, $expectedSql, $result]); + )->distinct() == [true]; +} + function <> meta::relational::tests::functions::sqlstring::testToSQLStringWithRepeatString():Boolean[1] { let sql = toSQLString(|Person.all()->project(p| repeatString('a', 2), 'repeat'), simpleRelationalMapping, DatabaseType.H2, meta::relational::extension::relationalExtensions()); diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLContext.java b/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLContext.java deleted file mode 100644 index 5f87c8476d0..00000000000 --- a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLContext.java +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2023 Goldman Sachs -// -// 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. -// - -package org.finos.legend.engine.query.sql.api.sources; - -import org.finos.legend.engine.protocol.sql.metamodel.Node; - -/** - * @deprecated - * Use {@link org.finos.legend.engine.query.sql.providers.core.SQLContext} - */ -@Deprecated -public class SQLContext extends org.finos.legend.engine.query.sql.providers.core.SQLContext -{ - public SQLContext(Node query) - { - super(query); - } -} diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSource.java b/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSource.java deleted file mode 100644 index 005acd21d37..00000000000 --- a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSource.java +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2023 Goldman Sachs -// -// 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. -// - -package org.finos.legend.engine.query.sql.api.sources; - -import org.eclipse.collections.impl.utility.ListIterate; -import org.finos.legend.engine.protocol.pure.v1.model.executionOption.ExecutionOption; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.runtime.Runtime; -import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda; -import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.executionContext.ExecutionContext; - -import java.util.List; - -/** - * @deprecated - * Use {@link org.finos.legend.engine.query.sql.providers.core.SQLSource} - */ -@Deprecated -public class SQLSource extends org.finos.legend.engine.query.sql.providers.core.SQLSource -{ - public SQLSource(String type, Lambda func, String mapping, Runtime runtime, List executionOptions, List key) - { - this(type, func, mapping, runtime, executionOptions, null, key); - } - - public SQLSource(String type, Lambda func, String mapping, Runtime runtime, List executionOptions, ExecutionContext executionContext, List key) - { - super(type, func, mapping, runtime, executionOptions, executionContext, ListIterate.collect(key, k -> new org.finos.legend.engine.query.sql.providers.core.SQLSourceArgument(k.getName(), k.getIndex(), k.getValue()))); - } -} \ No newline at end of file diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceArgument.java b/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceArgument.java deleted file mode 100644 index d0caf9a8470..00000000000 --- a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceArgument.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2023 Goldman Sachs -// -// 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. -// - -package org.finos.legend.engine.query.sql.api.sources; - -/** - * @deprecated - * Use {@link org.finos.legend.engine.query.sql.providers.core.SQLSourceArgument} - */ -@Deprecated -public class SQLSourceArgument extends org.finos.legend.engine.query.sql.providers.core.SQLSourceArgument -{ - public SQLSourceArgument(String name, Integer index, Object value) - { - super(name, index, value); - } -} \ No newline at end of file diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceProvider.java b/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceProvider.java deleted file mode 100644 index 398618954b2..00000000000 --- a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceProvider.java +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2023 Goldman Sachs -// -// 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. -// - -package org.finos.legend.engine.query.sql.api.sources; - -/** - * @deprecated - * Use {@link org.finos.legend.engine.query.sql.providers.core.SQLSourceProvider} - */ -@Deprecated -public interface SQLSourceProvider extends org.finos.legend.engine.query.sql.providers.core.SQLSourceProvider -{ -} \ No newline at end of file diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceResolvedContext.java b/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceResolvedContext.java deleted file mode 100644 index 97b82595f39..00000000000 --- a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/SQLSourceResolvedContext.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2023 Goldman Sachs -// -// 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. -// - -package org.finos.legend.engine.query.sql.api.sources; - -import org.eclipse.collections.impl.list.mutable.FastList; -import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContext; - -import java.util.List; - -/** - * @deprecated - * Use {@link org.finos.legend.engine.query.sql.providers.core.SQLSourceResolvedContext} - */ -@Deprecated -public class SQLSourceResolvedContext -{ - private final List pureModelContexts; - private final List sources; - - public SQLSourceResolvedContext(PureModelContext pureModelContext, List sources) - { - this(FastList.newListWith(pureModelContext), sources); - } - - public SQLSourceResolvedContext(List pureModelContexts, List sources) - { - this.pureModelContexts = pureModelContexts != null ? pureModelContexts : FastList.newList(); - this.sources = sources; - } - - @Deprecated - public PureModelContext getPureModelContext() - { - return pureModelContexts.get(0); - } - - public List getPureModelContexts() - { - return pureModelContexts; - } - - public List getSources() - { - return sources; - } -} diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/TableSource.java b/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/TableSource.java deleted file mode 100644 index ecad910e973..00000000000 --- a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/TableSource.java +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2023 Goldman Sachs -// -// 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. -// - -package org.finos.legend.engine.query.sql.api.sources; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.eclipse.collections.impl.utility.ListIterate; - -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -/** - * @deprecated - * Use {@link org.finos.legend.engine.query.sql.providers.core.TableSource} - */ -@Deprecated -public class TableSource -{ - private final String type; - private final List arguments; - - public TableSource(String type, List arguments) - { - this.type = type; - this.arguments = arguments == null ? Collections.emptyList() : arguments; - } - - public String getType() - { - return type; - } - - //get named argument, or default to index - public TableSourceArgument getArgument(String name, int index) - { - Optional found = getNamedArgument(name); - return found.orElseGet(() -> - { - if (this.arguments.size() > index && index >= 0) - { - return this.arguments.get(index); - } - throw new IllegalArgumentException("Argument of name " + name + " or " + index + " not found"); - }); - } - - public Optional getNamedArgument(String name) - { - return ListIterate.select(this.arguments, a -> name.equals(a.getName())).getFirstOptional(); - } - - public List getArguments() - { - return this.arguments; - } - - @Override - public boolean equals(Object o) - { - return EqualsBuilder.reflectionEquals(this, o); - } - - @Override - public int hashCode() - { - return HashCodeBuilder.reflectionHashCode(this); - } - - @Override - public String toString() - { - return ToStringBuilder.reflectionToString(this); - } -} \ No newline at end of file diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/TableSourceArgument.java b/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/TableSourceArgument.java deleted file mode 100644 index 2fb04368443..00000000000 --- a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/api/sources/TableSourceArgument.java +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2023 Goldman Sachs -// -// 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. -// - -package org.finos.legend.engine.query.sql.api.sources; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.commons.lang3.builder.ToStringBuilder; - -/** - * @deprecated - * Use {@link org.finos.legend.engine.query.sql.providers.core.TableSourceArgument} - */ -@Deprecated -public class TableSourceArgument -{ - private final String name; - private final Object value; - private final Integer index; - - public TableSourceArgument(String name, Integer index, Object value) - { - this.name = name; - this.value = value; - this.index = index; - } - - public String getName() - { - return name; - } - - public Integer getIndex() - { - return index; - } - - public Object getValue() - { - return value; - } - - @Override - public boolean equals(Object o) - { - return EqualsBuilder.reflectionEquals(this, o); - } - - @Override - public int hashCode() - { - return HashCodeBuilder.reflectionHashCode(this); - } - - @Override - public String toString() - { - return ToStringBuilder.reflectionToString(this); - } -} \ No newline at end of file diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/providers/core/SQLSourceProvider.java b/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/providers/core/SQLSourceProvider.java index 9bc416ef803..4e835b357b7 100644 --- a/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/providers/core/SQLSourceProvider.java +++ b/legend-engine-xts-sql/legend-engine-xt-sql-providers/legend-engine-xt-sql-providers-core/src/main/java/org/finos/legend/engine/query/sql/providers/core/SQLSourceProvider.java @@ -24,16 +24,5 @@ public interface SQLSourceProvider { String getType(); - //TODO remove default impl - default SQLSourceResolvedContext resolve(List sources, SQLContext context, MutableList profiles) - { - return null; - } - - //TODO remove default impl - @Deprecated - default org.finos.legend.engine.query.sql.api.sources.SQLSourceResolvedContext resolve(List sources, org.finos.legend.engine.query.sql.api.sources.SQLContext context, MutableList profiles) - { - return null; - } + SQLSourceResolvedContext resolve(List sources, SQLContext context, MutableList profiles); } \ No newline at end of file diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-pure/pom.xml b/legend-engine-xts-sql/legend-engine-xt-sql-pure/pom.xml index 495f27ca300..e284faab1fb 100644 --- a/legend-engine-xts-sql/legend-engine-xt-sql-pure/pom.xml +++ b/legend-engine-xts-sql/legend-engine-xt-sql-pure/pom.xml @@ -65,6 +65,7 @@ legend-pure-m2-dsl-diagram-grammar ${legend.pure.version} + org.finos.legend.pure legend-pure-m2-dsl-graph-grammar @@ -75,6 +76,11 @@ legend-engine-pure-code-compiled-core ${project.version} + + org.finos.legend.engine + legend-engine-pure-platform-store-relational-java + ${project.version} + org.finos.legend.engine legend-engine-language-pure-dsl-service-pure @@ -148,6 +154,11 @@ legend-engine-pure-code-compiled-core ${project.version} + + org.finos.legend.engine + legend-engine-pure-platform-store-relational-java + ${project.version} + org.finos.legend.engine legend-engine-language-pure-dsl-service-pure @@ -201,10 +212,16 @@ legend-pure-runtime-java-engine-compiled + org.finos.legend.engine legend-engine-pure-code-compiled-core + + org.finos.legend.engine + legend-engine-pure-platform-store-relational-java + ${project.version} + org.finos.legend.engine legend-engine-language-pure-dsl-service-pure diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-pure/src/main/resources/core_external_query_sql/binding/fromPure/fromPure.pure b/legend-engine-xts-sql/legend-engine-xt-sql-pure/src/main/resources/core_external_query_sql/binding/fromPure/fromPure.pure index 5d197636ec7..63d9f56e820 100644 --- a/legend-engine-xts-sql/legend-engine-xt-sql-pure/src/main/resources/core_external_query_sql/binding/fromPure/fromPure.pure +++ b/legend-engine-xts-sql/legend-engine-xt-sql-pure/src/main/resources/core_external_query_sql/binding/fromPure/fromPure.pure @@ -566,9 +566,6 @@ function <> meta::external::query::sql::transformation::queryToP function <> meta::external::query::sql::transformation::queryToPure::processExtend(select: Select[1], context: SqlTransformContext[1]):FunctionExpression[1] { debug('processExtend', $context.debug); - let typeArguments = ^GenericType(rawType = TDSRow); - let genericType = ^GenericType(rawType = BasicColumnSpecification, typeArguments = $typeArguments); - let selectItems = $select.selectItems->processSelectItems($context, false); let columns = $context.columns.name; @@ -576,13 +573,20 @@ function <> meta::external::query::sql::transformation::queryToP let args = $selectItems->map(item | let rename = $columns->contains($item.second); let name = if ($rename, | $item.second + '_1', | $item.second); - - sfe(col_Function_1__String_1__BasicColumnSpecification_1_, $genericType, $typeArguments, [$item.first->iv(), $name->iv()]); + createCol($item.first, $name); ); appendTdsFunc($context.expression->toOne(), extend_TabularDataSet_1__BasicColumnSpecification_MANY__TabularDataSet_1_, list(iv($args))); } +function meta::external::query::sql::transformation::queryToPure::createCol(lambda:LambdaFunction[1], name:String[1]):SimpleFunctionExpression[1] +{ + let typeArguments = ^GenericType(rawType = TDSRow); + let genericType = ^GenericType(rawType = BasicColumnSpecification, typeArguments = $typeArguments); + + sfe(col_Function_1__String_1__BasicColumnSpecification_1_, $genericType, $typeArguments, [iv($lambda), iv($name)]); +} + function <> meta::external::query::sql::transformation::queryToPure::processSelect(select: Select[1], restrict:Boolean[1], context: SqlTransformContext[1]):FunctionExpression[1] { debug('processSelect', $context.debug); @@ -649,7 +653,7 @@ function <> meta::external::query::sql::transformation::queryToP let genericType = ^GenericType(rawType = BasicColumnSpecification, typeArguments = $typeArguments); let args = $select.selectItems->processSelectItems($context, false)->map(item | - sfe(col_Function_1__String_1__BasicColumnSpecification_1_, $genericType, $typeArguments, [$item.first->iv(), $item.second->iv()]); + createCol($item.first, $item.second); ); let iv = iv($args); @@ -1984,12 +1988,14 @@ function meta::external::query::sql::transformation::queryToPure::functionProces }), processor('length', length_String_1__Integer_1_), processor('lower', toLower_String_1__String_1_), + processor('lpad', String, {args, fc, ctx | processPad($args, true)}), processor('ltrim', String, {args, fc, ctx | processTrim(ltrim_String_1__String_1_, $args)}), processor('md5', String, {args, fc, ctx | processHash($args, meta::pure::functions::hash::HashType.MD5)}), processor('regexp_like', matches_String_1__String_1__Boolean_1_), processor('repeat', repeatString_String_$0_1$__Integer_1__String_$0_1$_), processor('replace', replace_String_1__String_1__String_1__String_1_), processor('reverse', reverseString_String_1__String_1_), + processor('rpad', String, {args, fc, ctx | processPad($args, false)}), processor('rtrim', String, {args, fc, ctx | processTrim(rtrim_String_1__String_1_, $args)}), processor('sha256', String, {args, fc, ctx | processHash($args, meta::pure::functions::hash::HashType.SHA256)}), processor('split_part', String, {args, fc, ctx | @@ -2026,7 +2032,7 @@ function meta::external::query::sql::transformation::queryToPure::functionProces possiblyProcessParseDate($args->at(0)) }), processor('date_part', Integer, {args, fc, ctx | - assertEquals(2, $args->size(), 'incorrect number of args'); + assertEquals(2, $args->size(), 'incorrect number of args for date_part'); let part = $args->at(0); let value = $part->reactivate()->toOne()->cast(@String); @@ -2047,7 +2053,7 @@ function meta::external::query::sql::transformation::queryToPure::functionProces nullOrSfe($func, $args->at(1)); }), processor('date_trunc', Date, {args, fc, ctx | - assertEquals(2, $args->size(), 'incorrect number of args'); + assertEquals(2, $args->size(), 'incorrect number of args for date_trunc'); let part = $args->at(0); let value = $part->reactivate()->toOne()->cast(@String); @@ -2077,6 +2083,19 @@ function meta::external::query::sql::transformation::queryToPure::functionProces sfe(meta::pure::tds::extensions::firstNotNull_T_MANY__T_$0_1$_, ^GenericType(rawType = $type), ^GenericType(rawType = $type), $filteredArgs->iv()); }), + //FORMAT + processor('to_char', String, {args, fc, ctx | + assertEquals(2, $args->size(), 'incorrect number of args for t-_char'); + + let arg = $args->at(0); + let type = $arg.genericType.rawType; + let format = $args->at(1)->reactivate()->toOne()->cast(@String); + + assert($type->isNotEmpty() && $type->toOne()->normalizeType() == Date, 'to_char currently only supported for know date inputs'); + + toChar($format, [], $arg->evaluateAndDeactivate()); + }), + //WINDOW processor('row_number', false, true, [], {args, fc, ctx | let values = $ctx.defaultVar->toOne()->concatenate($args); @@ -2093,6 +2112,187 @@ function meta::external::query::sql::transformation::queryToPure::functionProces ] } +function <> meta::external::query::sql::transformation::queryToPure::toCharFormats():Pair ValueSpecification[1]}>>[*] +{ + [ + pair('HH', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('HH')}), + pair('HH12', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('HH12')}), + pair('HH24', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(hour_Date_1__Integer_1_, $a, false, false, 2, '0', [], [], $p, $s)}), + pair('MI', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(minute_Date_1__Integer_1_, $a, false, false, 2, '0', [], [], $p, $s)}), + pair('SS', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(second_Date_1__Integer_1_, $a, false, false, 2, '0', [], [], $p, $s)}), + pair('MS', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('MS')}), + pair('US', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('US')}), + pair('FF1', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('FF1')}), + pair('FF2', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('FF2')}), + pair('FF3', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('FF3')}), + pair('FF4', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('FF4')}), + pair('FF5', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('FF5')}), + pair('FF6', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('FF6')}), + pair('SSSS', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('SSSS')}), + pair('SSSSS', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('SSSSS')}), + pair('AM', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('AM')}), + pair('am', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('am')}), + pair('PM', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('PM')}), + pair('pm', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('pm')}), + pair('A.M', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('A.M')}), + pair('a.m', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('a.m')}), + pair('P.M', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('P.M')}), + pair('p.m', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('p.m')}), + pair('Y,YYY', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('Y,YYYY')}), + pair('YYYY', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(year_Date_1__Integer_1_, $a, $p, $s)}), + pair('YYY', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | processSubstring([toChar(year_Date_1__Integer_1_, $a, $p, $s), iv(2), iv(3)])}), + pair('YY', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | processSubstring([toChar(year_Date_1__Integer_1_, $a, $p, $s), iv(3), iv(2)])}), + pair('Y', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | processSubstring([toChar(year_Date_1__Integer_1_, $a, $p, $s), iv(4), iv(1)])}), + pair('IYYY', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('IYYY')}), + pair('IYY', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('IYY')}), + pair('IY', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('IY')}), + pair('I', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('I')}), + pair('BC', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('BC')}), + pair('bc', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('bc')}), + pair('AD', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('AD')}), + pair('ad', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('ad')}), + pair('B.C.', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('B.C.')}), + pair('b.c.', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('b.c.')}), + pair('A.D.', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('A.D.')}), + pair('a.d', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('a.d.')}), + pair('MONTH', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(month_Date_1__Month_1_, $a, true, false, [], [], 9, ' ', $p, $s)}), + pair('Month', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(month_Date_1__Month_1_, $a, false, false, [], [], 9, ' ', $p, $s)}), + pair('month', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(month_Date_1__Month_1_, $a, false, true, [], [], 9, ' ', $p, $s)}), + pair('MON', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(month_Date_1__Month_1_, $a, true, false, [], [], 3, ' ', $p, $s)}), + pair('Mon', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(month_Date_1__Month_1_, $a, false, false, [], [], 3, ' ', $p, $s)}), + pair('mon', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(month_Date_1__Month_1_, $a, false, true, [], [], 3, ' ', $p, $s)}), + pair('MM', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(monthNumber_Date_1__Integer_1_, $a, false, false, 2, '0', [], [], $p, $s)}), + pair('DAY', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(dayOfWeek_Date_1__DayOfWeek_1_, $a, true, false, [], [], 9, ' ', $p, $s)}), + pair('Day', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(dayOfWeek_Date_1__DayOfWeek_1_, $a, false, false, [], [], 9, ' ', $p, $s)}), + pair('day', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(dayOfWeek_Date_1__DayOfWeek_1_, $a, false, true, [], [], 9, ' ', $p, $s)}), + pair('DY', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(dayOfWeek_Date_1__DayOfWeek_1_, $a, true, false, [], [], 3, ' ', $p, $s)}), + pair('Dy', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(dayOfWeek_Date_1__DayOfWeek_1_, $a, false, false, [], [], 3, ' ', $p, $s)}), + pair('dy', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(dayOfWeek_Date_1__DayOfWeek_1_, $a, false, true, [], [], 3, ' ', $p, $s)}), + pair('DDD', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(dayOfYear_Date_1__Integer_1_, $a, false, false, 3, '0', [], [], $p, $s)}), + pair('IDDD', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('IDDD')}), + pair('DD', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(dayOfMonth_Date_1__Integer_1_, $a, false, false, 2, '0', [], [], $p, $s)}), + pair('D', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(dayOfWeekNumber_Date_1__Integer_1_, $a, $p, $s)}), + pair('ID', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('ID')}), + pair('W', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('W')}), + pair('WW', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(weekOfYear_Date_1__Integer_1_, $a, false, false, 2, '0', [], [], $p, $s)}), + pair('IW', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('IW')}), + pair('CC', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('CC')}), + pair('J', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('J')}), + pair('Q', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toChar(quarterNumber_Date_1__Integer_1_, $a, $p, $s)}), + pair('RM', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('RM')}), + pair('rm', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('rm')}), + pair('TZ', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('TZ')}), + pair('tz', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('tz')}), + pair('TZH', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('TZH')}), + pair('TZM', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('TZM')}), + pair('OF', {p:String[0..1], s:String[0..1], a:ValueSpecification[1] | toCharUnsupported('OF')}) + ]->sortBy(p | $p.first->length())->reverse(); +} + +Class meta::external::query::sql::transformation::queryToPure::ToCharContext +{ + format: String[1]; + result: ValueSpecification[0..1]; + matched: Boolean[1]; + prefix: String[0..1]; + suffix: String[0..1]; +} + +function <> meta::external::query::sql::transformation::queryToPure::toCharPrefixes():PairBoolean[1]}>>[*] +{ + [ + pair('FM', | true), + pair('FX', | toCharUnsupported('FX'); false;), + pair('TM', | toCharUnsupported('TM'); false;) + ]->sortBy(p | $p.first->length())->reverse(); +} + +//token -> supported +function <> meta::external::query::sql::transformation::queryToPure::toCharSuffixes():PairBoolean[1]}>>[*] +{ + [ + pair('TH', {| toCharUnsupported('th'); false;}), + pair('th', {| toCharUnsupported('th'); false;}), + pair('SP', {| toCharUnsupported('SP'); false;}) + ]->sortBy(p | $p.first->length())->reverse(); +} + +function <> meta::external::query::sql::transformation::queryToPure::toChar(format:String[1], result:ValueSpecification[0..1], arg:ValueSpecification[1]):ValueSpecification[1] +{ + let formats = toCharFormats(); + let prefixes = toCharPrefixes(); + let suffixes = toCharSuffixes(); + + if ($format->length() == 0, + | if ($result->isEmpty(), | $arg, | $result->toOne()), + | + let prefix = $prefixes->fold({p, acc | + if ($format->startsWith($p.first) && $p.second->eval(), | pair($format->substring($p.first->length(), $format->length()), $p.first), | $acc); + }, pair($format, '')); + + let scan = $formats->fold({token, acc | + if (!$acc.matched && $acc.format->startsWith($token.first), + | + let newFormat = $acc.format->substring($token.first->length(), $acc.format->length()); + + + let suffix = $suffixes->fold({s, acc | + if ($newFormat->startsWith($s.first) && $s.second->eval(), | pair($newFormat->substring($s.first->length(), $newFormat->length()), $s.first), | $acc); + }, pair($newFormat, '')); + + let newResult = toCharCombine($result->evaluateAndDeactivate(), $token.second->eval($acc.prefix, if ($suffix.second != '', | $suffix.second, | []), $arg)); + + ^$acc(format = $suffix.first, result = $newResult->evaluateAndDeactivate() , matched = true);, + | $acc); + }, ^ToCharContext(format = $prefix.first, result = $result->evaluateAndDeactivate(), matched = false, prefix = if ($prefix.second != '', | $prefix.second, | []))); + + if ($scan.matched, + | toChar($scan.format, $scan.result->evaluateAndDeactivate(), $arg), + | toChar($scan.format->substring(1, $scan.format->length()), toCharCombine($scan.result->evaluateAndDeactivate(), iv($scan.format->chunk(1)->at(0))), $arg)); + ); +} + +function <> meta::external::query::sql::transformation::queryToPure::toCharCombine(v:ValueSpecification[0..1], v2:ValueSpecification[1]):ValueSpecification[1] +{ + if ($v->isEmpty(), | $v2, | sfe(plus_String_MANY__String_1_, iv([$v->toOne(), $v2])))->evaluateAndDeactivate() +} + + +function <> meta::external::query::sql::transformation::queryToPure::toCharUnsupported(func:String[1]):ValueSpecification[1] +{ + fail($func + ' is not supported to_char token'); + iv(1); +} + +function <> meta::external::query::sql::transformation::queryToPure::toChar(func:Function[1], arg:ValueSpecification[1], prefix:String[0..1], suffix:String[0..1]):ValueSpecification[1] +{ + toChar($func, $arg, false, false, $prefix, $suffix) +} + +function <> meta::external::query::sql::transformation::queryToPure::toChar(func:Function[1], arg:ValueSpecification[1], upper:Boolean[1], lower:Boolean[1], prefix:String[0..1], suffix:String[0..1]):ValueSpecification[1] +{ + toChar($func, $arg, $upper, $lower, [], [], [], [], $prefix, $suffix) +} + +function <> meta::external::query::sql::transformation::queryToPure::toChar(func:Function[1], arg:ValueSpecification[1], upper:Boolean[1], lower:Boolean[1], lpadLength:Integer[0..1], lpadChar:String[0..1], rpadLength:Integer[0..1], rpadChar:String[0..1], prefix:String[0..1], suffix:String[0..1]):ValueSpecification[1] +{ + let f = nullOrSfe($func, $arg->evaluateAndDeactivate())->evaluateAndDeactivate(); + + let type = $func->functionReturnType().rawType->toOne(); + let str = if ($type != String, | nullOrSfe(toString_Any_1__String_1_, $f), | $f); + + let cased = if ($upper, + | nullOrSfe(toUpper_String_1__String_1_, $str), + | if ($lower, + | nullOrSfe(toLower_String_1__String_1_, $str), + | $str)); + + if ($prefix == 'FM', + | $cased, + | let lpad = if ($lpadLength->isNotEmpty() && $lpadChar->isNotEmpty(), | processPad([$cased, iv($lpadLength), iv($lpadChar)], true), | $cased); + if ($rpadLength->isNotEmpty() && $rpadChar->isNotEmpty(), | processPad([$cased, iv($rpadLength), iv($rpadChar)], false), | $lpad);); +} + function meta::external::query::sql::transformation::queryToPure::processPercentile(name:String[1], args:ValueSpecification[*], continuous:Boolean[1], fc:FunctionCall[1], expContext:SqlTransformExpressionContext[1]):ValueSpecification[1] { assert($fc.group->isNotEmpty(), | $name + ' must specify group'); @@ -2114,6 +2314,20 @@ function meta::external::query::sql::transformation::queryToPure::processTrim(fu nullOrSfe($func, $args->at(0)); } +function meta::external::query::sql::transformation::queryToPure::processPad(args:ValueSpecification[*], left:Boolean[1]):ValueSpecification[1] +{ + assert($args->size() == 2 || $args->size() == 3, | 'incorrect number of args for pad function'); + + let func = [ + pair($left && $args->size() == 2, lpad_String_1__Integer_1__String_1_), + pair($left && $args->size() == 3, lpad_String_1__Integer_1__String_1__String_1_), + pair(!$left && $args->size() == 2, rpad_String_1__Integer_1__String_1_), + pair(!$left && $args->size() == 3, rpad_String_1__Integer_1__String_1__String_1_) + ]->getValue(true); + + nullOrSfe($func, $args); +} + function meta::external::query::sql::transformation::queryToPure::processHash(args:ValueSpecification[*], type:meta::pure::functions::hash::HashType[1]):ValueSpecification[1] { assert($args->size() == 1, 'incorrect number of args'); @@ -2633,6 +2847,13 @@ function <> meta::external::query::sql::transformation::queryToP } +function meta::external::query::sql::transformation::queryToPure::appendTdsFunc(lambda:LambdaFunction[1], execFunc: meta::pure::metamodel::function::Function[1], args: List[*]): LambdaFunction[1] +{ + ^$lambda( + expressionSequence = appendTdsFunc($lambda.expressionSequence->last()->toOne()->cast(@FunctionExpression), $execFunc, $args) + ) +} + function <> meta::external::query::sql::transformation::queryToPure::appendTdsFunc(func: FunctionExpression[1], execFunc: meta::pure::metamodel::function::Function[1], args: List[*]): FunctionExpression[1] { let pvs = $args->fold( @@ -2760,6 +2981,8 @@ function <> meta::external::query::sql::transformation::queryToP ^Multiplicity(lowerBound = $mv, upperBound = $mv); ]); + + ^InstanceValue(multiplicity = $multiplicity, genericType = $genericType, values = $value); } diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-pure/src/main/resources/core_external_query_sql/binding/fromPure/tests/testTranspile.pure b/legend-engine-xts-sql/legend-engine-xt-sql-pure/src/main/resources/core_external_query_sql/binding/fromPure/tests/testTranspile.pure index 51b191d6194..9f54538f7a2 100644 --- a/legend-engine-xts-sql/legend-engine-xt-sql-pure/src/main/resources/core_external_query_sql/binding/fromPure/tests/testTranspile.pure +++ b/legend-engine-xts-sql/legend-engine-xt-sql-pure/src/main/resources/core_external_query_sql/binding/fromPure/tests/testTranspile.pure @@ -1600,7 +1600,8 @@ function <> meta::external::query::sql::transformation::queryToPure:: 'char_length(String) AS "CHAR_LENGTH", length(String) AS "LENGTH", ltrim(String) AS "LTRIM", ltrim(String, \' \') AS "LTRIM2", md5(String) AS "MD5", upper(String) AS "UPPER", ' + 'lower(String) AS "LOWER", repeat(String, 2) AS "REPEAT", replace(String, \'A\', \'a\') AS "REPLACE", starts_with(String, \'a\') AS "STARTSWITH", strpos(String, \'abc\') AS "STRPOS",' + 'reverse(String) AS "REVERSE", rtrim(String) AS "RTRIM", rtrim(String, \' \') AS "RTRIM2", sha256(String) AS "SHA256", split_part(String, \',\', 1) AS "SPLITPART", ' + - 'split_part(String, \',\', Integer) AS "SPLITPART2", substring(String, 1) AS "SUBSTRING", substr(String, 1, 2) AS "SUBSTR", btrim(String) AS "TRIM", btrim(String, \' \') AS "TRIM2" FROM service."/service/service1"', + 'split_part(String, \',\', Integer) AS "SPLITPART2", substring(String, 1) AS "SUBSTRING", substr(String, 1, 2) AS "SUBSTR", btrim(String) AS "TRIM", btrim(String, \' \') AS "TRIM2",' + + 'lpad(String, 2) AS "LPAD", lpad(String, 2, \'a\') AS "LPAD2", rpad(String, 2) AS "RPAD", rpad(String, 2, \'a\') AS "RPAD2" FROM service."/service/service1"', {| FlatInput.all() @@ -1633,7 +1634,11 @@ function <> meta::external::query::sql::transformation::queryToPure:: col(row:TDSRow[1] | substring($row.getString('String'), 1), 'SUBSTRING'), col(row:TDSRow[1] | substring($row.getString('String'), 1, 2), 'SUBSTR'), col(row:TDSRow[1] | trim($row.getString('String')), 'TRIM'), - col(row:TDSRow[1] | trim($row.getString('String')), 'TRIM2') + col(row:TDSRow[1] | trim($row.getString('String')), 'TRIM2'), + col(row:TDSRow[1] | lpad($row.getString('String'), 2), 'LPAD'), + col(row:TDSRow[1] | lpad($row.getString('String'), 2, 'a'), 'LPAD2'), + col(row:TDSRow[1] | rpad($row.getString('String'), 2), 'RPAD'), + col(row:TDSRow[1] | rpad($row.getString('String'), 2, 'a'), 'RPAD2') ]) }) } @@ -1644,7 +1649,8 @@ function <> meta::external::query::sql::transformation::queryToPure:: 'SELECT ascii(NULL) AS "ASCII", chr(NULL) AS "CHR", regexp_like(NULL, \'test\') AS "MATCH", char_length(NULL) AS "CHAR_LENGTH", length(NULL) AS "LENGTH", ltrim(NULL) AS "LTRIM", ' + 'ltrim(NULL, \' \') AS "LTRIM2", md5(NULL) AS "MD5", upper(NULL) AS "UPPER", lower(NULL) AS "LOWER", replace(NULL, \'A\', \'a\') AS "REPLACE", starts_with(NULL, \'a\') AS "STARTSWITH", ' + 'strpos(NULL, \'abc\') AS "STRPOS", reverse(NULL) AS "REVERSE", rtrim(NULL) AS "RTRIM", rtrim(NULL, \' \') AS "RTRIM2", sha256(NULL) AS "SHA256", substring(NULL, 1) AS "SUBSTRING", ' + - 'substr(NULL, 1, 2) AS "SUBSTR", btrim(NULL) AS "TRIM", btrim(NULL, \' \') AS "TRIM2" FROM service."/service/service1"', + 'substr(NULL, 1, 2) AS "SUBSTR", btrim(NULL) AS "TRIM", btrim(NULL, \' \') AS "TRIM2", lpad(NULL, 2) AS "LPAD", lpad(String, NULL) AS "LPAD2", lpad(String, 2, NULL) AS "LPAD3",' + + 'rpad(NULL, 2) AS "RPAD", rpad(String, NULL) AS "RPAD2", rpad(String, 2, NULL) AS "RPAD3" FROM service."/service/service1"', {| FlatInput.all() @@ -1672,12 +1678,133 @@ function <> meta::external::query::sql::transformation::queryToPure:: col(row:TDSRow[1] | []->cast(@String), 'SUBSTRING'), col(row:TDSRow[1] | []->cast(@String), 'SUBSTR'), col(row:TDSRow[1] | []->cast(@String), 'TRIM'), - col(row:TDSRow[1] | []->cast(@String), 'TRIM2') + col(row:TDSRow[1] | []->cast(@String), 'TRIM2'), + col(row:TDSRow[1] | []->cast(@String), 'LPAD'), + col(row:TDSRow[1] | []->cast(@String), 'LPAD2'), + col(row:TDSRow[1] | []->cast(@String), 'LPAD3'), + col(row:TDSRow[1] | []->cast(@String), 'RPAD'), + col(row:TDSRow[1] | []->cast(@String), 'RPAD2'), + col(row:TDSRow[1] | []->cast(@String), 'RPAD3') ]) }) } + + +Class meta::external::query::sql::transformation::queryToPure::tests::ToCharTestConfig +{ + sql: String[1]; + col: LambdaFunction<{TDSRow[1]->Any[*]}>[0..1]; + name : String[1]; + value: String[1]; +} + +function meta::external::query::sql::transformation::queryToPure::tests::tc(sql:String[1], col: LambdaFunction<{TDSRow[1]->Any[*]}>[0..1], name:String[1], value:String[1]):ToCharTestConfig[1] +{ + ^ToCharTestConfig(sql = $sql, col = $col, name = $name, value = $value); +} + +function meta::external::query::sql::transformation::queryToPure::tests::toCharTest(items:ToCharTestConfig[*], compareLambda:Boolean[1]):Boolean[1] +{ + let sqlString = 'SELECT ' + $items->map(i | $i.sql + ' AS "' + $i.name + '"')->joinStrings(', ') + ' FROM service."/service/service1"'; + + let sqlTransformContext = $sqlString->processQuery(); + let csv = 'default\n'+ + 'flat\n'+ + 'id,boolean,integer,float,decimal,strictDate,dateTime,string,enum,type\n'+ + '1,1,10,1.5,2.5,2023-10-02,2023-04-01T09:08:07,test,V1,T1\n'; + + let runtime = ^meta::core::runtime::Runtime( + connectionStores = ^meta::core::runtime::ConnectionStore( + element = meta::external::query::sql::transformation::queryToPure::tests::dummyDatabase, + connection = ^meta::external::store::relational::runtime::TestDatabaseConnection( + type=meta::relational::runtime::DatabaseType.H2, + testDataSetupCsv = $csv + )) + ); + + let sqlStatements = meta::alloy::service::execution::setUpDataSQLs($csv, meta::external::query::sql::transformation::queryToPure::tests::dummyDatabase); + $sqlStatements->map(sql| + meta::relational::functions::database::executeInDb($sql, $runtime.connectionStores->at(0), false); + )->size(); // NO NOT REMOVE: size called to inhibit lazy evaluation ensuring the map is activated; + + + if ($compareLambda, + | + let cols = $items->map(c | createCol($c.col->toOne(), $c.name)); + + let expected = {| + FlatInput.all() + ->project( + [ x | $x.booleanIn, x | $x.integerIn, x | $x.floatIn, x | $x.decimalIn, x | $x.strictDateIn, x | $x.dateTimeIn, x | $x.stringIn ], + [ 'Boolean', 'Integer', 'Float', 'Decimal', 'StrictDate', 'DateTime', 'String' ]) + }->appendTdsFunc(project_TabularDataSet_1__ColumnSpecification_MANY__TabularDataSet_1_, list(iv($cols))); + + + assertLambdaEquals($expected, $sqlTransformContext.lambda());, + | []); + + + let tds = meta::pure::router::execute($sqlTransformContext.lambda()->toOne()->cast(@LambdaFunction<{->TabularDataSet[1]}>), dummyMapping, $runtime, relationalExtensions()).values; + let values = $tds.rows->at(0).values; + + $items->forAll(i | + assertEquals($i.value, $values->at($items->indexOf($i)), | 'expected ' + $values->at($items->indexOf($i))->toString() + ' to equal ' + $i.value + ' sql: ' + $i.sql); + ); + +} + +function <> meta::external::query::sql::transformation::queryToPure::tests::testToChar():Boolean[1] +{ + toCharTest([ + tc('to_char(DateTime, \'HH24\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->hour()->toString()->lpad(2, '0')}, 'HH24', '09'), + tc('to_char(DateTime, \'FMHH24\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->hour()->toString()}, 'FMHH24', '9'), + tc('to_char(DateTime, \'MI\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->minute()->toString()->lpad(2, '0')}, 'MI', '08'), + tc('to_char(DateTime, \'FMMI\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->minute()->toString()}, 'FMMI', '8'), + tc('to_char(DateTime, \'SS\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->second()->toString()->lpad(2, '0')}, 'SS', '07'), + tc('to_char(DateTime, \'FMSS\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->second()->toString()}, 'FMSS', '7'), + tc('to_char(DateTime, \'YYYY\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->year()->toString()}, 'YYYY', '2023'), + tc('to_char(DateTime, \'YYY\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->year()->toString()->substring(2, 3)}, 'YYY', '023'), + tc('to_char(DateTime, \'YY\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->year()->toString()->substring(3, 2)}, 'YY', '23'), + tc('to_char(DateTime, \'Y\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->year()->toString()->substring(4, 1)}, 'Y', '3'), + tc('to_char(DateTime, \'MONTH\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->month()->toString()->toUpper()->rpad(9, ' ')}, 'MONTHUPPER', 'APRIL '), + tc('to_char(DateTime, \'FMMONTH\')',{row:TDSRow[1] | $row.getDateTime('DateTime')->month()->toString()->toUpper()}, 'FMMONTHUPPER', 'APRIL'), + tc('to_char(DateTime, \'Month\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->month()->toString()->rpad(9, ' ')}, 'Month', 'April '), + tc('to_char(DateTime, \'FMMonth\')',{row:TDSRow[1] | $row.getDateTime('DateTime')->month()->toString()}, 'FMMonth', 'April'), + tc('to_char(DateTime, \'month\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->month()->toString()->toLower()->rpad(9, ' ')}, 'monthLower', 'april '), + tc('to_char(DateTime, \'FMmonth\')',{row:TDSRow[1] | $row.getDateTime('DateTime')->month()->toString()->toLower()}, 'FMmonthLower', 'april'), + tc('to_char(DateTime, \'MM\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->monthNumber()->toString()->lpad(2, '0')}, 'MM', '04'), + tc('to_char(DateTime, \'FMMM\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->monthNumber()->toString()}, 'FMMM', '4'), + tc('to_char(DateTime, \'DAY\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfWeek()->toString()->toUpper()->rpad(9, ' ')}, 'DAYUPPER', 'SATURDAY '), + tc('to_char(DateTime, \'FMDAY\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfWeek()->toString()->toUpper()}, 'FMDAYUPPER', 'SATURDAY'), + tc('to_char(DateTime, \'Day\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfWeek()->toString()->rpad(9, ' ')}, 'Day', 'Saturday '), + tc('to_char(DateTime, \'FMDay\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfWeek()->toString()}, 'FMDay', 'Saturday'), + tc('to_char(DateTime, \'day\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfWeek()->toString()->toLower()->rpad(9, ' ')}, 'dayLower', 'saturday '), + tc('to_char(DateTime, \'FMday\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfWeek()->toString()->toLower()}, 'FMdayLower', 'saturday'), + tc('to_char(DateTime, \'DDD\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfYear()->toString()->lpad(3, '0')}, 'DDD', '091'), + tc('to_char(DateTime, \'FMDDD\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfYear()->toString()}, 'FMDDD', '91'), + tc('to_char(DateTime, \'DD\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfMonth()->toString()->lpad(2, '0')}, 'DD', '01'), + tc('to_char(DateTime, \'FMDD\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfMonth()->toString()}, 'FMDD', '1'), + tc('to_char(DateTime, \'D\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->dayOfWeekNumber()->toString()}, 'D', '7'), + tc('to_char(DateTime, \'WW\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->weekOfYear()->toString()->lpad(2, '0')}, 'WW', '13'), + tc('to_char(DateTime, \'FMWW\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->weekOfYear()->toString()}, 'FMWW', '13'), + tc('to_char(DateTime, \'Q\')', {row:TDSRow[1] | $row.getDateTime('DateTime')->quarterNumber()->toString()}, 'Q', '2') + ], true); +} + +function <> meta::external::query::sql::transformation::queryToPure::tests::testToCharCombined():Boolean[1] +{ + toCharTest([ + tc('to_char(DateTime, \'HH24-FMHH24-MI-FMMI-SS-FMSS-YYYY-YYY-YY-MONTH-FMMONTH-month-FMmonth-DAY-FMDAY-Day-FMDay-day-FMday-DDD-FMDDD-DD-FMDD-D-WW-FMWW-Q\')', [], + 'a-l-l', '09-9-08-8-07-7-2023-023-23-APRIL -APRIL-april -april-SATURDAY -SATURDAY-Saturday -Saturday-saturday -saturday-091-91-01-1-7-13-13-2'), + tc('to_char(DateTime, \'HH24FMHH24MIFMMISSFMSSYYYY-YYY-YYMONTHFMMONTHmonthFMmonthDAYFMDAYDayFMDaydayFMdayDDDFMDD-D-DDFMDDDWWFMWWQ\')', [], + 'all', '0990880772023-023-23APRIL APRILapril aprilSATURDAY SATURDAYSaturday Saturdaysaturday saturday0911-7-019113132'), + tc('to_char(DateTime, \'YYYY-MM-DD\')', [], 'yyyymmdd', '2023-04-01') + ], false); +} + + //MATH FUNCTIONS function <> meta::external::query::sql::transformation::queryToPure::tests::testMathFunctions():Boolean[1] { diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-query/src/main/java/org/finos/legend/engine/query/sql/api/SQLExecutor.java b/legend-engine-xts-sql/legend-engine-xt-sql-query/src/main/java/org/finos/legend/engine/query/sql/api/SQLExecutor.java index 674ec37df36..a419a751e68 100644 --- a/legend-engine-xts-sql/legend-engine-xt-sql-query/src/main/java/org/finos/legend/engine/query/sql/api/SQLExecutor.java +++ b/legend-engine-xts-sql/legend-engine-xt-sql-query/src/main/java/org/finos/legend/engine/query/sql/api/SQLExecutor.java @@ -52,7 +52,6 @@ import org.finos.legend.engine.query.sql.providers.core.SQLSourceProvider; import org.finos.legend.engine.query.sql.providers.core.SQLSourceResolvedContext; import org.finos.legend.engine.query.sql.providers.core.TableSource; -import org.finos.legend.engine.query.sql.api.sources.TableSourceArgument; import org.finos.legend.engine.shared.core.ObjectMapperFactory; import org.finos.legend.engine.shared.core.operational.errorManagement.EngineException; import org.finos.legend.engine.shared.core.operational.logs.LogInfo; @@ -243,15 +242,6 @@ private Pair, PureModelContext> getSourcesAndModel(Query private SQLSourceResolvedContext resolve(MutableCollection tables, SQLContext context, SQLSourceProvider extension, MutableList profiles) { - //TODO remove deprecated flow - org.finos.legend.engine.query.sql.api.sources.SQLSourceResolvedContext resolved = extension.resolve(tables.collect(t -> new org.finos.legend.engine.query.sql.api.sources.TableSource(t.getType(), - ListIterate.collect(t.getArguments(), a -> new TableSourceArgument(a.getName(), a.getIndex(), a.getValue())))).toList(), new org.finos.legend.engine.query.sql.api.sources.SQLContext(context.getQuery()), profiles); - - if (resolved != null) - { - return new SQLSourceResolvedContext(resolved.getPureModelContexts(), ListIterate.collect(resolved.getSources(), s -> new SQLSource(s.getType(), s.getFunc(), s.getMapping(), s.getRuntime(), s.getExecutionOptions(), s.getExecutionContext(), s.getKey()))); - } - return extension.resolve(tables.toList(), context, profiles); } diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-query/src/test/java/org/finos/legend/engine/query/sql/api/TestSQLSourceProvider.java b/legend-engine-xts-sql/legend-engine-xt-sql-query/src/test/java/org/finos/legend/engine/query/sql/api/TestSQLSourceProvider.java index eb5857cae0e..8268e162f5d 100644 --- a/legend-engine-xts-sql/legend-engine-xt-sql-query/src/test/java/org/finos/legend/engine/query/sql/api/TestSQLSourceProvider.java +++ b/legend-engine-xts-sql/legend-engine-xt-sql-query/src/test/java/org/finos/legend/engine/query/sql/api/TestSQLSourceProvider.java @@ -24,10 +24,10 @@ import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.PureSingleExecution; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.Service; -import org.finos.legend.engine.query.sql.api.sources.SQLSourceProvider; import org.finos.legend.engine.query.sql.providers.core.SQLContext; import org.finos.legend.engine.query.sql.providers.core.SQLSource; import org.finos.legend.engine.query.sql.providers.core.SQLSourceArgument; +import org.finos.legend.engine.query.sql.providers.core.SQLSourceProvider; import org.finos.legend.engine.query.sql.providers.core.SQLSourceResolvedContext; import org.finos.legend.engine.query.sql.providers.core.TableSource; import org.finos.legend.engine.query.sql.providers.core.TableSourceArgument; From 6fd07bced9ba92afb0b4aac4e2d0faa6fe915cf1 Mon Sep 17 00:00:00 2001 From: gs-jp1 <80327721+gs-jp1@users.noreply.github.com> Date: Fri, 10 Nov 2023 18:31:26 +0000 Subject: [PATCH 2/2] Fix user --- .../java/org/finos/legend/engine/query/sql/api/SQLExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legend-engine-xts-sql/legend-engine-xt-sql-query/src/main/java/org/finos/legend/engine/query/sql/api/SQLExecutor.java b/legend-engine-xts-sql/legend-engine-xt-sql-query/src/main/java/org/finos/legend/engine/query/sql/api/SQLExecutor.java index a419a751e68..74bf4bbf455 100644 --- a/legend-engine-xts-sql/legend-engine-xt-sql-query/src/main/java/org/finos/legend/engine/query/sql/api/SQLExecutor.java +++ b/legend-engine-xts-sql/legend-engine-xt-sql-query/src/main/java/org/finos/legend/engine/query/sql/api/SQLExecutor.java @@ -127,7 +127,7 @@ public Result execute(Query query, String user, SQLContext context, MutableList< { Root_meta_pure_executionPlan_ExecutionPlan l = PlanPlatform.JAVA.bindPlan(p._plan(), null, pureModel, routerExtensions.apply(pureModel)); SingleExecutionPlan m = transformExecutionPlan(l, pureModel, PureClientVersions.production, profiles, routerExtensions.apply(pureModel), transformers); - result = planExecutor.execute(m, Maps.mutable.empty(), "pentej", profiles); + result = planExecutor.execute(m, Maps.mutable.empty(), user, profiles); } return Tuples.pair(p._name(), result);