Skip to content

Commit 5062a4b

Browse files
Copilotmathiasrw
andauthored
Allow table names starting with numbers to fix #1185 (#2316)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: mathiasrw <[email protected]>
1 parent fc10673 commit 5062a4b

File tree

4 files changed

+68
-34
lines changed

4 files changed

+68
-34
lines changed

src/alasqlparser.jison

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,10 +270,9 @@ SETS return 'SET'
270270
'WITH' return 'WITH'
271271
'WORK' return 'TRANSACTION' /* Is this keyword required? */
272272

273-
/* Issue #1173: Reject invalid identifiers like 6minAvgOpac (number followed by letters without space) */
274-
/* This rule must precede NUMBER to catch invalid patterns before they're tokenized as NUMBER + LITERAL */
275-
\d+[a-zA-Z_][a-zA-Z_0-9]* return 'INVALID'
276-
(\d+\.?\d*|\.\d+)([eE][+-]?\d+)? return 'NUMBER'
273+
/* LITERAL must come before NUMBER to match identifiers like 50k, 100x as single tokens */
274+
[0-9]*[a-zA-Z_]+[a-zA-Z_0-9]* return 'LITERAL'
275+
(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?(?![a-zA-Z_0-9]) return 'NUMBER'
277276
'->' return 'ARROW'
278277
'#' return 'SHARP'
279278
'+' return 'PLUS'
@@ -318,7 +317,6 @@ SETS return 'SET'
318317

319318
'~' return 'TILDA'
320319

321-
[0-9]*[a-zA-Z_]+[a-zA-Z_0-9]* return 'LITERAL'
322320
'@' return 'AT'
323321
<<EOF>> return 'EOF'
324322
. return 'INVALID'

src/alasqlparser.js

Lines changed: 6 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/test1173.js

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ if (typeof exports === 'object') {
33
var alasql = require('..');
44
}
55

6-
describe('Test 1173 - Parser should error on column names starting with numbers', function () {
6+
describe('Test 1173 - Parser behavior for identifiers with special patterns', function () {
77
const test = '1173';
88

99
before(function () {
@@ -31,30 +31,21 @@ describe('Test 1173 - Parser should error on column names starting with numbers'
3131
assert.equal(ast.statements[0].columns[1].columnid, '6minAvgOpac');
3232
});
3333

34-
it('C) Should throw error for unquoted column name starting with number', function () {
34+
it('C) Should now parse unquoted column name starting with number (behavior changed in #1185)', function () {
35+
// After fix for #1185, identifiers starting with numbers are now allowed
3536
var sql = 'SELECT ID, 6minAvgOpac FROM test';
36-
assert.throws(
37-
function () {
38-
alasql.parse(sql);
39-
},
40-
function (err) {
41-
return err instanceof SyntaxError || err instanceof Error;
42-
},
43-
'Should throw a SyntaxError for invalid column name starting with number'
44-
);
37+
var ast = alasql.parse(sql);
38+
assert.equal(ast.statements[0].columns.length, 2);
39+
assert.equal(ast.statements[0].columns[0].columnid, 'ID');
40+
assert.equal(ast.statements[0].columns[1].columnid, '6minAvgOpac');
4541
});
4642

47-
it('D) Should throw error for similar invalid identifier pattern', function () {
43+
it('D) Should now parse identifiers like 123abc (behavior changed in #1185)', function () {
44+
// After fix for #1185, identifiers starting with numbers are now allowed
4845
var sql = 'SELECT 123abc FROM test';
49-
assert.throws(
50-
function () {
51-
alasql.parse(sql);
52-
},
53-
function (err) {
54-
return err instanceof SyntaxError || err instanceof Error;
55-
},
56-
'Should throw a SyntaxError for invalid identifier 123abc'
57-
);
46+
var ast = alasql.parse(sql);
47+
assert.equal(ast.statements[0].columns.length, 1);
48+
assert.equal(ast.statements[0].columns[0].columnid, '123abc');
5849
});
5950

6051
it('E) Valid number literals followed by proper aliases should still work', function () {

test/test1185.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
if (typeof exports === 'object') {
2+
var assert = require('assert');
3+
var alasql = require('..');
4+
}
5+
6+
describe('Test 1185 - Table names starting with numbers', function () {
7+
const test = '1185'; // insert test file number
8+
9+
before(function () {
10+
alasql('create database test' + test);
11+
alasql('use test' + test);
12+
});
13+
14+
after(function () {
15+
alasql('drop database test' + test);
16+
});
17+
18+
it('A) Table name starting with number (e.g., 50ks)', function () {
19+
alasql('CREATE TABLE `50ks` (id INT, name STRING)');
20+
alasql('INSERT INTO `50ks` VALUES (1, "test")');
21+
var res = alasql('SELECT * FROM `50ks`');
22+
assert.deepEqual(res, [{id: 1, name: 'test'}]);
23+
});
24+
25+
it('B) Table name starting with number without backticks', function () {
26+
alasql('CREATE TABLE `50k` (id INT, name STRING)');
27+
alasql('INSERT INTO `50k` VALUES (2, "test2")');
28+
// This should work without backticks after the fix
29+
var res = alasql('SELECT * FROM 50k');
30+
assert.deepEqual(res, [{id: 2, name: 'test2'}]);
31+
});
32+
33+
it('C) Table name with schema prefix starting with number', function () {
34+
// This is the specific case from the issue: csv.50k where csv is schema, 50k is table
35+
// Create a separate database called 'csv'
36+
alasql('CREATE DATABASE csv');
37+
alasql('USE csv');
38+
alasql('CREATE TABLE `50k` (id INT, name STRING)');
39+
alasql('INSERT INTO `50k` VALUES (3, "test3")');
40+
// Query with schema.table notation where table starts with number
41+
var res = alasql('SELECT * FROM csv.50k');
42+
assert.deepEqual(res, [{id: 3, name: 'test3'}]);
43+
// Cleanup
44+
alasql('USE test1185');
45+
alasql('DROP DATABASE csv');
46+
});
47+
});

0 commit comments

Comments
 (0)