Skip to content

Commit

Permalink
fix: Invalid query format: \"filters[0]\" does not match any of the a…
Browse files Browse the repository at this point in the history
…llowed types for `or` query
  • Loading branch information
paveltiunov committed May 22, 2023
1 parent 5da5e61 commit a3b4cd6
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 22 deletions.
45 changes: 23 additions & 22 deletions packages/cubejs-api-gateway/src/query.js
Expand Up @@ -70,7 +70,7 @@ const oneFilter = Joi.object().keys({
dimension: id,
member: id,
operator: Joi.valid(...operators).required(),
values: Joi.array().items(Joi.string().allow('', null), Joi.link('...'), Joi.number(), Joi.boolean())
values: Joi.array().items(Joi.string().allow('', null), Joi.number(), Joi.boolean(), Joi.link('...'))
}).xor('dimension', 'member');

const oneCondition = Joi.object().keys({
Expand Down Expand Up @@ -118,15 +118,16 @@ const normalizeQueryOrder = order => {

const DateRegex = /^\d\d\d\d-\d\d-\d\d$/;

const checkQueryFilters = (filter) => {
filter.find(f => {
const normalizeQueryFilters = (filter) => (
filter.map(f => {
const res = { ...f };
if (f.or) {
checkQueryFilters(f.or);
return false;
res.or = normalizeQueryFilters(f.or);
return res;
}
if (f.and) {
checkQueryFilters(f.and);
return false;
res.and = normalizeQueryFilters(f.and);
return res;
}

if (!f.operator) {
Expand All @@ -137,18 +138,27 @@ const checkQueryFilters = (filter) => {
throw new UserError(`Operator ${f.operator} not supported for filter: ${JSON.stringify(f)}`);
}

if (!f.values && ['set', 'notSet', 'measureFilter'].indexOf(f.operator) === -1) {
if ((!f.values || f.values.length === 0) && ['set', 'notSet', 'measureFilter'].indexOf(f.operator) === -1) {
throw new UserError(`Values required for filter: ${JSON.stringify(f)}`);
}
return false;
});

return true;
};
if (f.values) {
res.values = f.values.map(v => (v != null ? v.toString() : v));
}

if (f.dimension) {
res.member = f.dimension;
delete res.dimension;
}

return res;
})
);

/**
* Normalize incoming network query.
* @param {Query} query
* @param {boolean} persistent
* @throws {UserError}
* @returns {NormalizedQuery}
*/
Expand All @@ -166,8 +176,6 @@ const normalizeQuery = (query, persistent) => {
);
}

checkQueryFilters(query.filters || []);

const regularToTimeDimension = (query.dimensions || []).filter(d => d.split('.').length === 3).map(d => ({
dimension: d.split('.').slice(0, 2).join('.'),
granularity: d.split('.')[2]
Expand Down Expand Up @@ -198,14 +206,7 @@ const normalizeQuery = (query, persistent) => {
limit: newLimit,
timezone,
order: normalizeQueryOrder(query.order),
filters: (query.filters || []).map(f => {
const { dimension, member, ...filter } = f;
return {
...filter,
member: member || dimension,
values: filter.values?.map(v => (v != null ? v.toString() : v))
};
}),
filters: normalizeQueryFilters(query.filters || []),
dimensions: (query.dimensions || []).filter(d => d.split('.').length !== 3),
timeDimensions: (query.timeDimensions || []).map(td => {
let dateRange;
Expand Down
33 changes: 33 additions & 0 deletions packages/cubejs-api-gateway/test/index.test.ts
Expand Up @@ -297,6 +297,16 @@ describe('API Gateway', () => {
member: 'Foo.bar',
operator: 'gte',
values: [0]
}, {
or: [{
member: 'Foo.bar',
operator: 'gte',
values: [10.5]
}, {
member: 'Foo.bar',
operator: 'gte',
values: [0]
}]
}]
};

Expand All @@ -317,6 +327,16 @@ describe('API Gateway', () => {
member: 'Foo.bar',
operator: 'gte',
values: ['0']
}, {
or: [{
member: 'Foo.bar',
operator: 'gte',
values: ['10.5']
}, {
member: 'Foo.bar',
operator: 'gte',
values: ['0']
}]
}],
rowLimit: 10000,
limit: 10000,
Expand All @@ -329,6 +349,19 @@ describe('API Gateway', () => {
);
});

test('normalize empty filters', async () => {
const { app } = createApiGateway();

const res = await request(app)
.get(
'/cubejs-api/v1/load?query={"measures":["Foo.bar"],"filters":[{"member":"Foo.bar","operator":"equals","values":[]}]}'
)
.set('Authorization', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.t-IDcSemACt8x4iTMCda8Yhe3iZaWbvV5XKSTbuAn0M')
.expect(400);
console.log(res.body);
expect(res.body.error).toMatch(/Values required for filter/);
});

test('normalize queryRewrite limit', async () => {
const { app } = createApiGateway(
new AdapterApiMock(),
Expand Down

0 comments on commit a3b4cd6

Please sign in to comment.