mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-26 23:46:23 +00:00
expression parser
This commit is contained in:
5
packages/filterparser/jest.config.js
Normal file
5
packages/filterparser/jest.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
moduleFileExtensions: ['js'],
|
||||
};
|
||||
@@ -14,12 +14,16 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@dbgate/types": "^0.1.0",
|
||||
"@types/jest": "^25.1.4",
|
||||
"@types/node": "^13.7.0",
|
||||
"jest": "^25.1.0",
|
||||
"ts-jest": "^25.2.1",
|
||||
"typescript": "^3.7.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/parsimmon": "^1.10.1",
|
||||
"lodash": "^4.17.15",
|
||||
"moment": "^2.24.0",
|
||||
"parsimmon": "^1.13.0"
|
||||
}
|
||||
}
|
||||
|
||||
17
packages/filterparser/src/cli.ts
Normal file
17
packages/filterparser/src/cli.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { parseFilter } from './parseFilter';
|
||||
import { FilterType } from './types';
|
||||
import engines from '@dbgate/engines';
|
||||
import { dumpSqlCondition, treeToSql } from '@dbgate/sqltree';
|
||||
|
||||
const ast = parseFilter(process.argv[2], process.argv[3] as FilterType);
|
||||
|
||||
console.log(JSON.stringify(ast, null, ' '));
|
||||
|
||||
console.log('***************** MS SQL ******************');
|
||||
console.log(treeToSql(engines('mssql'), ast, dumpSqlCondition));
|
||||
|
||||
console.log('***************** MySql *******************');
|
||||
console.log(treeToSql(engines('mysql'), ast, dumpSqlCondition));
|
||||
|
||||
console.log('***************** Postgre *****************');
|
||||
console.log(treeToSql(engines('postgres'), ast, dumpSqlCondition));
|
||||
@@ -7,6 +7,10 @@ function token(parser) {
|
||||
return parser.skip(whitespace);
|
||||
}
|
||||
|
||||
function word(str) {
|
||||
return P.string(str).thru(token);
|
||||
}
|
||||
|
||||
function interpretEscapes(str) {
|
||||
let escapes = {
|
||||
b: '\b',
|
||||
@@ -28,17 +32,61 @@ function interpretEscapes(str) {
|
||||
});
|
||||
}
|
||||
|
||||
const parser = P.createLanguage({
|
||||
expr: r => P.alt(r.string),
|
||||
const binaryCondition = operator => value => ({
|
||||
conditionType: 'binary',
|
||||
operator,
|
||||
left: {
|
||||
exprType: 'placeholder',
|
||||
},
|
||||
right: {
|
||||
exprType: 'value',
|
||||
value,
|
||||
},
|
||||
});
|
||||
|
||||
string: () =>
|
||||
const compoudCondition = conditionType => conditions => {
|
||||
if (conditions.length == 1) return conditions[0];
|
||||
return {
|
||||
conditionType,
|
||||
conditions,
|
||||
};
|
||||
};
|
||||
|
||||
const parser = P.createLanguage({
|
||||
string1: () =>
|
||||
token(P.regexp(/"((?:\\.|.)*?)"/, 1))
|
||||
.map(interpretEscapes)
|
||||
.desc('string'),
|
||||
.map(binaryCondition('='))
|
||||
.desc('string quoted'),
|
||||
|
||||
string2: () =>
|
||||
token(P.regexp(/'((?:\\.|.)*?)'/, 1))
|
||||
.map(interpretEscapes)
|
||||
.map(binaryCondition('='))
|
||||
.desc('string quoted'),
|
||||
|
||||
number: () =>
|
||||
token(P.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/))
|
||||
.map(Number)
|
||||
.map(binaryCondition('='))
|
||||
.desc('number'),
|
||||
|
||||
noQuotedString: () =>
|
||||
P.regexp(/[^\s]+/)
|
||||
.desc('string unquoted')
|
||||
.map(binaryCondition('=')),
|
||||
|
||||
comma: () => word(','),
|
||||
not: () => word('NOT'),
|
||||
notNull: r => r.not.then(r.null).map(() => 'NOT_NULL'),
|
||||
null: () => word('NULL'),
|
||||
|
||||
element: r => P.alt(r.string1, r.string2, r.null, r.notNull, r.number, r.noQuotedString).trim(whitespace),
|
||||
factor: r => r.element.sepBy(whitespace).map(compoudCondition('and')),
|
||||
list: r => r.factor.sepBy(r.comma).map(compoudCondition('or')),
|
||||
});
|
||||
|
||||
export function parseFilter(value: string, filterType: FilterType) {
|
||||
const ast = parser.expr.tryParse(value);
|
||||
console.log(ast);
|
||||
const ast = parser.list.tryParse(value);
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import parserFilter, { parseFilter } from './parseFilter';
|
||||
import { parseFilter } from './parseFilter';
|
||||
|
||||
test('parse string', parseFilter('"123"', 'string'));
|
||||
test('parse string', () => {
|
||||
const ast = parseFilter('"123"', 'string');
|
||||
console.log(JSON.stringify(ast));
|
||||
expect(ast).toBe(3);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user