Skip to content
Snippets Groups Projects
Commit 1013a744 authored by Nikita Pettik's avatar Nikita Pettik Committed by Kirill Yukhin
Browse files

sql: allow to specify engine in CREATE TABLE stmt

Closes #4422

@TarantoolBot document
Title: Introduce <WITH ENGINE> clause for CREATE TABLE statement

To allow user to specify engine as per table option, CREATE TABLE
statement has been extended with optional <WITH ENGINE = engine_name>
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'.
parent 35177fe0
No related branches found
No related tags found
No related merge requests found
...@@ -93,6 +93,7 @@ static Keyword aKeywordTable[] = { ...@@ -93,6 +93,7 @@ static Keyword aKeywordTable[] = {
{ "DISTINCT", "TK_DISTINCT", true }, { "DISTINCT", "TK_DISTINCT", true },
{ "DROP", "TK_DROP", true }, { "DROP", "TK_DROP", true },
{ "END", "TK_END", true }, { "END", "TK_END", true },
{ "ENGINE", "TK_ENGINE", true },
{ "EACH", "TK_EACH", true }, { "EACH", "TK_EACH", true },
{ "ELSE", "TK_ELSE", true }, { "ELSE", "TK_ELSE", true },
{ "ESCAPE", "TK_ESCAPE", true }, { "ESCAPE", "TK_ESCAPE", true },
......
...@@ -177,7 +177,7 @@ cmd ::= ROLLBACK TO savepoint_opt nm(X). { ...@@ -177,7 +177,7 @@ cmd ::= ROLLBACK TO savepoint_opt nm(X). {
///////////////////// The CREATE TABLE statement //////////////////////////// ///////////////////// 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 ::= createkw TABLE ifnotexists(E) nm(Y). {
create_table_def_init(&pParse->create_table_def, &Y, E); create_table_def_init(&pParse->create_table_def, &Y, E);
pParse->create_table_def.new_space = sqlStartTable(pParse, &Y); pParse->create_table_def.new_space = sqlStartTable(pParse, &Y);
...@@ -189,10 +189,31 @@ createkw(A) ::= CREATE(A). {disableLookaside(pParse);} ...@@ -189,10 +189,31 @@ createkw(A) ::= CREATE(A). {disableLookaside(pParse);}
ifnotexists(A) ::= . {A = 0;} ifnotexists(A) ::= . {A = 0;}
ifnotexists(A) ::= IF NOT EXISTS. {A = 1;} ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
create_table_args ::= LP columnlist RP. { create_table_args ::= LP columnlist RP.
sqlEndTable(pParse);
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 * CREATE TABLE AS SELECT is broken. To be re-implemented
* in gh-3223. * in gh-3223.
......
...@@ -48,3 +48,88 @@ box.execute("DROP TABLE t3_memtx;") ...@@ -48,3 +48,88 @@ box.execute("DROP TABLE t3_memtx;")
--- ---
- row_count: 1 - 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'
...
...@@ -15,3 +15,33 @@ assert(box.space.T3_MEMTX.engine == 'memtx') ...@@ -15,3 +15,33 @@ assert(box.space.T3_MEMTX.engine == 'memtx')
box.execute("DROP TABLE t1_vinyl;") box.execute("DROP TABLE t1_vinyl;")
box.execute("DROP TABLE t2_vinyl;") box.execute("DROP TABLE t2_vinyl;")
box.execute("DROP TABLE t3_memtx;") 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'")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment