diff --git a/packages/filterparser/src/datetimeParser.ts b/packages/filterparser/src/datetimeParser.ts deleted file mode 100644 index 06f501340..000000000 --- a/packages/filterparser/src/datetimeParser.ts +++ /dev/null @@ -1,308 +0,0 @@ -import P from 'parsimmon'; -import moment from 'moment'; -import type { TransformType } from 'dbgate-types'; -import { token, word, whitespace } from './common'; - -const compoudCondition = conditionType => conditions => { - if (conditions.length == 1) return conditions[0]; - return { - [conditionType]: conditions, - }; -}; - -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 binaryCondition = operator => value => ({ - conditionType: 'binary', - operator, - left: { - exprType: 'placeholder', - }, - right: { - exprType: 'value', - value, - }, -}); - -const unaryCondition = conditionType => () => { - return { - conditionType, - expr: { - exprType: 'placeholder', - }, - }; -}; - -const sqlTemplate = templateSql => { - return { - conditionType: 'rawTemplate', - templateSql, - expr: { - exprType: 'placeholder', - }, - }; -}; - -const createParser = () => { - const langDef = { - comma: () => word(','), - - not: () => word('NOT'), - notNull: r => r.not.then(r.null).map(unaryCondition('isNotNull')), - null: () => word('NULL').map(unaryCondition('isNull')), - - sql: () => - token(P.regexp(/\{(.*?)\}/, 1)) - .map(sqlTemplate) - .desc('sql literal'), - - 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')), - - 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)), - - valueStart: r => - P.alt( - r.yearMonthDayMinuteSecondStart, - r.yearMonthDayMinuteStart, - r.yearMonthDayStart, - r.yearMonthStart, - r.yearNumStart - ), - valueEnd: r => - P.alt(r.yearMonthDayMinuteSecondEnd, r.yearMonthDayMinuteEnd, r.yearMonthDayEnd, r.yearMonthEnd, r.yearNumEnd), - - le: r => word('<=').then(r.valueEnd).map(binaryCondition('<=')), - ge: r => word('>=').then(r.valueStart).map(binaryCondition('>=')), - lt: r => word('<').then(r.valueStart).map(binaryCondition('<')), - gt: r => word('>').then(r.valueEnd).map(binaryCondition('>')), - - element: r => - P.alt( - r.yearMonthDaySecond, - r.yearMonthDayMinute, - r.yearMonthDayNum, - r.yearMonthNum, - r.yearNum, - r.yesterday, - r.today, - r.tomorrow, - r.lastWeek, - r.thisWeek, - r.nextWeek, - r.lastMonth, - r.thisMonth, - r.nextMonth, - r.lastYear, - r.thisYear, - r.nextYear, - r.null, - r.notNull, - r.le, - r.lt, - r.ge, - r.gt, - r.sql - ).trim(whitespace), - factor: r => r.element.sepBy(whitespace).map(compoudCondition('$and')), - list: r => r.factor.sepBy(r.comma).map(compoudCondition('$or')), - }; - - return P.createLanguage(langDef); -}; - -export const datetimeParser = createParser(); diff --git a/packages/filterparser/src/mongoParser.ts b/packages/filterparser/src/mongoParser.ts deleted file mode 100644 index 79c67f43c..000000000 --- a/packages/filterparser/src/mongoParser.ts +++ /dev/null @@ -1,151 +0,0 @@ -import P from 'parsimmon'; -import { interpretEscapes, token, word, whitespace } from './common'; - -const operatorCondition = operator => value => ({ - __placeholder__: { - [operator]: value, - }, -}); - -const regexCondition = regexString => value => ({ - __placeholder__: { - $regex: regexString.replace('#VALUE#', value), - $options: 'i', - }, -}); - -const numberTestCondition = () => value => ({ - $or: [ - { - __placeholder__: { - $regex: `.*${value}.*`, - $options: 'i', - }, - }, - { - __placeholder__: value, - }, - ], -}); - -const idRegex = /[('"]([0-9a-f]{24})['")]/; - -const objectIdTestCondition = () => value => ({ - $or: [ - { - __placeholder__: { $oid: value.match(idRegex)[1] }, - }, - ], -}); - -const testCondition = (operator, value) => () => ({ - __placeholder__: { - [operator]: value, - }, -}); - -const multiTestCondition = condition => () => ({ - __placeholder__: condition, -}); - -const compoudCondition = conditionType => conditions => { - if (conditions.length == 1) return conditions[0]; - return { - [conditionType]: conditions, - }; -}; - -const negateCondition = condition => ({ - __placeholder__: { - $not: condition.__placeholder__, - }, -}); - -const createParser = () => { - const langDef = { - string1: () => - token(P.regexp(/"((?:\\.|.)*?)"/, 1)) - .map(interpretEscapes) - .desc('string quoted'), - - string2: () => - token(P.regexp(/'((?:\\.|.)*?)'/, 1)) - .map(interpretEscapes) - .desc('string quoted'), - - number: () => - token(P.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/)) - .map(Number) - .desc('number'), - - objectid: () => token(P.regexp(/ObjectId\(['"]?[0-9a-f]{24}['"]?\)/)).desc('ObjectId'), - - noQuotedString: () => P.regexp(/[^\s^,^'^"]+/).desc('string unquoted'), - - value: r => P.alt(r.objectid, r.string1, r.string2, r.number, r.noQuotedString), - valueTestObjectId: r => r.objectid.map(objectIdTestCondition()), - valueTestNum: r => r.number.map(numberTestCondition()), - valueTest: r => r.value.map(regexCondition('.*#VALUE#.*')), - - comma: () => word(','), - not: () => word('NOT'), - empty: () => word('EMPTY'), - array: () => word('ARRAY'), - notExists: r => r.not.then(r.exists).map(testCondition('$exists', false)), - notEmptyArray: r => - r.not - .then(r.empty) - .then(r.array) - .map(multiTestCondition({ $exists: true, $type: 'array', $ne: [] })), - emptyArray: r => r.empty.then(r.array).map(multiTestCondition({ $exists: true, $eq: [] })), - exists: () => word('EXISTS').map(testCondition('$exists', true)), - true: () => word('TRUE').map(testCondition('$eq', true)), - false: () => word('FALSE').map(testCondition('$eq', false)), - - eq: r => word('=').then(r.value).map(operatorCondition('$eq')), - ne: r => word('!=').then(r.value).map(operatorCondition('$ne')), - ne2: r => word('<>').then(r.value).map(operatorCondition('$ne')), - lt: r => word('<').then(r.value).map(operatorCondition('$lt')), - gt: r => word('>').then(r.value).map(operatorCondition('$gt')), - le: r => word('<=').then(r.value).map(operatorCondition('$lte')), - ge: r => word('>=').then(r.value).map(operatorCondition('$gte')), - startsWith: r => word('^').then(r.value).map(regexCondition('#VALUE#.*')), - endsWith: r => word('$').then(r.value).map(regexCondition('.*#VALUE#')), - contains: r => word('+').then(r.value).map(regexCondition('.*#VALUE#.*')), - startsWithNot: r => word('!^').then(r.value).map(regexCondition('#VALUE#.*')).map(negateCondition), - endsWithNot: r => word('!$').then(r.value).map(regexCondition('.*#VALUE#')).map(negateCondition), - containsNot: r => word('~').then(r.value).map(regexCondition('.*#VALUE#.*')).map(negateCondition), - - element: r => - P.alt( - r.exists, - r.notExists, - r.true, - r.false, - r.eq, - r.ne, - r.ne2, - r.lt, - r.gt, - r.le, - r.ge, - r.notEmptyArray, - r.emptyArray, - r.startsWith, - r.endsWith, - r.contains, - r.startsWithNot, - r.endsWithNot, - r.containsNot, - r.valueTestObjectId, - r.valueTestNum, - r.valueTest - ).trim(whitespace), - factor: r => r.element.sepBy(whitespace).map(compoudCondition('$and')), - list: r => r.factor.sepBy(r.comma).map(compoudCondition('$or')), - }; - - return P.createLanguage(langDef); -}; - -export const mongoParser = createParser(); diff --git a/packages/filterparser/src/parseFilter.ts b/packages/filterparser/src/parseFilter.ts index 8939e07d6..7625ce10d 100644 --- a/packages/filterparser/src/parseFilter.ts +++ b/packages/filterparser/src/parseFilter.ts @@ -2,8 +2,6 @@ import P from 'parsimmon'; import moment from 'moment'; import { Condition } from 'dbgate-sqltree'; import { interpretEscapes, token, word, whitespace } from './common'; -import { mongoParser } from './mongoParser'; -import { datetimeParser } from './datetimeParser'; import { hexStringToArray } from 'dbgate-tools'; import { FilterBehaviour, TransformType } from 'dbgate-types'; @@ -533,12 +531,6 @@ const createParser = (filterBehaviour: FilterBehaviour) => { const cachedFilters: { [key: string]: P.Language } = {}; function getParser(filterBehaviour: FilterBehaviour) { - if (filterBehaviour.compilerType == 'mongoCondition') { - return mongoParser; - } - if (filterBehaviour.compilerType == 'datetime') { - return datetimeParser; - } const key = JSON.stringify(filterBehaviour); if (!cachedFilters[key]) { cachedFilters[key] = createParser(filterBehaviour); diff --git a/packages/tools/src/filterBehaviours.ts b/packages/tools/src/filterBehaviours.ts index c6cbbd7ac..f600c2e3c 100644 --- a/packages/tools/src/filterBehaviours.ts +++ b/packages/tools/src/filterBehaviours.ts @@ -1,7 +1,6 @@ import { FilterBehaviour } from 'dbgate-types'; export const numberFilterBehaviour: FilterBehaviour = { - compilerType: 'sqlTree', supportEquals: true, supportNumberLikeComparison: true, supportNullTesting: true, @@ -11,7 +10,6 @@ export const numberFilterBehaviour: FilterBehaviour = { }; export const stringFilterBehaviour: FilterBehaviour = { - compilerType: 'sqlTree', supportEquals: true, supportStringInclusion: true, supportEmpty: true, @@ -24,14 +22,12 @@ export const stringFilterBehaviour: FilterBehaviour = { }; export const logicalFilterBehaviour: FilterBehaviour = { - compilerType: 'sqlTree', supportBooleanValues: true, supportNullTesting: true, supportSqlCondition: true, }; export const datetimeFilterBehaviour: FilterBehaviour = { - compilerType: 'sqlTree', supportNullTesting: true, supportSqlCondition: true, supportDatetimeSymbols: true, @@ -39,7 +35,6 @@ export const datetimeFilterBehaviour: FilterBehaviour = { }; export const mongoFilterBehaviour: FilterBehaviour = { - compilerType: 'sqlTree', supportEquals: true, supportArrayTesting: true, supportNumberLikeComparison: true, @@ -53,7 +48,6 @@ export const mongoFilterBehaviour: FilterBehaviour = { }; export const evalFilterBehaviour: FilterBehaviour = { - compilerType: 'sqlTree', supportEquals: true, supportStringInclusion: true, supportEmpty: true, diff --git a/packages/types/filter-type.d.ts b/packages/types/filter-type.d.ts index 522490f37..1b36ae04c 100644 --- a/packages/types/filter-type.d.ts +++ b/packages/types/filter-type.d.ts @@ -1,8 +1,6 @@ export type FilterParserCompilerType = 'sqlTree' | 'mongoCondition' | 'datetime'; export interface FilterBehaviour { - compilerType: FilterParserCompilerType; - supportEquals?: boolean; supportStringInclusion?: boolean; supportEmpty?: boolean;