From 0226ab3c7dc5717f99cdf1b5c254745bfaf9203a Mon Sep 17 00:00:00 2001 From: taozhi8833998 Date: Sun, 13 Oct 2024 11:20:42 +0800 Subject: [PATCH] feat: support create table option in sqlite --- pegjs/sqlite.pegjs | 32 +++++++++++++++++++------------- src/create.js | 7 ++++++- src/tables.js | 2 +- test/sqlite.spec.js | 8 ++++---- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/pegjs/sqlite.pegjs b/pegjs/sqlite.pegjs index 0c519d23..fc98b698 100644 --- a/pegjs/sqlite.pegjs +++ b/pegjs/sqlite.pegjs @@ -417,15 +417,12 @@ create_view_stmt create_table_stmt = a:KW_CREATE __ - tp:KW_TEMPORARY? __ + tp:(KW_TEMPORARY / KW_TEMP)? __ KW_TABLE __ ife:if_not_exists_stmt? __ t:table_name __ - c:create_table_definition? __ - to:table_options? __ - ir: (KW_IGNORE / KW_REPLACE)? __ - as: KW_AS? __ - qe: union_stmt? { + c:create_table_definition __ + to:table_options? { if(t) tableList.add(`create::${t.db}::${t.table}`) return { tableList: Array.from(tableList), @@ -436,20 +433,18 @@ create_table_stmt temporary: tp && tp[0].toLowerCase(), if_not_exists:ife, table: [t], - ignore_replace: ir && ir[0].toLowerCase(), - as: as && as[0].toLowerCase(), - query_expr: qe && qe.ast, create_definitions: c, table_options: to } } } / a:KW_CREATE __ - tp:KW_TEMPORARY? __ + tp:(KW_TEMPORARY / KW_TEMP)? __ KW_TABLE __ ife:if_not_exists_stmt? __ t:table_name __ - lt:create_like_table { + as:KW_AS __ + qe:select_stmt { if(t) tableList.add(`create::${t.db}::${t.table}`) return { tableList: Array.from(tableList), @@ -458,9 +453,10 @@ create_table_stmt type: a[0].toLowerCase(), keyword: 'table', temporary: tp && tp[0].toLowerCase(), - if_not_exists:ife, + if_not_exists: ife, table: [t], - like: lt + as: 'as', + query_expr: qe, } } } @@ -1144,6 +1140,16 @@ table_option value: c.toUpperCase() } } + / 'WITHOUT'i __ 'ROWID'i { + return { + keyword: 'without rowid' + } + } + / 'STRICT'i { + return { + keyword: 'strict' + } + } rename_stmt diff --git a/src/create.js b/src/create.js index 95fee43d..f459ce86 100644 --- a/src/create.js +++ b/src/create.js @@ -16,6 +16,7 @@ import { commentToSQL, commonTypeValue, dataTypeToSQL, + getParserOpt, toUpper, hasVal, identifierToSql, @@ -85,7 +86,11 @@ function createTableToSQL(stmt) { } if (partitionOf) return sql.concat([createTablePartitionOfToSQL(partitionOf)]).filter(hasVal).join(' ') if (createDefinition) sql.push(`(${createDefinition.map(createDefinitionToSQL).join(', ')})`) - if (tableOptions) sql.push(tableOptions.map(tableOptionToSQL).join(' ')) + if (tableOptions) { + const { database } = getParserOpt() + const symbol = database && database.toLowerCase() === 'sqlite' ? ', ' : ' ' + sql.push(tableOptions.map(tableOptionToSQL).join(symbol)) + } if (withExpr) { const withSQL = withExpr.map(withExprItem => [literalToSQL(withExprItem.keyword), toUpper(withExprItem.symbol), literalToSQL(withExprItem.value)].join(' ')).join(', ') sql.push(`WITH (${withSQL})`) diff --git a/src/tables.js b/src/tables.js index ac57b85c..068ebd60 100644 --- a/src/tables.js +++ b/src/tables.js @@ -200,7 +200,7 @@ function tableOptionToSQL(tableOption) { break } sql.push(val) - return sql.join(' ') + return sql.filter(hasVal).join(' ') } export { diff --git a/test/sqlite.spec.js b/test/sqlite.spec.js index c6326cf3..2a518c03 100644 --- a/test/sqlite.spec.js +++ b/test/sqlite.spec.js @@ -176,11 +176,11 @@ describe('sqlite', () => { let sql = `CREATE TABLE IF NOT EXISTS posts ( user_id INTEGER NOT NULL, FOREIGN KEY (user_id) REFERENCES users(user_id) - ); + ) WITHOUT ROWID; ` - 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"))') - sql = 'CREATE TABLE users (age INTEGER CHECK(age >= 18));' - expect(getParsedSql(sql)).to.be.equal('CREATE TABLE "users" ("age" INTEGER CHECK ("age" >= 18))') + 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")) WITHOUT ROWID') + sql = 'CREATE TABLE users (age INTEGER CHECK(age >= 18)) STRICT, WITHOUT ROWID;' + expect(getParsedSql(sql)).to.be.equal('CREATE TABLE "users" ("age" INTEGER CHECK ("age" >= 18)) STRICT, WITHOUT ROWID') sql = 'ALTER TABLE customers RENAME COLUMN age TO customer_age;' expect(getParsedSql(sql)).to.be.equal('ALTER TABLE "customers" RENAME COLUMN "age" TO "customer_age"') })