Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {
constructDimensionsNameMap,
constructMeasuresNameMap,
ContextParams,
createBaseTableSchema,
generateResolutionJoinPaths,
Expand Down Expand Up @@ -41,24 +43,31 @@ export const cubeQueryToSQLWithResolution = async ({
return baseSql;
}

const columnNameMap = {
...constructMeasuresNameMap(tableSchemas),
...constructDimensionsNameMap(tableSchemas),
};

// Create a table schema for the base query.
const baseTable: TableSchema = createBaseTableSchema(
baseSql,
tableSchemas,
columnNameMap,
resolutionConfig,
query.measures,
query.dimensions
);

const resolutionSchemas: TableSchema[] =
generateResolutionSchemas(resolutionConfig);
const resolutionSchemas: TableSchema[] = generateResolutionSchemas(
resolutionConfig,
columnNameMap
);

const resolveParams: CubeQueryToSQLParams = {
connection: connection,
query: {
measures: [],
dimensions: generateResolvedDimensions(query, resolutionConfig),
joinPaths: generateResolutionJoinPaths(resolutionConfig),
joinPaths: generateResolutionJoinPaths(resolutionConfig, columnNameMap),
},
tableSchemas: [baseTable, ...resolutionSchemas],
};
Expand Down
10 changes: 8 additions & 2 deletions meerkat-browser/src/browser-cube-to-sql/browser-cube-to-sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
cubeToDuckdbAST,
deserializeQuery,
detectApplyContextParamsToBaseSQL,
getAliases,
getCombinedTableSchema,
getFilterParamsSQL,
getFinalBaseSQL,
Expand Down Expand Up @@ -37,11 +38,14 @@ export const cubeQueryToSQL = async ({
tableSchemas,
contextParams,
}: CubeQueryToSQLParams) => {
const aliases = getAliases(tableSchemas);

const updatedTableSchemas: TableSchema[] = await Promise.all(
tableSchemas.map(async (schema: TableSchema) => {
const baseFilterParamsSQL = await getFinalBaseSQL({
query,
tableSchema: schema,
aliases,
getQueryOutput: (query) => getQueryOutput(query, connection),
});
return {
Expand All @@ -56,7 +60,7 @@ export const cubeQueryToSQL = async ({
query
);

const ast = cubeToDuckdbAST(query, updatedTableSchema);
const ast = cubeToDuckdbAST(query, updatedTableSchema, aliases);
if (!ast) {
throw new Error('Could not generate AST');
}
Expand All @@ -71,6 +75,7 @@ export const cubeQueryToSQL = async ({
getQueryOutput: (query) => getQueryOutput(query, connection),
query,
tableSchema: updatedTableSchema,
aliases,
filterType: 'BASE_FILTER',
});

Expand Down Expand Up @@ -104,7 +109,8 @@ export const cubeQueryToSQL = async ({
dimensions,
measures,
updatedTableSchema,
replaceBaseTableName
replaceBaseTableName,
aliases
);

return finalQuery;
Expand Down
21 changes: 21 additions & 0 deletions meerkat-core/src/aliases/aliases.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { TableSchema } from '../types/cube-types';

export const getAliases = (
tableSchemas: TableSchema[]
): Record<string, string> => {
const aliases: Record<string, string> = {};

tableSchemas.forEach((table) => {
table.measures.forEach((measure) => {
if (measure.alias) {
aliases[`${table.name}.${measure.name}`] = measure.alias;
}
});
table.dimensions.forEach((dimension) => {
if (dimension.alias) {
aliases[`${table.name}.${dimension.name}`] = dimension.alias;
}
});
});
return aliases;
};
42 changes: 42 additions & 0 deletions meerkat-core/src/ast-builder/ast-builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,46 @@ describe('cubeToDuckdbAST', () => {
type: 'COLUMN_REF',
});
});

it('should handle aliases', () => {
const tableSchema: TableSchema = {
name: 'test_table',
sql: 'test_table',
measures: [
{
name: 'measure',
sql: 'test_table.measure',
type: 'number',
alias: 'measure_with_alias',
},
],
dimensions: [
{
name: 'dimension',
sql: 'test_table.dimension',
type: 'string',
alias: 'dimension_with_alias',
},
],
};

const query: Query = {
measures: ['test_table.measure'],
dimensions: ['test_table.dimension'],
};

const aliases = {
'test_table.measure': 'measure_with_alias',
'test_table.dimension': 'dimension_with_alias',
};
const result = cubeToDuckdbAST(query, tableSchema, aliases);
expect(result.node.type).toBe(QueryNodeType.SELECT_NODE);
expect(result.node.group_expressions).toHaveLength(1);
expect(result.node.group_expressions[0]).toEqual({
alias: '',
class: 'COLUMN_REF',
column_names: ['dimension_with_alias'],
type: 'COLUMN_REF',
});
});
});
19 changes: 14 additions & 5 deletions meerkat-core/src/ast-builder/ast-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
QueryFiltersWithInfoSingular,
} from '../cube-to-duckdb/cube-filter-to-duckdb';
import { traverseAndFilter } from '../filter-params/filter-params-ast';
import { memberKeyToSafeKey } from '../member-formatters/member-key-to-safe-key';
import { getAlias } from '../member-formatters';
import {
FilterType,
MeerkatQueryFilter,
Expand All @@ -22,6 +22,7 @@ import { modifyLeafMeerkatFilter } from '../utils/modify-meerkat-filter';

const formatFilters = (
queryFiltersWithInfo: QueryFiltersWithInfo,
aliases?: Record<string, string>,
filterType?: FilterType
) => {
/*
Expand All @@ -32,7 +33,7 @@ const formatFilters = (
: (modifyLeafMeerkatFilter(queryFiltersWithInfo, (item) => {
return {
...item,
member: memberKeyToSafeKey(item.member),
member: getAlias(item.member, aliases),
};
}) as QueryFiltersWithInfo);
};
Expand All @@ -42,22 +43,25 @@ const getFormattedFilters = ({
filterType,
mapperFn,
baseAST,
aliases,
}: {
queryFiltersWithInfo: QueryFiltersWithInfo;
filterType?: FilterType;
baseAST: SelectStatement;
mapperFn: (val: QueryFiltersWithInfoSingular) => MeerkatQueryFilter | null;
aliases?: Record<string, string>;
}) => {
const filters = queryFiltersWithInfo
.map((item) => mapperFn(item))
.filter(Boolean) as QueryFiltersWithInfoSingular[];
const formattedFilters = formatFilters(filters, filterType);
const formattedFilters = formatFilters(filters, aliases, filterType);
return cubeFilterToDuckdbAST(formattedFilters, baseAST);
};

export const cubeToDuckdbAST = (
query: Query,
tableSchema: TableSchema,
aliases?: Record<string, string>,
options?: { filterType: FilterType }
) => {
/**
Expand Down Expand Up @@ -91,6 +95,7 @@ export const cubeToDuckdbAST = (
),
queryFiltersWithInfo,
filterType: options?.filterType,
aliases,
});

const havingClause = getFormattedFilters({
Expand All @@ -101,6 +106,7 @@ export const cubeToDuckdbAST = (
),
queryFiltersWithInfo,
filterType: options?.filterType,
aliases,
});

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
Expand All @@ -113,7 +119,10 @@ export const cubeToDuckdbAST = (
query.dimensions &&
query.dimensions?.length > 0
) {
node.group_expressions = cubeDimensionToGroupByAST(query.dimensions);
node.group_expressions = cubeDimensionToGroupByAST(
query.dimensions,
aliases
);
const groupSets = [];
/**
* We only support one group set for now.
Expand All @@ -125,7 +134,7 @@ export const cubeToDuckdbAST = (
}
node.modifiers = [];
if (query.order && Object.keys(query.order).length > 0) {
node.modifiers.push(cubeOrderByToAST(query.order));
node.modifiers.push(cubeOrderByToAST(query.order, aliases));
}
if (query.limit || query.offset) {
// Type assertion is needed here because the AST is not typed correctly.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { memberKeyToSafeKey } from '../member-formatters';
import { getAlias } from '../member-formatters';
import { Member } from '../types/cube-types/query';
import {
ExpressionClass,
ExpressionType,
} from '../types/duckdb-serialization-types/serialization/Expression';

export const cubeDimensionToGroupByAST = (dimensions: Member[]) => {
export const cubeDimensionToGroupByAST = (
dimensions: Member[],
aliases?: Record<string, string>
) => {
const groupByAST = dimensions.map((dimension) => {
const dimensionAST = {
class: ExpressionClass.COLUMN_REF,
type: ExpressionType.COLUMN_REF,
alias: '',
column_names: [memberKeyToSafeKey(dimension)],
column_names: [getAlias(dimension, aliases)],
};

return dimensionAST;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ describe('cubeMeasureToSQLSelectString', () => {
expect(result).toBe(`SELECT test.*`);
});

it('should use alias for measures when provided', () => {
const measures: Member[] = ['temp.measure1', 'temp.measure2'];
const aliases = {
'temp.measure1': 'alias_measure1',
'temp.measure2': 'alias_measure2',
};
const result = cubeMeasureToSQLSelectString(measures, tableSchema, aliases);
expect(result).toBe(
`SELECT COUNT(*) AS "alias_measure1" , SUM(total) AS "alias_measure2" `
);
});

it('should replace the select portion of a SQL string using replaceSelectWithCubeMeasure 1', () => {
const measures: Member[] = ['temp.measure1', 'temp.measure2'];
const sqlToReplace = 'SELECT * FROM my_table';
Expand Down Expand Up @@ -89,6 +101,25 @@ describe('cubeMeasureToSQLSelectString', () => {
`SELECT COUNT(*) AS temp__measure1 , SUM(total) AS temp__measure2 , temp__dimension1, temp__dimension2 FROM (SELECT * FROM TABLE_1)`
);
});

it('should use aliases when provided', () => {
const measures: Member[] = ['temp.measure1', 'temp.measure2'];
const aliases = {
'temp.measure1': 'alias_measure1',
'temp.measure2': 'alias_measure2',
};
const sqlToReplace = 'SELECT * FROM my_table';
const result = applyProjectionToSQLQuery(
[],
measures,
tableSchema,
sqlToReplace,
aliases
);
expect(result).toBe(
`SELECT COUNT(*) AS "alias_measure1" , SUM(total) AS "alias_measure2" FROM my_table`
);
});
});

describe('getAllColumnUsedInMeasures', () => {
Expand Down
Loading