mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-26 17:55:59 +00:00
datetime filters added to standard filters
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
import P from 'parsimmon';
|
import P from 'parsimmon';
|
||||||
|
import moment from 'moment';
|
||||||
import { Condition } from 'dbgate-sqltree';
|
import { Condition } from 'dbgate-sqltree';
|
||||||
import { interpretEscapes, token, word, whitespace } from './common';
|
import { interpretEscapes, token, word, whitespace } from './common';
|
||||||
import { mongoParser } from './mongoParser';
|
import { mongoParser } from './mongoParser';
|
||||||
import { datetimeParser } from './datetimeParser';
|
import { datetimeParser } from './datetimeParser';
|
||||||
import { hexStringToArray } from 'dbgate-tools';
|
import { hexStringToArray } from 'dbgate-tools';
|
||||||
import { FilterBehaviour } from 'dbgate-types';
|
import { FilterBehaviour, TransformType } from 'dbgate-types';
|
||||||
|
|
||||||
const binaryCondition = operator => value => ({
|
const binaryCondition = operator => value => ({
|
||||||
conditionType: 'binary',
|
conditionType: 'binary',
|
||||||
@@ -128,6 +129,163 @@ const sqlTemplate = templateSql => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getTransformCondition(transform: TransformType, value) {
|
||||||
|
return {
|
||||||
|
conditionType: 'binary',
|
||||||
|
operator: '=',
|
||||||
|
left: {
|
||||||
|
exprType: 'transform',
|
||||||
|
transform,
|
||||||
|
expr: {
|
||||||
|
exprType: 'placeholder',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
exprType: 'value',
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const yearCondition = () => value => {
|
||||||
|
return getTransformCondition('YEAR', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const yearMonthCondition = () => value => {
|
||||||
|
const m = value.match(/(\d\d\d\d)-(\d\d?)/);
|
||||||
|
|
||||||
|
return {
|
||||||
|
conditionType: 'and',
|
||||||
|
conditions: [getTransformCondition('YEAR', m[1]), getTransformCondition('MONTH', m[2])],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const yearMonthDayCondition = () => value => {
|
||||||
|
const m = value.match(/(\d\d\d\d)-(\d\d?)-(\d\d?)/);
|
||||||
|
|
||||||
|
return {
|
||||||
|
conditionType: 'and',
|
||||||
|
conditions: [
|
||||||
|
getTransformCondition('YEAR', m[1]),
|
||||||
|
getTransformCondition('MONTH', m[2]),
|
||||||
|
getTransformCondition('DAY', m[3]),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const yearEdge = edgeFunction => value => {
|
||||||
|
return moment(new Date(parseInt(value), 0, 1))
|
||||||
|
[edgeFunction]('year')
|
||||||
|
.format('YYYY-MM-DDTHH:mm:ss.SSS');
|
||||||
|
};
|
||||||
|
|
||||||
|
const yearMonthEdge = edgeFunction => value => {
|
||||||
|
const m = value.match(/(\d\d\d\d)-(\d\d?)/);
|
||||||
|
|
||||||
|
return moment(new Date(parseInt(m[1]), parseInt(m[2]) - 1, 1))
|
||||||
|
[edgeFunction]('month')
|
||||||
|
.format('YYYY-MM-DDTHH:mm:ss.SSS');
|
||||||
|
};
|
||||||
|
|
||||||
|
const yearMonthDayEdge = edgeFunction => value => {
|
||||||
|
const m = value.match(/(\d\d\d\d)-(\d\d?)-(\d\d?)/);
|
||||||
|
|
||||||
|
return moment(new Date(parseInt(m[1]), parseInt(m[2]) - 1, parseInt(m[3])))
|
||||||
|
[edgeFunction]('day')
|
||||||
|
.format('YYYY-MM-DDTHH:mm:ss.SSS');
|
||||||
|
};
|
||||||
|
|
||||||
|
const yearMonthDayMinuteEdge = edgeFunction => value => {
|
||||||
|
const m = value.match(/(\d\d\d\d)-(\d\d?)-(\d\d?)\s+(\d\d?):(\d\d?)/);
|
||||||
|
const year = m[1];
|
||||||
|
const month = m[2];
|
||||||
|
const day = m[3];
|
||||||
|
const hour = m[4];
|
||||||
|
const minute = m[5];
|
||||||
|
const dateObject = new Date(year, month - 1, day, hour, minute);
|
||||||
|
|
||||||
|
return moment(dateObject)[edgeFunction]('minute').format('YYYY-MM-DDTHH:mm:ss.SSS');
|
||||||
|
};
|
||||||
|
|
||||||
|
const yearMonthDayMinuteSecondEdge = edgeFunction => value => {
|
||||||
|
const m = value.match(/(\d\d\d\d)-(\d\d?)-(\d\d?)(T|\s+)(\d\d?):(\d\d?):(\d\d?)/);
|
||||||
|
const year = m[1];
|
||||||
|
const month = m[2];
|
||||||
|
const day = m[3];
|
||||||
|
const hour = m[5];
|
||||||
|
const minute = m[6];
|
||||||
|
const second = m[7];
|
||||||
|
const dateObject = new Date(year, month - 1, day, hour, minute, second);
|
||||||
|
|
||||||
|
return moment(dateObject)[edgeFunction]('second').format('YYYY-MM-DDTHH:mm:ss.SSS');
|
||||||
|
};
|
||||||
|
|
||||||
|
const createIntervalCondition = (start, end) => {
|
||||||
|
return {
|
||||||
|
conditionType: 'and',
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
conditionType: 'binary',
|
||||||
|
operator: '>=',
|
||||||
|
left: {
|
||||||
|
exprType: 'placeholder',
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
exprType: 'value',
|
||||||
|
value: start,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
conditionType: 'binary',
|
||||||
|
operator: '<=',
|
||||||
|
left: {
|
||||||
|
exprType: 'placeholder',
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
exprType: 'value',
|
||||||
|
value: end,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const createDateIntervalCondition = (start, end) => {
|
||||||
|
return createIntervalCondition(start.format('YYYY-MM-DDTHH:mm:ss.SSS'), end.format('YYYY-MM-DDTHH:mm:ss.SSS'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const fixedMomentIntervalCondition = (intervalType, diff) => () => {
|
||||||
|
return createDateIntervalCondition(
|
||||||
|
moment().add(intervalType, diff).startOf(intervalType),
|
||||||
|
moment().add(intervalType, diff).endOf(intervalType)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const yearMonthDayMinuteCondition = () => value => {
|
||||||
|
const m = value.match(/(\d\d\d\d)-(\d\d?)-(\d\d?)\s+(\d\d?):(\d\d?)/);
|
||||||
|
const year = m[1];
|
||||||
|
const month = m[2];
|
||||||
|
const day = m[3];
|
||||||
|
const hour = m[4];
|
||||||
|
const minute = m[5];
|
||||||
|
const dateObject = new Date(year, month - 1, day, hour, minute);
|
||||||
|
|
||||||
|
return createDateIntervalCondition(moment(dateObject).startOf('minute'), moment(dateObject).endOf('minute'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const yearMonthDaySecondCondition = () => value => {
|
||||||
|
const m = value.match(/(\d\d\d\d)-(\d\d?)-(\d\d?)(T|\s+)(\d\d?):(\d\d?):(\d\d?)/);
|
||||||
|
const year = m[1];
|
||||||
|
const month = m[2];
|
||||||
|
const day = m[3];
|
||||||
|
const hour = m[5];
|
||||||
|
const minute = m[6];
|
||||||
|
const second = m[7];
|
||||||
|
const dateObject = new Date(year, month - 1, day, hour, minute, second);
|
||||||
|
|
||||||
|
return createDateIntervalCondition(moment(dateObject).startOf('second'), moment(dateObject).endOf('second'));
|
||||||
|
};
|
||||||
|
|
||||||
const createParser = (filterBehaviour: FilterBehaviour) => {
|
const createParser = (filterBehaviour: FilterBehaviour) => {
|
||||||
const langDef = {
|
const langDef = {
|
||||||
string1: () =>
|
string1: () =>
|
||||||
@@ -184,6 +342,66 @@ const createParser = (filterBehaviour: FilterBehaviour) => {
|
|||||||
emptyArray: r => r.empty.then(r.array).map(specificPredicateCondition('emptyArray')),
|
emptyArray: r => r.empty.then(r.array).map(specificPredicateCondition('emptyArray')),
|
||||||
exists: () => word('EXISTS').map(specificPredicateCondition('exists')),
|
exists: () => word('EXISTS').map(specificPredicateCondition('exists')),
|
||||||
|
|
||||||
|
this: () => word('THIS'),
|
||||||
|
last: () => word('LAST'),
|
||||||
|
next: () => word('NEXT'),
|
||||||
|
week: () => word('WEEK'),
|
||||||
|
month: () => word('MONTH'),
|
||||||
|
year: () => word('YEAR'),
|
||||||
|
|
||||||
|
yesterday: () => word('YESTERDAY').map(fixedMomentIntervalCondition('day', -1)),
|
||||||
|
today: () => word('TODAY').map(fixedMomentIntervalCondition('day', 0)),
|
||||||
|
tomorrow: () => word('TOMORROW').map(fixedMomentIntervalCondition('day', 1)),
|
||||||
|
|
||||||
|
lastWeek: r => r.last.then(r.week).map(fixedMomentIntervalCondition('week', -1)),
|
||||||
|
thisWeek: r => r.this.then(r.week).map(fixedMomentIntervalCondition('week', 0)),
|
||||||
|
nextWeek: r => r.next.then(r.week).map(fixedMomentIntervalCondition('week', 1)),
|
||||||
|
|
||||||
|
lastMonth: r => r.last.then(r.month).map(fixedMomentIntervalCondition('month', -1)),
|
||||||
|
thisMonth: r => r.this.then(r.month).map(fixedMomentIntervalCondition('month', 0)),
|
||||||
|
nextMonth: r => r.next.then(r.month).map(fixedMomentIntervalCondition('month', 1)),
|
||||||
|
|
||||||
|
lastYear: r => r.last.then(r.year).map(fixedMomentIntervalCondition('year', -1)),
|
||||||
|
thisYear: r => r.this.then(r.year).map(fixedMomentIntervalCondition('year', 0)),
|
||||||
|
nextYear: r => r.next.then(r.year).map(fixedMomentIntervalCondition('year', 1)),
|
||||||
|
|
||||||
|
dateValueStart: r =>
|
||||||
|
P.alt(
|
||||||
|
r.yearMonthDayMinuteSecondStart,
|
||||||
|
r.yearMonthDayMinuteStart,
|
||||||
|
r.yearMonthDayStart,
|
||||||
|
r.yearMonthStart,
|
||||||
|
r.yearNumStart
|
||||||
|
),
|
||||||
|
dateValueEnd: r =>
|
||||||
|
P.alt(r.yearMonthDayMinuteSecondEnd, r.yearMonthDayMinuteEnd, r.yearMonthDayEnd, r.yearMonthEnd, r.yearNumEnd),
|
||||||
|
|
||||||
|
dateLe: r => word('<=').then(r.dateValueEnd).map(binaryCondition('<=')),
|
||||||
|
dateGe: r => word('>=').then(r.dateValueStart).map(binaryCondition('>=')),
|
||||||
|
dateLt: r => word('<').then(r.dateValueStart).map(binaryCondition('<')),
|
||||||
|
dateGt: r => word('>').then(r.dateValueEnd).map(binaryCondition('>')),
|
||||||
|
|
||||||
|
yearNum: () => P.regexp(/\d\d\d\d/).map(yearCondition()),
|
||||||
|
yearMonthNum: () => P.regexp(/\d\d\d\d-\d\d?/).map(yearMonthCondition()),
|
||||||
|
yearMonthDayNum: () => P.regexp(/\d\d\d\d-\d\d?-\d\d?/).map(yearMonthDayCondition()),
|
||||||
|
yearMonthDayMinute: () => P.regexp(/\d\d\d\d-\d\d?-\d\d?\s+\d\d?:\d\d?/).map(yearMonthDayMinuteCondition()),
|
||||||
|
yearMonthDaySecond: () =>
|
||||||
|
P.regexp(/\d\d\d\d-\d\d?-\d\d?(\s+|T)\d\d?:\d\d?:\d\d?/).map(yearMonthDaySecondCondition()),
|
||||||
|
|
||||||
|
yearNumStart: () => P.regexp(/\d\d\d\d/).map(yearEdge('startOf')),
|
||||||
|
yearNumEnd: () => P.regexp(/\d\d\d\d/).map(yearEdge('endOf')),
|
||||||
|
yearMonthStart: () => P.regexp(/\d\d\d\d-\d\d?/).map(yearMonthEdge('startOf')),
|
||||||
|
yearMonthEnd: () => P.regexp(/\d\d\d\d-\d\d?/).map(yearMonthEdge('endOf')),
|
||||||
|
yearMonthDayStart: () => P.regexp(/\d\d\d\d-\d\d?-\d\d?/).map(yearMonthDayEdge('startOf')),
|
||||||
|
yearMonthDayEnd: () => P.regexp(/\d\d\d\d-\d\d?-\d\d?/).map(yearMonthDayEdge('endOf')),
|
||||||
|
yearMonthDayMinuteStart: () =>
|
||||||
|
P.regexp(/\d\d\d\d-\d\d?-\d\d?\s+\d\d?:\d\d?/).map(yearMonthDayMinuteEdge('startOf')),
|
||||||
|
yearMonthDayMinuteEnd: () => P.regexp(/\d\d\d\d-\d\d?-\d\d?\s+\d\d?:\d\d?/).map(yearMonthDayMinuteEdge('endOf')),
|
||||||
|
yearMonthDayMinuteSecondStart: () =>
|
||||||
|
P.regexp(/\d\d\d\d-\d\d?-\d\d?(\s+|T)\d\d?:\d\d?:\d\d?/).map(yearMonthDayMinuteSecondEdge('startOf')),
|
||||||
|
yearMonthDayMinuteSecondEnd: () =>
|
||||||
|
P.regexp(/\d\d\d\d-\d\d?-\d\d?(\s+|T)\d\d?:\d\d?:\d\d?/).map(yearMonthDayMinuteSecondEdge('endOf')),
|
||||||
|
|
||||||
comma: () => word(','),
|
comma: () => word(','),
|
||||||
not: () => word('NOT'),
|
not: () => word('NOT'),
|
||||||
empty: () => word('EMPTY'),
|
empty: () => word('EMPTY'),
|
||||||
@@ -227,6 +445,30 @@ const createParser = (filterBehaviour: FilterBehaviour) => {
|
|||||||
|
|
||||||
const allowedElements = [];
|
const allowedElements = [];
|
||||||
|
|
||||||
|
if (filterBehaviour.supportDatetimeComparison) {
|
||||||
|
allowedElements.push('yearMonthDaySecond', 'yearMonthDayMinute', 'yearMonthDayNum', 'yearMonthNum', 'yearNum');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filterBehaviour.supportDatetimeSymbols) {
|
||||||
|
allowedElements.push(
|
||||||
|
'today',
|
||||||
|
'tomorrow',
|
||||||
|
'lastWeek',
|
||||||
|
'thisWeek',
|
||||||
|
'nextWeek',
|
||||||
|
'lastMonth',
|
||||||
|
'thisMonth',
|
||||||
|
'nextMonth',
|
||||||
|
'lastYear',
|
||||||
|
'thisYear',
|
||||||
|
'nextYear'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filterBehaviour.supportDatetimeComparison) {
|
||||||
|
allowedElements.push('dateLe', 'dateGe', 'dateLt', 'dateGt');
|
||||||
|
}
|
||||||
|
|
||||||
if (filterBehaviour.supportExistsTesting) {
|
if (filterBehaviour.supportExistsTesting) {
|
||||||
allowedElements.push('exists', 'notExists');
|
allowedElements.push('exists', 'notExists');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const logicalFilterBehaviour: FilterBehaviour = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const datetimeFilterBehaviour: FilterBehaviour = {
|
export const datetimeFilterBehaviour: FilterBehaviour = {
|
||||||
compilerType: 'datetime',
|
compilerType: 'sqlTree',
|
||||||
supportNullTesting: true,
|
supportNullTesting: true,
|
||||||
supportSqlCondition: true,
|
supportSqlCondition: true,
|
||||||
supportDatetimeSymbols: true,
|
supportDatetimeSymbols: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user