Skip to content

Commit 6b9ae70

Browse files
authored
feat(cubesql): Add ability to filter dates inclusive of date being passed in when using <= or >= (#7041) Thanks @darapuk !
* (Fix) Add ability to filter dates inclusive of date being passed in when using <= or >= * fix test + fmt * missed fmt * Fix date_trunc * revert/patch tests * Fix tests * consolidate code * fix test * fix tests * Make sure valid filters are passed in + sort dates correctly
1 parent 5e5fb18 commit 6b9ae70

File tree

12 files changed

+194
-70
lines changed

12 files changed

+194
-70
lines changed

examples/apollo-federation-with-cube/apollo-server-app/graphql/cube.graphql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ input DateTimeFilter {
3333
inDateRange: [String]
3434
notInDateRange: [String]
3535
beforeDate: String
36+
beforeOrOnDate: String
3637
afterDate: String
38+
afterOrOnDate: String
3739
set: Boolean
3840
}
3941

examples/apollo-federation-with-cube/apollo-server-app/graphql/supergraph.graphql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ input DateTimeFilter
3232
inDateRange: [String]
3333
notInDateRange: [String]
3434
beforeDate: String
35+
beforeOrOnDate: String
3536
afterDate: String
37+
afterOrOnDate: String
3638
set: Boolean
3739
}
3840

packages/cubejs-api-gateway/src/graphql.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ const DateTimeFilter = inputObjectType({
7777
t.list.string('inDateRange');
7878
t.list.string('notInDateRange');
7979
t.string('beforeDate');
80+
t.string('beforeOrOnDate');
8081
t.string('afterDate');
82+
t.string('afterOrOnDate');
8183
t.boolean('set');
8284
}
8385
});

packages/cubejs-api-gateway/src/query.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ const operators = [
6969
'notInDateRange',
7070
'onTheDate',
7171
'beforeDate',
72+
'beforeOrOnDate',
7273
'afterDate',
74+
'afterOrOnDate',
7375
'measureFilter',
7476
];
7577

packages/cubejs-api-gateway/src/types/strings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ type FilterOperator =
7575
'notInDateRange' |
7676
'onTheDate' |
7777
'beforeDate' |
78+
'beforeOrOnDate' |
7879
'afterDate' |
80+
'afterOrOnDate' |
7981
'measureFilter';
8082

8183
/**

packages/cubejs-client-core/index.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,9 @@ declare module '@cubejs-client/core' {
774774
| 'inDateRange'
775775
| 'notInDateRange'
776776
| 'beforeDate'
777-
| 'afterDate';
777+
| 'beforeOrOnDate'
778+
| 'afterDate'
779+
| 'afterOrOnDate';
778780

779781
export type TimeDimensionGranularity = 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
780782

packages/cubejs-client-core/src/Meta.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ const operators = {
3535
{ name: 'inDateRange', title: 'in date range' },
3636
{ name: 'notInDateRange', title: 'not in date range' },
3737
{ name: 'afterDate', title: 'after date' },
38+
{ name: 'afterOrOnDate', title: 'after or on date' },
3839
{ name: 'beforeDate', title: 'before date' },
40+
{ name: 'beforeOrOnDate', title: 'before or on date' },
3941
],
4042
};
4143

packages/cubejs-schema-compiler/src/adapter/BaseFilter.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { BaseDimension } from './BaseDimension';
77

88
const moment = momentRange.extendMoment(require('moment-timezone'));
99

10-
const DATE_OPERATORS = ['inDateRange', 'notInDateRange', 'onTheDate', 'beforeDate', 'afterDate'];
10+
const DATE_OPERATORS = ['inDateRange', 'notInDateRange', 'onTheDate', 'beforeDate', 'beforeOrOnDate', 'afterDate', 'afterOrOnDate'];
1111
const dateTimeLocalMsRegex = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\d$/;
1212
const dateRegex = /^\d\d\d\d-\d\d-\d\d$/;
1313

@@ -332,11 +332,21 @@ export class BaseFilter extends BaseDimension {
332332
return this.query.beforeDateFilter(column, before);
333333
}
334334

335+
beforeOrOnDateWhere(column) {
336+
const [before] = this.allocateTimestampParams();
337+
return this.query.beforeOrOnDateFilter(column, before);
338+
}
339+
335340
afterDateWhere(column) {
336341
const [after] = this.allocateTimestampParams();
337342
return this.query.afterDateFilter(column, after);
338343
}
339344

345+
afterOrOnDateWhere(column) {
346+
const [after] = this.allocateTimestampParams();
347+
return this.query.afterOrOnDateFilter(column, after);
348+
}
349+
340350
formatFromDate(date) {
341351
if (date && date.match(dateTimeLocalMsRegex)) {
342352
return date;

packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,10 +1074,18 @@ class BaseQuery {
10741074
return `${dimensionSql} < ${timeStampParam}`;
10751075
}
10761076

1077+
beforeOrOnDateFilter(dimensionSql, timeStampParam) {
1078+
return `${dimensionSql} <= ${timeStampParam}`;
1079+
}
1080+
10771081
afterDateFilter(dimensionSql, timeStampParam) {
10781082
return `${dimensionSql} > ${timeStampParam}`;
10791083
}
10801084

1085+
afterOrOnDateFilter(dimensionSql, timeStampParam) {
1086+
return `${dimensionSql} >= ${timeStampParam}`;
1087+
}
1088+
10811089
timeStampCast(value) {
10821090
return `${value}::timestamptz`;
10831091
}

rust/cubesql/cubesql/src/compile/legacy_compiler.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,9 @@ fn compiled_binary_op_expr(
557557
ast::BinaryOperator::Eq => (filter_expr, "equals".to_string()),
558558
ast::BinaryOperator::NotEq => (filter_expr, "notEquals".to_string()),
559559
ast::BinaryOperator::GtEq => match filter_expr {
560-
CompiledExpression::DateLiteral(_) => (filter_expr, "afterDate".to_string()),
560+
CompiledExpression::DateLiteral(_) => {
561+
(filter_expr, "afterOrOnDate".to_string())
562+
}
561563
_ => (filter_expr, "gte".to_string()),
562564
},
563565
ast::BinaryOperator::Gt => match filter_expr {
@@ -575,7 +577,9 @@ fn compiled_binary_op_expr(
575577
_ => (filter_expr, "lt".to_string()),
576578
},
577579
ast::BinaryOperator::LtEq => match filter_expr {
578-
CompiledExpression::DateLiteral(_) => (filter_expr, "beforeDate".to_string()),
580+
CompiledExpression::DateLiteral(_) => {
581+
(filter_expr, "beforeOrOnDate".to_string())
582+
}
579583
_ => (filter_expr, "lte".to_string()),
580584
},
581585
_ => {
@@ -742,7 +746,11 @@ fn binary_op_create_node_and(
742746
&& ((l_op.eq(&"beforeDate".to_string())
743747
&& r_op.eq(&"afterDate".to_string()))
744748
|| (l_op.eq(&"afterDate".to_string())
745-
&& r_op.eq(&"beforeDate".to_string())))
749+
&& r_op.eq(&"beforeDate".to_string()))
750+
|| (l_op.eq(&"afterOrOnDate".to_string())
751+
&& r_op.eq(&"beforeOrOnDate".to_string()))
752+
|| (l_op.eq(&"beforeOrOnDate".to_string())
753+
&& r_op.eq(&"afterOrOnDate".to_string())))
746754
{
747755
return Ok(CompiledFilterTree::Filter(CompiledFilter::Filter {
748756
member: l_member.clone(),

0 commit comments

Comments
 (0)