diff --git a/src/50expression.js b/src/50expression.js index a340d3c995..ba98b231cc 100755 --- a/src/50expression.js +++ b/src/50expression.js @@ -689,14 +689,27 @@ } toString() { - let s = this.columnid; + let s; - if (this.columnid == +this.columnid) { + // Check if columnid is an object with val and wrap properties (e.g., from bracket notation) + const isBracketedColumnId = + typeof this.columnid === 'object' && + this.columnid !== null && + this.columnid.val !== undefined; + + if (isBracketedColumnId) { + const wrap = this.columnid.wrap; + const closeWrap = wrap === '[' ? ']' : '`'; + s = wrap + this.columnid.val + closeWrap; + } else if (this.columnid == +this.columnid) { s = '[' + this.columnid + ']'; + } else { + s = this.columnid; } if (this.tableid) { - s = this.tableid + (this.columnid === +this.columnid ? '' : '.') + s; + const isNumericColumnId = this.columnid === +this.columnid; + s = this.tableid + (isNumericColumnId || isBracketedColumnId ? '' : '.') + s; if (this.databaseid) { s = this.databaseid + '.' + s; diff --git a/src/alasqlparser.jison b/src/alasqlparser.jison index 2e910b001c..d75f66cfec 100755 --- a/src/alasqlparser.jison +++ b/src/alasqlparser.jison @@ -356,7 +356,7 @@ Literal else $$ = $1.toLowerCase(); } | BRALITERAL - { $$ = {val:doubleq($1.substr(1,$1.length-2)), wrap:$1.substr(0,1)}; } + { $$ = {val:doubleq($1.substr(1,$1.length-2)), wrap:$1.substr(0,1)}; } | error NonReserved { $$ = $2.toLowerCase() } ; diff --git a/test/test1740.js b/test/test1740.js new file mode 100644 index 0000000000..4b4c39c436 --- /dev/null +++ b/test/test1740.js @@ -0,0 +1,44 @@ +if (typeof exports === 'object') { + var assert = require('assert'); + var alasql = require('..'); +} + +describe('Test 1740 - Parse() then AST.toString() should restore square brackets on column names', function () { + const test = '1740'; + + it('A) Column name with space should preserve square brackets', function () { + var ast = alasql.parse('SELECT [Foo Bar] FROM tbl'); + var result = ast.toString(); + assert.strictEqual(result, 'SELECT [Foo Bar] FROM tbl'); + }); + + it('B) Column name with period should preserve square brackets', function () { + var ast = alasql.parse('SELECT [Foo.Bar] FROM tbl'); + var result = ast.toString(); + assert.strictEqual(result, 'SELECT [Foo.Bar] FROM tbl'); + }); + + it('C) Regular column name should not get square brackets', function () { + var ast = alasql.parse('SELECT FooBar FROM tbl'); + var result = ast.toString(); + assert.strictEqual(result, 'SELECT FooBar FROM tbl'); + }); + + it('D) Multiple bracketed columns should all preserve square brackets', function () { + var ast = alasql.parse('SELECT [First Name], [Last Name], Age FROM users'); + var result = ast.toString(); + assert.strictEqual(result, 'SELECT [First Name], [Last Name], Age FROM users'); + }); + + it('E) Bracketed column with special characters should preserve square brackets', function () { + var ast = alasql.parse('SELECT [Column!@#] FROM tbl'); + var result = ast.toString(); + assert.strictEqual(result, 'SELECT [Column!@#] FROM tbl'); + }); + + it('F) Column name with backticks should preserve backticks', function () { + var ast = alasql.parse('SELECT `Foo Bar` FROM tbl'); + var result = ast.toString(); + assert.strictEqual(result, 'SELECT `Foo Bar` FROM tbl'); + }); +});