-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Adding support for having clause (#56)
* having support added * reverted test case changes * reusing traverse and filter * removed unneeded function * code refactor * bumped up versions * fixed test cases * fixed test cases * self review * added test case for having/where filter
- Loading branch information
1 parent
1dd17d4
commit db41f2b
Showing
13 changed files
with
406 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 75 additions & 26 deletions
101
meerkat-core/src/get-projection-clause/get-projection-clause.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,85 @@ | ||
import { TableSchema } from "../types/cube-types"; | ||
import { findInSchema } from "../utils/find-in-table-schema"; | ||
import { findInDimensionSchema, findInMeasureSchema } from "../utils/find-in-table-schema"; | ||
import { memberKeyToSafeKey } from "../utils/member-key-to-safe-key"; | ||
|
||
export const getMemberProjection = ({ key, tableSchema }: { | ||
key: string; | ||
tableSchema: TableSchema; | ||
}) => { | ||
// Find the table access key | ||
const measureWithoutTable = key.split('.')[1]; | ||
|
||
const foundMember = findInSchema(measureWithoutTable, tableSchema) | ||
if (!foundMember) { | ||
// If the selected member is not found in the table schema or if it is already selected, continue. | ||
return { | ||
sql: undefined, | ||
foundMember: undefined, | ||
aliasKey: undefined | ||
} | ||
|
||
export const getFilterMeasureProjection = ({ key, tableSchema, measures }: { | ||
key: string; | ||
tableSchema: TableSchema; | ||
measures: string[] | ||
}) => { | ||
const measureWithoutTable = key.split('.')[1]; | ||
const foundMember = findInMeasureSchema(measureWithoutTable, tableSchema); | ||
const isMeasure = measures.includes(key); | ||
if (!foundMember || isMeasure) { | ||
// If the selected member is not found in the table schema or if it is already selected, continue. | ||
// If the selected member is a measure, don't create an alias. Since measure computation is done in the outermost level of the query | ||
return { | ||
sql: undefined, | ||
foundMember: undefined, | ||
aliasKey: undefined | ||
} | ||
const aliasKey = memberKeyToSafeKey(key); | ||
// Add the alias key to the set. So we have a reference to all the previously selected members. | ||
return { sql: `${foundMember.sql} AS ${aliasKey}` , foundMember, aliasKey } | ||
} | ||
const aliasKey = memberKeyToSafeKey(key); | ||
return { sql: `${key} AS ${aliasKey}` , foundMember, aliasKey } | ||
} | ||
|
||
export const getDimensionProjection = ({ key, tableSchema }: { | ||
key: string; | ||
tableSchema: TableSchema; | ||
}) => { | ||
// Find the table access key | ||
const measureWithoutTable = key.split('.')[1]; | ||
|
||
export const getProjectionClause = (members: string[], tableSchema: TableSchema, aliasedColumnSet: Set<string>) => { | ||
return members.reduce((acc, member) => { | ||
const { sql: memberSql } = getMemberProjection({ key: member, tableSchema }) | ||
if (aliasedColumnSet.has(member)) { | ||
return acc | ||
const foundMember = findInDimensionSchema(measureWithoutTable, tableSchema) | ||
if (!foundMember) { | ||
// If the selected member is not found in the table schema or if it is already selected, continue. | ||
return { | ||
sql: undefined, | ||
foundMember: undefined, | ||
aliasKey: undefined | ||
} | ||
acc += `, ${memberSql}` | ||
} | ||
const aliasKey = memberKeyToSafeKey(key); | ||
// Add the alias key to the set. So we have a reference to all the previously selected members. | ||
return { sql: `${foundMember.sql} AS ${aliasKey}` , foundMember, aliasKey } | ||
} | ||
|
||
const aggregator = ({ | ||
member, | ||
aliasedColumnSet, | ||
acc, | ||
currentIndex, | ||
members, | ||
sql | ||
}: { | ||
member: string; | ||
aliasedColumnSet: Set<string>; | ||
acc: string; | ||
sql?: string; | ||
currentIndex: number, | ||
members: string[] | ||
}) => { | ||
if (aliasedColumnSet.has(member) || !sql) { | ||
return acc | ||
} | ||
aliasedColumnSet.add(member) | ||
acc += sql | ||
if (currentIndex !== members.length - 1) { | ||
acc += `, ` | ||
} | ||
return acc | ||
} | ||
|
||
|
||
export const getProjectionClause = (measures: string[], dimensions: string[], tableSchema: TableSchema, aliasedColumnSet: Set<string>) => { | ||
const dimensionsProjections = dimensions.reduce((acc, member, currentIndex, members) => { | ||
const { sql: memberSql } = getDimensionProjection({ key: member, tableSchema }) | ||
return aggregator({ member, aliasedColumnSet, acc, currentIndex, members, sql: memberSql }) | ||
}, '') | ||
} | ||
const measureProjections = measures.reduce((acc, member, currentIndex, members) => { | ||
const { sql: memberSql } = getFilterMeasureProjection({ key: member, tableSchema, measures }) | ||
return aggregator({ member, aliasedColumnSet, acc, currentIndex, members, sql: memberSql }) | ||
}, '') | ||
return dimensionsProjections + (dimensionsProjections.length && measureProjections.length ? ', ' : '') + measureProjections | ||
} |
Oops, something went wrong.