Skip to content

Commit 6d4be38

Browse files
Merge pull request #2030 from taozhi8833998/refactor-sqlite
refactor: change sqlite identify from bracket to double quotation / support double equal symbol and subquery
2 parents d4f8ea1 + 4517695 commit 6d4be38

File tree

3 files changed

+47
-30
lines changed

3 files changed

+47
-30
lines changed

pegjs/sqlite.pegjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2049,7 +2049,7 @@ arithmetic_op_right
20492049
}
20502050

20512051
arithmetic_comparison_operator
2052-
= ">=" / ">" / "<=" / "<>" / "<" / "=" / "!="
2052+
= ">=" / ">" / "<=" / "<>" / "<" / "==" / "=" / "!="
20532053

20542054
is_op_right
20552055
= KW_IS __ right:additive_expr {

src/util.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ function columnIdentifierToSql(ident) {
138138
case 'snowflake':
139139
case 'noql':
140140
case 'trino':
141+
case 'sqlite':
141142
return `"${ident}"`
142143
case 'transactsql':
143144
return `[${ident}]`
@@ -157,13 +158,13 @@ function identifierToSql(ident, isDual) {
157158
switch (database && database.toLowerCase()) {
158159
case 'mysql':
159160
case 'mariadb':
160-
case 'sqlite':
161161
return `\`${ident}\``
162162
case 'postgresql':
163163
case 'redshift':
164164
case 'snowflake':
165165
case 'trino':
166166
case 'noql':
167+
case 'sqlite':
167168
return `"${ident}"`
168169
case 'transactsql':
169170
return `[${ident}]`

test/sqlite.spec.js

+44-28
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ describe('sqlite', () => {
1212

1313
it('should support analyze', () => {
1414
const sql = 'analyze schemaName.tableName'
15-
expect(getParsedSql(sql)).to.be.equal('ANALYZE `schemaName`.`tableName`')
15+
expect(getParsedSql(sql)).to.be.equal('ANALYZE "schemaName"."tableName"')
1616
})
1717

1818
it('should support attach', () => {
1919
const sql = "attach database 'c:\sqlite\db\contacts.db' as contacts;"
20-
expect(getParsedSql(sql)).to.be.equal("ATTACH DATABASE 'c:\sqlite\db\contacts.db' AS `contacts`")
20+
expect(getParsedSql(sql)).to.be.equal(`ATTACH DATABASE 'c:sqlitedbcontacts.db' AS "contacts"`)
2121
})
2222

2323
it('should support json function in from clause', () => {
@@ -27,7 +27,7 @@ describe('sqlite', () => {
2727
json_each(post.author, '$')
2828
GROUP BY
2929
author_id;`
30-
expect(getParsedSql(sql)).to.be.equal("SELECT json_extract(`value`, '$.id') AS `author_id` FROM `post`, json_each(`post`.`author`, '$') GROUP BY `author_id`")
30+
expect(getParsedSql(sql)).to.be.equal(`SELECT json_extract("value", '$.id') AS "author_id" FROM "post", json_each("post"."author", '$') GROUP BY "author_id"`)
3131
})
3232

3333
it('should support || in where clause', () => {
@@ -39,7 +39,7 @@ describe('sqlite', () => {
3939
WHERE user.name = "pepe" || "rone"
4040
) u ON pets.owner = u.id
4141
GROUP BY pets.id;`
42-
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM `pets` LEFT JOIN (SELECT * FROM `user` WHERE `user`.`name` = "pepe" || "rone") AS `u` ON `pets`.`owner` = `u`.`id` GROUP BY `pets`.`id`')
42+
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM "pets" LEFT JOIN (SELECT * FROM "user" WHERE "user"."name" = "pepe" || "rone") AS "u" ON "pets"."owner" = "u"."id" GROUP BY "pets"."id"')
4343
})
4444

4545
it('should support or combine with )', () => {
@@ -51,7 +51,7 @@ describe('sqlite', () => {
5151
WHERE user.code = UPPER("test")
5252
OR user.name = "pepe") u ON pets.owner = u.id
5353
GROUP BY pets.id;`
54-
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM `pets` LEFT JOIN (SELECT * FROM `user` WHERE `user`.`code` = UPPER("test") OR `user`.`name` = "pepe") AS `u` ON `pets`.`owner` = `u`.`id` GROUP BY `pets`.`id`')
54+
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM "pets" LEFT JOIN (SELECT * FROM "user" WHERE "user"."code" = UPPER("test") OR "user"."name" = "pepe") AS "u" ON "pets"."owner" = "u"."id" GROUP BY "pets"."id"')
5555
sql = `SELECT *
5656
FROM
5757
pets
@@ -62,7 +62,7 @@ describe('sqlite', () => {
6262
OR user.code = UPPER("more_test")
6363
) u ON pets.owner = u.id
6464
GROUP BY pets.id;`
65-
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM `pets` LEFT JOIN (SELECT * FROM `user` WHERE `user`.`name` = "pepe" || "rone" OR `user`.`code` = UPPER("test") OR `user`.`code` = UPPER("more_test")) AS `u` ON `pets`.`owner` = `u`.`id` GROUP BY `pets`.`id`')
65+
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM "pets" LEFT JOIN (SELECT * FROM "user" WHERE "user"."name" = "pepe" || "rone" OR "user"."code" = UPPER("test") OR "user"."code" = UPPER("more_test")) AS "u" ON "pets"."owner" = "u"."id" GROUP BY "pets"."id"')
6666
})
6767

6868
it('should support json as function name', () => {
@@ -79,34 +79,34 @@ describe('sqlite', () => {
7979
floor
8080
WHERE
8181
floor.id = 1;`
82-
expect(getParsedSql(sql)).to.be.equal("SELECT `id`, json_object('hasGeometry', CASE WHEN json_extract(`floor`.`rect`, '$') IS '{\"boundariesList\":[]}' THEN json('false') ELSE json('true') END) AS `metadata` FROM `floor` WHERE `floor`.`id` = 1")
82+
expect(getParsedSql(sql)).to.be.equal(`SELECT "id", json_object('hasGeometry', CASE WHEN json_extract("floor"."rect", '$') IS '{"boundariesList":[]}' THEN json('false') ELSE json('true') END) AS "metadata" FROM "floor" WHERE "floor"."id" = 1`)
8383
})
8484

8585
it('should support glob operator', () => {
8686
const sql = "SELECT device.id FROM device WHERE device.model GLOB '*XYZ';"
87-
expect(getParsedSql(sql)).to.be.equal("SELECT `device`.`id` FROM `device` WHERE `device`.`model` GLOB '*XYZ'")
87+
expect(getParsedSql(sql)).to.be.equal(`SELECT "device"."id" FROM "device" WHERE "device"."model" GLOB '*XYZ'`)
8888
})
8989

9090
it('should support create table...as', () => {
9191
const sql = `CREATE TABLE IF NOT EXISTS stg_devices AS SELECT * FROM devices WHERE 1 = 0;`
92-
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE IF NOT EXISTS `stg_devices` AS SELECT * FROM `devices` WHERE 1 = 0')
92+
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE IF NOT EXISTS "stg_devices" AS SELECT * FROM "devices" WHERE 1 = 0')
9393
})
9494

9595
it('should support escape single quote', () => {
9696
const sql = "SELECT name, 'doesn''t smoke' FROM people WHERE name = 'John';"
97-
expect(getParsedSql(sql)).to.be.equal("SELECT `name`, 'doesn''t smoke' FROM `people` WHERE `name` = 'John'")
97+
expect(getParsedSql(sql)).to.be.equal(`SELECT "name", 'doesn''t smoke' FROM "people" WHERE "name" = 'John'`)
9898
})
9999

100100
it('should support create with autoincrement, boolean type and definition could be empty', () => {
101101
let sql = 'CREATE TABLE `foobar1` (`id` integer not null primary key autoincrement, `name` varchar(255), `batch` boolean, `migration_time` datetime)'
102-
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE `foobar1` (`id` INTEGER NOT NULL AUTOINCREMENT PRIMARY KEY, `name` VARCHAR(255), `batch` BOOLEAN, `migration_time` DATETIME)')
102+
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE "foobar1" ("id" INTEGER NOT NULL AUTOINCREMENT PRIMARY KEY, "name" VARCHAR(255), "batch" BOOLEAN, "migration_time" DATETIME)')
103103
sql = 'CREATE TABLE sqlite_stat4(tbl,idx,neq,nlt,ndlt,sample)'
104-
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE `sqlite_stat4` (`tbl`, `idx`, `neq`, `nlt`, `ndlt`, `sample`)')
104+
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE "sqlite_stat4" ("tbl", "idx", "neq", "nlt", "ndlt", "sample")')
105105
})
106106

107107
it('should support with clause table name', () => {
108108
const sql = 'with `e` as (select * from employees) SELECT name,`e`.`hired_on` FROM `e`'
109-
expect(getParsedSql(sql)).to.be.equal('WITH `e` AS (SELECT * FROM `employees`) SELECT `name`, `e`.`hired_on` FROM `e`')
109+
expect(getParsedSql(sql)).to.be.equal('WITH "e" AS (SELECT * FROM "employees") SELECT "name", "e"."hired_on" FROM "e"')
110110
})
111111

112112
it('should support blob type', () => {
@@ -116,36 +116,36 @@ describe('sqlite', () => {
116116
"expires_at" INTEGER,
117117
PRIMARY KEY("service_name","expires_at")
118118
)`
119-
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE `session_caches` (`service_name` TEXT NOT NULL, `session_data` BLOB NOT NULL, `expires_at` INTEGER, PRIMARY KEY (`service_name`, `expires_at`))')
119+
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE "session_caches" ("service_name" TEXT NOT NULL, "session_data" BLOB NOT NULL, "expires_at" INTEGER, PRIMARY KEY ("service_name", "expires_at"))')
120120
})
121121
it('should support missing number after dot in number', () => {
122122
const sql = 'select count(*)*1. from abc'
123-
expect(getParsedSql(sql)).to.be.equal('SELECT COUNT(*) * 1 FROM `abc`')
123+
expect(getParsedSql(sql)).to.be.equal('SELECT COUNT(*) * 1 FROM "abc"')
124124
})
125125
it('should support create trigger', () => {
126126
let sql = `CREATE TRIGGER update_customer_address UPDATE OF address ON customers
127127
BEGIN
128128
UPDATE orders SET address = new.address WHERE customer_name = old.name;
129129
END;`
130-
expect(getParsedSql(sql)).to.be.equal('CREATE TRIGGER `update_customer_address` UPDATE OF `address` ON `customers` BEGIN UPDATE `orders` SET `address` = `new`.`address` WHERE `customer_name` = `old`.`name` END')
130+
expect(getParsedSql(sql)).to.be.equal('CREATE TRIGGER "update_customer_address" UPDATE OF "address" ON "customers" BEGIN UPDATE "orders" SET "address" = "new"."address" WHERE "customer_name" = "old"."name" END')
131131
})
132132

133133
it('should support union', () => {
134134
let sql = `SELECT * FROM a UNION SELECT * FROM b`
135-
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM `a` UNION SELECT * FROM `b`')
135+
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM "a" UNION SELECT * FROM "b"')
136136

137137
sql = `SELECT * FROM a UNION ALL SELECT * FROM b`
138-
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM `a` UNION ALL SELECT * FROM `b`')
138+
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM "a" UNION ALL SELECT * FROM "b"')
139139

140140
sql = `SELECT * FROM a UNION DISTINCT SELECT * FROM b`
141-
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM `a` UNION DISTINCT SELECT * FROM `b`')
141+
expect(getParsedSql(sql)).to.be.equal('SELECT * FROM "a" UNION DISTINCT SELECT * FROM "b"')
142142
})
143143

144144
it('should support keyword as column name in create table sql', () => {
145145
let sql = 'CREATE TABLE IF NOT EXISTS "Test" (Id INTEGER NOT NULL PRIMARY KEY UNIQUE, like TEXT NOT NULL, Difficulty TEXT, percent real, PRIMARY KEY(Id));'
146-
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE IF NOT EXISTS `Test` (`Id` INTEGER NOT NULL PRIMARY KEY UNIQUE, `like` TEXT NOT NULL, `Difficulty` TEXT, `percent` REAL, PRIMARY KEY (`Id`))')
146+
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE IF NOT EXISTS "Test" ("Id" INTEGER NOT NULL PRIMARY KEY UNIQUE, "like" TEXT NOT NULL, "Difficulty" TEXT, "percent" REAL, PRIMARY KEY ("Id"))')
147147
sql = "SELECT * from tb WHERE NOT EXISTS (SELECT * FROM tb WHERE field1 = 'c' AND field2 = d)"
148-
expect(getParsedSql(sql)).to.be.equal("SELECT * FROM `tb` WHERE NOT EXISTS (SELECT * FROM `tb` WHERE `field1` = 'c' AND `field2` = `d`)")
148+
expect(getParsedSql(sql)).to.be.equal(`SELECT * FROM "tb" WHERE NOT EXISTS (SELECT * FROM "tb" WHERE "field1" = 'c' AND "field2" = "d")`)
149149
})
150150

151151
it('should support sqlify autoincrement to other db', () => {
@@ -154,16 +154,16 @@ describe('sqlite', () => {
154154
expect(parser.sqlify(ast, { database: 'mariadb'})).to.be.equal('CREATE TABLE IF NOT EXISTS `SampleTable` (`ID` INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY UNIQUE, `Name` TEXT NOT NULL)')
155155
sql = ' CREATE TABLE `Test` ( `id` int(11) NOT NULL, `name` varchar(255) COLLATE utf8mb4_unicode_520_ci NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`));'
156156
ast = parser.astify(sql, { database: 'mariadb' })
157-
expect(parser.sqlify(ast, DEFAULT_OPT)).to.be.equal('CREATE TABLE `Test` (`id` INT(11) NOT NULL, `name` VARCHAR(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE (`name`))')
157+
expect(parser.sqlify(ast, DEFAULT_OPT)).to.be.equal('CREATE TABLE "Test" ("id" INT(11) NOT NULL, "name" VARCHAR(255) NOT NULL, PRIMARY KEY ("id"), UNIQUE ("name"))')
158158
})
159159

160160
it('should support create or drop view', () => {
161161
let sql = 'create view v1 as select * from t1'
162-
expect(getParsedSql(sql)).to.be.equal('CREATE VIEW `v1` AS SELECT * FROM `t1`')
162+
expect(getParsedSql(sql)).to.be.equal('CREATE VIEW "v1" AS SELECT * FROM "t1"')
163163
sql = 'create temp view if not exists s.v1(a, b, c) as select * from t1'
164-
expect(getParsedSql(sql)).to.be.equal('CREATE TEMP VIEW IF NOT EXISTS `s`.`v1` (`a`, `b`, `c`) AS SELECT * FROM `t1`')
164+
expect(getParsedSql(sql)).to.be.equal('CREATE TEMP VIEW IF NOT EXISTS "s"."v1" ("a", "b", "c") AS SELECT * FROM "t1"')
165165
sql = 'DROP VIEW IF EXISTS view_name;',
166-
expect(getParsedSql(sql)).to.be.equal('DROP VIEW IF EXISTS `view_name`')
166+
expect(getParsedSql(sql)).to.be.equal('DROP VIEW IF EXISTS "view_name"')
167167
})
168168

169169
it('should create table and alter table', () => {
@@ -172,10 +172,26 @@ describe('sqlite', () => {
172172
FOREIGN KEY (user_id) REFERENCES users(user_id)
173173
);
174174
`
175-
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE IF NOT EXISTS `posts` (`user_id` INTEGER NOT NULL, FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`))')
175+
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE IF NOT EXISTS "posts" ("user_id" INTEGER NOT NULL, FOREIGN KEY ("user_id") REFERENCES "users" ("user_id"))')
176176
sql = 'CREATE TABLE users (age INTEGER CHECK(age >= 18));'
177-
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE `users` (`age` INTEGER CHECK (`age` >= 18))')
177+
expect(getParsedSql(sql)).to.be.equal('CREATE TABLE "users" ("age" INTEGER CHECK ("age" >= 18))')
178178
sql = 'ALTER TABLE customers RENAME COLUMN age TO customer_age;'
179-
expect(getParsedSql(sql)).to.be.equal('ALTER TABLE `customers` RENAME COLUMN `age` TO `customer_age`')
179+
expect(getParsedSql(sql)).to.be.equal('ALTER TABLE "customers" RENAME COLUMN "age" TO "customer_age"')
180+
})
181+
182+
it('should support double equal', () => {
183+
const sql = "SELECT * FROM sqlite_master WHERE name == 'test'"
184+
expect(getParsedSql(sql)).to.be.equal(`SELECT * FROM "sqlite_master" WHERE "name" == 'test'`)
185+
})
186+
187+
it('should support subquery', () => {
188+
const sql = `SELECT SUM("Hours Spent") AS "Total Hours"
189+
FROM "Work_Records"
190+
WHERE "Partner ID" =
191+
(SELECT "Partner ID"
192+
FROM "Employees"
193+
WHERE "Firstname" = 'John' AND "Lastname" = 'Smith')
194+
`
195+
expect(getParsedSql(sql)).to.be.equal(`SELECT SUM("Hours Spent") AS "Total Hours" FROM "Work_Records" WHERE "Partner ID" = (SELECT "Partner ID" FROM "Employees" WHERE "Firstname" = 'John' AND "Lastname" = 'Smith')`)
180196
})
181197
})

0 commit comments

Comments
 (0)