Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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