Skip to content

Commit ff3aa74

Browse files
committed
add util
1 parent 7510382 commit ff3aa74

File tree

9 files changed

+147
-43
lines changed

9 files changed

+147
-43
lines changed

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import {
77
QueryFiltersWithInfoSingular,
88
} from '../cube-to-duckdb/cube-filter-to-duckdb';
99
import { traverseAndFilter } from '../filter-params/filter-params-ast';
10-
import { constructAlias } from '../member-formatters/get-alias';
10+
import {
11+
constructAlias,
12+
shouldUseSafeAlias,
13+
} from '../member-formatters/get-alias';
1114
import {
1215
FilterType,
1316
MeerkatQueryFilter,
@@ -32,7 +35,13 @@ const formatFilters = (
3235
: (modifyLeafMeerkatFilter(queryFiltersWithInfo, (item) => {
3336
return {
3437
...item,
35-
member: constructAlias(item.member, item.memberInfo.alias),
38+
member: constructAlias({
39+
name: item.member,
40+
alias: item.memberInfo.alias,
41+
safe: shouldUseSafeAlias({
42+
isAstIdentifier: true,
43+
}),
44+
}),
3645
};
3746
}) as QueryFiltersWithInfo);
3847
};

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { getAliasFromSchema } from '../member-formatters/get-alias';
1+
import {
2+
getAliasFromSchema,
3+
shouldUseSafeAlias,
4+
} from '../member-formatters/get-alias';
25
import { TableSchema } from '../types/cube-types';
36
import { Member } from '../types/cube-types/query';
47
import {
@@ -15,7 +18,13 @@ export const cubeDimensionToGroupByAST = (
1518
class: ExpressionClass.COLUMN_REF,
1619
type: ExpressionType.COLUMN_REF,
1720
alias: '',
18-
column_names: [getAliasFromSchema({ name: dimension, tableSchema })],
21+
column_names: [
22+
getAliasFromSchema({
23+
name: dimension,
24+
tableSchema,
25+
safe: shouldUseSafeAlias({ isAstIdentifier: true }),
26+
}),
27+
],
1928
};
2029

2130
return dimensionAST;

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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
import { getNamespacedKey } from '../member-formatters';
2-
import { getAliasFromSchema } from '../member-formatters/get-alias';
1+
import {
2+
getAliasFromSchema,
3+
getNamespacedKey,
4+
shouldUseSafeAlias,
5+
} from '../member-formatters';
36
import { splitIntoDataSourceAndFields } from '../member-formatters/split-into-data-source-and-fields';
47
import { Member } from '../types/cube-types/query';
58
import { Measure, TableSchema } from '../types/cube-types/table';
@@ -22,7 +25,9 @@ export const cubeMeasureToSQLSelectString = (
2225
const aliasKey = getAliasFromSchema({
2326
name: measure,
2427
tableSchema,
25-
safe: true,
28+
safe: shouldUseSafeAlias({
29+
isAstIdentifier: false,
30+
}),
2631
});
2732
const measureSchema = tableSchema.measures.find(
2833
(m) => m.name === measureKeyWithoutTable
@@ -56,7 +61,9 @@ export const cubeMeasureToSQLSelectString = (
5661
const columnKey = getAliasFromSchema({
5762
name: memberKey,
5863
tableSchema,
59-
safe: true,
64+
safe: shouldUseSafeAlias({
65+
isAstIdentifier: false,
66+
}),
6067
});
6168
meerkatReplacedSqlString = meerkatReplacedSqlString.replace(
6269
memberKey,
@@ -88,7 +95,9 @@ const addDimensionToSQLProjection = (
8895
const aliasKey = getAliasFromSchema({
8996
name: dimension,
9097
tableSchema,
91-
safe: true,
98+
safe: shouldUseSafeAlias({
99+
isAstIdentifier: false,
100+
}),
92101
});
93102

94103
if (!dimensionSchema) {

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { getAliasFromSchema } from '../member-formatters/get-alias';
1+
import {
2+
getAliasFromSchema,
3+
shouldUseSafeAlias,
4+
} from '../member-formatters/get-alias';
25
import { TableSchema } from '../types/cube-types';
36
import {
47
ExpressionClass,
@@ -26,7 +29,13 @@ export const cubeOrderByToAST = (
2629
/**
2730
* We need to convert the key in the __ format as they are being projected in this format
2831
*/
29-
column_names: [getAliasFromSchema({ name: key, tableSchema })],
32+
column_names: [
33+
getAliasFromSchema({
34+
name: key,
35+
tableSchema,
36+
safe: shouldUseSafeAlias({ isAstIdentifier: true }),
37+
}),
38+
],
3039
},
3140
};
3241
orderArr.push(orderByAST);

meerkat-core/src/get-wrapped-base-query-with-projections/get-aliased-columns-from-filters.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { getAliasFromSchema } from '../member-formatters/get-alias';
1+
import {
2+
getAliasFromSchema,
3+
shouldUseSafeAlias,
4+
} from '../member-formatters/get-alias';
25
import { splitIntoDataSourceAndFields } from '../member-formatters/split-into-data-source-and-fields';
36
import { MeerkatQueryFilter, Query, TableSchema } from '../types/cube-types';
47
import {
@@ -40,7 +43,11 @@ export const getDimensionProjection = ({
4043
query,
4144
});
4245

43-
const aliasKey = getAliasFromSchema({ name: key, tableSchema, safe: true });
46+
const aliasKey = getAliasFromSchema({
47+
name: key,
48+
tableSchema,
49+
safe: shouldUseSafeAlias({ isAstIdentifier: false }),
50+
});
4451
// Add the alias key to the set. So we have a reference to all the previously selected members.
4552
return { sql: `${modifiedSql} AS ${aliasKey}`, foundMember, aliasKey };
4653
};
@@ -67,7 +74,11 @@ export const getFilterMeasureProjection = ({
6774
aliasKey: undefined,
6875
};
6976
}
70-
const aliasKey = getAliasFromSchema({ name: key, tableSchema, safe: true });
77+
const aliasKey = getAliasFromSchema({
78+
name: key,
79+
tableSchema,
80+
safe: shouldUseSafeAlias({ isAstIdentifier: false }),
81+
});
7182
return { sql: `${key} AS ${aliasKey}`, foundMember, aliasKey };
7283
};
7384

meerkat-core/src/get-wrapped-base-query-with-projections/get-projection-clause.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { getAllColumnUsedInMeasures } from '../cube-measure-transformer/cube-measure-transformer';
2-
import { getAliasFromSchema } from '../member-formatters/get-alias';
2+
import {
3+
getAliasFromSchema,
4+
shouldUseSafeAlias,
5+
} from '../member-formatters/get-alias';
36
import { splitIntoDataSourceAndFields } from '../member-formatters/split-into-data-source-and-fields';
47
import { Query, TableSchema } from '../types/cube-types';
58
import {
@@ -52,7 +55,11 @@ export const getProjectionClause = (
5255
query,
5356
});
5457
return memberClauseAggregator({
55-
member: getAliasFromSchema({ name: member, tableSchema, safe: true }),
58+
member: getAliasFromSchema({
59+
name: member,
60+
tableSchema,
61+
safe: shouldUseSafeAlias({ isAstIdentifier: false }),
62+
}),
5663
aliasedColumnSet,
5764
acc,
5865
currentIndex,

meerkat-core/src/member-formatters/get-alias.ts

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,53 @@ import { findInSchema } from '../utils/find-in-table-schema';
33
import { memberKeyToSafeKey } from './member-key-to-safe-key';
44
import { splitIntoDataSourceAndFields } from './split-into-data-source-and-fields';
55

6+
export const shouldUseSafeAlias = ({
7+
isAstIdentifier,
8+
isTableSchemaAlias,
9+
}: {
10+
isAstIdentifier?: boolean;
11+
isTableSchemaAlias?: boolean;
12+
}): boolean => {
13+
if (isAstIdentifier) {
14+
// Duckdb will automatically quote identifiers that contain special characters or spaces.
15+
// when converting the AST to SQL.
16+
return false;
17+
}
18+
if (isTableSchemaAlias) {
19+
// No need to wrap alias in quotes as part of table schema
20+
return false;
21+
}
22+
// For other cases such as directly using the alias in SQL queries,
23+
// we should make the alias safe to avoid issues with special characters or spaces.
24+
return true;
25+
};
26+
627
export const getAliasFromSchema = ({
728
name,
829
tableSchema,
930
safe,
1031
}: {
1132
name: string;
1233
tableSchema: TableSchema;
13-
safe?: boolean;
34+
safe: boolean;
1435
}): string => {
1536
const [, field] = splitIntoDataSourceAndFields(name);
16-
return constructAlias(name, findInSchema(field, tableSchema)?.alias, safe);
37+
return constructAlias({
38+
name,
39+
alias: findInSchema(field, tableSchema)?.alias,
40+
safe,
41+
});
1742
};
1843

19-
export const constructAlias = (
20-
name: string,
21-
alias?: string,
22-
safe?: boolean
23-
): string => {
44+
export const constructAlias = ({
45+
name,
46+
alias,
47+
safe,
48+
}: {
49+
name: string;
50+
alias?: string;
51+
safe: boolean;
52+
}): string => {
2453
if (alias) {
2554
if (safe) {
2655
// Alias may contain special characters or spaces, so we need to wrap in quotes.
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
export { COLUMN_NAME_DELIMITER } from './constants';
2-
export { constructAlias, getAliasFromSchema } from './get-alias';
2+
export {
3+
constructAlias,
4+
getAliasFromSchema,
5+
shouldUseSafeAlias,
6+
} from './get-alias';
37
export { getNamespacedKey } from './get-namespaced-key';
48
export { memberKeyToSafeKey } from './member-key-to-safe-key';
59
export { splitIntoDataSourceAndFields } from './split-into-data-source-and-fields';

meerkat-core/src/resolution/resolution.ts

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
import { getNamespacedKey, memberKeyToSafeKey } from '../member-formatters';
2-
import { constructAlias } from '../member-formatters/get-alias';
1+
import {
2+
constructAlias,
3+
getNamespacedKey,
4+
memberKeyToSafeKey,
5+
shouldUseSafeAlias,
6+
} from '../member-formatters';
37
import { JoinPath, Member, Query } from '../types/cube-types/query';
48
import { Dimension, Measure, TableSchema } from '../types/cube-types/table';
59
import {
@@ -11,10 +15,18 @@ import { BASE_DATA_SOURCE_NAME, ResolutionConfig } from './types';
1115
const constructBaseDimension = (name: string, schema: Measure | Dimension) => {
1216
return {
1317
name: memberKeyToSafeKey(name),
14-
sql: `${BASE_DATA_SOURCE_NAME}.${constructAlias(name, schema.alias, true)}`,
18+
sql: `${BASE_DATA_SOURCE_NAME}.${constructAlias({
19+
name,
20+
alias: schema.alias,
21+
safe: shouldUseSafeAlias({ isAstIdentifier: false }),
22+
})}`,
1523
type: schema.type,
1624
// Constructs alias to match the name in the base query.
17-
alias: constructAlias(name, schema.alias),
25+
alias: constructAlias({
26+
name,
27+
alias: schema.alias,
28+
safe: shouldUseSafeAlias({ isTableSchemaAlias: true }),
29+
}),
1830
};
1931
};
2032

@@ -49,11 +61,11 @@ export const createBaseTableSchema = (
4961
}
5062
}),
5163
joins: resolutionConfig.columnConfigs.map((config) => ({
52-
sql: `${BASE_DATA_SOURCE_NAME}.${constructAlias(
53-
config.name,
54-
schemaByName[config.name]?.alias,
55-
true
56-
)} = ${memberKeyToSafeKey(config.name)}.${config.joinColumn}`,
64+
sql: `${BASE_DATA_SOURCE_NAME}.${constructAlias({
65+
name: config.name,
66+
alias: schemaByName[config.name]?.alias,
67+
safe: shouldUseSafeAlias({ isAstIdentifier: false }),
68+
})} = ${memberKeyToSafeKey(config.name)}.${config.joinColumn}`,
5769
})),
5870
};
5971
};
@@ -72,10 +84,11 @@ export const generateResolutionSchemas = (
7284
}
7385

7486
const baseName = memberKeyToSafeKey(colConfig.name);
75-
const baseAlias = constructAlias(
76-
colConfig.name,
77-
findInSchemas(colConfig.name, baseTableSchemas)?.alias
78-
);
87+
const baseAlias = constructAlias({
88+
name: colConfig.name,
89+
alias: findInSchemas(colConfig.name, baseTableSchemas)?.alias,
90+
safe: shouldUseSafeAlias({ isTableSchemaAlias: true }),
91+
});
7992

8093
// For each column that needs to be resolved, create a copy of the relevant table schema.
8194
// We use the name of the column in the base query as the table schema name
@@ -98,7 +111,11 @@ export const generateResolutionSchemas = (
98111
name: memberKeyToSafeKey(getNamespacedKey(colConfig.name, col)),
99112
sql: `${baseName}.${col}`,
100113
type: dimension.type,
101-
alias: `${baseAlias} - ${constructAlias(col, dimension.alias)}`,
114+
alias: `${baseAlias} - ${constructAlias({
115+
name: col,
116+
alias: dimension.alias,
117+
safe: shouldUseSafeAlias({ isTableSchemaAlias: true }),
118+
})}`,
102119
};
103120
}),
104121
};
@@ -143,11 +160,11 @@ export const generateResolutionJoinPaths = (
143160
{
144161
left: BASE_DATA_SOURCE_NAME,
145162
right: memberKeyToSafeKey(config.name),
146-
on: constructAlias(
147-
config.name,
148-
findInSchemas(config.name, baseTableSchemas)?.alias,
149-
true
150-
),
163+
on: constructAlias({
164+
name: config.name,
165+
alias: findInSchemas(config.name, baseTableSchemas)?.alias,
166+
safe: shouldUseSafeAlias({ isAstIdentifier: false }),
167+
}),
151168
},
152169
]);
153170
};

0 commit comments

Comments
 (0)