diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/pom.xml b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/pom.xml index e080820e339..d2c5c0b016a 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/pom.xml +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/pom.xml @@ -175,6 +175,18 @@ legend-engine-xt-relationalStore-pure + + org.finos.legend.pure + legend-pure-m2-dsl-mapping-pure + + + org.finos.legend.engine + legend-engine-pure-platform-dsl-store-java + + + org.finos.legend.engine + legend-engine-pure-platform-store-relational-java + org.eclipse.collections diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/src/main/resources/core_relational_duckdb/relational/sqlQueryToString/duckdbExtension.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/src/main/resources/core_relational_duckdb/relational/sqlQueryToString/duckdbExtension.pure index 4d82ff9f2c0..dd1ba2cf377 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/src/main/resources/core_relational_duckdb/relational/sqlQueryToString/duckdbExtension.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/src/main/resources/core_relational_duckdb/relational/sqlQueryToString/duckdbExtension.pure @@ -29,6 +29,7 @@ function <> meta::relational::functions::sqlQueryToString::duckD joinStringsProcessor = processJoinStringsOperationWithConcatCall_JoinStrings_1__SqlGenerationContext_1__String_1_, literalProcessor = $literalProcessor, selectSQLQueryProcessor = processSelectSQLQueryForDuckDB_SelectSQLQuery_1__SqlGenerationContext_1__Boolean_1__String_1_, + selectSQLQueryWithCTEsProcessor = processSelectSQLQueryWithCTEsDefault_SelectSQLQueryWithCommonTableExpressions_1__SqlGenerationContext_1__Boolean_1__String_1_, columnNameToIdentifier = columnNameToIdentifierForDuckDB_String_1__DbConfig_1__String_1_, identifierProcessor = processIdentifierWithDoubleQuotes_String_1__DbConfig_1__String_1_, dynaFuncDispatch = $dynaFuncDispatch, diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/src/main/resources/core_relational_duckdb/relational/sqlQueryToString/tests/testDuckDBSQLGeneration.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/src/main/resources/core_relational_duckdb/relational/sqlQueryToString/tests/testDuckDBSQLGeneration.pure new file mode 100644 index 00000000000..12df861e484 --- /dev/null +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-duckdb/legend-engine-xt-relationalStore-duckdb-pure/src/main/resources/core_relational_duckdb/relational/sqlQueryToString/tests/testDuckDBSQLGeneration.pure @@ -0,0 +1,37 @@ +// Copyright 2024 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. + +###Pure +import meta::core::runtime::*; +import meta::external::store::relational::runtime::*; +import meta::relational::extension::*; +import meta::relational::functions::sqlQueryToString::*; +import meta::relational::functions::sqlstring::*; +import meta::relational::metamodel::relation::*; +import meta::relational::runtime::*; +import meta::relational::tests::*; +import meta::relational::tests::model::simple::*; +import meta::relational::tests::postProcessor::cteExtraction::*; + +function <> meta::relational::tests::sqlQueryToString::duckDB::testCTESQLGeneration(): Boolean[1] +{ + let func = {|Trade.all()->project([x|$x.id, x|$x.quantity], ['TradeID', 'Quantity'])->limit(10)->filter(x | $x.getInteger('TradeID') == 100)}; + let pp = testRuntimeWithCTEPP().connectionStores->at(0).connection->cast(@DatabaseConnection).sqlQueryPostProcessors; + let result = toSQLString($func, simpleRelationalMapping, DatabaseType.DuckDB, []->cast(@String), $pp, ^Format(newLine='', indent=''), relationalExtensions(), noDebug()); + assertEquals( + 'WITH subquery_cte_1_1 AS (select "root".ID as "TradeID", "root".quantity as "Quantity" from tradeTable as "root" limit 10) \n' + + 'select "TradeID" as "TradeID", "Quantity" as "Quantity" from subquery_cte_1_1 as "subselect" where "TradeID" = 100', + $result + ); +} \ No newline at end of file diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/postprocessor/cteExtractionPostProcessor.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/postprocessor/cteExtractionPostProcessor.pure index 88c47e5c323..4d3d68a75fc 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/postprocessor/cteExtractionPostProcessor.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/postprocessor/cteExtractionPostProcessor.pure @@ -138,7 +138,7 @@ function <> meta::relational::tests::postProcessor::cteExtra meta::relational::tests::createTablesAndFillDb(); } -function <> meta::relational::tests::postProcessor::cteExtraction::testRuntimeWithCTEPP(): Runtime[1] +function meta::relational::tests::postProcessor::cteExtraction::testRuntimeWithCTEPP(): Runtime[1] { ^Runtime ( @@ -244,3 +244,18 @@ function <> meta::relational::tests::postProcessor::cteExtraction::te let resultWithoutCTEPP = execute($func, simpleRelationalMapping, testRuntime(), relationalExtensions()); assertEquals($resultWithoutCTEPP.values->toCSV(), $result.values->toCSV()); } + +function <> meta::relational::tests::postProcessor::cteExtraction::testCorrelatedSubQueryIsolationStrategy(): Boolean[1] +{ + let func = {| + Person.all()->project([x|$x.firm.legalName, x|$x.firm.employeeByLastName('Smith').firstName], ['Legal Name','Employee Name']) + }; + let result = execute($func, simpleRelationalMapping, testRuntimeWithCTEPP(), relationalExtensions()); + assertSameSQL( + 'WITH subquery_cte_1_1 AS (select "persontable_2".FIRMID as FIRMID, "persontable_2".FIRSTNAME as FIRSTNAME from personTable as "persontable_2" where "persontable_2".LASTNAME = \'Smith\') ' + + 'select "firmtable_0".LEGALNAME as "Legal Name", "persontable_1".FIRSTNAME as "Employee Name" from personTable as "root" left outer join firmTable as "firmtable_0" on ("firmtable_0".ID = "root".FIRMID) left outer join subquery_cte_1_1 as "persontable_1" on ("firmtable_0".ID = "persontable_1".FIRMID)', + $result + ); + let resultWithoutCTEPP = execute($func, simpleRelationalMapping, testRuntime(), relationalExtensions()); + assertEquals($resultWithoutCTEPP.values->toCSV(), $result.values->toCSV()); +} 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 b5f6b15e3ec..a814e663ff2 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 @@ -309,7 +309,7 @@ function <> meta::relational::functions::sqlQueryToString::defau ): String[1] { $ctes->map(cte | - $cte.name + ' AS (' + $sgc.dbConfig.selectSQLQueryProcessor($cte->cast(@SelectCommonTableExpression).selectSQLQuery->cast(@SelectSQLQuery), $sgc, $isSubSelect) + ')' + $cte.name + ' AS (' + $sgc.dbConfig.selectSQLQueryProcessor($cte->cast(@SelectCommonTableExpression).selectSQLQuery->cast(@SelectSQLQuery), ^$sgc(format = $sgc.format->indent()), $isSubSelect) + ')' )->joinStrings(', \n') + ' \n'; }