diff --git a/src/adapter/postgres.ts b/src/adapter/postgres.ts index ad6d4285b0a03f710de503b2f7100c2940a5dfc4..b1156e8d6251ebdf501c2330f4aa466b5fe142fb 100644 --- a/src/adapter/postgres.ts +++ b/src/adapter/postgres.ts @@ -105,6 +105,16 @@ export class PostgresAdapter extends Adapter { } } + const blackList = view.dimensions.map((i) => i.name); + for (let i = 0; i < view.clauses.length; ++i) { + if (view.clauses[i].filters.length === 1) { + let filter = view.clauses[i].filters[0]; + if (filter.operator === FilterOperator.EQUAL) { + blackList.push(filter.target.name); + } + } + } + /* If there is more than one source of data (tables/views) a join is needed. @@ -244,8 +254,23 @@ export class PostgresAdapter extends Adapter { array of strings. */ const sorted = partialJoin.sort((a, b) => { - return this.compareKeys(a.keys, b.keys); + return this.compareKeys(a.keys, b.keys, blackList); }); + /* + SUPER WARNING: WHEN THE BLACK LIST IS USED THE VIEW IS + UNMATERIALIZEBLE, BUT THE QUERY CAN AGGREGATE THE VALUES + + The blackList is the array of dimensions of the query plus + the dimensions in filters using the equality operator. + In further coments is expained that the relation to make + a join must be one-to-one between the tables. + However and a dimension is choosed, a sub view is + created and if the relation is preserved in the sub view + the query can be agregated, but this view cannot be re-used + so it is unmaterializeble. + + The equality operator is the same as select one subview. + */ /* First of all, the remaining views are splited in segments. @@ -259,7 +284,7 @@ export class PostgresAdapter extends Adapter { const segment = [[sorted[0]]]; let segmentId = 0; for (let i = 1; i < sorted.length; ++i) { - if (this.compareKeys(sorted[i - 1].keys, sorted[i].keys) === 0) { + if (this.compareKeys(sorted[i - 1].keys, sorted[i].keys, blackList) === 0) { segment[segmentId].push(sorted[i]); } else { @@ -805,22 +830,28 @@ export class PostgresAdapter extends Adapter { } } - private compareKeys(a: Dimension[], b: Dimension[]): number { + private compareKeys(a: Dimension[], b: Dimension[], blackList: string[]): number { + /* + SUPER WARNING: WHEN THE BLACK LIST IS USED THE VIEW IS + UNMATERIALIZEBLE, BUT THE QUERY CAN AGGREGATE THE VALUES + */ + let c = a.filter((i) => !blackList.some((bad) => bad === i.name)); + let d = b.filter((i) => !blackList.some((bad) => bad === i.name)); let length = 0; - let res = a.length - b.length; - if (a.length < b.length) { - length = a.length; + let res = c.length - d.length; + if (c.length < d.length) { + length = c.length; } else { - length = b.length; + length = d.length; } for (let i = 0; i < length; ++i) { - if (a[i].name < b[i].name) { + if (c[i].name < d[i].name) { return -1; } - else if (a[i].name > b[i].name) { + else if (c[i].name > d[i].name) { return 1; } }