diff --git a/.changeset/bright-weeks-chew.md b/.changeset/bright-weeks-chew.md new file mode 100644 index 0000000..199b8be --- /dev/null +++ b/.changeset/bright-weeks-chew.md @@ -0,0 +1,5 @@ +--- +"sqlseal": patch +--- + +fixing issue with select keywords outside SQL queries diff --git a/src/modules/editor/parser.test.ts b/src/modules/editor/parser.test.ts index 4917f51..316eaf5 100644 --- a/src/modules/editor/parser.test.ts +++ b/src/modules/editor/parser.test.ts @@ -336,6 +336,58 @@ describe('parseWithDefaults', () => { }) }) + it('should not treat "select" as SQL keyword when it appears as part of a config property name', () => { + // Regression test for main-0e3: `selectedMode` in a GRID/CHART config object + // was incorrectly parsed as the start of a SQL SELECT query, causing a parse error. + expect(parseWithDefaults(` + TABLE data = file(test_data.csv) +GRID { + selectedMode: true, + selectAll: false +} +SELECT * FROM data`, DEFAULT_VIEWS, DEFAULTS)).toEqual({ + flags: { explain: false, refresh: true }, + query: 'SELECT * FROM data', + renderer: { + type: 'GRID', + options: `{ + selectedMode: true, + selectAll: false +}`, + }, + tables: [{ tableAlias: 'data', arguments: ['test_data.csv'], type: 'file' }] + }) + }) + + it('should not treat "with" as SQL keyword when it appears as part of a config property name', () => { + // Same word-boundary fix covers "with" prefix: `withAnimation`, `without`, etc. + expect(parseWithDefaults(` + TABLE data = file(test_data.csv) +GRID { + withAnimation: true +} +SELECT * FROM data`, DEFAULT_VIEWS, DEFAULTS)).toEqual({ + flags: { explain: false, refresh: true }, + query: 'SELECT * FROM data', + renderer: { + type: 'GRID', + options: `{ + withAnimation: true +}`, + }, + tables: [{ tableAlias: 'data', arguments: ['test_data.csv'], type: 'file' }] + }) + }) + + it('should still parse SELECT as keyword when used as a standalone SQL clause', () => { + expect(parseWithDefaults(`SELECT * FROM files`, DEFAULT_VIEWS, DEFAULTS)).toEqual({ + flags: { explain: false, refresh: true }, + query: 'SELECT * FROM files', + renderer: { type: 'GRID', name: 'GRID', options: '' }, + tables: [] + }) + }) + it('should properly handle chart', () => { expect(parseWithDefaults(` TABLE data = file(test_data.csv) @@ -398,4 +450,61 @@ SELECT id, value FROM data`, DEFAULT_VIEWS, DEFAULTS)).toEqual({ }] }) }) + + it('should not treat "select" as SQL keyword when it appears as a quoted config property key', () => { + // Test case for fix: quoted string "select" as a property key should not break the parser + expect(parseWithDefaults(` +GRID { + "select": 4 +} +SELECT * FROM files`, DEFAULT_VIEWS, DEFAULTS)).toEqual({ + flags: { explain: false, refresh: true }, + query: 'SELECT * FROM files', + renderer: { + type: 'GRID', + options: `{ + "select": 4 +}`, + }, + tables: [] + }) + }) + + it('should not treat "select" as SQL keyword when it appears as an unquoted config property key', () => { + // Bonus test: unquoted property key with colon immediately following + expect(parseWithDefaults(` +GRID { + select: 4 +} +SELECT * FROM files`, DEFAULT_VIEWS, DEFAULTS)).toEqual({ + flags: { explain: false, refresh: true }, + query: 'SELECT * FROM files', + renderer: { + type: 'GRID', + options: `{ + select: 4 +}`, + }, + tables: [] + }) + }) + + it('should handle "select" as property key with space before colon', () => { + // Edge case: space between quoted key and colon + expect(parseWithDefaults(` +GRID { + "select" : 4 +} +SELECT * FROM files`, DEFAULT_VIEWS, DEFAULTS)).toEqual({ + flags: { explain: false, refresh: true }, + query: 'SELECT * FROM files', + renderer: { + type: 'GRID', + options: `{ + "select" : 4 +}`, + }, + tables: [] + }) + }) }) \ No newline at end of file diff --git a/src/modules/editor/parser.ts b/src/modules/editor/parser.ts index 9d5f08a..5209ba9 100644 --- a/src/modules/editor/parser.ts +++ b/src/modules/editor/parser.ts @@ -53,7 +53,7 @@ export const SQLSealLangDefinition = (views: ViewDefinition[], flags: readonly F anyObject = "{" (~selectKeyword any)* handlebarsTemplate = (~selectKeyword any)* javascriptTemplate = (~selectKeyword any)* - selectKeyword = caseInsensitive<"WITH"> | caseInsensitive<"SELECT"> + selectKeyword = (caseInsensitive<"WITH"> | caseInsensitive<"SELECT">) &(space | nl | end) tableKeyword = caseInsensitive<"TABLE"> nl = "\n" character = (alnum | "." | "-" | space | "_")