diff --git a/packages/cubejs-api-gateway/index.js b/packages/cubejs-api-gateway/index.js index 7271aa71d3391..6cf88495376f4 100644 --- a/packages/cubejs-api-gateway/index.js +++ b/packages/cubejs-api-gateway/index.js @@ -102,7 +102,7 @@ const operators = [ ]; const querySchema = Joi.object().keys({ - measures: Joi.array().items(id.required()), + measures: Joi.array().items(id), dimensions: Joi.array().items(dimensionWithTime), filters: Joi.array().items(Joi.object().keys({ dimension: id.required(), @@ -121,7 +121,7 @@ const querySchema = Joi.object().keys({ segments: Joi.array().items(id), timezone: Joi.string(), limit: Joi.number().integer().min(1).max(50000) -}).or("measures", "dimensions"); +}); const normalizeQuery = (query) => { // eslint-disable-next-line no-unused-vars @@ -129,6 +129,14 @@ const normalizeQuery = (query) => { if (error) { throw new UserError(`Invalid query format: ${error.message || error.toString()}`); } + const validQuery = query.measures && query.measures.length || + query.dimensions && query.dimensions.length || + query.timeDimensions && query.timeDimensions.filter(td => !!td.granularity).length; + if (!validQuery) { + throw new UserError( + 'Query should contain either measures, dimensions or timeDimensions with granularities in order to be valid' + ); + } const filterWithoutOperator = (query.filters || []).find(f => !f.operator); if (filterWithoutOperator) { throw new UserError(`Operator required for filter: ${JSON.stringify(filterWithoutOperator)}`);