mirror of
https://github.com/h-sphere/sql-seal.git
synced 2026-07-22 10:10:28 +00:00
fix(parser): fixing select keyword parsing outside the SQL queries (#206)
* fix(parser): prevent 'select' keyword in config objects from being parsed as SQL query * fix: fixing parsing with SELECT keywords outside sql queries * chore: adding changeset
This commit is contained in:
parent
d9cb4d5fea
commit
03dfcd78b2
3 changed files with 115 additions and 1 deletions
5
.changeset/bright-weeks-chew.md
Normal file
5
.changeset/bright-weeks-chew.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"sqlseal": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fixing issue with select keywords outside SQL queries
|
||||||
|
|
@ -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', () => {
|
it('should properly handle chart', () => {
|
||||||
expect(parseWithDefaults(`
|
expect(parseWithDefaults(`
|
||||||
TABLE data = file(test_data.csv)
|
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: []
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
@ -53,7 +53,7 @@ export const SQLSealLangDefinition = (views: ViewDefinition[], flags: readonly F
|
||||||
anyObject = "{" (~selectKeyword any)*
|
anyObject = "{" (~selectKeyword any)*
|
||||||
handlebarsTemplate = (~selectKeyword any)*
|
handlebarsTemplate = (~selectKeyword any)*
|
||||||
javascriptTemplate = (~selectKeyword any)*
|
javascriptTemplate = (~selectKeyword any)*
|
||||||
selectKeyword = caseInsensitive<"WITH"> | caseInsensitive<"SELECT">
|
selectKeyword = (caseInsensitive<"WITH"> | caseInsensitive<"SELECT">) &(space | nl | end)
|
||||||
tableKeyword = caseInsensitive<"TABLE">
|
tableKeyword = caseInsensitive<"TABLE">
|
||||||
nl = "\n"
|
nl = "\n"
|
||||||
character = (alnum | "." | "-" | space | "_")
|
character = (alnum | "." | "-" | space | "_")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue