Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pegjs/sqlite.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -1316,7 +1316,7 @@ with_clause
}

cte_definition
= name:(literal_string / ident_name / table_name) __ columns:cte_column_definition? __ KW_AS __ LPAREN __ stmt:union_stmt __ RPAREN {
= name:(literal_string / ident_name / table_name) __ columns:cte_column_definition? __ KW_AS __ LPAREN __ stmt:(value_clause / union_stmt) __ RPAREN {
if (typeof name === 'string') name = { type: 'default', value: name }
if (name.table) name = { type: 'default', value: name.table }
return { name, stmt, columns };
Expand Down
74 changes: 74 additions & 0 deletions test/sqlite.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,78 @@ describe('sqlite', () => {
'SELECT * FROM "t1" CROSS JOIN "t2" INNER JOIN "t3" ON "t2"."id" = "t3"."id"'
);
});

it('should support VALUES in a CTE', () => {
const sql = `WITH cte1 (col1, col2) AS (
VALUES ('Name1', 'type1'), ('Name2', 'type1')
)
SELECT a.name
FROM table1 a
JOIN cte1 c ON lower(a.name) = lower(c.col1)`;
expect(getParsedSql(sql)).to.be.equal(
`WITH "cte1"("col1", "col2") AS (VALUES ('Name1','type1'), ('Name2','type1')) SELECT "a"."name" FROM "table1" AS "a" INNER JOIN "cte1" AS "c" ON lower("a"."name") = lower("c"."col1")`
);
});

it('should support single-column VALUES in a CTE', () => {
const sql = `WITH cte1 (col1) AS (
VALUES ('Value1'), ('Value2')
)
SELECT a.name FROM table1 a JOIN cte1 c ON lower(a.name) = lower(c.col1)`;
expect(getParsedSql(sql)).to.be.equal(
`WITH "cte1"("col1") AS (VALUES ('Value1'), ('Value2')) SELECT "a"."name" FROM "table1" AS "a" INNER JOIN "cte1" AS "c" ON lower("a"."name") = lower("c"."col1")`
);
});

it('should support VALUES in a CTE without an explicit column list', () => {
const sql = `WITH cte1 AS (
VALUES ('Value1'), ('Value2')
)
SELECT * FROM cte1`;
expect(getParsedSql(sql)).to.be.equal(
`WITH "cte1" AS (VALUES ('Value1'), ('Value2')) SELECT * FROM "cte1"`
);
});

it('should support VALUES in a CTE with a trailing semicolon', () => {
const sql = `WITH cte1 (col1) AS (
VALUES ('Value1'), ('Value2')
)
SELECT a.name FROM table1 a JOIN cte1 c ON lower(a.name) = lower(c.col1);`;
expect(getParsedSql(sql)).to.be.equal(
`WITH "cte1"("col1") AS (VALUES ('Value1'), ('Value2')) SELECT "a"."name" FROM "table1" AS "a" INNER JOIN "cte1" AS "c" ON lower("a"."name") = lower("c"."col1")`
);
});

it('should support multiple CTEs with VALUES and SELECT', () => {
const sql = `WITH cte1 (col1) AS (
VALUES ('Value1'), ('Value2')
),
cte2 AS (
SELECT name FROM table1 WHERE name IS NOT NULL
)
SELECT f.name, c.col1
FROM cte2 f
JOIN cte1 c ON lower(f.name) = lower(c.col1)`;
expect(getParsedSql(sql)).to.be.equal(
`WITH "cte1"("col1") AS (VALUES ('Value1'), ('Value2')), "cte2" AS (SELECT "name" FROM "table1" WHERE "name" IS NOT NULL) SELECT "f"."name", "c"."col1" FROM "cte2" AS "f" INNER JOIN "cte1" AS "c" ON lower("f"."name") = lower("c"."col1")`
);
});

it('should support VALUES and UNION ALL CTEs in the same query', () => {
const sql = `WITH cte1 (col1, col2) AS (
VALUES ('Name1', 'type1')
),
cte2 AS (
SELECT 'Name2' AS col1, 'type1' AS col2
UNION ALL
SELECT 'Name3', 'type1'
)
SELECT v.col1 FROM cte1 v
UNION ALL
SELECT u.col1 FROM cte2 u`;
expect(getParsedSql(sql)).to.be.equal(
`WITH "cte1"("col1", "col2") AS (VALUES ('Name1','type1')), "cte2" AS (SELECT 'Name2' AS "col1", 'type1' AS "col2" UNION ALL SELECT 'Name3', 'type1') SELECT "v"."col1" FROM "cte1" AS "v" UNION ALL SELECT "u"."col1" FROM "cte2" AS "u"`
);
});
})