Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion meerkat-browser/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@devrev/meerkat-browser",
"version": "0.0.103",
"version": "0.0.104",
"dependencies": {
"tslib": "^2.3.0",
"@devrev/meerkat-core": "*",
Expand Down
2 changes: 1 addition & 1 deletion meerkat-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@devrev/meerkat-core",
"version": "0.0.103",
"version": "0.0.104",
"dependencies": {
"tslib": "^2.3.0"
},
Expand Down
50 changes: 49 additions & 1 deletion meerkat-core/src/filter-params/filter-params-ast.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { MeerkatQueryFilter } from '../types/cube-types';
import {
applyFilterParamsToBaseSQL,
detectAllFilterParamsFromSQL,
getFilterByMemberKey,
traverseMeerkatQueryFilter,
} from './filter-params-ast';

describe('getFilterByMemberKey', () => {
it('should return an empty array when filters are undefined', () => {
const result = getFilterByMemberKey(undefined, 'memberKey');
Expand Down Expand Up @@ -178,3 +179,50 @@ describe('applyFilterParamsToBaseSQL function', () => {
expect(applyFilterParamsToBaseSQL(baseSQL, filterParamsSQL)).toBe(expected);
});
});

describe('traverseMeerkatQueryFilter function', () => {
it('should traverse the MeerkatQueryFilter JSON and call the callback for each leaf type', () => {
const filters: MeerkatQueryFilter[] = [
{ member: 'memberKey', operator: 'equals', values: ['value1'] },
{ member: 'differentMember', operator: 'equals', values: ['value1'] },
{
and: [
{ member: 'memberKey', operator: 'equals', values: ['value1'] },
{ member: 'differentMember', operator: 'equals', values: ['value1'] },
],
},
{ or: [{ member: 'memberKey', operator: 'equals', values: ['value1'] }] },
];

const callbackFn = jest.fn();

traverseMeerkatQueryFilter(filters as MeerkatQueryFilter[], callbackFn);

expect(callbackFn).toHaveBeenCalledTimes(5);
expect(callbackFn).toHaveBeenCalledWith({
member: 'memberKey',
operator: 'equals',
values: ['value1'],
});
expect(callbackFn).toHaveBeenCalledWith({
member: 'differentMember',
operator: 'equals',
values: ['value1'],
});
expect(callbackFn).toHaveBeenCalledWith({
member: 'memberKey',
operator: 'equals',
values: ['value1'],
});
expect(callbackFn).toHaveBeenCalledWith({
member: 'differentMember',
operator: 'equals',
values: ['value1'],
});
expect(callbackFn).toHaveBeenCalledWith({
member: 'memberKey',
operator: 'equals',
values: ['value1'],
});
});
});
58 changes: 44 additions & 14 deletions meerkat-core/src/filter-params/filter-params-ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,39 @@ import {
MeerkatQueryFilter,
Query,
QueryFilter,
TableSchema
TableSchema,
} from '../types/cube-types';
import { SelectStatement } from '../types/duckdb-serialization-types/serialization/Statement';

/*
** This function traverse the MeerkatQueryFilter JSON, and calls the callback for each leaf type.
** This way we need no rewrite the traversal logic again and again.
*/
export const traverseMeerkatQueryFilter = (
filters: MeerkatQueryFilter[],
callback: (value: QueryFilter) => void
) => {
filters.forEach((filter: MeerkatQueryFilter) => {
if ('member' in filter) {
callback(filter);
return;
}
if ('and' in filter) {
filter.and.forEach((subFilter: MeerkatQueryFilter) =>
traverseMeerkatQueryFilter([subFilter], callback)
);
}
if ('or' in filter) {
filter.or.forEach((subFilter: MeerkatQueryFilter) =>
traverseMeerkatQueryFilter([subFilter], callback)
);
}
});
};

/**
* Get the query filter with only where filterKey matches
*/

export const traverseAndFilter = (
filter: MeerkatQueryFilter,
callback: (value: QueryFilter) => boolean
Expand Down Expand Up @@ -42,14 +67,15 @@ export const traverseAndFilter = (
return null;
};


export const getFilterByMemberKey = (
filters: MeerkatQueryFilter[] | undefined,
memberKey: string
): MeerkatQueryFilter[] => {
if (!filters) return [];
return filters
.map((filter) => traverseAndFilter(filter, (value) => value.member === memberKey))
.map((filter) =>
traverseAndFilter(filter, (value) => value.member === memberKey)
)
.filter(Boolean) as MeerkatQueryFilter[];
};

Expand Down Expand Up @@ -82,8 +108,6 @@ export const detectAllFilterParamsFromSQL = (
return matches;
};



export const getFilterParamsAST = (
query: Query,
tableSchema: TableSchema,
Expand All @@ -95,13 +119,13 @@ export const getFilterParamsAST = (
}[] => {
const filterParamKeys = detectAllFilterParamsFromSQL(tableSchema.sql);
const filterParamsAST = [];

for (const filterParamKey of filterParamKeys) {
const filters = getFilterByMemberKey(
query.filters,
filterParamKey.memberKey
);

if (filters && filters.length > 0) {
filterParamsAST.push({
memberKey: filterParamKey.memberKey,
Expand All @@ -110,7 +134,7 @@ export const getFilterParamsAST = (
{ filters, measures: [], dimensions: [] },
tableSchema,
{
filterType
filterType,
}
),
});
Expand All @@ -124,9 +148,12 @@ type FilterParamsSQL = {
memberKey: string;
sql: string;
matchKey: string;
}
};

const replaceWhereClauseWithFiltersParamsSQL = (baseSQL: string, filterParamsSQL: FilterParamsSQL[]) => {
const replaceWhereClauseWithFiltersParamsSQL = (
baseSQL: string,
filterParamsSQL: FilterParamsSQL[]
) => {
let finalSQL = baseSQL;

for (const filterParam of filterParamsSQL) {
Expand All @@ -139,14 +166,17 @@ const replaceWhereClauseWithFiltersParamsSQL = (baseSQL: string, filterParamsSQL
*/
finalSQL = finalSQL.replace(filterParam.matchKey, whereClause);
}
return finalSQL
}
return finalSQL;
};

export const applyFilterParamsToBaseSQL = (
baseSQL: string,
filterParamsSQL: FilterParamsSQL[]
) => {
let finalSQL = replaceWhereClauseWithFiltersParamsSQL(baseSQL, filterParamsSQL);
let finalSQL = replaceWhereClauseWithFiltersParamsSQL(
baseSQL,
filterParamsSQL
);
for (const filterParam of filterParamsSQL) {
/**
* Get SQL expression after WHERE clause
Expand Down
Loading