Skip to content

Commit

Permalink
Fix sqlGeneration for filters without aliases in relational queries (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
siaka-Akash authored Nov 2, 2023
1 parent 1358bcf commit 432217c
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,31 @@ function <<test.Test>> meta::relational::tests::projection::filter::isolation::t
assertEquals(['Firm X, UK', 'Firm X, Europe', 'Firm X, Europe', 'Firm X, Europe', 'Firm A, Europe', 'Firm B, Europe', 'Firm C, Europe'],$tds.rows->map(r|$r.values->makeString(', ')));
assertEquals('select "root".LEGALNAME as "legalName", case when ("firmpersonbridgetable_0".ADDRESSID = 1 or "addresstable_0".ID = 1) then \'UK\' else \'Europe\' end as "addressName" from firmTable as "root" left outer join (select "firmpersonbridgetable_1".FIRM_ID as FIRM_ID, "persontable_0".ADDRESSID as ADDRESSID from firmPersonBridgeTable as "firmpersonbridgetable_1" inner join personTable as "persontable_0" on ("persontable_0".ID = "firmpersonbridgetable_1".PERSON_ID)) as "firmpersonbridgetable_0" on ("root".ID = "firmpersonbridgetable_0".FIRM_ID) left outer join addressTable as "addresstable_0" on ("addresstable_0".ID = "root".ADDRESSID)', $result->sqlRemoveFormatting());
}

// Filters having no table alias like 'Smith' = 'Smith'
function <<test.Test>> meta::relational::tests::projection::filter::isolation::testIsolationOfFiltersWithoutAlias():Boolean[1]
{
let result1 = execute(|Firm.all()->project([f|$f.employeeByLastName('Smith').address.name, f | $f.employeeByLastName('Smith').firstName],['address', 'employeeFirstName']), meta::relational::tests::mapping::join::model::mapping::MappingWithLiteral, testRuntime(), meta::relational::extension::relationalExtensions());
let result2 = execute(|Firm.all()->project([f|$f.employeeByLastName('Roberts').address.name, f | $f.employeeByLastName('Roberts').firstName],['address', 'employeeFirstName']), meta::relational::tests::mapping::join::model::mapping::MappingWithLiteral, testRuntime(), meta::relational::extension::relationalExtensions());
let result3 = execute(|Firm.all()->project([f|$f.employeeByLastName('Roberts').address.name, f | $f.employeeByLastName('Smith').firstName],['address', 'employeeFirstName']), meta::relational::tests::mapping::join::model::mapping::MappingWithLiteral, testRuntime(), meta::relational::extension::relationalExtensions());

let tds1 = $result1.values->at(0);
assertEquals(['Hoboken, Peter', 'New York, John', 'New York, John', 'New York, Anthony', 'San Fransisco, Fabrice', 'Hong Kong, Oliver', 'New York, David'], $tds1.rows->map(r|$r.values->makeString(', ')));
assertEquals('select "addresstable_0".NAME as "address", "persontable_0".FIRSTNAME as "employeeFirstName" from firmTable as "root" left outer join personTable as "persontable_0" on ("root".ID = "persontable_0".FIRMID and \'Smith\' = \'Smith\') left outer join addressTable as "addresstable_0" on ("addresstable_0".ID = "persontable_0".ADDRESSID)', $result1->sqlRemoveFormatting());

let tds2 = $result2.values->at(0);
assertEquals(['TDSNull, TDSNull', 'TDSNull, TDSNull', 'TDSNull, TDSNull', 'TDSNull, TDSNull'], $tds2.rows->map(r|$r.values->makeString(', ')));
assertEquals('select "addresstable_0".NAME as "address", "persontable_0".FIRSTNAME as "employeeFirstName" from firmTable as "root" left outer join personTable as "persontable_0" on ("root".ID = "persontable_0".FIRMID and \'Smith\' = \'Roberts\') left outer join addressTable as "addresstable_0" on ("addresstable_0".ID = "persontable_0".ADDRESSID)', $result2->sqlRemoveFormatting());

let tds3 = $result3.values->at(0);
assertEquals(['TDSNull, Peter', 'TDSNull, John', 'TDSNull, John', 'TDSNull, Anthony', 'TDSNull, Fabrice', 'TDSNull, Oliver', 'TDSNull, David'], $tds3.rows->map(r|$r.values->makeString(', ')));
assertEquals('select "addresstable_0".NAME as "address", "persontable_1".FIRSTNAME as "employeeFirstName" from firmTable as "root" left outer join personTable as "persontable_0" on ("root".ID = "persontable_0".FIRMID and \'Smith\' = \'Roberts\') left outer join addressTable as "addresstable_0" on ("addresstable_0".ID = "persontable_0".ADDRESSID) left outer join personTable as "persontable_1" on ("root".ID = "persontable_1".FIRMID and \'Smith\' = \'Smith\')', $result3->sqlRemoveFormatting());
}

function <<test.Test>> meta::relational::tests::projection::filter::lessThanEqual::testIsolationOfFiltersWithoutAliasWithChainedJoins():Boolean[1]
{
let result = execute(|Trade.all()->project([t | $t.id, t| $t.product.synonymByType(ProductSynonymType.CUSIP).name, t| $t.product.synonymByType(ProductSynonymType.ISIN).name], ['tradeId','SynonyName1', 'SynonymName2']), meta::relational::tests::mapping::join::model::mapping::MappingWithLiteral, testRuntime(), meta::relational::extension::relationalExtensions());
let tds = $result.values->at(0);
assertEquals(['1, CUSIP1, TDSNull', '1, ISIN1, TDSNull', '2, CUSIP1, TDSNull', '2, ISIN1, TDSNull', '3, CUSIP2, TDSNull', '3, ISIN2, TDSNull', '4, CUSIP2, TDSNull', '4, ISIN2, TDSNull', '5, CUSIP2, TDSNull', '5, ISIN2, TDSNull', '6, CUSIP3, TDSNull', '6, ISIN3, TDSNull', '7, CUSIP3, TDSNull', '7, ISIN3, TDSNull', '8, CUSIP3, TDSNull', '8, ISIN3, TDSNull', '9, CUSIP3, TDSNull', '9, ISIN3, TDSNull', '10, CUSIP3, TDSNull', '10, ISIN3, TDSNull', '11, TDSNull, TDSNull'], $tds.rows->map(r|$r.values->makeString(', ')));
assertEquals('select "root".ID as "tradeId", "synonymtable_0".NAME as "SynonyName1", "synonymtable_2".NAME as "SynonymName2" from tradeTable as "root" left outer join productSchema.productTable as "producttable_0" on ("root".prodId = "producttable_0".ID) left outer join (select "synonymtable_1".PRODID as PRODID, "synonymtable_1".NAME as NAME from productSchema.synonymTable as "synonymtable_1" where \'CUSIP\' = \'CUSIP\') as "synonymtable_0" on ("synonymtable_0".PRODID = "producttable_0".ID) left outer join (select "synonymtable_1".PRODID as PRODID, "synonymtable_1".NAME as NAME from productSchema.synonymTable as "synonymtable_1" where \'CUSIP\' = \'ISIN\') as "synonymtable_2" on ("synonymtable_2".PRODID = "producttable_0".ID)', $result->sqlRemoveFormatting());
}
Original file line number Diff line number Diff line change
Expand Up @@ -5872,7 +5872,10 @@ function meta::relational::functions::pureToSqlQuery::findBestNodeToIsolate(sele
{
let joinThreads = ^List<RelationalTreeNode>(values=$select.data)->buildThreads();

let aliasesWithConstraints = $select.savedFilteringOperation.second->extractTableAliasColumns().alias->removeDuplicates();
//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();

let filterThreadsWithAllConditions = $joinThreads->filter(thread| $thread->matchAllAliases($aliasesWithConstraints));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,21 @@ function <<test.BeforePackage>> meta::relational::tests::mapping::innerjoin::iso
}
function <<test.Test>> meta::relational::tests::mapping::innerjoin::isolation::testIsolationOfInnerJoins():Any[*]
{
let func = {| Car.all()->filter(c|$c.org.publicAncestor.name != 'GSorg2'
&& $c.org.publicAncestor.name->contains('GSorg')
&& $c.org.publicAncestor.name->contains('toReturn')
let func = {| Car.all()->filter(c|$c.org.privateAncestor.name != 'GSorg2'
&& $c.org.privateAncestor.name->contains('GSorg')
&& $c.org.privateAncestor.name->contains('toReturn')
)->project([col(c|$c.id, 'Id'), col(c|$c.type, 'type')])};
let result = execute($func,AutoMapping,autoMobileRuntime(), meta::relational::extension::relationalExtensions());
assertEquals([ 3, 'Mercedes3'],$result.values.rows->map(r|$r.values));
assertSize($result.values.rows, 1);
assertEquals('select "root".vehicleId as "Id", "root".type as "type" from AutomobileTable as "root" left outer join AutomobileTable as "automobiletable_1" on ("root".vehicleId = "automobiletable_1".vehicleId and "root".orgId < 100) left outer join (select "autoancestor_1".childId as childId, "autoancestor_2".orgName as orgName from AutoAncestor as "autoancestor_1" left outer join (select "autoancestor_2".parentId as parentId, "automobiletable_2".orgName as orgName from AutoAncestor as "autoancestor_2" inner join AutomobileTable as "automobiletable_2" on ("autoancestor_2".parentId = "automobiletable_2".orgId and case when "automobiletable_2".orgtype = \'public\' then \'N\' else \'Y\' end = \'Y\')) as "autoancestor_2" on ("autoancestor_1".parentId = "autoancestor_2".parentId)) as "autoancestor_0" on ("automobiletable_1".orgId = "autoancestor_0".childId) left outer join (select "autoancestor_4".childId as childId, "automobiletable_3".orgName as orgName from AutoAncestor as "autoancestor_4" inner join AutomobileTable as "automobiletable_3" on ("autoancestor_4".parentId = "automobiletable_3".orgId) where case when "automobiletable_3".orgtype = \'public\' then \'N\' else \'Y\' end = \'Y\') as "autoancestor_3" on ("automobiletable_1".orgId = "autoancestor_3".childId) where ((("autoancestor_3".orgName <> \'GSorg2\' OR "autoancestor_3".orgName is null) and ("autoancestor_0".orgName is not null and "autoancestor_3".orgName like \'%GSorg%\')) and ("autoancestor_0".orgName is not null and "autoancestor_3".orgName like \'%toReturn%\'))',$result->sqlRemoveFormatting());
}

function <<test.Test>> meta::relational::tests::mapping::innerjoin::isolation::testIsolationForFiltersWithoutAliasAndInnerJoins():Any[*]
{
let func = {| Car.all()->project([col(c|$c.org.privateAncestor.name, 'privateAncestorName'), col(c|$c.org.publicAncestor.name, 'publicAncestorName')])};
let result = execute($func,MappingWithConstant,autoMobileRuntime(), meta::relational::extension::relationalExtensions());
let tds = $result.values->at(0);
assertEquals(['GSorg4, TDSNull', 'GSorg3, TDSNull', 'GSorgtoReturn, TDSNull', 'TDSNull, TDSNull'], $tds.rows->map(r|$r.values->makeString(', ')));
assertEquals('select "autoancestor_0".orgName as "privateAncestorName", "autoancestor_2".orgName as "publicAncestorName" from AutomobileTable as "root" left outer join AutomobileTable as "automobiletable_1" on ("root".vehicleId = "automobiletable_1".vehicleId and "root".orgId < 100) left outer join (select "autoancestor_1".childId as childId, "automobiletable_2".orgName as orgName from AutoAncestor as "autoancestor_1" inner join AutomobileTable as "automobiletable_2" on ("autoancestor_1".parentId = "automobiletable_2".orgId) where \'Y\' = \'Y\') as "autoancestor_0" on ("automobiletable_1".orgId = "autoancestor_0".childId) left outer join (select "autoancestor_1".childId as childId, "automobiletable_2".orgName as orgName from AutoAncestor as "autoancestor_1" inner join AutomobileTable as "automobiletable_2" on ("autoancestor_1".parentId = "automobiletable_2".orgId) where \'Y\' = \'N\') as "autoancestor_2" on ("automobiletable_1".orgId = "autoancestor_2".childId)',$result->sqlRemoveFormatting());
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,17 @@ Class meta::relational::tests::mapping::innerjoin::isolation::AutomobileUnion
isPrivate: String[0..1];
ancestors: AutomobileUnion[0..*];
children: AutomobileUnion[0..*];
publicAncestor()
privateAncestor()
{
$this.ancestors->filter(a|$a.isPrivate =='Y')->toOne()
}:AutomobileUnion[1];

publicAncestor2()
publicAncestor()
{
$this.ancestors->filter(a|$a.isPrivate =='N')->toOne()
}:AutomobileUnion[1];

privateAncestor2()
{
$this.ancestors->filter(a|$a.isPrivate =='Y').name=='haha' || ($this.ancestors->filter(a|$a.isPrivate=='Y').name=='ahah')
}: Boolean[1];
Expand All @@ -63,8 +68,8 @@ function meta::relational::tests::mapping::innerjoin::isolation::initAutomobileD
executeInDb('Create Table AutomobileTable (vehicleId INT, type VARCHAR(20),orgId INT, orgName VARCHAR(40),orgtype VARCHAR(40));', $connection);
executeInDb('insert into AutomobileTable (vehicleId, type, orgId,orgName,orgType) values (1, \'Mercedes1\',17,\'GSorgtoReturn\' ,\'private\');', $connection);
executeInDb('insert into AutomobileTable (vehicleId, type, orgId,orgName,orgType) values (2, \'Mercedes2\',18,\'GSorgtoReturn2\' ,\'private\');', $connection);
executeInDb('insert into AutomobileTable (vehicleId, type, orgId,orgName,orgType) values (3, \'Mercedes3\',19,\'GSorg3\' ,\'public3\');', $connection);
executeInDb('insert into AutomobileTable (vehicleId, type, orgId,orgName,orgType) values (4, \'Mercedes4\',20,\'GSorg4\' ,\'public4\');', $connection);
executeInDb('insert into AutomobileTable (vehicleId, type, orgId,orgName,orgType) values (3, \'Mercedes3\',19,\'GSorg3\' ,\'public\');', $connection);
executeInDb('insert into AutomobileTable (vehicleId, type, orgId,orgName,orgType) values (4, \'Mercedes4\',20,\'GSorg4\' ,\'public\');', $connection);

executeInDb('Drop table if exists AutoAncestor;', $connection);
executeInDb('Create Table AutoAncestor (childId INT ,parentId INT);',$connection);
Expand Down Expand Up @@ -118,6 +123,36 @@ Mapping meta::relational::tests::mapping::innerjoin::isolation::AutoMapping
)
}

)

###Mapping
import meta::relational::tests::mapping::innerjoin::isolation::*;
Mapping meta::relational::tests::mapping::innerjoin::isolation::MappingWithConstant
(
Car :Relational
{
scope([AutomobileDb])
(
type: AutomobileTable.type,
id: AutomobileTable.vehicleId,
org(
name: AutomobileTable.orgName,
isPrivate: 'Y',
ancestors: @ Auto_Auto > @Auto_Ancestor > (INNER)@AncestorAuto
)
)
}

AutomobileUnion:Relational
{
scope([AutomobileDb])
(
name: AutomobileTable.orgName,
isPrivate: 'Y',
ancestors: @Auto_Ancestor > (INNER)@AncestorAuto
)
}

)
###Relational
Database meta::relational::tests::mapping::innerjoin::isolation::AutomobileDb
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,68 @@ Mapping meta::relational::tests::mapping::join::model::mapping::JoinSchemaBWithS
}
)

###Mapping
import meta::relational::tests::model::simple::*;
import meta::relational::tests::*;
Mapping meta::relational::tests::mapping::join::model::mapping::MappingWithLiteral
(
Person : Relational
{
scope([dbInc])
(
firstName : personTable.FIRSTNAME,
age : personTable.AGE
),
scope([dbInc]default.personTable)
(
lastName : 'Smith'
),
firm : [dbInc]@Firm_Person,
address : [dbInc]@Address_Person,
locations : [dbInc]@Person_Location,
manager : [dbInc]@Person_Manager
}

Firm : Relational
{
~mainTable [dbInc] firmTable
legalName : [dbInc]firmTable.LEGALNAME,
employees : [dbInc]@Firm_Person,
address : [dbInc]@Address_Firm
}

Address : Relational
{
name : [dbInc]addressTable.NAME,
street : [dbInc]addressTable.STREET,
comments : [dbInc]addressTable.COMMENTS
}

Product : Relational
{
name : [db]productSchema.productTable.NAME,
synonyms : [db]@Product_Synonym
}

ProductSynonymType: EnumerationMapping SynonymEnum
{
CUSIP: 'CUSIP',
ISIN: 'ISIN'
}

Synonym : Relational
{
name : [db]productSchema.synonymTable.NAME,
type : EnumerationMapping SynonymEnum: 'CUSIP'
}

Trade : Relational
{
id : [db]tradeTable.ID,
product : [db]@Trade_Product
}
)

###Pure
import meta::relational::tests::mapping::join::model::store::*;
import meta::pure::profiles::*;
Expand Down Expand Up @@ -494,4 +556,4 @@ function meta::relational::tests::mapping::join::model::store::createTablesAndFi
executeInDb('insert into schemaB.PersonTable (id, firstName, LastName) values (4, \'Anthonye\', \'Anthony B\');', $connection);
executeInDb('insert into schemaB.PersonTable (id, firstName, LastName) values (5, \'Oliver\', \'Oliver B\');', $connection);
true;
}
}

0 comments on commit 432217c

Please sign in to comment.