package de.superx.bianalysis; import static org.junit.Assert.assertEquals; import java.util.List; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import de.superx.BIATestUtils; import de.superx.BaseDbTest; import de.superx.bianalysis.models.Right; import de.superx.bianalysis.service.BiAnalysisManager; import de.superx.bianalysis.service.DbMetaAdapter; import de.superx.rest.model.Column; import static de.superx.BIATestUtils.getParsedSqlFromString; import static de.superx.BIATestUtils.getSqlFromReportDefinition; import static de.superx.BIATestUtils.getResultColumnsFromReport; public class ConformedTest extends BaseDbTest { @Autowired DbMetaAdapter dbAdapter; @Autowired BiAnalysisManager biAnalysisManager; @Before public void init() { setRight(Right.CREATE_ANALYSIS); } @Test public void twoFactTablesTwoJoinCriteriaUnionJoin() { String json = """ { "factTableId": "res_nom:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "res_nom:5", "res_nom:7" ], "measureIds": [ "res_nom:17" ], "secondaryFacttables": [ { "factId": "res_patent:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "res_nom:4", "secondaryRolePlayingDimensionId": "res_patent:10" }, { "leadingRolePlayingDimensionId": "res_nom:6", "secondaryRolePlayingDimensionId": "res_patent:78999" } ], "measureIds": [ "res_patent:28" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_prize_aggregated AS (SELECT nomination_date.year_actual AS year_actual_5, grouping(nomination_date.year_actual) AS g_year_actual_5, nomination_date.year_actual_sort_order AS year_actual_5_year_actual_sort_order, grouping(nomination_date.year_actual_sort_order) AS g_year_actual_5_year_actual_sort_order, awardee.gender AS gender_7, grouping(awardee.gender) AS g_gender_7, awardee.gender_sort_order AS gender_7_gender_sort_order, grouping(awardee.gender_sort_order) AS g_gender_7_gender_sort_order, COUNT(distinct(fact_prize.nomination_id)) AS "col0", NULL::bigint AS "col1" FROM presentation.fact_prize JOIN presentation.dim_person_researcher AS awardee ON fact_prize.person_id = awardee.id AND awardee.is_current = TRUE JOIN presentation.dim_date AS nomination_date ON fact_prize.nomination_date_id = nomination_date.id GROUP BY GROUPING SETS ((nomination_date.year_actual, nomination_date.year_actual_sort_order, awardee.gender, awardee.gender_sort_order), (nomination_date.year_actual, nomination_date.year_actual_sort_order), ()) ORDER BY nomination_date.year_actual_sort_order, awardee.gender_sort_order), fact_patent_aggregated AS (SELECT date_registration.year_actual AS year_actual_11, grouping(date_registration.year_actual) AS g_year_actual_11, date_registration.year_actual_sort_order AS year_actual_11_year_actual_sort_order, grouping(date_registration.year_actual_sort_order) AS g_year_actual_11_year_actual_sort_order, conformed_person.gender AS gender_79000, grouping(conformed_person.gender) AS g_gender_79000, conformed_person.gender_sort_order AS gender_79000_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_79000_gender_sort_order, NULL::bigint AS "col0", COUNT(distinct(fact_patent.id)) AS "col1" FROM presentation.fact_patent JOIN presentation.dim_date AS date_registration ON fact_patent.registration_date_id = date_registration.id JOIN presentation.dim_person_researcher AS conformed_person ON fact_patent.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((date_registration.year_actual, date_registration.year_actual_sort_order, conformed_person.gender, conformed_person.gender_sort_order), (date_registration.year_actual, date_registration.year_actual_sort_order), ()) ORDER BY date_registration.year_actual_sort_order, conformed_person.gender_sort_order) SELECT year_actual, year_actual_sort_order, gender, gender_sort_order, SUM(col0) AS col0, SUM(col1) AS col1 FROM (SELECT year_actual_11 AS year_actual, g_year_actual_11 AS g_year_actual, year_actual_11_year_actual_sort_order AS year_actual_sort_order, g_year_actual_11_year_actual_sort_order AS g_year_actual_sort_order, gender_79000 AS gender, g_gender_79000 AS g_gender, gender_79000_gender_sort_order AS gender_sort_order, g_gender_79000_gender_sort_order AS g_gender_sort_order, col0, col1 FROM fact_patent_aggregated UNION ALL SELECT year_actual_5 AS year_actual, g_year_actual_5 AS g_year_actual, year_actual_5_year_actual_sort_order AS year_actual_sort_order, g_year_actual_5_year_actual_sort_order AS g_year_actual_sort_order, gender_7 AS gender, g_gender_7 AS g_gender, gender_7_gender_sort_order AS gender_sort_order, g_gender_7_gender_sort_order AS g_gender_sort_order, col0, col1 FROM fact_prize_aggregated) x GROUP BY year_actual, g_year_actual, year_actual_sort_order, g_year_actual_sort_order, gender, g_gender, gender_sort_order, g_gender_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesOneConformedAttributeUnionJoin() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:63" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_doctoral_program:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:62", "secondaryRolePlayingDimensionId": "res_doctoral_program:43" } ], "measureIds": [ "res_doctoral_program:57" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT date.year_actual AS year_actual_63, grouping(date.year_actual) AS g_year_actual_63, date.year_actual_sort_order AS year_actual_63_year_actual_sort_order, grouping(date.year_actual_sort_order) AS g_year_actual_63_year_actual_sort_order, COUNT(distinct(fact_application.person_id)) AS "col0", NULL::bigint AS "col1" FROM presentation.fact_application JOIN presentation.dim_date AS date ON fact_application.receipt_date_id = date.id GROUP BY GROUPING SETS ((date.year_actual, date.year_actual_sort_order), ()) ORDER BY date.year_actual_sort_order), fact_doctoral_program_aggregated AS (SELECT date.year_actual AS year_actual_44, grouping(date.year_actual) AS g_year_actual_44, date.year_actual_sort_order AS year_actual_44_year_actual_sort_order, grouping(date.year_actual_sort_order) AS g_year_actual_44_year_actual_sort_order, NULL::bigint AS "col0", COUNT(distinct(fact_doctoral_program.doctoral_candidate_person_id)) AS "col1" FROM presentation.fact_doctoral_program JOIN presentation.dim_date AS date ON fact_doctoral_program.admission_date_id = date.id GROUP BY GROUPING SETS ((date.year_actual, date.year_actual_sort_order), ()) ORDER BY date.year_actual_sort_order) SELECT year_actual, year_actual_sort_order, SUM(col0) AS col0, SUM(col1) AS col1 FROM (SELECT year_actual_63 AS year_actual, g_year_actual_63 AS g_year_actual, year_actual_63_year_actual_sort_order AS year_actual_sort_order, g_year_actual_63_year_actual_sort_order AS g_year_actual_sort_order, col0, col1 FROM fact_application_aggregated UNION ALL SELECT year_actual_44 AS year_actual, g_year_actual_44 AS g_year_actual, year_actual_44_year_actual_sort_order AS year_actual_sort_order, g_year_actual_44_year_actual_sort_order AS g_year_actual_sort_order, col0, col1 FROM fact_doctoral_program_aggregated) x GROUP BY year_actual, g_year_actual, year_actual_sort_order, g_year_actual_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesOneConformedAttributeOneAsymmetricAttributeUnionJoin() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:63", "app_basic:12" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_doctoral_program:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:62", "secondaryRolePlayingDimensionId": "res_doctoral_program:43" } ], "measureIds": [ "res_doctoral_program:57" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT date.year_actual AS year_actual_63, grouping(date.year_actual) AS g_year_actual_63, date.year_actual_sort_order AS year_actual_63_year_actual_sort_order, grouping(date.year_actual_sort_order) AS g_year_actual_63_year_actual_sort_order, conformed_location.country AS country_12, grouping(conformed_location.country) AS g_country_12, COUNT(distinct(fact_application.person_id)) AS "col0", NULL::bigint AS "col1" FROM presentation.fact_application JOIN presentation.dim_date AS date ON fact_application.receipt_date_id = date.id JOIN presentation.dim_location AS conformed_location ON fact_application.location_lid = conformed_location.lid AND conformed_location.is_current = TRUE GROUP BY GROUPING SETS ((date.year_actual, date.year_actual_sort_order, conformed_location.country), (date.year_actual, date.year_actual_sort_order), ()) ORDER BY date.year_actual_sort_order, country_12), fact_doctoral_program_aggregated AS (SELECT date.year_actual AS year_actual_44, grouping(date.year_actual) AS g_year_actual_44, date.year_actual_sort_order AS year_actual_44_year_actual_sort_order, grouping(date.year_actual_sort_order) AS g_year_actual_44_year_actual_sort_order, NULL::text AS country_12, 1 AS g_country_12, NULL::bigint AS "col0", COUNT(distinct(fact_doctoral_program.doctoral_candidate_person_id)) AS "col1" FROM presentation.fact_doctoral_program JOIN presentation.dim_date AS date ON fact_doctoral_program.admission_date_id = date.id GROUP BY GROUPING SETS ((date.year_actual, date.year_actual_sort_order), ()) ORDER BY date.year_actual_sort_order) SELECT year_actual, year_actual_sort_order, country, SUM(col0) AS col0, SUM(col1) AS col1 FROM (SELECT year_actual_63 AS year_actual, g_year_actual_63 AS g_year_actual, year_actual_63_year_actual_sort_order AS year_actual_sort_order, g_year_actual_63_year_actual_sort_order AS g_year_actual_sort_order, country_12 AS country, g_country_12 AS g_country, col0, col1 FROM fact_application_aggregated UNION ALL SELECT year_actual_44 AS year_actual, g_year_actual_44 AS g_year_actual, year_actual_44_year_actual_sort_order AS year_actual_sort_order, g_year_actual_44_year_actual_sort_order AS g_year_actual_sort_order, country_12 AS country, g_country_12 AS g_country, col0, col1 FROM fact_doctoral_program_aggregated) x GROUP BY year_actual, g_year_actual, year_actual_sort_order, g_year_actual_sort_order, country, g_country """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void threeFactTablesOneConformedAttributeUnionJoin() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:3" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_doctoral_program:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_doctoral_program:3" } ], "measureIds": [ "res_doctoral_program:57" ] }, { "factId": "res_pub:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_pub:21020" } ], "measureIds": [ "res_pub:21037" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT conformed_person.gender AS gender_3, grouping(conformed_person.gender) AS g_gender_3, conformed_person.gender_sort_order AS gender_3_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_3_gender_sort_order, COUNT(distinct(fact_application.person_id)) AS "col0", NULL::bigint AS "col1", NULL::bigint AS "col2" FROM presentation.fact_application JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order), fact_doctoral_program_aggregated AS (SELECT conformed_person.gender AS gender_6, grouping(conformed_person.gender) AS g_gender_6, conformed_person.gender_sort_order AS gender_6_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_6_gender_sort_order, NULL::bigint AS "col0", COUNT(distinct(fact_doctoral_program.doctoral_candidate_person_id)) AS "col1", NULL::bigint AS "col2" FROM presentation.fact_doctoral_program JOIN presentation.dim_person_doctoral AS conformed_person ON fact_doctoral_program.doctoral_candidate_person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order), fact_publication_aggregated AS (SELECT conformed_person.gender AS gender_21021, grouping(conformed_person.gender) AS g_gender_21021, conformed_person.gender_sort_order AS gender_21021_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_21021_gender_sort_order, NULL::bigint AS "col0", NULL::bigint AS "col1", COUNT(distinct(fact_publication.publication_id)) AS "col2" FROM presentation.fact_publication JOIN presentation.dim_person_researcher AS conformed_person ON fact_publication.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order) SELECT gender, gender_sort_order, SUM(col0) AS col0, SUM(col1) AS col1, SUM(col2) AS col2 FROM (SELECT gender_3 AS gender, g_gender_3 AS g_gender, gender_3_gender_sort_order AS gender_sort_order, g_gender_3_gender_sort_order AS g_gender_sort_order, col0, col1, col2 FROM fact_application_aggregated UNION ALL SELECT gender_6 AS gender, g_gender_6 AS g_gender, gender_6_gender_sort_order AS gender_sort_order, g_gender_6_gender_sort_order AS g_gender_sort_order, col0, col1, col2 FROM fact_doctoral_program_aggregated UNION ALL SELECT gender_21021 AS gender, g_gender_21021 AS g_gender, gender_21021_gender_sort_order AS gender_sort_order, g_gender_21021_gender_sort_order AS g_gender_sort_order, col0, col1, col2 FROM fact_publication_aggregated) x GROUP BY gender, g_gender, gender_sort_order, g_gender_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void threeFactTablesTwoConformedAttributesUnionJoin() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:3", "app_basic:142" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_doctoral_program:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_doctoral_program:3" } ], "measureIds": [ "res_doctoral_program:57" ] }, { "factId": "res_pub:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_pub:21020" } ], "measureIds": [ "res_pub:21037" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT conformed_person.gender AS gender_3, grouping(conformed_person.gender) AS g_gender_3, conformed_person.gender_sort_order AS gender_3_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_3_gender_sort_order, conformed_person.first_nationality AS first_nationality_142, grouping(conformed_person.first_nationality) AS g_first_nationality_142, COUNT(DISTINCT (fact_application.person_id)) AS "col0", NULL::bigint AS "col1", NULL::bigint AS "col2" FROM presentation.fact_application JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order, conformed_person.first_nationality), (conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order, first_nationality_142), fact_doctoral_program_aggregated AS (SELECT conformed_person.gender AS gender_6, grouping(conformed_person.gender) AS g_gender_6, conformed_person.gender_sort_order AS gender_6_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_6_gender_sort_order, conformed_person.first_nationality AS first_nationality_9, grouping(conformed_person.first_nationality) AS g_first_nationality_9, NULL::bigint AS "col0", COUNT(DISTINCT (fact_doctoral_program.doctoral_candidate_person_id)) AS "col1", NULL::bigint AS "col2" FROM presentation.fact_doctoral_program JOIN presentation.dim_person_doctoral AS conformed_person ON fact_doctoral_program.doctoral_candidate_person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order, conformed_person.first_nationality), (conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order, first_nationality_9), fact_publication_aggregated AS (SELECT conformed_person.gender AS gender_21021, grouping(conformed_person.gender) AS g_gender_21021, conformed_person.gender_sort_order AS gender_21021_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_21021_gender_sort_order, conformed_person.first_nationality AS first_nationality_21041, grouping(conformed_person.first_nationality) AS g_first_nationality_21041, NULL::bigint AS "col0", NULL::bigint AS "col1", COUNT(DISTINCT (fact_publication.publication_id)) AS "col2" FROM presentation.fact_publication JOIN presentation.dim_person_researcher AS conformed_person ON fact_publication.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order, conformed_person.first_nationality), (conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order, first_nationality_21041) SELECT gender, gender_sort_order, first_nationality, SUM(col0) AS col0, SUM(col1) AS col1, SUM(col2) AS col2 FROM (SELECT gender_3 AS gender, g_gender_3 AS g_gender, gender_3_gender_sort_order AS gender_sort_order, g_gender_3_gender_sort_order AS g_gender_sort_order, first_nationality_142 AS first_nationality, g_first_nationality_142 AS g_first_nationality, col0, col1, col2 FROM fact_application_aggregated UNION ALL SELECT gender_6 AS gender, g_gender_6 AS g_gender, gender_6_gender_sort_order AS gender_sort_order, g_gender_6_gender_sort_order AS g_gender_sort_order, first_nationality_9 AS first_nationality, g_first_nationality_9 AS g_first_nationality, col0, col1, col2 FROM fact_doctoral_program_aggregated UNION ALL SELECT gender_21021 AS gender, g_gender_21021 AS g_gender, gender_21021_gender_sort_order AS gender_sort_order, g_gender_21021_gender_sort_order AS g_gender_sort_order, first_nationality_21041 AS first_nationality, g_first_nationality_21041 AS g_first_nationality, col0, col1, col2 FROM fact_publication_aggregated) x GROUP BY gender, g_gender, gender_sort_order, g_gender_sort_order, first_nationality, g_first_nationality """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesOneConformedTopAttributeOneConformedLeftAttributeUnionJoin() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:142" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_doctoral_program:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_doctoral_program:3" } ], "measureIds": [ "res_doctoral_program:57" ] } ], "topDimensionAttributeIds": [ "app_basic:3" ] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT conformed_person.first_nationality AS first_nationality_142, grouping(conformed_person.first_nationality) AS g_first_nationality_142, COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.gender = 'männlich') AS "col0", NULL::bigint AS "col1", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.gender = 'weiblich') AS "col2", NULL::bigint AS "col3", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.gender = 'divers') AS "col4", NULL::bigint AS "col5", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.gender = 'undefiniert / k.A.') AS "col6", NULL::bigint AS "col7" FROM presentation.fact_application JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.first_nationality), ()) ORDER BY first_nationality_142), fact_doctoral_program_aggregated AS (SELECT conformed_person.first_nationality AS first_nationality_9, grouping(conformed_person.first_nationality) AS g_first_nationality_9, NULL::bigint AS "col0", COUNT(DISTINCT fact_doctoral_program.doctoral_candidate_person_id) FILTER ( WHERE conformed_person.gender = 'männlich') AS "col1", NULL::bigint AS "col2", COUNT(DISTINCT fact_doctoral_program.doctoral_candidate_person_id) FILTER ( WHERE conformed_person.gender = 'weiblich') AS "col3", NULL::bigint AS "col4", COUNT(DISTINCT fact_doctoral_program.doctoral_candidate_person_id) FILTER ( WHERE conformed_person.gender = 'divers') AS "col5", NULL::bigint AS "col6", COUNT(DISTINCT fact_doctoral_program.doctoral_candidate_person_id) FILTER ( WHERE conformed_person.gender = 'undefiniert / k.A.') AS "col7" FROM presentation.fact_doctoral_program JOIN presentation.dim_person_doctoral AS conformed_person ON fact_doctoral_program.doctoral_candidate_person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.first_nationality), ()) ORDER BY first_nationality_9) SELECT first_nationality, SUM(col0) AS col0, SUM(col1) AS col1, SUM(col2) AS col2, SUM(col3) AS col3, SUM(col4) AS col4, SUM(col5) AS col5, SUM(col6) AS col6, SUM(col7) AS col7 FROM (SELECT first_nationality_142 AS first_nationality, g_first_nationality_142 AS g_first_nationality, col0, col1, col2, col3, col4, col5, col6, col7 FROM fact_application_aggregated UNION ALL SELECT first_nationality_9 AS first_nationality, g_first_nationality_9 AS g_first_nationality, col0, col1, col2, col3, col4, col5, col6, col7 FROM fact_doctoral_program_aggregated) x GROUP BY first_nationality, g_first_nationality """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesOneConformedTopAttributeOneConformedLeftAttributeLeftJoin() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:142" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_doctoral_program:1", "join": "left", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_doctoral_program:3" } ], "measureIds": [ "res_doctoral_program:57" ] } ], "topDimensionAttributeIds": [ "app_basic:3" ] } """; String expectedSql = """ SELECT conformed_person.first_nationality AS first_nationality_142, COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.gender = 'n. v.') AS "col0", COUNT(DISTINCT fact_doctoral_program.doctoral_candidate_person_id) FILTER ( WHERE conformed_person.gender = 'n. v.') AS "col1", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.gender = 'männlich') AS "col2", COUNT(DISTINCT fact_doctoral_program.doctoral_candidate_person_id) FILTER ( WHERE conformed_person.gender = 'männlich') AS "col3", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.gender = 'weiblich') AS "col4", COUNT(DISTINCT fact_doctoral_program.doctoral_candidate_person_id) FILTER ( WHERE conformed_person.gender = 'weiblich') AS "col5", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.gender = 'divers') AS "col6", COUNT(DISTINCT fact_doctoral_program.doctoral_candidate_person_id) FILTER ( WHERE conformed_person.gender = 'divers') AS "col7", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.gender = 'undefiniert / k.A.') AS "col8", COUNT(DISTINCT fact_doctoral_program.doctoral_candidate_person_id) FILTER ( WHERE conformed_person.gender = 'undefiniert / k.A.') AS "col9" FROM presentation.fact_application LEFT JOIN (SELECT DISTINCT doctoral_candidate_person_id FROM presentation.fact_doctoral_program) AS fact_doctoral_program ON fact_doctoral_program.doctoral_candidate_person_id = fact_application.person_id JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.first_nationality), ()) ORDER BY first_nationality_142 """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesOneConformedAttributeLeftJoin() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:3" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_doctoral_program:1", "join": "left", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_doctoral_program:3" } ], "measureIds": [ "res_doctoral_program:56" ] } ], "topDimensionAttributeIds": [] } """ ; String expectedSql = """ SELECT conformed_person.gender AS gender_3, conformed_person.gender_sort_order AS gender_3_gender_sort_order, COUNT(distinct(fact_application.person_id)) AS "col0", COUNT(distinct(fact_doctoral_program.doctoral_program_id)) AS "col1" FROM presentation.fact_application LEFT JOIN (SELECT DISTINCT doctoral_candidate_person_id, doctoral_program_id FROM presentation.fact_doctoral_program) AS fact_doctoral_program ON fact_doctoral_program.doctoral_candidate_person_id = fact_application.person_id JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void threeFactTablesOneConformedAttributeOneLeftJoinOneunion() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:3" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_doctoral_program:1", "join": "left", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_doctoral_program:3" } ], "measureIds": [ "res_doctoral_program:56" ] }, { "factId": "res_pub:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_pub:21020" } ], "measureIds": [ "res_pub:21037" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT conformed_person.gender AS gender_3, grouping(conformed_person.gender) AS g_gender_3, conformed_person.gender_sort_order AS gender_3_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_3_gender_sort_order, COUNT(distinct(fact_application.person_id)) AS "col0", COUNT(distinct(fact_doctoral_program.doctoral_program_id)) AS "col1", NULL::bigint AS "col2" FROM presentation.fact_application LEFT JOIN (SELECT DISTINCT doctoral_candidate_person_id, doctoral_program_id FROM presentation.fact_doctoral_program) AS fact_doctoral_program ON fact_doctoral_program.doctoral_candidate_person_id = fact_application.person_id JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order), fact_publication_aggregated AS (SELECT conformed_person.gender AS gender_21021, grouping(conformed_person.gender) AS g_gender_21021, conformed_person.gender_sort_order AS gender_21021_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_21021_gender_sort_order, NULL::bigint AS "col0", NULL::bigint AS "col1", COUNT(distinct(fact_publication.publication_id)) AS "col2" FROM presentation.fact_publication JOIN presentation.dim_person_researcher AS conformed_person ON fact_publication.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order) SELECT gender, gender_sort_order, SUM(col0) AS col0, SUM(col1) AS col1, SUM(col2) AS col2 FROM (SELECT gender_3 AS gender, g_gender_3 AS g_gender, gender_3_gender_sort_order AS gender_sort_order, g_gender_3_gender_sort_order AS g_gender_sort_order, col0, col1, col2 FROM fact_application_aggregated UNION ALL SELECT gender_21021 AS gender, g_gender_21021 AS g_gender, gender_21021_gender_sort_order AS gender_sort_order, g_gender_21021_gender_sort_order AS g_gender_sort_order, col0, col1, col2 FROM fact_publication_aggregated) x GROUP BY gender, g_gender, gender_sort_order, g_gender_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesTwoConformedAttributesUnionJoin() { String json = """ { "factTableId": "res_nom:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "res_nom:5", "res_nom:7" ], "measureIds": [ "res_nom:17" ], "secondaryFacttables": [ { "factId": "res_patent:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "res_nom:4", "secondaryRolePlayingDimensionId": "res_patent:10" } ], "measureIds": [ "res_patent:28" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_prize_aggregated AS (SELECT nomination_date.year_actual AS year_actual_5, grouping(nomination_date.year_actual) AS g_year_actual_5, nomination_date.year_actual_sort_order AS year_actual_5_year_actual_sort_order, grouping(nomination_date.year_actual_sort_order) AS g_year_actual_5_year_actual_sort_order, awardee.gender AS gender_7, grouping(awardee.gender) AS g_gender_7, awardee.gender_sort_order AS gender_7_gender_sort_order, grouping(awardee.gender_sort_order) AS g_gender_7_gender_sort_order, COUNT(DISTINCT (fact_prize.nomination_id)) AS "col0", NULL::bigint AS "col1" FROM presentation.fact_prize JOIN presentation.dim_person_researcher AS awardee ON fact_prize.person_id = awardee.id AND awardee.is_current = TRUE JOIN presentation.dim_date AS nomination_date ON fact_prize.nomination_date_id = nomination_date.id GROUP BY GROUPING SETS ((nomination_date.year_actual, nomination_date.year_actual_sort_order, awardee.gender, awardee.gender_sort_order), (nomination_date.year_actual, nomination_date.year_actual_sort_order), ()) ORDER BY nomination_date.year_actual_sort_order, awardee.gender_sort_order), fact_patent_aggregated AS (SELECT date_registration.year_actual AS year_actual_11, grouping(date_registration.year_actual) AS g_year_actual_11, date_registration.year_actual_sort_order AS year_actual_11_year_actual_sort_order, grouping(date_registration.year_actual_sort_order) AS g_year_actual_11_year_actual_sort_order, NULL::text AS gender_7, 1 AS g_gender_7, NULL::bigint AS gender_7_gender_sort_order, 1 AS g_gender_7_gender_sort_order, NULL::bigint AS "col0", COUNT(DISTINCT (fact_patent.id)) AS "col1" FROM presentation.fact_patent JOIN presentation.dim_date AS date_registration ON fact_patent.registration_date_id = date_registration.id GROUP BY GROUPING SETS ((date_registration.year_actual, date_registration.year_actual_sort_order), ()) ORDER BY date_registration.year_actual_sort_order) SELECT year_actual, year_actual_sort_order, gender, gender_sort_order, SUM(col0) AS col0, SUM(col1) AS col1 FROM (SELECT year_actual_11 AS year_actual, g_year_actual_11 AS g_year_actual, year_actual_11_year_actual_sort_order AS year_actual_sort_order, g_year_actual_11_year_actual_sort_order AS g_year_actual_sort_order, gender_7 AS gender, g_gender_7 AS g_gender, gender_7_gender_sort_order AS gender_sort_order, g_gender_7_gender_sort_order AS g_gender_sort_order, col0, col1 FROM fact_patent_aggregated UNION ALL SELECT year_actual_5 AS year_actual, g_year_actual_5 AS g_year_actual, year_actual_5_year_actual_sort_order AS year_actual_sort_order, g_year_actual_5_year_actual_sort_order AS g_year_actual_sort_order, gender_7 AS gender, g_gender_7 AS g_gender, gender_7_gender_sort_order AS gender_sort_order, g_gender_7_gender_sort_order AS g_gender_sort_order, col0, col1 FROM fact_prize_aggregated) x GROUP BY year_actual, g_year_actual, year_actual_sort_order, g_year_actual_sort_order, gender, g_gender, gender_sort_order, g_gender_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesWithFilterUnionJoin() { String json = """ { "factTableId": "app_basic:1", "filters": [ { "dimensionAttributeId": "app_basic:3", "filterValues": [ "männlich" ] } ], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:3" ], "measureIds": [ "app_basic:82" ], "secondaryFacttables": [ { "factId": "res_habilitation:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_habilitation:3" } ], "measureIds": [ "res_habilitation:45" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT conformed_person.gender AS gender_3, grouping(conformed_person.gender) AS g_gender_3, conformed_person.gender_sort_order AS gender_3_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_3_gender_sort_order, COUNT(fact_application.requestsubject_id) AS "col0", NULL::bigint AS "col1" FROM presentation.fact_application JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE WHERE conformed_person.gender IN ('männlich') GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order), fact_habilitation_aggregated AS (SELECT conformed_person.gender AS gender_6, grouping(conformed_person.gender) AS g_gender_6, conformed_person.gender_sort_order AS gender_6_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_6_gender_sort_order, NULL::bigint AS "col0", COUNT(distinct(fact_habilitation.person_id)) AS "col1" FROM presentation.fact_habilitation JOIN presentation.dim_person_doctoral AS conformed_person ON fact_habilitation.person_id = conformed_person.id AND conformed_person.is_current = TRUE WHERE conformed_person.gender IN ('männlich') GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order) SELECT gender, gender_sort_order, SUM(col0) AS col0, SUM(col1) AS col1 FROM (SELECT gender_3 AS gender, g_gender_3 AS g_gender, gender_3_gender_sort_order AS gender_sort_order, g_gender_3_gender_sort_order AS g_gender_sort_order, col0, col1 FROM fact_application_aggregated UNION ALL SELECT gender_6 AS gender, g_gender_6 AS g_gender, gender_6_gender_sort_order AS gender_sort_order, g_gender_6_gender_sort_order AS g_gender_sort_order, col0, col1 FROM fact_habilitation_aggregated) x GROUP BY gender, g_gender, gender_sort_order, g_gender_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesWithSortOrderColumnAsNullAttribute() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:6" ], "measureIds": [ "app_basic:82" ], "secondaryFacttables": [ { "factId": "res_habilitation:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_habilitation:3" } ], "measureIds": [ "res_habilitation:45" ] } ], "topDimensionAttributeIds": [] } """ ; String expectedSql = """ WITH fact_application_aggregated AS (SELECT age_semester_start.age AS age_6, grouping(age_semester_start.age) AS g_age_6, age_semester_start.id AS age_6_id, grouping(age_semester_start.id) AS g_age_6_id, COUNT(fact_application.requestsubject_id) AS "col0", NULL::bigint AS "col1" FROM presentation.fact_application JOIN presentation.dim_age AS age_semester_start ON fact_application.age_semester_start_id = age_semester_start.id GROUP BY GROUPING SETS ((age_semester_start.age, age_semester_start.id), ()) ORDER BY age_semester_start.id), fact_habilitation_aggregated AS (SELECT NULL::text AS age_6, 1 AS g_age_6, NULL::bigint AS age_6_id, 1 AS g_age_6_id, NULL::bigint AS "col0", NULL::bigint AS "col1" FROM presentation.fact_habilitation GROUP BY GROUPING SETS (())) SELECT age, id, SUM(col0) AS col0, SUM(col1) AS col1 FROM (SELECT age_6 AS age, g_age_6 AS g_age, age_6_id AS id, g_age_6_id AS g_id, col0, col1 FROM fact_application_aggregated UNION ALL SELECT age_6 AS age, g_age_6 AS g_age, age_6_id AS id, g_age_6_id AS g_id, col0, col1 FROM fact_habilitation_aggregated) x GROUP BY age, g_age, id, g_id """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesWithFirstAttributeNullAttributeAndFollowingNonNullAttributes() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:6", "app_basic:3" ], "measureIds": [ "app_basic:82" ], "secondaryFacttables": [ { "factId": "res_habilitation:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_habilitation:3" } ], "measureIds": [ "res_habilitation:45" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT age_semester_start.age AS age_6, grouping(age_semester_start.age) AS g_age_6, age_semester_start.id AS age_6_id, grouping(age_semester_start.id) AS g_age_6_id, conformed_person.gender AS gender_3, grouping(conformed_person.gender) AS g_gender_3, conformed_person.gender_sort_order AS gender_3_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_3_gender_sort_order, COUNT(fact_application.requestsubject_id) AS "col0", NULL::bigint AS "col1" FROM presentation.fact_application JOIN presentation.dim_age AS age_semester_start ON fact_application.age_semester_start_id = age_semester_start.id JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((age_semester_start.age, age_semester_start.id, conformed_person.gender, conformed_person.gender_sort_order), (age_semester_start.age, age_semester_start.id), ()) ORDER BY age_semester_start.id, conformed_person.gender_sort_order), fact_habilitation_aggregated AS (SELECT NULL::text AS age_6, 1 AS g_age_6, NULL::bigint AS age_6_id, 1 AS g_age_6_id, NULL::text AS gender_6, 1 AS g_gender_6, NULL::bigint AS gender_6_gender_sort_order, 1 AS g_gender_6_gender_sort_order, NULL::bigint AS "col0", NULL::bigint AS "col1" FROM presentation.fact_habilitation GROUP BY GROUPING SETS (())) SELECT age, id, gender, gender_sort_order, SUM(col0) AS col0, SUM(col1) AS col1 FROM (SELECT age_6 AS age, g_age_6 AS g_age, age_6_id AS id, g_age_6_id AS g_id, gender_3 AS gender, g_gender_3 AS g_gender, gender_3_gender_sort_order AS gender_sort_order, g_gender_3_gender_sort_order AS g_gender_sort_order, col0, col1 FROM fact_application_aggregated UNION ALL SELECT age_6 AS age, g_age_6 AS g_age, age_6_id AS id, g_age_6_id AS g_id, gender_6 AS gender, g_gender_6 AS g_gender, gender_6_gender_sort_order AS gender_sort_order, g_gender_6_gender_sort_order AS g_gender_sort_order, col0, col1 FROM fact_habilitation_aggregated) x GROUP BY age, g_age, id, g_id, gender, g_gender, gender_sort_order, g_gender_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesWithOneConformedRowAttributeAndOneAsymmetricColumnAttributeOuterJoin() { String json = """ { "factTableId": "res_pub:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "res_pub:38" ], "measureIds": [ "res_pub:21037" ], "secondaryFacttables": [ { "factId": "res_nom:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "res_pub:37", "secondaryRolePlayingDimensionId": "res_nom:4" } ], "measureIds": [ "res_nom:17" ] } ], "topDimensionAttributeIds": [ "res_pub:21048" ] } """; String expectedSql = """ WITH fact_publication_aggregated AS (SELECT date.year_actual AS year_actual_38, grouping(date.year_actual) AS g_year_actual_38, date.year_actual_sort_order AS year_actual_38_year_actual_sort_order, grouping(date.year_actual_sort_order) AS g_year_actual_38_year_actual_sort_order, COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_publication.peer_reviewed = 'n. v.') AS "col0", NULL::bigint AS "col1", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_publication.peer_reviewed = 'ja') AS "col2", NULL::bigint AS "col3", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_publication.peer_reviewed = 'nein') AS "col4", NULL::bigint AS "col5" FROM presentation.fact_publication JOIN presentation.dim_date AS date ON fact_publication.publication_date_id = date.id JOIN presentation.dim_publication AS conformed_publication ON fact_publication.publication_id = conformed_publication.id GROUP BY GROUPING SETS ((date.year_actual, date.year_actual_sort_order), ()) ORDER BY date.year_actual_sort_order), fact_prize_aggregated AS (SELECT nomination_date.year_actual AS year_actual_5, grouping(nomination_date.year_actual) AS g_year_actual_5, nomination_date.year_actual_sort_order AS year_actual_5_year_actual_sort_order, grouping(nomination_date.year_actual_sort_order) AS g_year_actual_5_year_actual_sort_order, NULL::bigint AS "col0", NULL::bigint AS "col1", NULL::bigint AS "col2", NULL::bigint AS "col3", NULL::bigint AS "col4", NULL::bigint AS "col5" FROM presentation.fact_prize JOIN presentation.dim_date AS nomination_date ON fact_prize.nomination_date_id = nomination_date.id GROUP BY GROUPING SETS ((nomination_date.year_actual, nomination_date.year_actual_sort_order), ()) ORDER BY nomination_date.year_actual_sort_order) SELECT year_actual, year_actual_sort_order, SUM(col0) AS col0, SUM(col1) AS col1, SUM(col2) AS col2, SUM(col3) AS col3, SUM(col4) AS col4, SUM(col5) AS col5 FROM (SELECT year_actual_38 AS year_actual, g_year_actual_38 AS g_year_actual, year_actual_38_year_actual_sort_order AS year_actual_sort_order, g_year_actual_38_year_actual_sort_order AS g_year_actual_sort_order, col0, col1, col2, col3, col4, col5 FROM fact_publication_aggregated UNION ALL SELECT year_actual_5 AS year_actual, g_year_actual_5 AS g_year_actual, year_actual_5_year_actual_sort_order AS year_actual_sort_order, g_year_actual_5_year_actual_sort_order AS g_year_actual_sort_order, col0, col1, col2, col3, col4, col5 FROM fact_prize_aggregated) x GROUP BY year_actual, g_year_actual, year_actual_sort_order, g_year_actual_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesWithTopAttributesWithDifferentValuesOuterJoin() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:3" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_pub:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_pub:21020" } ], "measureIds": [ "res_pub:21037" ] } ], "topDimensionAttributeIds": [ "app_basic:144" ] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT conformed_person.gender AS gender_3, grouping(conformed_person.gender) AS g_gender_3, conformed_person.gender_sort_order AS gender_3_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_3_gender_sort_order, COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'n. v.') AS "col0", NULL::bigint AS "col1", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'Ja') AS "col2", NULL::bigint AS "col3", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'Nein') AS "col4", NULL::bigint AS "col5" FROM presentation.fact_application JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order), fact_publication_aggregated AS (SELECT conformed_person.gender AS gender_21021, grouping(conformed_person.gender) AS g_gender_21021, conformed_person.gender_sort_order AS gender_21021_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_21021_gender_sort_order, NULL::bigint AS "col0", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'n. v.') AS "col1", NULL::bigint AS "col2", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'Ja') AS "col3", NULL::bigint AS "col4", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'Nein') AS "col5" FROM presentation.fact_publication JOIN presentation.dim_person_researcher AS conformed_person ON fact_publication.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order) SELECT gender, gender_sort_order, SUM(col0) AS col0, SUM(col1) AS col1, SUM(col2) AS col2, SUM(col3) AS col3, SUM(col4) AS col4, SUM(col5) AS col5 FROM (SELECT gender_3 AS gender, g_gender_3 AS g_gender, gender_3_gender_sort_order AS gender_sort_order, g_gender_3_gender_sort_order AS g_gender_sort_order, col0, col1, col2, col3, col4, col5 FROM fact_application_aggregated UNION ALL SELECT gender_21021 AS gender, g_gender_21021 AS g_gender, gender_21021_gender_sort_order AS gender_sort_order, g_gender_21021_gender_sort_order AS g_gender_sort_order, col0, col1, col2, col3, col4, col5 FROM fact_publication_aggregated) x GROUP BY gender, g_gender, gender_sort_order, g_gender_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesTwoFilterForTopAndRowAttributes() { String json = """ { "factTableId": "app_basic:1", "filters": [ { "dimensionAttributeId": "app_basic:3", "filterValues": [ "männlich", "weiblich" ] }, { "dimensionAttributeId": "app_basic:144", "filterValues": [ "Ja", "Nein" ] } ], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:3" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_pub:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_pub:21020" } ], "measureIds": [ "res_pub:21037" ] } ], "topDimensionAttributeIds": [ "app_basic:144" ] } """ ; String expectedSql = """ WITH fact_application_aggregated AS (SELECT conformed_person.gender AS gender_3, grouping(conformed_person.gender) AS g_gender_3, conformed_person.gender_sort_order AS gender_3_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_3_gender_sort_order, COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'Ja') AS "col0", NULL::bigint AS "col1", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'Nein') AS "col2", NULL::bigint AS "col3" FROM presentation.fact_application JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE WHERE conformed_person.gender IN ('männlich', 'weiblich') AND conformed_person.german IN ('Ja', 'Nein') GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order), fact_publication_aggregated AS (SELECT conformed_person.gender AS gender_21021, grouping(conformed_person.gender) AS g_gender_21021, conformed_person.gender_sort_order AS gender_21021_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_21021_gender_sort_order, NULL::bigint AS "col0", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'Ja') AS "col1", NULL::bigint AS "col2", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'Nein') AS "col3" FROM presentation.fact_publication JOIN presentation.dim_person_researcher AS conformed_person ON fact_publication.person_id = conformed_person.id AND conformed_person.is_current = TRUE WHERE conformed_person.gender IN ('männlich', 'weiblich') AND conformed_person.german IN ('Ja', 'Nein') GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order) SELECT gender, gender_sort_order, SUM(col0) AS col0, SUM(col1) AS col1, SUM(col2) AS col2, SUM(col3) AS col3 FROM (SELECT gender_3 AS gender, g_gender_3 AS g_gender, gender_3_gender_sort_order AS gender_sort_order, g_gender_3_gender_sort_order AS g_gender_sort_order, col0, col1, col2, col3 FROM fact_application_aggregated UNION ALL SELECT gender_21021 AS gender, g_gender_21021 AS g_gender, gender_21021_gender_sort_order AS gender_sort_order, g_gender_21021_gender_sort_order AS g_gender_sort_order, col0, col1, col2, col3 FROM fact_publication_aggregated) x GROUP BY gender, g_gender, gender_sort_order, g_gender_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void totalsColumnTwoFactTablesOneTopOneLeftAttribute() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:3" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_pub:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_pub:21020" } ], "measureIds": [ "res_pub:21037" ] } ], "topDimensionAttributeIds": [ "app_basic:144" ] } """ ; String expectedSql = """ WITH fact_application_aggregated AS (SELECT conformed_person.gender AS gender_3, grouping(conformed_person.gender) AS g_gender_3, conformed_person.gender_sort_order AS gender_3_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_3_gender_sort_order, COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'n. v.') AS "col0", NULL::bigint AS "col1", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'Ja') AS "col2", NULL::bigint AS "col3", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'Nein') AS "col4", NULL::bigint AS "col5" FROM presentation.fact_application JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order), fact_publication_aggregated AS (SELECT conformed_person.gender AS gender_21021, grouping(conformed_person.gender) AS g_gender_21021, conformed_person.gender_sort_order AS gender_21021_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_21021_gender_sort_order, NULL::bigint AS "col0", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'n. v.') AS "col1", NULL::bigint AS "col2", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'Ja') AS "col3", NULL::bigint AS "col4", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'Nein') AS "col5" FROM presentation.fact_publication JOIN presentation.dim_person_researcher AS conformed_person ON fact_publication.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order) SELECT gender, gender_sort_order, SUM(col0) AS col0, SUM(col1) AS col1, SUM(col2) AS col2, SUM(col3) AS col3, SUM(col4) AS col4, SUM(col5) AS col5 FROM (SELECT gender_3 AS gender, g_gender_3 AS g_gender, gender_3_gender_sort_order AS gender_sort_order, g_gender_3_gender_sort_order AS g_gender_sort_order, col0, col1, col2, col3, col4, col5 FROM fact_application_aggregated UNION ALL SELECT gender_21021 AS gender, g_gender_21021 AS g_gender, gender_21021_gender_sort_order AS gender_sort_order, g_gender_21021_gender_sort_order AS g_gender_sort_order, col0, col1, col2, col3, col4, col5 FROM fact_publication_aggregated) x GROUP BY gender, g_gender, gender_sort_order, g_gender_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void twoFactTablesWithOneSymmetricOneAsymmetricLeftAttributeOneConformedTopAttribute() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:3", "app_basic:12" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_pub:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_pub:21020" } ], "measureIds": [ "res_pub:21037" ] } ], "topDimensionAttributeIds": [ "app_basic:144" ] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT conformed_person.gender AS gender_3, grouping(conformed_person.gender) AS g_gender_3, conformed_person.gender_sort_order AS gender_3_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_3_gender_sort_order, conformed_location.country AS country_12, grouping(conformed_location.country) AS g_country_12, COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'n. v.') AS "col0", NULL::bigint AS "col1", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'Ja') AS "col2", NULL::bigint AS "col3", COUNT(DISTINCT fact_application.person_id) FILTER ( WHERE conformed_person.german = 'Nein') AS "col4", NULL::bigint AS "col5" FROM presentation.fact_application JOIN presentation.dim_person_applicant AS conformed_person ON fact_application.person_id = conformed_person.id AND conformed_person.is_current = TRUE JOIN presentation.dim_location AS conformed_location ON fact_application.location_lid = conformed_location.lid AND conformed_location.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order, conformed_location.country), (conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order, country_12), fact_publication_aggregated AS (SELECT conformed_person.gender AS gender_21021, grouping(conformed_person.gender) AS g_gender_21021, conformed_person.gender_sort_order AS gender_21021_gender_sort_order, grouping(conformed_person.gender_sort_order) AS g_gender_21021_gender_sort_order, NULL::text AS country_12, 1 AS g_country_12, NULL::bigint AS "col0", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'n. v.') AS "col1", NULL::bigint AS "col2", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'Ja') AS "col3", NULL::bigint AS "col4", COUNT(DISTINCT fact_publication.publication_id) FILTER ( WHERE conformed_person.german = 'Nein') AS "col5" FROM presentation.fact_publication JOIN presentation.dim_person_researcher AS conformed_person ON fact_publication.person_id = conformed_person.id AND conformed_person.is_current = TRUE GROUP BY GROUPING SETS ((conformed_person.gender, conformed_person.gender_sort_order), ()) ORDER BY conformed_person.gender_sort_order) SELECT gender, gender_sort_order, country, SUM(col0) AS col0, SUM(col1) AS col1, SUM(col2) AS col2, SUM(col3) AS col3, SUM(col4) AS col4, SUM(col5) AS col5 FROM (SELECT gender_3 AS gender, g_gender_3 AS g_gender, gender_3_gender_sort_order AS gender_sort_order, g_gender_3_gender_sort_order AS g_gender_sort_order, country_12 AS country, g_country_12 AS g_country, col0, col1, col2, col3, col4, col5 FROM fact_application_aggregated UNION ALL SELECT gender_21021 AS gender, g_gender_21021 AS g_gender, gender_21021_gender_sort_order AS gender_sort_order, g_gender_21021_gender_sort_order AS g_gender_sort_order, country_12 AS country, g_country_12 AS g_country, col0, col1, col2, col3, col4, col5 FROM fact_publication_aggregated) x GROUP BY gender, g_gender, gender_sort_order, g_gender_sort_order, country, g_country """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void testConformedWithHiddenEmptyColumns() throws Exception { String json = """ { "factTableId": "res_nom:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "res_nom:79102", "res_nom:79101" ], "measureIds": [ "res_nom:17" ], "secondaryFacttables": [ { "factId": "res_infra:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "res_nom:4", "secondaryRolePlayingDimensionId": "res_infra:34" }, { "leadingRolePlayingDimensionId": "res_nom:79090", "secondaryRolePlayingDimensionId": "res_infra:79074" } ], "measureIds": [ "res_infra:16" ] } ], "topDimensionAttributeIds": [ "res_nom:5" ] } """; String expectedColumnsJson = """ { "columns": [ { "field": "res_nom:79102", "header": "Typ" }, { "field": "res_nom:79101", "header": "Name Organisationseinheit" }, { "field": "conf:49: conf:50|n. v. || Kennzahl|res_nom:17", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung|n. v. || Kennzahl|Preisanerkennungen [Anzahl] (PR)" }, { "field": "conf:49: conf:50|n. v. || Kennzahl|res_infra:16", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung|n. v. || Kennzahl|Forschungsinfrastruktur [Anzahl] (FI)" }, { "field": "conf:49: conf:50|2023 || Kennzahl|res_nom:17", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung|2023 || Kennzahl|Preisanerkennungen [Anzahl] (PR)" }, { "field": "conf:49: conf:50|2023 || Kennzahl|res_infra:16", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung|2023 || Kennzahl|Forschungsinfrastruktur [Anzahl] (FI)" }, { "field": "conf:49: conf:50|2024 || Kennzahl|res_nom:17", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung|2024 || Kennzahl|Preisanerkennungen [Anzahl] (PR)" }, { "field": "conf:49: conf:50|2024 || Kennzahl|res_infra:16", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung|2024 || Kennzahl|Forschungsinfrastruktur [Anzahl] (FI)" }, { "field": "conf:49: conf:50|2025 || Kennzahl|res_nom:17", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung|2025 || Kennzahl|Preisanerkennungen [Anzahl] (PR)" }, { "field": "conf:49: conf:50|2025 || Kennzahl|res_infra:16", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung|2025 || Kennzahl|Forschungsinfrastruktur [Anzahl] (FI)" }, { "field": "conf:49: conf:50|2026 || Kennzahl|res_nom:17", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung|2026 || Kennzahl|Preisanerkennungen [Anzahl] (PR)" }, { "field": "conf:49: conf:50|2026 || Kennzahl|res_infra:16", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung|2026 || Kennzahl|Forschungsinfrastruktur [Anzahl] (FI)" }, { "field": "conf:49: conf:50|Gesamt || Kennzahl|res_nom:17", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung| Gesamt || Kennzahl|Preisanerkennungen [Anzahl] (PR)" }, { "field": "conf:49: conf:50|Gesamt || Kennzahl|res_infra:16", "header": "Jahr der Auszeichnung: Jahr der Auszeichnung| Gesamt || Kennzahl|Forschungsinfrastruktur [Anzahl] (FI)" } ] } """; List actualColumns = getResultColumnsFromReport(json, dbAdapter, biAnalysisManager); List expectedColumns = BIATestUtils.parseColumns(expectedColumnsJson); assertEquals("Column list size differs", expectedColumns.size(), actualColumns.size()); for (int i = 0; i < expectedColumns.size(); i++) { Column expected = expectedColumns.get(i); Column actual = actualColumns.get(i); assertEquals("Field differs at index " + i, expected.field, actual.field); assertEquals("Header differs at index " + i, expected.header, actual.header); } } @Test public void testCriteriaGroupWithUnion() { String json = """ { "factTableId": "app_basic:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "app_basic:12393" ], "measureIds": [ "app_basic:80" ], "secondaryFacttables": [ { "factId": "res_doctoral_program:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "app_basic:2", "secondaryRolePlayingDimensionId": "res_doctoral_program:3" } ], "measureIds": [ "res_doctoral_program:57" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_application_aggregated AS (SELECT age_semester_start.age_category_his AS age_category_his_12393, grouping(age_semester_start.age_category_his) AS g_age_category_his_12393, age_semester_start.age_category_his_sort_order AS age_category_his_12393_age_category_his_sort_order, grouping(age_semester_start.age_category_his_sort_order) AS g_age_category_his_12393_age_category_his_sort_order, COUNT(DISTINCT (fact_application.person_id)) AS "col0", NULL::bigint AS "col1" FROM presentation.fact_application JOIN presentation.dim_age AS age_semester_start ON fact_application.age_semester_start_id = age_semester_start.id GROUP BY GROUPING SETS ((age_semester_start.age_category_his, age_semester_start.age_category_his_sort_order), ()) ORDER BY age_semester_start.age_category_his_sort_order), fact_doctoral_program_aggregated AS (SELECT NULL::text AS age_category_his_12393, 1 AS g_age_category_his_12393, NULL::bigint AS age_category_his_12393_age_category_his_sort_order, 1 AS g_age_category_his_12393_age_category_his_sort_order, NULL::bigint AS "col0", NULL::bigint AS "col1" FROM presentation.fact_doctoral_program GROUP BY GROUPING SETS (())) SELECT age_category_his, age_category_his_sort_order, SUM(col0) AS col0, SUM(col1) AS col1 FROM (SELECT age_category_his_12393 AS age_category_his, g_age_category_his_12393 AS g_age_category_his, age_category_his_12393_age_category_his_sort_order AS age_category_his_sort_order, g_age_category_his_12393_age_category_his_sort_order AS g_age_category_his_sort_order, col0, col1 FROM fact_application_aggregated UNION ALL SELECT age_category_his_12393 AS age_category_his, g_age_category_his_12393 AS g_age_category_his, age_category_his_12393_age_category_his_sort_order AS age_category_his_sort_order, g_age_category_his_12393_age_category_his_sort_order AS g_age_category_his_sort_order, col0, col1 FROM fact_doctoral_program_aggregated) x GROUP BY age_category_his, g_age_category_his, age_category_his_sort_order, g_age_category_his_sort_order """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void testWithFirstTwoLeftAttributesNonNullAndLastAttributeNull() { String json = """ { "factTableId": "res:66", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "res:79093", "res:619", "res:627" ], "measureIds": [ "res:104" ], "secondaryFacttables": [ { "factId": "res_pub:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "res:79091", "secondaryRolePlayingDimensionId": "res_pub:79096" }, { "leadingRolePlayingDimensionId": "res:618", "secondaryRolePlayingDimensionId": "res_pub:2" } ], "measureIds": [ "res_pub:21037" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_project_aggregated AS (SELECT orgunit_project_person_flat.orgunittype AS orgunittype_79093, grouping(orgunit_project_person_flat.orgunittype) AS g_orgunittype_79093, project_publication.title AS title_619, grouping(project_publication.title) AS g_title_619, project.project_name AS project_name_627, grouping(project.project_name) AS g_project_name_627, COUNT(DISTINCT (fact_project.project_id)) AS "col0", NULL::bigint AS "col1" FROM presentation.fact_project JOIN presentation.dim_orgunit_flat AS orgunit_project_person_flat ON fact_project.orgunit_project_person_lid = orgunit_project_person_flat.lid AND orgunit_project_person_flat.is_current = TRUE JOIN presentation.dim_project AS project ON fact_project.project_id = project.id JOIN presentation.dim_publication AS project_publication ON fact_project.publication_id = project_publication.id GROUP BY GROUPING SETS ((orgunit_project_person_flat.orgunittype, project_publication.title, project.project_name), (orgunit_project_person_flat.orgunittype, project_publication.title), (orgunit_project_person_flat.orgunittype), ()) ORDER BY orgunittype_79093, title_619, project_name_627), fact_publication_aggregated AS ( SELECT creator_orgunit_flat.orgunittype AS orgunittype_79098, grouping(creator_orgunit_flat.orgunittype) AS g_orgunittype_79098, conformed_publication.title AS title_21047, grouping(conformed_publication.title) AS g_title_21047, NULL::text AS project_name_627, 1 AS g_project_name_627, NULL::bigint AS "col0", COUNT(DISTINCT (fact_publication.publication_id)) AS "col1" FROM presentation.fact_publication JOIN presentation.dim_publication AS conformed_publication ON fact_publication.publication_id = conformed_publication.id JOIN presentation.dim_orgunit_flat AS creator_orgunit_flat ON fact_publication.creator_orgunit_lid = creator_orgunit_flat.lid AND creator_orgunit_flat.is_current = TRUE GROUP BY GROUPING SETS ((creator_orgunit_flat.orgunittype, conformed_publication.title), (creator_orgunit_flat.orgunittype), ()) ORDER BY orgunittype_79098, title_21047 ) SELECT orgunittype, title, project_name, SUM(col0) AS col0, SUM(col1) AS col1 FROM (SELECT orgunittype_79093 AS orgunittype, g_orgunittype_79093 AS g_orgunittype, title_619 AS title, g_title_619 AS g_title, project_name_627 AS project_name, g_project_name_627 AS g_project_name, col0, col1 FROM fact_project_aggregated UNION ALL SELECT orgunittype_79098 AS orgunittype, g_orgunittype_79098 AS g_orgunittype, title_21047 AS title, g_title_21047 AS g_title, project_name_627 AS project_name, g_project_name_627 AS g_project_name, col0, col1 FROM fact_publication_aggregated) x GROUP BY orgunittype, g_orgunittype, title, g_title, project_name, g_project_name """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } @Test public void testRightReplacementForUnion() { String json = """ { "factTableId": "res_pub:1", "filters": [], "hideEmptyColumns": false, "leftDimensionAttributeIds": [ "res_pub:79097" ], "measureIds": [ "res_pub:21037" ], "secondaryFacttables": [ { "factId": "res_nom:1", "join": "union", "joinCriterias": [ { "leadingRolePlayingDimensionId": "res_pub:79096", "secondaryRolePlayingDimensionId": "res_nom:79090" } ], "measureIds": [ "res_nom:17" ] } ], "topDimensionAttributeIds": [] } """; String expectedSql = """ WITH fact_publication_aggregated AS (SELECT creator_orgunit_flat.orgunit_name AS orgunit_name_79097, grouping(creator_orgunit_flat.orgunit_name) AS g_orgunit_name_79097, COUNT(DISTINCT (fact_publication.publication_id)) AS "col0", NULL::bigint AS "col1" FROM (SELECT * FROM presentation.fact_publication) AS fact_publication JOIN presentation.dim_orgunit_flat AS creator_orgunit_flat ON fact_publication.creator_orgunit_lid = creator_orgunit_flat.lid AND creator_orgunit_flat.is_current = TRUE GROUP BY GROUPING SETS ((creator_orgunit_flat.orgunit_name), ()) ORDER BY orgunit_name_79097), fact_prize_aggregated AS (SELECT orgunit_intern_flat.orgunit_name AS orgunit_name_79101, grouping(orgunit_intern_flat.orgunit_name) AS g_orgunit_name_79101, NULL::bigint AS "col0", COUNT(DISTINCT (fact_prize.nomination_id)) AS "col1" FROM (SELECT * FROM presentation.fact_prize) AS fact_prize JOIN presentation.dim_orgunit_flat AS orgunit_intern_flat ON fact_prize.orgunit_intern_lid = orgunit_intern_flat.lid AND orgunit_intern_flat.is_current = TRUE GROUP BY GROUPING SETS ((orgunit_intern_flat.orgunit_name), ()) ORDER BY orgunit_name_79101) SELECT orgunit_name, SUM(col0) AS col0, SUM(col1) AS col1 FROM (SELECT orgunit_name_79097 AS orgunit_name, g_orgunit_name_79097 AS g_orgunit_name, col0, col1 FROM fact_publication_aggregated UNION ALL SELECT orgunit_name_79101 AS orgunit_name, g_orgunit_name_79101 AS g_orgunit_name, col0, col1 FROM fact_prize_aggregated) x GROUP BY orgunit_name, g_orgunit_name """; String actualSqlParsed = getSqlFromReportDefinition(json, dbAdapter); actualSqlParsed = dbAdapter.applyAccessRestrictions(actualSqlParsed); String expectedSqlParsed = getParsedSqlFromString(expectedSql); assertEquals(expectedSqlParsed, actualSqlParsed); } }