Skip to content

Commit d724e27

Browse files
authored
support aliases (#154)
* member formatters * support aliasing * update browser and add tests * update browser * review comments * restore unchanged files * restore more * update name * use table schemas * update version * use map * cleanup * add util * refactor --------- Co-authored-by: Eric Gan <[email protected]>
1 parent 7b88fb0 commit d724e27

File tree

27 files changed

+1358
-307
lines changed

27 files changed

+1358
-307
lines changed

meerkat-browser/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devrev/meerkat-browser",
3-
"version": "0.0.98",
3+
"version": "0.0.99",
44
"dependencies": {
55
"tslib": "^2.3.0",
66
"@devrev/meerkat-core": "*",

meerkat-browser/src/browser-cube-to-sql-with-resolution/browser-cube-to-sql-with-resolution.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,17 @@ export const cubeQueryToSQLWithResolution = async ({
5050
query.dimensions
5151
);
5252

53-
const resolutionSchemas: TableSchema[] =
54-
generateResolutionSchemas(resolutionConfig);
53+
const resolutionSchemas: TableSchema[] = generateResolutionSchemas(
54+
resolutionConfig,
55+
tableSchemas
56+
);
5557

5658
const resolveParams: CubeQueryToSQLParams = {
5759
connection: connection,
5860
query: {
5961
measures: [],
6062
dimensions: generateResolvedDimensions(query, resolutionConfig),
61-
joinPaths: generateResolutionJoinPaths(resolutionConfig),
63+
joinPaths: generateResolutionJoinPaths(resolutionConfig, tableSchemas),
6264
},
6365
tableSchemas: [baseTable, ...resolutionSchemas],
6466
};

meerkat-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devrev/meerkat-core",
3-
"version": "0.0.98",
3+
"version": "0.0.99",
44
"dependencies": {
55
"tslib": "^2.3.0"
66
},

meerkat-core/src/ast-builder/ast-builder.spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,4 +377,42 @@ describe('cubeToDuckdbAST', () => {
377377
type: 'COLUMN_REF',
378378
});
379379
});
380+
381+
it('should handle aliases', () => {
382+
const tableSchema: TableSchema = {
383+
name: 'test_table',
384+
sql: 'test_table',
385+
measures: [
386+
{
387+
name: 'measure',
388+
sql: 'test_table.measure',
389+
type: 'number',
390+
alias: 'measure_with_alias',
391+
},
392+
],
393+
dimensions: [
394+
{
395+
name: 'dimension',
396+
sql: 'test_table.dimension',
397+
type: 'string',
398+
alias: 'dimension_with_alias',
399+
},
400+
],
401+
};
402+
403+
const query: Query = {
404+
measures: ['test_table.measure'],
405+
dimensions: ['test_table.dimension'],
406+
};
407+
408+
const result = cubeToDuckdbAST(query, tableSchema);
409+
expect(result.node.type).toBe(QueryNodeType.SELECT_NODE);
410+
expect(result.node.group_expressions).toHaveLength(1);
411+
expect(result.node.group_expressions[0]).toEqual({
412+
alias: '',
413+
class: 'COLUMN_REF',
414+
column_names: ['dimension_with_alias'],
415+
type: 'COLUMN_REF',
416+
});
417+
});
380418
});

meerkat-core/src/ast-builder/ast-builder.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
QueryFiltersWithInfoSingular,
88
} from '../cube-to-duckdb/cube-filter-to-duckdb';
99
import { traverseAndFilter } from '../filter-params/filter-params-ast';
10-
import { memberKeyToSafeKey } from '../member-formatters/member-key-to-safe-key';
10+
import { constructAlias } from '../member-formatters/get-alias';
1111
import {
1212
FilterType,
1313
MeerkatQueryFilter,
@@ -32,7 +32,13 @@ const formatFilters = (
3232
: (modifyLeafMeerkatFilter(queryFiltersWithInfo, (item) => {
3333
return {
3434
...item,
35-
member: memberKeyToSafeKey(item.member),
35+
member: constructAlias({
36+
name: item.member,
37+
alias: item.memberInfo.alias,
38+
aliasContext: {
39+
isAstIdentifier: true,
40+
},
41+
}),
3642
};
3743
}) as QueryFiltersWithInfo);
3844
};
@@ -113,7 +119,10 @@ export const cubeToDuckdbAST = (
113119
query.dimensions &&
114120
query.dimensions?.length > 0
115121
) {
116-
node.group_expressions = cubeDimensionToGroupByAST(query.dimensions);
122+
node.group_expressions = cubeDimensionToGroupByAST(
123+
query.dimensions,
124+
tableSchema
125+
);
117126
const groupSets = [];
118127
/**
119128
* We only support one group set for now.
@@ -125,7 +134,7 @@ export const cubeToDuckdbAST = (
125134
}
126135
node.modifiers = [];
127136
if (query.order && Object.keys(query.order).length > 0) {
128-
node.modifiers.push(cubeOrderByToAST(query.order));
137+
node.modifiers.push(cubeOrderByToAST(query.order, tableSchema));
129138
}
130139
if (query.limit || query.offset) {
131140
// Type assertion is needed here because the AST is not typed correctly.

meerkat-core/src/cube-group-by-transformer/cube-group-by-transformer.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
1-
import { memberKeyToSafeKey } from '../member-formatters';
1+
import { getAliasFromSchema } from '../member-formatters/get-alias';
2+
import { TableSchema } from '../types/cube-types';
23
import { Member } from '../types/cube-types/query';
34
import {
45
ExpressionClass,
56
ExpressionType,
67
} from '../types/duckdb-serialization-types/serialization/Expression';
78

8-
export const cubeDimensionToGroupByAST = (dimensions: Member[]) => {
9+
export const cubeDimensionToGroupByAST = (
10+
dimensions: Member[],
11+
tableSchema: TableSchema
12+
) => {
913
const groupByAST = dimensions.map((dimension) => {
1014
const dimensionAST = {
1115
class: ExpressionClass.COLUMN_REF,
1216
type: ExpressionType.COLUMN_REF,
1317
alias: '',
14-
column_names: [memberKeyToSafeKey(dimension)],
18+
column_names: [
19+
getAliasFromSchema({
20+
name: dimension,
21+
tableSchema,
22+
aliasContext: { isAstIdentifier: true },
23+
}),
24+
],
1525
};
1626

1727
return dimensionAST;

meerkat-core/src/cube-measure-transformer/cube-measure-transformer.spec.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from './cube-measure-transformer';
88

99
describe('cubeMeasureToSQLSelectString', () => {
10-
let tableSchema: TableSchema;
10+
let tableSchema: TableSchema, tableSchemaWithAliases: TableSchema;
1111
const cube = 'cube_test';
1212

1313
beforeEach(() => {
@@ -27,6 +27,26 @@ describe('cubeMeasureToSQLSelectString', () => {
2727
},
2828
],
2929
};
30+
31+
tableSchemaWithAliases = {
32+
name: 'test_with_aliases',
33+
sql: cube,
34+
measures: [
35+
{
36+
name: 'measure1',
37+
sql: 'COUNT(*)',
38+
type: 'number',
39+
alias: 'alias_measure1',
40+
},
41+
{
42+
name: 'measure2',
43+
sql: 'SUM(total)',
44+
type: 'number',
45+
alias: 'alias_measure2',
46+
},
47+
],
48+
dimensions: [],
49+
};
3050
});
3151

3252
it('should construct a SQL select string with COUNT(*) when provided with correct measure', () => {
@@ -47,6 +67,17 @@ describe('cubeMeasureToSQLSelectString', () => {
4767
expect(result).toBe(`SELECT test.*`);
4868
});
4969

70+
it('should use alias for measures when provided', () => {
71+
const measures: Member[] = ['temp.measure1', 'temp.measure2'];
72+
const result = cubeMeasureToSQLSelectString(
73+
measures,
74+
tableSchemaWithAliases
75+
);
76+
expect(result).toBe(
77+
`SELECT COUNT(*) AS "alias_measure1" , SUM(total) AS "alias_measure2" `
78+
);
79+
});
80+
5081
it('should replace the select portion of a SQL string using replaceSelectWithCubeMeasure 1', () => {
5182
const measures: Member[] = ['temp.measure1', 'temp.measure2'];
5283
const sqlToReplace = 'SELECT * FROM my_table';
@@ -89,6 +120,20 @@ describe('cubeMeasureToSQLSelectString', () => {
89120
`SELECT COUNT(*) AS temp__measure1 , SUM(total) AS temp__measure2 , temp__dimension1, temp__dimension2 FROM (SELECT * FROM TABLE_1)`
90121
);
91122
});
123+
124+
it('should use aliases when provided', () => {
125+
const measures: Member[] = ['temp.measure1', 'temp.measure2'];
126+
const sqlToReplace = 'SELECT * FROM my_table';
127+
const result = applyProjectionToSQLQuery(
128+
[],
129+
measures,
130+
tableSchemaWithAliases,
131+
sqlToReplace
132+
);
133+
expect(result).toBe(
134+
`SELECT COUNT(*) AS "alias_measure1" , SUM(total) AS "alias_measure2" FROM my_table`
135+
);
136+
});
92137
});
93138

94139
describe('getAllColumnUsedInMeasures', () => {

meerkat-core/src/cube-measure-transformer/cube-measure-transformer.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { memberKeyToSafeKey } from '../member-formatters/member-key-to-safe-key';
1+
import { getAliasFromSchema, getNamespacedKey } from '../member-formatters';
22
import { splitIntoDataSourceAndFields } from '../member-formatters/split-into-data-source-and-fields';
33
import { Member } from '../types/cube-types/query';
44
import { Measure, TableSchema } from '../types/cube-types/table';
@@ -18,7 +18,13 @@ export const cubeMeasureToSQLSelectString = (
1818
const [tableSchemaName, measureKeyWithoutTable] =
1919
splitIntoDataSourceAndFields(measure);
2020

21-
const aliasKey = memberKeyToSafeKey(measure);
21+
const aliasKey = getAliasFromSchema({
22+
name: measure,
23+
tableSchema,
24+
aliasContext: {
25+
isAstIdentifier: false,
26+
},
27+
});
2228
const measureSchema = tableSchema.measures.find(
2329
(m) => m.name === measureKeyWithoutTable
2430
);
@@ -47,8 +53,14 @@ export const cubeMeasureToSQLSelectString = (
4753
//Replace all the columnsUsedInMeasure with safeKey
4854
columnsUsedInMeasure?.forEach((measureKey) => {
4955
const [_, column] = splitIntoDataSourceAndFields(measureKey);
50-
const memberKey = `${tableSchemaName}.${column}`;
51-
const columnKey = memberKeyToSafeKey(memberKey);
56+
const memberKey = getNamespacedKey(tableSchemaName, column);
57+
const columnKey = getAliasFromSchema({
58+
name: memberKey,
59+
tableSchema,
60+
aliasContext: {
61+
isAstIdentifier: false,
62+
},
63+
});
5264
meerkatReplacedSqlString = meerkatReplacedSqlString.replace(
5365
memberKey,
5466
columnKey
@@ -76,7 +88,13 @@ const addDimensionToSQLProjection = (
7688
const dimensionSchema = tableSchema.dimensions.find(
7789
(m) => m.name === dimensionKeyWithoutTable
7890
);
79-
const aliasKey = memberKeyToSafeKey(dimension);
91+
const aliasKey = getAliasFromSchema({
92+
name: dimension,
93+
tableSchema,
94+
aliasContext: {
95+
isAstIdentifier: false,
96+
},
97+
});
8098

8199
if (!dimensionSchema) {
82100
continue;

meerkat-core/src/cube-order-by-transformer/cube-order-by-transformer.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
import { memberKeyToSafeKey } from '../member-formatters/member-key-to-safe-key';
1+
import { getAliasFromSchema } from '../member-formatters/get-alias';
2+
import { TableSchema } from '../types/cube-types';
23
import {
34
ExpressionClass,
45
ExpressionType,
56
} from '../types/duckdb-serialization-types/serialization/Expression';
67
import { OrderType } from '../types/duckdb-serialization-types/serialization/Nodes';
78
import { ResultModifierType } from '../types/duckdb-serialization-types/serialization/ResultModifier';
89

9-
export const cubeOrderByToAST = (order: { [key: string]: 'asc' | 'desc' }) => {
10+
export const cubeOrderByToAST = (
11+
order: { [key: string]: 'asc' | 'desc' },
12+
tableSchema: TableSchema
13+
) => {
1014
const orderArr = [];
1115
for (const key in order) {
1216
const value = order[key];
@@ -22,7 +26,13 @@ export const cubeOrderByToAST = (order: { [key: string]: 'asc' | 'desc' }) => {
2226
/**
2327
* We need to convert the key in the __ format as they are being projected in this format
2428
*/
25-
column_names: [memberKeyToSafeKey(key)],
29+
column_names: [
30+
getAliasFromSchema({
31+
name: key,
32+
tableSchema,
33+
aliasContext: { isAstIdentifier: true },
34+
}),
35+
],
2636
},
2737
};
2838
orderArr.push(orderByAST);

0 commit comments

Comments
 (0)