From 854b0fb1a4fe2b5bfef1755861e03784faf5bf37 Mon Sep 17 00:00:00 2001 From: Shuai Yang Date: Mon, 11 Nov 2019 14:26:57 +0800 Subject: [PATCH 1/2] Format code. --- js/builder.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/js/builder.js b/js/builder.js index 97e8acc..5771c65 100644 --- a/js/builder.js +++ b/js/builder.js @@ -54,14 +54,12 @@ class Generator { for (let i = 0; i < args.length; i++) { let arg = args[i]; - if (typeof arg === 'number') { + if (typeof arg === 'number' || arg === true || arg === false || (typeof arg == 'string' && arg.startsWith('function'))) { res.push(arg); } else if (Array.isArray(arg)) { res.push(`[${this.generateArgs(arg).join(',')}]`) } else if (arg instanceof Generator) { res.push(arg.generate(1, false)); - } else if (arg === true || arg === false || (typeof arg == 'string' && arg.startsWith('function'))) { - res.push(arg); } else { res.push(`'${arg}'`); } @@ -190,22 +188,20 @@ class Builder { } } - orderBy() - { + orderBy() { if (this.input.order !== null) { for (const order of this.input.order.orderings) { this.generator.addFunction('orderBy', [ - this.parseQualfiedIdFromLiteralValue(order.value), - order.direction, + this.parseQualfiedIdFromLiteralValue(order.value), + order.direction, ]); } } } - groupBy() - { + groupBy() { if (this.input.group != null) { - this.generator.addFunction('groupBy',...this.input.group.fields.map(f => this.parseQualfiedIdFromLiteralValue(f))); + this.generator.addFunction('groupBy', ...this.input.group.fields.map(f => this.parseQualfiedIdFromLiteralValue(f))); if (this.input.group.having != null) { this.generator.addFunction('having', [ From 41c99ef9e15a7d259ccfbfc4b4bb08508a3df7ca Mon Sep 17 00:00:00 2001 From: Shuai Yang Date: Mon, 11 Nov 2019 15:41:17 +0800 Subject: [PATCH 2/2] Add where exists support. --- index.html | 2 + js/builder.js | 95 ++++++++++++++++++++++++++++-------------------- js/sql-parser.js | 4 +- 3 files changed, 59 insertions(+), 42 deletions(-) diff --git a/index.html b/index.html index 81656b1..e762918 100644 --- a/index.html +++ b/index.html @@ -77,6 +77,7 @@

try { parsed = SQLParser.parse(input); + console.log(parsed); } catch (e) { document.getElementById("output").value = e.message; } @@ -89,6 +90,7 @@

try { output = builder.convert(); } catch (e) { + console.log(e); output = e.message; } diff --git a/js/builder.js b/js/builder.js index 5771c65..5034f29 100644 --- a/js/builder.js +++ b/js/builder.js @@ -129,7 +129,6 @@ class Builder { select() { if (this.input.fields.length == 1 && this.input.fields[0].constructor.name == 'Star') { - console.log('star'); return; } @@ -215,45 +214,59 @@ class Builder { parseWhere(op, pre_operation = null) { let func_name = ''; - let args = [this.parseQualfiedIdFromLiteralValue(op.left)]; - - switch (op.operation) { - case '=': - func_name = 'where'; - args.push(op.right.value); - break; - case 'IS': - if (op.right.value == null) { - func_name = 'whereNull'; - } else { + let args = []; + + if (op.constructor.name == 'UnaryOp') { + if (op.operator == 'EXISTS') { + func_name = 'whereExists'; + } else { + func_name = 'whereNotExists'; + } + + args.push(`function($query) { + ${(new Builder(op.operand.select)).convert(7, false)} + }`) + } else { + args.push(this.parseQualfiedIdFromLiteralValue(op.left)); + + switch (op.operation) { + case '=': func_name = 'where'; args.push(op.right.value); - } - - break; - case 'IS NOT': - if (op.right.value == null) { - func_name = 'whereNotNull' - } else { + break; + case 'IS': + if (op.right.value == null) { + func_name = 'whereNull'; + } else { + func_name = 'where'; + args.push(op.right.value); + } + + break; + case 'IS NOT': + if (op.right.value == null) { + func_name = 'whereNotNull' + } else { + func_name = 'where'; + args.push(op.right.value); + } + + break; + case 'IN': + func_name = 'whereIn'; + args.push(op.right.value.map(v => v.value)); + + break; + case '<': + case '!=': + case '<>': func_name = 'where'; + args.push(op.operation); args.push(op.right.value); - } - - break; - case 'IN': - func_name = 'whereIn'; - args.push(op.right.value.map(v => v.value)); - - break; - case '<': - case '!=': - case '<>': - func_name = 'where'; - args.push(op.operation); - args.push(op.right.value); - break; - default: - throw new Error(`Operator ${op.operation} not supported.`) + break; + default: + throw new Error(`Operator ${op.operation} not supported.`) + } } return new Meta(this.formatFuncName(pre_operation, func_name), args); @@ -279,13 +292,13 @@ class Builder { if (literal.nested == false) { qualfied_id = literal.value; } else { - qualfied_id = `${this.alias_table_map[literal.values[0]]}.${literal.values[1]}`; + qualfied_id = `${this.alias_table_map[literal.values[0]] ? this.alias_table_map[literal.values[0]] : literal.values[0]}.${literal.values[1]}`; } return qualfied_id; } - convert() { + convert(tab_count = 1, add_get = true) { this.source(); this.joins(); this.where(this.generator, this.input.where !== null ? this.input.where.conditions : null) @@ -293,9 +306,11 @@ class Builder { this.orderBy(); this.groupBy(); - this.generator.addFunction('get'); + if (add_get) { + this.generator.addFunction('get'); + } - return this.generator.generate(); + return this.generator.generate(tab_count); } } diff --git a/js/sql-parser.js b/js/sql-parser.js index a3cf815..5c383f8 100644 --- a/js/sql-parser.js +++ b/js/sql-parser.js @@ -209,7 +209,7 @@ SUB_SELECT_OP = ['IN', 'NOT IN', 'ANY', 'ALL', 'SOME']; - SUB_SELECT_UNARY_OP = ['EXISTS']; + SUB_SELECT_UNARY_OP = ['EXISTS', 'NOT EXISTS']; SQL_CONDITIONALS = ['AND', 'OR']; @@ -1241,4 +1241,4 @@ if (typeof module !== 'undefined' && require.main === module) { if(typeof define === 'function' && define.amd) { define(function() { return SQLParser }); } else { root.SQLParser = SQLParser } -}(this)); \ No newline at end of file +}(this));