@@ -71,13 +71,11 @@ const prepareAnnotation = (metaConfig, query) => {
71
71
} ;
72
72
} ;
73
73
74
- const getQueryGranularity = ( queries ) => {
75
- return R . pipe (
76
- R . map ( ( { timeDimensions } ) => timeDimensions [ 0 ] && timeDimensions [ 0 ] . granularity || null ) ,
77
- R . filter ( Boolean ) ,
78
- R . uniq
79
- ) ( queries ) ;
80
- } ;
74
+ const getQueryGranularity = ( queries ) => R . pipe (
75
+ R . map ( ( { timeDimensions } ) => timeDimensions [ 0 ] && timeDimensions [ 0 ] . granularity || null ) ,
76
+ R . filter ( Boolean ) ,
77
+ R . uniq
78
+ ) ( queries ) ;
81
79
82
80
const getPivotQuery = ( queryType , queries ) => {
83
81
let [ pivotQuery ] = queries ;
@@ -188,15 +186,22 @@ const operators = [
188
186
'measureFilter' ,
189
187
] ;
190
188
189
+ const oneFilter = Joi . object ( ) . keys ( {
190
+ dimension : id ,
191
+ member : id ,
192
+ operator : Joi . valid ( operators ) . required ( ) ,
193
+ values : Joi . array ( ) . items ( Joi . string ( ) . allow ( '' , null ) , Joi . lazy ( ( ) => oneFilter ) )
194
+ } ) . xor ( 'dimension' , 'member' ) ;
195
+
196
+ const oneCondition = Joi . object ( ) . keys ( {
197
+ or : Joi . array ( ) . items ( oneFilter , Joi . lazy ( ( ) => oneCondition ) . description ( 'oneCondition schema' ) ) ,
198
+ and : Joi . array ( ) . items ( oneFilter , Joi . lazy ( ( ) => oneCondition ) . description ( 'oneCondition schema' ) ) ,
199
+ } ) . xor ( 'or' , 'and' ) ;
200
+
191
201
const querySchema = Joi . object ( ) . keys ( {
192
202
measures : Joi . array ( ) . items ( id ) ,
193
203
dimensions : Joi . array ( ) . items ( dimensionWithTime ) ,
194
- filters : Joi . array ( ) . items ( Joi . object ( ) . keys ( {
195
- dimension : id ,
196
- member : id ,
197
- operator : Joi . valid ( operators ) . required ( ) ,
198
- values : Joi . array ( ) . items ( Joi . string ( ) . allow ( '' , null ) )
199
- } ) . xor ( 'dimension' , 'member' ) ) ,
204
+ filters : Joi . array ( ) . items ( oneFilter , oneCondition ) ,
200
205
timeDimensions : Joi . array ( ) . items ( Joi . object ( ) . keys ( {
201
206
dimension : id . required ( ) ,
202
207
granularity : Joi . valid ( 'day' , 'month' , 'year' , 'week' , 'hour' , 'minute' , 'second' , null ) ,
@@ -234,6 +239,34 @@ const normalizeQueryOrder = order => {
234
239
235
240
const DateRegex = / ^ \d \d \d \d - \d \d - \d \d $ / ;
236
241
242
+ const checkQueryFilters = ( filter ) => {
243
+ filter . find ( f => {
244
+ if ( f . or ) {
245
+ checkQueryFilters ( f . or ) ;
246
+ return false ;
247
+ }
248
+ if ( f . and ) {
249
+ checkQueryFilters ( f . and ) ;
250
+ return false ;
251
+ }
252
+
253
+ if ( ! f . operator ) {
254
+ throw new UserError ( `Operator required for filter: ${ JSON . stringify ( f ) } ` ) ;
255
+ }
256
+
257
+ if ( operators . indexOf ( f . operator ) === - 1 ) {
258
+ throw new UserError ( `Operator ${ f . operator } not supported for filter: ${ JSON . stringify ( f ) } ` ) ;
259
+ }
260
+
261
+ if ( ! f . values && [ 'set' , 'notSet' , 'measureFilter' ] . indexOf ( f . operator ) === - 1 ) {
262
+ throw new UserError ( `Values required for filter: ${ JSON . stringify ( f ) } ` ) ;
263
+ }
264
+ return false ;
265
+ } ) ;
266
+
267
+ return true ;
268
+ } ;
269
+
237
270
const normalizeQuery = ( query ) => {
238
271
const { error } = Joi . validate ( query , querySchema ) ;
239
272
if ( error ) {
@@ -247,41 +280,9 @@ const normalizeQuery = (query) => {
247
280
'Query should contain either measures, dimensions or timeDimensions with granularities in order to be valid'
248
281
) ;
249
282
}
250
- const filterWithoutOperator = ( query . filters || [ ] ) . find ( f => ! f . operator ) ;
251
- if ( filterWithoutOperator ) {
252
- throw new UserError ( `Operator required for filter: ${ JSON . stringify ( filterWithoutOperator ) } ` ) ;
253
- }
254
- const filterWithIncorrectOperator = ( query . filters || [ ] )
255
- . find ( f => [
256
- 'equals' ,
257
- 'notEquals' ,
258
- 'contains' ,
259
- 'notContains' ,
260
- 'in' ,
261
- 'notIn' ,
262
- 'gt' ,
263
- 'gte' ,
264
- 'lt' ,
265
- 'lte' ,
266
- 'set' ,
267
- 'notSet' ,
268
- 'inDateRange' ,
269
- 'notInDateRange' ,
270
- 'onTheDate' ,
271
- 'beforeDate' ,
272
- 'afterDate' ,
273
- 'measureFilter' ,
274
- ] . indexOf ( f . operator ) === - 1 ) ;
275
-
276
- if ( filterWithIncorrectOperator ) {
277
- throw new UserError ( `Operator ${ filterWithIncorrectOperator . operator } not supported for filter: ${ JSON . stringify ( filterWithIncorrectOperator ) } ` ) ;
278
- }
283
+
284
+ checkQueryFilters ( query . filters || [ ] ) ;
279
285
280
- const filterWithoutValues = ( query . filters || [ ] )
281
- . find ( f => ! f . values && [ 'set' , 'notSet' , 'measureFilter' ] . indexOf ( f . operator ) === - 1 ) ;
282
- if ( filterWithoutValues ) {
283
- throw new UserError ( `Values required for filter: ${ JSON . stringify ( filterWithoutValues ) } ` ) ;
284
- }
285
286
const regularToTimeDimension = ( query . dimensions || [ ] ) . filter ( d => d . split ( '.' ) . length === 3 ) . map ( d => ( {
286
287
dimension : d . split ( '.' ) . slice ( 0 , 2 ) . join ( '.' ) ,
287
288
granularity : d . split ( '.' ) [ 2 ]
0 commit comments