Skip to content
Snippets Groups Projects
Commit 7324a1cf authored by Kirill Shcherbatov's avatar Kirill Shcherbatov Committed by Kirill Yukhin
Browse files

sql: prevent executing cross-engine sql

Some sql requests are complex and could contain R/W with
multiple spaces. As we have no ability to make such changes
transactionaly, we have to disallow such requests.
Since now iterators in SQL start transaction so we cant prevent
such vicious and dangerous things.

Closes #3551
parent 13df2b1f
No related branches found
No related tags found
No related merge requests found
...@@ -1118,12 +1118,21 @@ cursor_seek(BtCursor *pCur, int *pRes) ...@@ -1118,12 +1118,21 @@ cursor_seek(BtCursor *pCur, int *pRes)
return SQL_TARANTOOL_ITERATOR_FAIL; return SQL_TARANTOOL_ITERATOR_FAIL;
} }
struct iterator *it = index_create_iterator(pCur->index, pCur->iter_type, struct space *space = pCur->space;
key, part_count); struct txn *txn = NULL;
if (space->def->id != 0 && txn_begin_ro_stmt(space, &txn) != 0)
return SQL_TARANTOOL_ERROR;
struct iterator *it =
index_create_iterator(pCur->index, pCur->iter_type, key,
part_count);
if (it == NULL) { if (it == NULL) {
if (txn != NULL)
txn_rollback_stmt();
pCur->eState = CURSOR_INVALID; pCur->eState = CURSOR_INVALID;
return SQL_TARANTOOL_ITERATOR_FAIL; return SQL_TARANTOOL_ITERATOR_FAIL;
} }
if (txn != NULL)
txn_commit_ro_stmt(txn);
pCur->iter = it; pCur->iter = it;
pCur->eState = CURSOR_VALID; pCur->eState = CURSOR_VALID;
......
...@@ -246,3 +246,113 @@ box.sql.execute("DROP VIEW V1;") ...@@ -246,3 +246,113 @@ box.sql.execute("DROP VIEW V1;")
box.sql.execute("DROP TABLE T1;") box.sql.execute("DROP TABLE T1;")
--- ---
... ...
--
-- gh-3531: Assertion with trigger and two storage engines
--
-- Case 1: Src 'vinyl' table; Dst 'memtx' table
box.sql.execute("PRAGMA sql_default_engine ('vinyl');")
---
...
box.sql.execute("CREATE TABLE m (s1 SCALAR PRIMARY KEY);")
---
...
box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = DATETIME('now'); END;")
---
...
box.sql.execute("PRAGMA sql_default_engine('memtx');")
---
...
box.sql.execute("CREATE TABLE n (s1 CHAR PRIMARY KEY, s2 char);")
---
...
box.sql.execute("INSERT INTO m VALUES ('');")
---
...
box.sql.execute("INSERT INTO n VALUES ('',null);")
---
...
box.sql.execute("UPDATE m SET s1 = 'The Rain In Spain';")
---
- error: A multi-statement transaction can not use multiple storage engines
...
-- ANALYZE operates with _sql_stat{1,4} tables should work
box.sql.execute("ANALYZE m;")
---
...
box.sql.execute("DROP TABLE m;")
---
...
box.sql.execute("DROP TABLE n;")
---
...
-- Case 2: Src 'memtx' table; Dst 'vinyl' table
box.sql.execute("PRAGMA sql_default_engine ('memtx');")
---
...
box.sql.execute("CREATE TABLE m (s1 SCALAR PRIMARY KEY);")
---
...
box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = DATETIME('now'); END;")
---
...
box.sql.execute("PRAGMA sql_default_engine('vinyl');")
---
...
box.sql.execute("CREATE TABLE n (s1 CHAR PRIMARY KEY, s2 char);")
---
...
box.sql.execute("INSERT INTO m VALUES ('');")
---
...
box.sql.execute("INSERT INTO n VALUES ('',null);")
---
...
box.sql.execute("UPDATE m SET s1 = 'The Rain In Spain';")
---
- error: A multi-statement transaction can not use multiple storage engines
...
-- ANALYZE operates with _sql_stat{1,4} tables should work
box.sql.execute("ANALYZE n;")
---
...
box.sql.execute("DROP TABLE m;")
---
...
box.sql.execute("DROP TABLE n;")
---
...
-- Test SQL Transaction with LUA
box.sql.execute("PRAGMA sql_default_engine ('memtx');")
---
...
box.sql.execute("CREATE TABLE test (id INT PRIMARY KEY)")
---
...
box.sql.execute("PRAGMA sql_default_engine='vinyl'")
---
...
box.sql.execute("CREATE TABLE test2 (id INT PRIMARY KEY)")
---
...
box.sql.execute("INSERT INTO test2 VALUES (2)")
---
...
box.sql.execute("START TRANSACTION")
---
...
box.sql.execute("INSERT INTO test VALUES (1)")
---
...
box.sql.execute("SELECT * FROM test2")
---
- error: A multi-statement transaction can not use multiple storage engines
...
box.sql.execute("ROLLBACK;")
---
...
box.sql.execute("DROP TABLE test;")
---
...
box.sql.execute("DROP TABLE test2;")
---
...
...@@ -95,3 +95,50 @@ box.space._trigger:insert(tuple) ...@@ -95,3 +95,50 @@ box.space._trigger:insert(tuple)
box.sql.execute("DROP VIEW V1;") box.sql.execute("DROP VIEW V1;")
box.sql.execute("DROP TABLE T1;") box.sql.execute("DROP TABLE T1;")
--
-- gh-3531: Assertion with trigger and two storage engines
--
-- Case 1: Src 'vinyl' table; Dst 'memtx' table
box.sql.execute("PRAGMA sql_default_engine ('vinyl');")
box.sql.execute("CREATE TABLE m (s1 SCALAR PRIMARY KEY);")
box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = DATETIME('now'); END;")
box.sql.execute("PRAGMA sql_default_engine('memtx');")
box.sql.execute("CREATE TABLE n (s1 CHAR PRIMARY KEY, s2 char);")
box.sql.execute("INSERT INTO m VALUES ('');")
box.sql.execute("INSERT INTO n VALUES ('',null);")
box.sql.execute("UPDATE m SET s1 = 'The Rain In Spain';")
-- ANALYZE operates with _sql_stat{1,4} tables should work
box.sql.execute("ANALYZE m;")
box.sql.execute("DROP TABLE m;")
box.sql.execute("DROP TABLE n;")
-- Case 2: Src 'memtx' table; Dst 'vinyl' table
box.sql.execute("PRAGMA sql_default_engine ('memtx');")
box.sql.execute("CREATE TABLE m (s1 SCALAR PRIMARY KEY);")
box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = DATETIME('now'); END;")
box.sql.execute("PRAGMA sql_default_engine('vinyl');")
box.sql.execute("CREATE TABLE n (s1 CHAR PRIMARY KEY, s2 char);")
box.sql.execute("INSERT INTO m VALUES ('');")
box.sql.execute("INSERT INTO n VALUES ('',null);")
box.sql.execute("UPDATE m SET s1 = 'The Rain In Spain';")
-- ANALYZE operates with _sql_stat{1,4} tables should work
box.sql.execute("ANALYZE n;")
box.sql.execute("DROP TABLE m;")
box.sql.execute("DROP TABLE n;")
-- Test SQL Transaction with LUA
box.sql.execute("PRAGMA sql_default_engine ('memtx');")
box.sql.execute("CREATE TABLE test (id INT PRIMARY KEY)")
box.sql.execute("PRAGMA sql_default_engine='vinyl'")
box.sql.execute("CREATE TABLE test2 (id INT PRIMARY KEY)")
box.sql.execute("INSERT INTO test2 VALUES (2)")
box.sql.execute("START TRANSACTION")
box.sql.execute("INSERT INTO test VALUES (1)")
box.sql.execute("SELECT * FROM test2")
box.sql.execute("ROLLBACK;")
box.sql.execute("DROP TABLE test;")
box.sql.execute("DROP TABLE test2;")
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