diff --git a/pegjs/mariadb.pegjs b/pegjs/mariadb.pegjs index f7646dff..34a55f4f 100644 --- a/pegjs/mariadb.pegjs +++ b/pegjs/mariadb.pegjs @@ -316,7 +316,7 @@ column_order_list } column_order_item - = c:expr o:(KW_ASC / KW_DESC)? { + = c:expr __ o:(KW_ASC / KW_DESC)? { return { ...c, order_by: o && o.toLowerCase(), diff --git a/pegjs/mysql.pegjs b/pegjs/mysql.pegjs index a4a64440..8d623afa 100644 --- a/pegjs/mysql.pegjs +++ b/pegjs/mysql.pegjs @@ -513,7 +513,8 @@ column_order_list } column_order_item - = c:expr o:(KW_ASC / KW_DESC)? { return { + = c:expr __ o:(KW_ASC / KW_DESC)? { + return { ...c, order_by: o && o.toLowerCase(), } diff --git a/pegjs/sqlite.pegjs b/pegjs/sqlite.pegjs index fc98b698..7b753b8f 100644 --- a/pegjs/sqlite.pegjs +++ b/pegjs/sqlite.pegjs @@ -226,6 +226,7 @@ cmd_stmt create_stmt = create_table_stmt / create_db_stmt + / create_index_stmt / create_trigger_stmt / create_view_stmt @@ -386,6 +387,57 @@ create_db_stmt } } +column_order_list + = head:column_order_item tail:(__ COMMA __ column_order_item)* { + return createList(head, tail) + } + +column_order_item + = c:expr __ ce:collate_expr? __ o:(KW_ASC / KW_DESC)? { + return { + ...c, + collate: ce, + order_by: o && o.toLowerCase(), + } + } + / column_order + +column_order + = c:column_ref __ ce:collate_expr? __ o:(KW_ASC / KW_DESC)? { + return { + ...c, + collate: ce, + order_by: o && o.toLowerCase(), + } + } + +create_index_stmt + = a:KW_CREATE __ + kw:(KW_UNIQUE)? __ + t:KW_INDEX __ + ife:if_not_exists_stmt? __ + n:table_name __ + um:index_type? __ + on:KW_ON __ + ta:table_name __ LPAREN __ cols:column_order_list __ RPAREN __ + where:where_clause? { + return { + tableList: Array.from(tableList), + columnList: columnListTableAlias(columnList), + ast: { + type: a[0].toLowerCase(), + index_type: kw && kw.toLowerCase(), + keyword: t.toLowerCase(), + if_not_exists: ife, + index: { schema: n.db, name: n.table }, + on_kw: on[0].toLowerCase(), + table: ta, + index_columns: cols, + where, + } + } + } + view_with = KW_WITH __ c:("CASCADED"i / "LOCAL"i) __ "CHECK"i __ "OPTION" { return `with ${c.toLowerCase()} check option` diff --git a/pegjs/transactsql.pegjs b/pegjs/transactsql.pegjs index 8cdcb32d..d3ed08d1 100644 --- a/pegjs/transactsql.pegjs +++ b/pegjs/transactsql.pegjs @@ -309,7 +309,8 @@ column_order_list } column_order_item - = LBRAKE __ c:column_ref __ RBRAKE __ o:(KW_ASC / KW_DESC) { return { + = LBRAKE __ c:column_ref __ RBRAKE __ o:(KW_ASC / KW_DESC) { + return { ...c, order_by: o.toLowerCase() } diff --git a/src/create.js b/src/create.js index f459ce86..2e889579 100644 --- a/src/create.js +++ b/src/create.js @@ -177,15 +177,19 @@ function createExtensionToSQL(stmt) { function createIndexToSQL(stmt) { const { - concurrently, filestream_on: fileStream, keyword, include, index_columns: indexColumns, + concurrently, filestream_on: fileStream, keyword, if_not_exists: ifNotExists, include, index_columns: indexColumns, index_type: indexType, index_using: indexUsing, index, on, index_options: indexOpt, algorithm_option: algorithmOpt, lock_option: lockOpt, on_kw: onKw, table, tablespace, type, where, with: withExpr, with_before_where: withBeforeWhere, } = stmt const withIndexOpt = withExpr && `WITH (${indexOptionListToSQL(withExpr).join(', ')})` const includeColumns = include && `${toUpper(include.keyword)} (${include.columns.map(col => identifierToSql(col)).join(', ')})` + let indexName = index + if (index) { + indexName = typeof index === 'string' ? identifierToSql(index) : [identifierToSql(index.schema), identifierToSql(index.name)].filter(hasVal).join('.') + } const sql = [ - toUpper(type), toUpper(indexType), toUpper(keyword), toUpper(concurrently), - identifierToSql(index), toUpper(onKw), tableToSQL(table), ...indexTypeToSQL(indexUsing), + toUpper(type), toUpper(indexType), toUpper(keyword), toUpper(ifNotExists), toUpper(concurrently), + indexName, toUpper(onKw), tableToSQL(table), ...indexTypeToSQL(indexUsing), `(${columnOrderListToSQL(indexColumns)})`, includeColumns, indexOptionListToSQL(indexOpt).join(' '), alterExprToSQL(algorithmOpt), alterExprToSQL(lockOpt), commonOptionConnector('TABLESPACE', literalToSQL, tablespace), ] diff --git a/test/sqlite.spec.js b/test/sqlite.spec.js index 2a518c03..22481774 100644 --- a/test/sqlite.spec.js +++ b/test/sqlite.spec.js @@ -200,4 +200,10 @@ describe('sqlite', () => { ` 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')`) }) + it('should support create index', () => { + let sql = 'CREATE INDEX visits_url_index ON visits (url);' + expect(getParsedSql(sql)).to.be.equal('CREATE INDEX "visits_url_index" ON "visits" ("url")') + sql = 'CREATE INDEX if not exists schema_name.visits_url_index ON visits (url collate cn asc) where id > 10;' + expect(getParsedSql(sql)).to.be.equal('CREATE INDEX IF NOT EXISTS "schema_name"."visits_url_index" ON "visits" ("url" COLLATE cn ASC) WHERE "id" > 10') + }) })