diff --git a/pegjs/athena.pegjs b/pegjs/athena.pegjs index eb2228ae..d2e69b88 100644 --- a/pegjs/athena.pegjs +++ b/pegjs/athena.pegjs @@ -285,18 +285,19 @@ if_not_exists_stmt create_db_stmt = a:KW_CREATE __ - k:(KW_DATABASE / KW_SCHEME) __ + k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } @@ -2305,7 +2306,7 @@ KW_AS = "AS"i !ident_start KW_TABLE = "TABLE"i !ident_start { return 'TABLE'; } KW_TABLES = "TABLES"i !ident_start { return 'TABLES'; } KW_DATABASE = "DATABASE"i !ident_start { return 'DATABASE'; } -KW_SCHEME = "SCHEME"i !ident_start { return 'SCHEME'; } +KW_SCHEMA = "SCHEMA"i !ident_start { return 'SCHEMA'; } KW_COLLATE = "COLLATE"i !ident_start { return 'COLLATE'; } KW_ON = "ON"i !ident_start diff --git a/pegjs/bigquery.pegjs b/pegjs/bigquery.pegjs index 3b59dbbd..d68020da 100644 --- a/pegjs/bigquery.pegjs +++ b/pegjs/bigquery.pegjs @@ -904,16 +904,17 @@ create_db_stmt = a:KW_CREATE __ k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } diff --git a/pegjs/db2.pegjs b/pegjs/db2.pegjs index ed376e8d..f5aa4540 100644 --- a/pegjs/db2.pegjs +++ b/pegjs/db2.pegjs @@ -284,18 +284,19 @@ if_not_exists_stmt create_db_stmt = a:KW_CREATE __ - k:(KW_DATABASE / KW_SCHEME) __ + k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } @@ -2277,7 +2278,7 @@ KW_AS = "AS"i !ident_start KW_TABLE = "TABLE"i !ident_start { return 'TABLE'; } KW_TABLES = "TABLES"i !ident_start { return 'TABLES'; } KW_DATABASE = "DATABASE"i !ident_start { return 'DATABASE'; } -KW_SCHEME = "SCHEME"i !ident_start { return 'SCHEME'; } +KW_SCHEMA = "SCHEMA"i !ident_start { return 'SCHEMA'; } KW_COLLATE = "COLLATE"i !ident_start { return 'COLLATE'; } KW_ON = "ON"i !ident_start diff --git a/pegjs/flinksql.pegjs b/pegjs/flinksql.pegjs index 44c2b9f4..c670500f 100644 --- a/pegjs/flinksql.pegjs +++ b/pegjs/flinksql.pegjs @@ -626,18 +626,19 @@ create_db_definition create_db_stmt = a:KW_CREATE __ - k:(KW_DATABASE / KW_SCHEME) __ + k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } @@ -3359,7 +3360,7 @@ KW_AS = "AS"i !ident_start KW_TABLE = "TABLE"i !ident_start { return 'TABLE'; } KW_TABLESPACE = "TABLESPACE"i !ident_start { return 'TABLESPACE'; } KW_DATABASE = "DATABASE"i !ident_start { return 'DATABASE'; } -KW_SCHEME = "SCHEME"i !ident_start { return 'SCHEME'; } +KW_SCHEMA = "SCHEMA"i !ident_start { return 'SCHEMA'; } KW_COLLATE = "COLLATE"i !ident_start { return 'COLLATE'; } KW_ON = "ON"i !ident_start diff --git a/pegjs/hive.pegjs b/pegjs/hive.pegjs index ebbd01f9..1efe153c 100644 --- a/pegjs/hive.pegjs +++ b/pegjs/hive.pegjs @@ -285,18 +285,19 @@ if_not_exists_stmt create_db_stmt = a:KW_CREATE __ - k:(KW_DATABASE / KW_SCHEME) __ + k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } @@ -2275,7 +2276,7 @@ KW_AS = "AS"i !ident_start KW_TABLE = "TABLE"i !ident_start { return 'TABLE'; } KW_TABLES = "TABLES"i !ident_start { return 'TABLES'; } KW_DATABASE = "DATABASE"i !ident_start { return 'DATABASE'; } -KW_SCHEME = "SCHEME"i !ident_start { return 'SCHEME'; } +KW_SCHEMA = "SCHEMA"i !ident_start { return 'SCHEMA'; } KW_COLLATE = "COLLATE"i !ident_start { return 'COLLATE'; } KW_ON = "ON"i !ident_start diff --git a/pegjs/mariadb.pegjs b/pegjs/mariadb.pegjs index 612e97a8..a1c4b2c8 100644 --- a/pegjs/mariadb.pegjs +++ b/pegjs/mariadb.pegjs @@ -344,16 +344,17 @@ create_db_stmt = a:KW_CREATE __ k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } diff --git a/pegjs/mysql.pegjs b/pegjs/mysql.pegjs index 04e049e0..cafb4c11 100644 --- a/pegjs/mysql.pegjs +++ b/pegjs/mysql.pegjs @@ -540,16 +540,17 @@ create_db_stmt = a:KW_CREATE __ k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', - if_not_exists: ife, - database: t, + keyword, + if_not_exists:ife, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } diff --git a/pegjs/noql.pegjs b/pegjs/noql.pegjs index 585bf194..f82a6867 100644 --- a/pegjs/noql.pegjs +++ b/pegjs/noql.pegjs @@ -359,30 +359,22 @@ create_db_stmt = a:KW_CREATE __ k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { - /* - export type create_db_stmt = { - type: 'create', - keyword: 'database' | 'schema', - if_not_exists?: 'if not exists', - database: ident_without_kw_type, - create_definitions?: create_db_definition - } - => AstStatement - */ + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } } + view_with = KW_WITH __ c:("CASCADED"i / "LOCAL"i) __ "CHECK"i __ "OPTION" { // => string diff --git a/pegjs/postgresql.pegjs b/pegjs/postgresql.pegjs index 9233c84f..65ef8f53 100644 --- a/pegjs/postgresql.pegjs +++ b/pegjs/postgresql.pegjs @@ -386,19 +386,22 @@ create_db_stmt type: 'create', keyword: 'database' | 'schema', if_not_exists?: 'if not exists', - database: ident_without_kw_type, + database?: { db: string, schema: string }; + schema?: { db: string, schema: string }; create_definitions?: create_db_definition } => AstStatement */ + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + replace: or && 'or replace', + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } diff --git a/pegjs/redshift.pegjs b/pegjs/redshift.pegjs index 063e2fa0..81d93a6c 100644 --- a/pegjs/redshift.pegjs +++ b/pegjs/redshift.pegjs @@ -369,30 +369,22 @@ create_db_stmt = a:KW_CREATE __ k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { - /* - export type create_db_stmt = { - type: 'create', - keyword: 'database' | 'schema', - if_not_exists?: 'if not exists', - database: ident_without_kw_type, - create_definitions?: create_db_definition - } - => AstStatement - */ + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } } + view_with = KW_WITH __ c:("CASCADED"i / "LOCAL"i) __ "CHECK"i __ "OPTION" { // => string diff --git a/pegjs/snowflake.pegjs b/pegjs/snowflake.pegjs index 48b504f6..2e79ba96 100644 --- a/pegjs/snowflake.pegjs +++ b/pegjs/snowflake.pegjs @@ -233,7 +233,6 @@ create_stmt / create_index_stmt / create_sequence / create_db_stmt - / create_schema_stmt / create_domain_stmt / create_type_stmt / create_view_stmt @@ -350,65 +349,37 @@ create_db_definition create_db_stmt = a:KW_CREATE __ + or:(KW_OR __ KW_REPLACE)? __ k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { /* export type create_db_stmt = { type: 'create', keyword: 'database' | 'schema', if_not_exists?: 'if not exists', - database: ident_without_kw_type, + database?: { db: string, schema: string }; + schema?: { db: string, schema: string }; create_definitions?: create_db_definition } => AstStatement */ + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + replace: or && 'or replace', + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } } -db_schema - = dt:ident tail:(__ DOT __ ident)? { - // => IGNORE - const obj = {}; - if (tail !== null) { - obj.db = dt; - obj.schema = tail[3]; - } - else { - obj.db = null - obj.schema = dt - } - return obj; - } - -create_schema_stmt - = a:KW_CREATE __ or:(KW_OR __ KW_REPLACE __)? - k:(KW_SCHEMA) __ - ife:if_not_exists_stmt? __ - t:db_schema { - return { - tableList: Array.from(tableList), - columnList: columnListTableAlias(columnList), - ast: { - type: a[0].toLowerCase(), - keyword: 'database', - if_not_exists:ife, - db: t.db, - schema: t.schema - } - } - } view_with = KW_WITH __ c:("CASCADED"i / "LOCAL"i) __ "CHECK"i __ "OPTION" { // => string @@ -542,7 +513,7 @@ create_domain_stmt } create_table_stmt = a:KW_CREATE __ - or: (KW_OR __ KW_REPLACE __)? + or:(KW_OR __ KW_REPLACE)? __ tp:KW_TEMPORARY? __ KW_TABLE __ ife:if_not_exists_stmt? __ @@ -558,6 +529,7 @@ create_table_stmt type: 'create'; keyword: 'table'; temporary?: 'temporary'; + replace?: string; if_not_exists?: 'if not exists'; table: table_ref_list; } @@ -579,8 +551,8 @@ create_table_stmt keyword: 'table', temporary: tp && tp[0].toLowerCase(), if_not_exists:ife, - or_replace: or && (or[0] + ' ' + or[2][0]).toUpperCase(), table: t, + replace: or && 'or replace', ignore_replace: ir && ir[0].toLowerCase(), as: as && as[0].toLowerCase(), query_expr: qe && qe.ast, @@ -591,6 +563,7 @@ create_table_stmt } } / a:KW_CREATE __ + or:(KW_OR __ KW_REPLACE)? __ tp:KW_TEMPORARY? __ KW_TABLE __ ife:if_not_exists_stmt? __ @@ -612,7 +585,7 @@ create_table_stmt keyword: 'table', temporary: tp && tp[0].toLowerCase(), if_not_exists:ife, - or_replace: or && (or[0] + ' ' + or[2][0]).toUpperCase(), + replace: or && (or[0] + ' ' + or[2][0]).toUpperCase(), table: t, like: lt } @@ -2563,9 +2536,10 @@ where_clause = KW_WHERE __ e:or_and_where_expr { /* => binary_expr */ return e; } group_by_clause - = KW_GROUP __ KW_BY __ e:expr_list { + = KW_GROUP __ KW_BY __ e:(KW_ALL / expr_list) { + const columns = e === 'ALL' ? [{ type: 'origin', value: 'all'}] : e.value return { - columns: e.value + columns } } diff --git a/pegjs/sqlite.pegjs b/pegjs/sqlite.pegjs index 340f3310..ddda6b66 100644 --- a/pegjs/sqlite.pegjs +++ b/pegjs/sqlite.pegjs @@ -368,18 +368,19 @@ trigger_when create_db_stmt = a:KW_CREATE __ - k:(KW_DATABASE / KW_SCHEME) __ + k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', - if_not_exists: ife, - database: t, + keyword, + if_not_exists:ife, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } @@ -2640,7 +2641,7 @@ KW_AS = "AS"i !ident_start KW_TABLE = "TABLE"i !ident_start { return 'TABLE'; } KW_TABLES = "TABLES"i !ident_start { return 'TABLES'; } KW_DATABASE = "DATABASE"i !ident_start { return 'DATABASE'; } -KW_SCHEME = "SCHEME"i !ident_start { return 'SCHEME'; } +KW_SCHEMA = "SCHEMA"i !ident_start { return 'SCHEMA'; } KW_COLLATE = "COLLATE"i !ident_start { return 'COLLATE'; } KW_ON = "ON"i !ident_start diff --git a/pegjs/transactsql.pegjs b/pegjs/transactsql.pegjs index d8f59c39..36224550 100644 --- a/pegjs/transactsql.pegjs +++ b/pegjs/transactsql.pegjs @@ -378,18 +378,19 @@ if_not_exists_stmt create_db_stmt = a:KW_CREATE __ - k:(KW_DATABASE / KW_SCHEME) __ + k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', - if_not_exists: ife, - database: t, + keyword, + if_not_exists:ife, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } @@ -2947,7 +2948,7 @@ KW_AS = "AS"i !ident_start KW_TABLE = "TABLE"i !ident_start { return 'TABLE'; } KW_VIEW = "VIEW"i !ident_start { return 'VIEW'; } KW_DATABASE = "DATABASE"i !ident_start { return 'DATABASE'; } -KW_SCHEME = "SCHEME"i !ident_start { return 'SCHEME'; } +KW_SCHEMA = "SCHEMA"i !ident_start { return 'SCHEMA'; } KW_TABLES = "TABLES"i !ident_start { return 'TABLES'; } KW_COLLATE = "COLLATE"i !ident_start { return 'COLLATE'; } diff --git a/pegjs/trino.pegjs b/pegjs/trino.pegjs index dd023ec5..80440c0b 100644 --- a/pegjs/trino.pegjs +++ b/pegjs/trino.pegjs @@ -380,30 +380,22 @@ create_db_stmt = a:KW_CREATE __ k:(KW_DATABASE / KW_SCHEMA) __ ife:if_not_exists_stmt? __ - t:ident_without_kw_type __ + t:proc_func_name __ c:create_db_definition? { - /* - export type create_db_stmt = { - type: 'create', - keyword: 'database' | 'schema', - if_not_exists?: 'if not exists', - database: ident_without_kw_type, - create_definitions?: create_db_definition - } - => AstStatement - */ + const keyword = k.toLowerCase() return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: a[0].toLowerCase(), - keyword: 'database', + keyword, if_not_exists:ife, - database: t, + [keyword]: { db: t.schema, schema: t.name }, create_definitions: c, } } } + view_with = KW_WITH __ c:("CASCADED"i / "LOCAL"i) __ "CHECK"i __ "OPTION" { // => string diff --git a/src/create.js b/src/create.js index 53e2d6ab..42b896c3 100644 --- a/src/create.js +++ b/src/create.js @@ -205,17 +205,20 @@ function createSequenceToSQL(stmt) { return sql.filter(hasVal).join(' ') } -function createDatabaseToSQL(stmt) { +function createDatabaseOrSchemaToSQL(stmt) { const { - type, keyword, database, + type, keyword, replace, if_not_exists: ifNotExists, create_definitions: createDefinition, } = stmt + const { db, schema } = stmt[keyword] + const name = [literalToSQL(db), schema.map(literalToSQL).join('.')].filter(hasVal).join('.') const sql = [ toUpper(type), + toUpper(replace), toUpper(keyword), toUpper(ifNotExists), - literalToSQL(database), + name, ] if (createDefinition) sql.push(createDefinition.map(tableOptionToSQL).join(' ')) return sql.filter(hasVal).join(' ') @@ -412,7 +415,8 @@ function createToSQL(stmt) { sql = createSequenceToSQL(stmt) break case 'database': - sql = createDatabaseToSQL(stmt) + case 'schema': + sql = createDatabaseOrSchemaToSQL(stmt) break case 'view': sql = createViewToSQL(stmt) diff --git a/test/snowflake.spec.js b/test/snowflake.spec.js index b3668814..496614ce 100644 --- a/test/snowflake.spec.js +++ b/test/snowflake.spec.js @@ -218,9 +218,37 @@ describe('snowflake', () => { primary key ("att1") ); `, - `CREATE TABLE "TEST_SNOWFLAKE" ("att1" NUMERIC(3, 3), "att2" BYTEINT, "att3_SAMPLE_3" BINARY, "att4_SAMPLE_4" VARBINARY, "att5_SAMPLE_5" GEOGRAPHY, "att6_SAMPLE_6" TIMESTAMP_TZ, PRIMARY KEY ("att1"))` + `CREATE TABLE "TEST_SNOWFLAKE" ("att1" NUMERIC(3, 3), "att2" BYTEINT, "att3_SAMPLE_3" BINARY, "att4_SAMPLE_4" VARBINARY, "att5_SAMPLE_5" GEOGRAPHY, "att6_SAMPLE_6" TIMESTAMP_TZ, PRIMARY KEY ("att1"))` ] - } + }, + { + title: 'create or replace table', + sql: [ + 'create or replace TABLE HOSPITAL.PUBLIC.BILLING (BILL_ID VARCHAR(16777216) NOT NULL, DATE TIMESTAMP_NTZ(9), B_ID VARBINARY(333), primary key (BILL_ID));', + 'CREATE OR REPLACE TABLE "HOSPITAL"."PUBLIC"."BILLING" ("BILL_ID" VARCHAR(16777216) NOT NULL, "DATE" TIMESTAMP_NTZ(9), "B_ID" VARBINARY(333), PRIMARY KEY ("BILL_ID"))' + ] + }, + { + title: 'create or replace schema', + sql: [ + 'create or replace schema DELETETHISDB.PUBLIC;', + 'CREATE OR REPLACE SCHEMA DELETETHISDB.PUBLIC' + ] + }, + { + title: 'table name start with digit', + sql: [ + 'CREATE TABLE 1dog (id INT);', + 'CREATE TABLE "1dog" ("id" INT)' + ] + }, + { + title: 'group by all', + sql: [ + 'SELECT A, B, COUNT(*) FROM T GROUP BY All', + 'SELECT "A", "B", COUNT(*) FROM "T" GROUP BY ALL' + ] + }, ] SQL_LIST.forEach(sqlInfo => { const { title, sql } = sqlInfo