From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 7482A26F5D for ; Mon, 19 Aug 2019 10:49:39 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id izXBFS5py3-m for ; Mon, 19 Aug 2019 10:49:39 -0400 (EDT) Received: from smtpng3.m.smailru.net (smtpng3.m.smailru.net [94.100.177.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 21D9626EB9 for ; Mon, 19 Aug 2019 10:49:39 -0400 (EDT) From: Nikita Pettik Subject: [tarantool-patches] [PATCH 2/2] sql: allow to specify engine in CREATE TABLE stmt Date: Mon, 19 Aug 2019 17:49:34 +0300 Message-Id: <31336993247e9b53cf3c41f1cdb2bba14a61e31a.1566223966.git.korablev@tarantool.org> In-Reply-To: References: In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-Help: List-Unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-Subscribe: List-Owner: List-post: List-Archive: To: tarantool-patches@freelists.org Cc: v.shpilevoy@tarantool.org, kostja@tarantool.org, Nikita Pettik Closes #4422 @TarantoolBot document Title: Introduce clause for CREATE TABLE statement To allow user to specify engine as per table option, CREATE TABLE statement has been extended with optional clause. This clause comes at the end of CREATE TABLE statement. For instance: CREATE TABLE t_vinyl (id INT PRIMARY KEY) WITH ENGINE = 'vinyl'; Name of engine is considered to be string literal ergo should be enclosed in single quotation marks and be lower-cased. Note that engine specified in WITH ENGINE clause overwrites default engine, which is set via 'pragma sql_default_engine'. --- extra/mkkeywordhash.c | 1 + src/box/sql/parse.y | 27 +++++++++++++-- test/sql/engine.result | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ test/sql/engine.test.lua | 30 +++++++++++++++++ 4 files changed, 140 insertions(+), 3 deletions(-) diff --git a/extra/mkkeywordhash.c b/extra/mkkeywordhash.c index a6d0f79a4..d0aa39a43 100644 --- a/extra/mkkeywordhash.c +++ b/extra/mkkeywordhash.c @@ -111,6 +111,7 @@ static Keyword aKeywordTable[] = { { "DISTINCT", "TK_DISTINCT", ALWAYS, true }, { "DROP", "TK_DROP", ALWAYS, true }, { "END", "TK_END", ALWAYS, true }, + { "ENGINE", "TK_ENGINE", ALWAYS, true }, { "EACH", "TK_EACH", TRIGGER, true }, { "ELSE", "TK_ELSE", ALWAYS, true }, { "ESCAPE", "TK_ESCAPE", ALWAYS, true }, diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y index ca6df0a40..be3c5c399 100644 --- a/src/box/sql/parse.y +++ b/src/box/sql/parse.y @@ -177,7 +177,7 @@ cmd ::= ROLLBACK TO savepoint_opt nm(X). { ///////////////////// The CREATE TABLE statement //////////////////////////// // -cmd ::= create_table create_table_args. +cmd ::= create_table create_table_args with_opts create_table_end. create_table ::= createkw TABLE ifnotexists(E) nm(Y). { create_table_def_init(&pParse->create_table_def, &Y, E); pParse->create_table_def.new_space = sqlStartTable(pParse, &Y); @@ -189,10 +189,31 @@ createkw(A) ::= CREATE(A). {disableLookaside(pParse);} ifnotexists(A) ::= . {A = 0;} ifnotexists(A) ::= IF NOT EXISTS. {A = 1;} -create_table_args ::= LP columnlist RP. { - sqlEndTable(pParse); +create_table_args ::= LP columnlist RP. + +with_opts ::= WITH engine_opts. +with_opts ::= . + +engine_opts ::= ENGINE EQ STRING(A). { + /* Note that specifying engine clause overwrites default engine. */ + if (A.n > ENGINE_NAME_MAX) { + diag_set(ClientError, ER_CREATE_SPACE, + pParse->create_table_def.new_space->def->name, + "space engine name is too long"); + pParse->is_aborted = true; + return; + } + /* Need to dequote name. */ + char *normalized_name = sql_name_from_token(pParse->db, &A); + if (normalized_name == NULL) + return; + memcpy(pParse->create_table_def.new_space->def->engine_name, normalized_name, + strlen(normalized_name) + 1); + sqlDbFree(pParse->db, normalized_name); } +create_table_end ::= . { sqlEndTable(pParse); } + /* * CREATE TABLE AS SELECT is broken. To be re-implemented * in gh-3223. diff --git a/test/sql/engine.result b/test/sql/engine.result index cee9f7f32..3ee93ad19 100644 --- a/test/sql/engine.result +++ b/test/sql/engine.result @@ -48,3 +48,88 @@ box.execute("DROP TABLE t3_memtx;") --- - row_count: 1 ... +-- gh-4422: allow to specify engine in CREATE TABLE statement. +-- +box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = 'vinyl'") +--- +- row_count: 1 +... +assert(box.space.T1_VINYL.engine == 'vinyl') +--- +- true +... +box.execute("CREATE TABLE t1_memtx (id INT PRIMARY KEY) WITH ENGINE = 'memtx'") +--- +- row_count: 1 +... +assert(box.space.T1_MEMTX.engine == 'memtx') +--- +- true +... +box.execute("pragma sql_default_engine='vinyl'") +--- +- row_count: 0 +... +box.execute("CREATE TABLE t2_vinyl (id INT PRIMARY KEY) WITH ENGINE = 'vinyl'") +--- +- row_count: 1 +... +assert(box.space.T2_VINYL.engine == 'vinyl') +--- +- true +... +box.execute("CREATE TABLE t2_memtx (id INT PRIMARY KEY) WITH ENGINE = 'memtx'") +--- +- row_count: 1 +... +assert(box.space.T2_MEMTX.engine == 'memtx') +--- +- true +... +box.space.T1_VINYL:drop() +--- +... +box.space.T1_MEMTX:drop() +--- +... +box.space.T2_VINYL:drop() +--- +... +box.space.T2_MEMTX:drop() +--- +... +-- Name of engine considered to be string literal, so should be +-- lowercased and quoted. +-- +box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = VINYL") +--- +- null +- Syntax error near 'VINYL' +... +box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = vinyl") +--- +- null +- Syntax error near 'vinyl' +... +box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = 'VINYL'") +--- +- null +- Space engine 'VINYL' does not exist +... +box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = \"vinyl\"") +--- +- null +- Syntax error near '"vinyl"' +... +-- Make sure that wrong engine name is handled properly. +-- +box.execute("CREATE TABLE t_wrong_engine (id INT PRIMARY KEY) WITH ENGINE = 'abc'") +--- +- null +- Space engine 'abc' does not exist +... +box.execute("CREATE TABLE t_long_engine_name (id INT PRIMARY KEY) WITH ENGINE = 'very_long_engine_name'") +--- +- null +- 'Failed to create space ''T_LONG_ENGINE_NAME'': space engine name is too long' +... diff --git a/test/sql/engine.test.lua b/test/sql/engine.test.lua index 51d6939e7..112d3d3ff 100644 --- a/test/sql/engine.test.lua +++ b/test/sql/engine.test.lua @@ -15,3 +15,33 @@ assert(box.space.T3_MEMTX.engine == 'memtx') box.execute("DROP TABLE t1_vinyl;") box.execute("DROP TABLE t2_vinyl;") box.execute("DROP TABLE t3_memtx;") + +-- gh-4422: allow to specify engine in CREATE TABLE statement. +-- +box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = 'vinyl'") +assert(box.space.T1_VINYL.engine == 'vinyl') +box.execute("CREATE TABLE t1_memtx (id INT PRIMARY KEY) WITH ENGINE = 'memtx'") +assert(box.space.T1_MEMTX.engine == 'memtx') +box.execute("pragma sql_default_engine='vinyl'") +box.execute("CREATE TABLE t2_vinyl (id INT PRIMARY KEY) WITH ENGINE = 'vinyl'") +assert(box.space.T2_VINYL.engine == 'vinyl') +box.execute("CREATE TABLE t2_memtx (id INT PRIMARY KEY) WITH ENGINE = 'memtx'") +assert(box.space.T2_MEMTX.engine == 'memtx') + +box.space.T1_VINYL:drop() +box.space.T1_MEMTX:drop() +box.space.T2_VINYL:drop() +box.space.T2_MEMTX:drop() + +-- Name of engine considered to be string literal, so should be +-- lowercased and quoted. +-- +box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = VINYL") +box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = vinyl") +box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = 'VINYL'") +box.execute("CREATE TABLE t1_vinyl (id INT PRIMARY KEY) WITH ENGINE = \"vinyl\"") + +-- Make sure that wrong engine name is handled properly. +-- +box.execute("CREATE TABLE t_wrong_engine (id INT PRIMARY KEY) WITH ENGINE = 'abc'") +box.execute("CREATE TABLE t_long_engine_name (id INT PRIMARY KEY) WITH ENGINE = 'very_long_engine_name'") -- 2.15.1