[tarantool-patches] [PATCH v9 7/7] sql: remove box.sql.execute()

imeevma at tarantool.org imeevma at tarantool.org
Fri Mar 22 13:50:46 MSK 2019


This patch replaces box.sql.execute() by box.execute() in tests
and removes box.sql.execute() from code.

Closes #3505
---
 src/box/CMakeLists.txt                             |   1 -
 src/box/lua/console.lua                            |   2 +-
 src/box/lua/init.c                                 |   2 -
 src/box/lua/load_cfg.lua                           |  13 +-
 src/box/lua/sql.c                                  | 129 ----
 src/box/lua/sql.h                                  |  46 --
 test/box/cfg.result                                |  17 -
 test/box/cfg.test.lua                              |  10 -
 test/box/misc.result                               |   1 -
 test/box/sql-update-with-nested-select.result      |  25 +-
 test/box/sql-update-with-nested-select.test.lua    |  14 +-
 test/sql-tap/alter.test.lua                        |   8 +-
 test/sql-tap/alter2.test.lua                       |  12 +-
 test/sql-tap/analyze1.test.lua                     |   6 +-
 test/sql-tap/analyze9.test.lua                     |   2 +-
 test/sql-tap/autoinc.test.lua                      |   4 +-
 test/sql-tap/between.test.lua                      |   2 +-
 test/sql-tap/check.test.lua                        |  30 +-
 test/sql-tap/delete1.test.lua                      |   4 +-
 test/sql-tap/distinct.test.lua                     |   6 +-
 test/sql-tap/fkey1.test.lua                        |   4 +-
 test/sql-tap/fkey2.test.lua                        |  92 +--
 test/sql-tap/fkey3.test.lua                        |  18 +-
 test/sql-tap/fkey4.test.lua                        |  10 +-
 test/sql-tap/func.test.lua                         |  12 +-
 test/sql-tap/gh-2723-concurrency.test.lua          |  36 +-
 test/sql-tap/gh-2931-savepoints.test.lua           |   6 +-
 .../gh-3083-ephemeral-unref-tuples.test.lua        |   4 +-
 .../gh-3251-string-pattern-comparison.test.lua     |   6 +-
 .../gh-3307-xfer-optimization-issue.test.lua       |  10 +-
 test/sql-tap/gh-3332-tuple-format-leak.test.lua    |  12 +-
 test/sql-tap/gh2140-trans.test.lua                 |  26 +-
 test/sql-tap/gh2250-trigger-chain-limit.test.lua   |  21 +-
 test/sql-tap/gh2259-in-stmt-trans.test.lua         |  42 +-
 test/sql-tap/gh2548-select-compound-limit.test.lua |  14 +-
 test/sql-tap/gh2964-abort.test.lua                 |   2 +-
 test/sql-tap/index1.test.lua                       |   2 +-
 test/sql-tap/intpkey.test.lua                      |   2 +-
 test/sql-tap/limit.test.lua                        |  12 +-
 test/sql-tap/lua/sqltester.lua                     |  43 +-
 test/sql-tap/misc1.test.lua                        |   2 +-
 test/sql-tap/orderby9.test.lua                     |   2 +
 test/sql-tap/pragma.test.lua                       |   8 +-
 test/sql-tap/select1.test.lua                      |  20 +-
 test/sql-tap/select9.test.lua                      |   5 +-
 test/sql-tap/selectB.test.lua                      |   4 +-
 test/sql-tap/table.test.lua                        |  20 +-
 test/sql-tap/tkt-4a03edc4c8.test.lua               |   2 +-
 test/sql-tap/trigger1.test.lua                     |  12 +-
 test/sql-tap/triggerC.test.lua                     |  14 +-
 test/sql-tap/unique.test.lua                       |  10 +-
 test/sql/check-clear-ephemeral.result              |  22 +-
 test/sql/check-clear-ephemeral.test.lua            |  12 +-
 test/sql/checks.result                             |   9 +-
 test/sql/checks.test.lua                           |   8 +-
 test/sql/clear.result                              |  49 +-
 test/sql/clear.test.lua                            |  20 +-
 test/sql/collation.result                          | 817 +++++++++++++++------
 test/sql/collation.test.lua                        | 350 ++++-----
 test/sql/delete-multiple-idx.result                |  44 +-
 test/sql/delete-multiple-idx.test.lua              |  24 +-
 test/sql/delete.result                             | 114 ++-
 test/sql/delete.test.lua                           |  68 +-
 test/sql/drop-index.result                         |  35 +-
 test/sql/drop-index.test.lua                       |  24 +-
 test/sql/drop-table.result                         |  44 +-
 test/sql/drop-table.test.lua                       |  32 +-
 test/sql/engine.result                             |  24 +-
 test/sql/engine.test.lua                           |  16 +-
 test/sql/errinj.result                             | 156 ++--
 test/sql/errinj.test.lua                           |  86 +--
 test/sql/foreign-keys.result                       |  58 +-
 test/sql/foreign-keys.test.lua                     |  40 +-
 test/sql/func-recreate.result                      |  11 +-
 test/sql/func-recreate.test.lua                    |   4 +-
 test/sql/gh-2347-max-int-literals.result           |  23 +-
 test/sql/gh-2347-max-int-literals.test.lua         |  10 +-
 test/sql/gh-2362-select-access-rights.result       |  33 +-
 test/sql/gh-2362-select-access-rights.test.lua     |  22 +-
 test/sql/gh-2929-primary-key.result                |  19 +-
 test/sql/gh-2929-primary-key.test.lua              |  16 +-
 test/sql/gh-2981-check-autoinc.result              |  49 +-
 test/sql/gh-2981-check-autoinc.test.lua            |  30 +-
 test/sql/gh-3199-no-mem-leaks.result               | 188 +++--
 test/sql/gh-3199-no-mem-leaks.test.lua             |  40 +-
 test/sql/gh-3613-idx-alter-update-2.result         |  18 +-
 test/sql/gh-3613-idx-alter-update-2.test.lua       |  12 +-
 test/sql/gh-3613-idx-alter-update.result           |  26 +-
 test/sql/gh-3613-idx-alter-update.test.lua         |  18 +-
 test/sql/gh-3888-values-blob-assert.result         |  47 +-
 test/sql/gh-3888-values-blob-assert.test.lua       |  22 +-
 test/sql/gh2141-delete-trigger-drop-table.result   |  46 +-
 test/sql/gh2141-delete-trigger-drop-table.test.lua |  22 +-
 test/sql/gh2251-multiple-update.result             |  49 +-
 test/sql/gh2251-multiple-update.test.lua           |  26 +-
 test/sql/gh2483-remote-persistency-check.result    |  24 +-
 test/sql/gh2483-remote-persistency-check.test.lua  |  12 +-
 .../gh2808-inline-unique-persistency-check.result  |  37 +-
 ...gh2808-inline-unique-persistency-check.test.lua |  14 +-
 test/sql/icu-upper-lower.result                    | 161 +++-
 test/sql/icu-upper-lower.test.lua                  |  10 +-
 test/sql/insert-unique.result                      |  30 +-
 test/sql/insert-unique.test.lua                    |  18 +-
 test/sql/integer-overflow.result                   |  26 +-
 test/sql/integer-overflow.test.lua                 |  24 +-
 test/sql/iproto.result                             |  48 +-
 test/sql/iproto.test.lua                           |  26 +-
 test/sql/max-on-index.result                       |  62 +-
 test/sql/max-on-index.test.lua                     |  32 +-
 test/sql/message-func-indexes.result               |  29 +-
 test/sql/message-func-indexes.test.lua             |  22 +-
 test/sql/min-on-index.result                       |  59 --
 test/sql/misc.result                               |  23 +-
 test/sql/misc.test.lua                             |  16 +-
 test/sql/no-pk-space.result                        |  19 +-
 test/sql/no-pk-space.test.lua                      |  16 +-
 test/sql/on-conflict.result                        | 130 +++-
 test/sql/on-conflict.test.lua                      |  70 +-
 test/sql/persistency.result                        | 425 ++++++++---
 test/sql/persistency.test.lua                      | 102 +--
 test/sql/row-count.result                          | 290 ++++++--
 test/sql/row-count.test.lua                        | 112 +--
 test/sql/savepoints.result                         |  31 +-
 test/sql/savepoints.test.lua                       |  28 +-
 test/sql/select-null.result                        |  31 +-
 test/sql/select-null.test.lua                      |  14 +-
 test/sql/sql-debug.result                          |  26 +-
 test/sql/sql-debug.test.lua                        |  10 +-
 test/sql/sql-statN-index-drop.result               | 197 +++--
 test/sql/sql-statN-index-drop.test.lua             |  58 +-
 test/sql/tokenizer.result                          |   3 +-
 test/sql/tokenizer.test.lua                        |   2 +-
 test/sql/transition.result                         | 387 +++++++---
 test/sql/transition.test.lua                       |  88 +--
 test/sql/transitive-transactions.result            |  48 +-
 test/sql/transitive-transactions.test.lua          |  42 +-
 test/sql/triggers.result                           | 245 ++++--
 test/sql/triggers.test.lua                         | 144 ++--
 test/sql/types.result                              | 104 ++-
 test/sql/types.test.lua                            |  66 +-
 test/sql/update-with-nested-select.result          |  28 +-
 test/sql/update-with-nested-select.test.lua        |  16 +-
 test/sql/upgrade.result                            |  40 +-
 test/sql/upgrade.test.lua                          |  20 +-
 test/sql/view.result                               | 131 ++--
 test/sql/view.test.lua                             |  94 +--
 test/sql/view_delayed_wal.result                   |  14 +-
 test/sql/view_delayed_wal.test.lua                 |  10 +-
 test/sql/vinyl-opts.result                         |   9 +-
 test/sql/vinyl-opts.test.lua                       |   6 +-
 150 files changed, 4491 insertions(+), 2828 deletions(-)
 delete mode 100644 src/box/lua/sql.c
 delete mode 100644 src/box/lua/sql.h
 delete mode 100644 test/sql/min-on-index.result

diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 59e91b6..7675156 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -138,7 +138,6 @@ add_library(box STATIC
     lua/session.c
     lua/net_box.c
     lua/xlog.c
-    lua/sql.c
     ${bin_sources})
 
 target_link_libraries(box box_error tuple stat xrow xlog vclock crc32 scramble
diff --git a/src/box/lua/console.lua b/src/box/lua/console.lua
index 33aefd6..f922f03 100644
--- a/src/box/lua/console.lua
+++ b/src/box/lua/console.lua
@@ -135,7 +135,7 @@ local function local_eval(storage, line)
         return preprocess(storage, line:sub(2))
     end
     if storage.language == 'sql' then
-        return format(pcall(box.sql.execute, line))
+        return format(pcall(box.execute, line))
     end
     --
     -- Attempt to append 'return ' before the chunk: if the chunk is
diff --git a/src/box/lua/init.c b/src/box/lua/init.c
index eb2ca31..af1bcdf 100644
--- a/src/box/lua/init.c
+++ b/src/box/lua/init.c
@@ -59,7 +59,6 @@
 #include "box/lua/xlog.h"
 #include "box/lua/console.h"
 #include "box/lua/tuple.h"
-#include "box/lua/sql.h"
 
 extern char session_lua[],
 	tuple_lua[],
@@ -330,7 +329,6 @@ box_lua_init(struct lua_State *L)
 	box_lua_ctl_init(L);
 	box_lua_session_init(L);
 	box_lua_xlog_init(L);
-	box_lua_sql_init(L);
 	luaopen_net_box(L);
 	lua_pop(L, 1);
 	tarantool_lua_console_init(L);
diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua
index 6c9a820..5530b2c 100644
--- a/src/box/lua/load_cfg.lua
+++ b/src/box/lua/load_cfg.lua
@@ -505,17 +505,14 @@ end
 box.cfg = locked(load_cfg)
 
 --
--- This makes possible do box.sql.execute without calling box.cfg
+-- This makes possible do box.execute without calling box.cfg
 -- manually. The load_cfg call overwrites following table and
 -- metatable.
 --
-box.sql = {}
-setmetatable(box.sql, {
-    __index = function(table, index)
-        load_cfg()
-        return box.sql[index]
-    end,
-})
+function box.execute(...)
+    load_cfg()
+    return box.execute(...)
+end
 
 -- gh-810:
 -- hack luajit default cpath
diff --git a/src/box/lua/sql.c b/src/box/lua/sql.c
deleted file mode 100644
index cd6e75c..0000000
--- a/src/box/lua/sql.c
+++ /dev/null
@@ -1,129 +0,0 @@
-#include "sql.h"
-#include "box/sql.h"
-#include "lua/msgpack.h"
-
-#include "box/sql/sqlInt.h"
-#include "info/info.h"
-#include "lua/info.h"
-#include "lua/utils.h"
-
-static void
-lua_push_column_names(struct lua_State *L, struct sql_stmt *stmt)
-{
-	int column_count = sql_column_count(stmt);
-	lua_createtable(L, column_count, 0);
-	for (int i = 0; i < column_count; i++) {
-		const char *name = sql_column_name(stmt, i);
-		lua_pushstring(L, name == NULL ? "" : name);
-		lua_rawseti(L, -2, i+1);
-	}
-}
-
-static void
-lua_push_row(struct lua_State *L, struct sql_stmt *stmt)
-{
-	int column_count = sql_column_count(stmt);
-
-	lua_createtable(L, column_count, 0);
-	lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_array_metatable_ref);
-	lua_setmetatable(L, -2);
-
-	for (int i = 0; i < column_count; i++) {
-		int type = sql_column_type(stmt, i);
-		switch (type) {
-		case SQL_INTEGER:
-			luaL_pushint64(L, sql_column_int64(stmt, i));
-			break;
-		case SQL_FLOAT:
-			lua_pushnumber(L, sql_column_double(stmt, i));
-			break;
-		case SQL_TEXT: {
-			const void *text = sql_column_text(stmt, i);
-			lua_pushlstring(L, text,
-					sql_column_bytes(stmt, i));
-			break;
-		}
-		case SQL_BLOB: {
-			const void *blob = sql_column_blob(stmt, i);
-			if (sql_column_subtype(stmt,i) == SQL_SUBTYPE_MSGPACK) {
-				luamp_decode(L, luaL_msgpack_default,
-					     (const char **)&blob);
-			} else {
-				lua_pushlstring(L, blob,
-					sql_column_bytes(stmt, i));
-			}
-			break;
-		}
-		case SQL_NULL:
-			lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_nil_ref);
-			break;
-		default:
-			assert(0);
-		}
-		lua_rawseti(L, -2, i+1);
-	}
-}
-
-static int
-lua_sql_execute(struct lua_State *L)
-{
-	sql *db = sql_get();
-	if (db == NULL)
-		return luaL_error(L, "not ready");
-
-	size_t length;
-	const char *sql = lua_tolstring(L, 1, &length);
-	if (sql == NULL)
-		return luaL_error(L, "usage: box.sql.execute(sqlstring)");
-
-	struct sql_stmt *stmt;
-	if (sql_prepare_v2(db, sql, length, &stmt, &sql) != SQL_OK)
-		goto sqlerror;
-	assert(stmt != NULL);
-
-	int rc;
-	int retval_count;
-	if (sql_column_count(stmt) == 0) {
-		while ((rc = sql_step(stmt)) == SQL_ROW);
-		retval_count = 0;
-	} else {
-		lua_newtable(L);
-		lua_pushvalue(L, lua_upvalueindex(1));
-		lua_setmetatable(L, -2);
-		lua_push_column_names(L, stmt);
-		lua_rawseti(L, -2, 0);
-
-		int row_count = 0;
-		while ((rc = sql_step(stmt)) == SQL_ROW) {
-			lua_push_row(L, stmt);
-			lua_rawseti(L, -2, ++row_count);
-		}
-		retval_count = 1;
-	}
-        if (rc != SQL_OK && rc != SQL_DONE)
-		goto sqlerror;
-	sql_finalize(stmt);
-	return retval_count;
-sqlerror:
-	lua_pushstring(L, sql_errmsg(db));
-	sql_finalize(stmt);
-	return lua_error(L);
-}
-
-void
-box_lua_sql_init(struct lua_State *L)
-{
-	static const struct luaL_Reg module_funcs [] = {
-		{"execute", lua_sql_execute},
-		{NULL, NULL}
-	};
-
-	/* used by lua_sql_execute via upvalue */
-	lua_createtable(L, 0, 1);
-	lua_pushstring(L, "sequence");
-	lua_setfield(L, -2, "__serialize");
-
-	luaL_openlib(L, "box.sql", module_funcs, 1);
-	lua_pop(L, 1);
-}
-
diff --git a/src/box/lua/sql.h b/src/box/lua/sql.h
deleted file mode 100644
index 2543e94..0000000
--- a/src/box/lua/sql.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef INCLUDES_TARANTOOL_LUA_SQL_H
-#define INCLUDES_TARANTOOL_LUA_SQL_H
-/*
- * Copyright 2010-2015, Tarantool AUTHORS, please see AUTHORS file.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct lua_State;
-
-void box_lua_sql_init(struct lua_State *L);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/test/box/cfg.result b/test/box/cfg.result
index 7778f82..66b02f5 100644
--- a/test/box/cfg.result
+++ b/test/box/cfg.result
@@ -528,23 +528,6 @@ box.cfg{net_msg_max = old + 1000}
 box.cfg{net_msg_max = old}
 ---
 ...
---
--- gh-3266: box.cfg{} still not optional on 2.0 brach
---
--- box.sql defined with __index function in metatable overridden
--- with first box.cfg() call
---
-box.cfg()
----
-...
-assert(next(box.sql) ~= nil)
----
-- true
-...
-assert(getmetatable(box.sql) == nil)
----
-- true
-...
 test_run:cmd("clear filter")
 ---
 - true
diff --git a/test/box/cfg.test.lua b/test/box/cfg.test.lua
index a641624..eddeab1 100644
--- a/test/box/cfg.test.lua
+++ b/test/box/cfg.test.lua
@@ -131,14 +131,4 @@ box.cfg{net_msg_max = 2}
 box.cfg{net_msg_max = old + 1000}
 box.cfg{net_msg_max = old}
 
---
--- gh-3266: box.cfg{} still not optional on 2.0 brach
---
--- box.sql defined with __index function in metatable overridden
--- with first box.cfg() call
---
-box.cfg()
-assert(next(box.sql) ~= nil)
-assert(getmetatable(box.sql) == nil)
-
 test_run:cmd("clear filter")
diff --git a/test/box/misc.result b/test/box/misc.result
index 714d5de..1b1a630 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -83,7 +83,6 @@ t
   - slab
   - snapshot
   - space
-  - sql
   - stat
   - tuple
 ...
diff --git a/test/box/sql-update-with-nested-select.result b/test/box/sql-update-with-nested-select.result
index 64a4fb6..24da618 100644
--- a/test/box/sql-update-with-nested-select.result
+++ b/test/box/sql-update-with-nested-select.result
@@ -3,31 +3,40 @@ test_run = require('test_run').new()
 ...
 -- box.cfg()
 -- create space
-box.sql.execute("CREATE TABLE t1(a integer primary key, b int UNIQUE, e int);");
+box.execute("CREATE TABLE t1(a integer primary key, b int UNIQUE, e int);");
 ---
+- rowcount: 1
 ...
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 -- Seed entries
-box.sql.execute("INSERT INTO t1 VALUES(1,4,6);");
+box.execute("INSERT INTO t1 VALUES(1,4,6);");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES(2,5,7);");
+box.execute("INSERT INTO t1 VALUES(2,5,7);");
 ---
+- rowcount: 1
 ...
 -- Both entries must be updated
-box.sql.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);");
+box.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);");
 ---
+- rowcount: 2
 ...
 -- Check
-box.sql.execute("SELECT e FROM t1");
+box.execute("SELECT e FROM t1");
 ---
-- - [7]
+- metadata:
+  - name: E
+    type: INTEGER
+  rows:
+  - [7]
   - [8]
 ...
 -- Cleanup
-box.sql.execute("DROP TABLE t1;");
+box.execute("DROP TABLE t1;");
 ---
+- rowcount: 1
 ...
 -- Debug
 -- require("console").start()
diff --git a/test/box/sql-update-with-nested-select.test.lua b/test/box/sql-update-with-nested-select.test.lua
index 9421a3b..5c5dd96 100644
--- a/test/box/sql-update-with-nested-select.test.lua
+++ b/test/box/sql-update-with-nested-select.test.lua
@@ -3,23 +3,23 @@ test_run = require('test_run').new()
 -- box.cfg()
 
 -- create space
-box.sql.execute("CREATE TABLE t1(a integer primary key, b int UNIQUE, e int);");
+box.execute("CREATE TABLE t1(a integer primary key, b int UNIQUE, e int);");
 
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 
 -- Seed entries
-box.sql.execute("INSERT INTO t1 VALUES(1,4,6);");
-box.sql.execute("INSERT INTO t1 VALUES(2,5,7);");
+box.execute("INSERT INTO t1 VALUES(1,4,6);");
+box.execute("INSERT INTO t1 VALUES(2,5,7);");
 
 -- Both entries must be updated
-box.sql.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);");
+box.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);");
 
 -- Check
-box.sql.execute("SELECT e FROM t1");
+box.execute("SELECT e FROM t1");
 
 -- Cleanup
-box.sql.execute("DROP TABLE t1;");
+box.execute("DROP TABLE t1;");
 
 -- Debug
 -- require("console").start()
diff --git a/test/sql-tap/alter.test.lua b/test/sql-tap/alter.test.lua
index 3b2eceb..2331cd0 100755
--- a/test/sql-tap/alter.test.lua
+++ b/test/sql-tap/alter.test.lua
@@ -359,7 +359,7 @@ test:do_catchsql_test(
         INSERT INTO t5 VALUES(2, 1, 3);
     ]], {
         -- <alter-7.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </alter-7.2>
     })
 
@@ -369,7 +369,7 @@ test:do_catchsql_test(
         INSERT INTO t5 VALUES(2, 2, 2);
     ]], {
         -- <alter-7.3>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </alter-7.3>
     })
 
@@ -435,7 +435,7 @@ test:do_catchsql_test(
         INSERT INTO t5 VALUES(4, 5, 3);
     ]], {
         -- <alter-7.9>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </alter-7.9>
     })
 
@@ -490,7 +490,7 @@ test:do_catchsql_test(
         INSERT INTO t5 VALUES(6, 5, 10);
     ]], {
         -- <alter-7.14>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </alter-7.14>
     })
 
diff --git a/test/sql-tap/alter2.test.lua b/test/sql-tap/alter2.test.lua
index beb6f5d..612dd74 100755
--- a/test/sql-tap/alter2.test.lua
+++ b/test/sql-tap/alter2.test.lua
@@ -24,7 +24,7 @@ test:do_catchsql_test(
         INSERT INTO t1 VALUES(2, 3, 2);
     ]], {
         -- <alter2-1.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </alter2-1.2>
     })
 
@@ -45,7 +45,7 @@ test:do_catchsql_test(
         INSERT INTO t1 VALUES(2, 3, 2);
     ]], {
         -- <alter2-1.4>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </alter2-1.4>
     })
 
@@ -83,7 +83,7 @@ test:do_catchsql_test(
         INSERT INTO t1 VALUES(4, 2, 1);
     ]], {
         -- <alter2-1.6>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </alter2-1.6>
     })
 
@@ -143,7 +143,7 @@ test:do_catchsql_test(
         INSERT INTO parent VALUES(1, 2, 3);
     ]], {
         -- <alter2-2.1>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </alter2-2.1>
     })
 
@@ -154,7 +154,7 @@ test:do_catchsql_test(
         INSERT INTO child VALUES(2, 1, 1);
     ]], {
         -- <alter2-2.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </alter2-2.2>
     })
 
@@ -165,7 +165,7 @@ test:do_catchsql_test(
         INSERT INTO parent VALUES(3, 4, 2);
     ]], {
         -- <alter2-2.3>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </alter2-2.3>
     })
 
diff --git a/test/sql-tap/analyze1.test.lua b/test/sql-tap/analyze1.test.lua
index cc12593..f274cee 100755
--- a/test/sql-tap/analyze1.test.lua
+++ b/test/sql-tap/analyze1.test.lua
@@ -499,13 +499,13 @@ test:do_test(
         test:execsql("CREATE INDEX i2 ON t1(e);")
 
         for i = 0, 100 do
-            box.sql.execute(string.format("INSERT INTO t1 VALUES(null, 'x', 'y', 'z', %s, %s);", i, math.floor(i / 2)))
+            box.execute(string.format("INSERT INTO t1 VALUES(null, 'x', 'y', 'z', %s, %s);", i, math.floor(i / 2)))
         end;
         for i = 0, 20 do
-            box.sql.execute("INSERT INTO t1 VALUES(null, 'x', 'y', 'z', 101, "..i..");")
+            box.execute("INSERT INTO t1 VALUES(null, 'x', 'y', 'z', 101, "..i..");")
         end;
         for i = 102, 200 do
-            box.sql.execute(string.format("INSERT INTO t1 VALUES(null, 'x', 'y', 'z', %s, %s);", i, math.floor(i / 2)))
+            box.execute(string.format("INSERT INTO t1 VALUES(null, 'x', 'y', 'z', %s, %s);", i, math.floor(i / 2)))
         end;
 
         test:execsql("ANALYZE;")
diff --git a/test/sql-tap/analyze9.test.lua b/test/sql-tap/analyze9.test.lua
index 3969c45..02eb49f 100755
--- a/test/sql-tap/analyze9.test.lua
+++ b/test/sql-tap/analyze9.test.lua
@@ -240,7 +240,7 @@ insert_filler_rows_n = function(iStart, nCopy, nVal)
     for i = 0, nVal-1 do
         local iVal = iStart+i
         for j = 0, nCopy-1 do
-            box.sql.execute(string.format("INSERT INTO t1 VALUES (null, %s, %s, '%s')", iVal, iVal, iVal))
+            box.execute(string.format("INSERT INTO t1 VALUES (null, %s, %s, '%s')", iVal, iVal, iVal))
         end
     end
 end
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index dc2f60e..bdc0053 100755
--- a/test/sql-tap/autoinc.test.lua
+++ b/test/sql-tap/autoinc.test.lua
@@ -531,7 +531,7 @@ test:do_catchsql_test(
         INSERT INTO t6 VALUES(NULL,1);
     ]], {
         -- <autoinc-6.2>
-        1, "Sequence 'T6' has overflowed"
+        1, "Error during execution of VDBE byte-code: Sequence 'T6' has overflowed"
         -- </autoinc-6.2>
     })
 
@@ -810,7 +810,7 @@ test:do_catchsql_test(
         INSERT INTO t1 SELECT s2, s2 FROM t1;
     ]], {
         -- <autoinc-gh-3670>
-        1, "datatype mismatch"
+        1, "Error during execution of VDBE byte-code: datatype mismatch"
         -- </autoinc-gh-3670>
     })
 
diff --git a/test/sql-tap/between.test.lua b/test/sql-tap/between.test.lua
index 79583af..4395b28 100755
--- a/test/sql-tap/between.test.lua
+++ b/test/sql-tap/between.test.lua
@@ -58,7 +58,7 @@ local function queryplan(sql)
         x = "sort"
     end
     table.insert(data,x)
-    local eqp = box.sql.execute("EXPLAIN QUERY PLAN "..sql.."")
+    local eqp = box.execute("EXPLAIN QUERY PLAN "..sql.."").rows
     -- puts eqp=$eqp
     for i, val in ipairs(eqp) do
         --local a = val[1]
diff --git a/test/sql-tap/check.test.lua b/test/sql-tap/check.test.lua
index 0d8bf15..c7ef1a1 100755
--- a/test/sql-tap/check.test.lua
+++ b/test/sql-tap/check.test.lua
@@ -55,7 +55,7 @@ test:do_catchsql_test(
         INSERT INTO t1 VALUES(6,7, 2);
     ]], {
         -- <check-1.3>
-        1, "CHECK constraint failed: T1"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T1"
         -- </check-1.3>
     })
 
@@ -75,7 +75,7 @@ test:do_catchsql_test(
         INSERT INTO t1 VALUES(4,3, 2);
     ]], {
         -- <check-1.5>
-        1, "CHECK constraint failed: T1"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T1"
         -- </check-1.5>
     })
 
@@ -147,7 +147,7 @@ test:do_catchsql_test(
         UPDATE t1 SET x=7 WHERE x==2
     ]], {
         -- <check-1.12>
-        1, "CHECK constraint failed: T1"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T1"
         -- </check-1.12>
     })
 
@@ -167,7 +167,7 @@ test:do_catchsql_test(
         UPDATE t1 SET x=5 WHERE x==2
     ]], {
         -- <check-1.14>
-        1, "CHECK constraint failed: T1"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T1"
         -- </check-1.14>
     })
 
@@ -246,7 +246,7 @@ test:do_catchsql_test(
         INSERT INTO t2 VALUES(3, 1.1, NULL, NULL);
     ]], {
         -- <check-2.4>
-        1, "CHECK constraint failed: ONE"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: ONE"
         -- </check-2.4>
     })
 
@@ -256,7 +256,7 @@ test:do_catchsql_test(
         INSERT INTO t2 VALUES(4, NULL, 5, NULL);
     ]], {
         -- <check-2.5>
-        1, "CHECK constraint failed: TWO"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: TWO"
         -- </check-2.5>
     })
 
@@ -266,7 +266,7 @@ test:do_catchsql_test(
         INSERT INTO t2 VALUES(5, NULL, NULL, 3.14159);
     ]], {
         -- <check-2.6>
-        1, "CHECK constraint failed: THREE"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: THREE"
         -- </check-2.6>
     })
 
@@ -413,7 +413,7 @@ test:do_catchsql_test(
         INSERT INTO t3 VALUES(111,222,333);
     ]], {
         -- <check-3.9>
-        1, "CHECK constraint failed: T3"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T3"
         -- </check-3.9>
     })
 
@@ -484,7 +484,7 @@ test:do_catchsql_test(
         UPDATE t4 SET x=0, y=1;
     ]], {
         -- <check-4.6>
-        1, "CHECK constraint failed: T4"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T4"
         -- </check-4.6>
     })
 
@@ -504,7 +504,7 @@ test:do_catchsql_test(
         UPDATE t4 SET x=0, y=2;
     ]], {
         -- <check-4.9>
-        1, "CHECK constraint failed: T4"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T4"
         -- </check-4.9>
     })
 
@@ -581,7 +581,7 @@ test:do_catchsql_test(
         UPDATE OR FAIL t1 SET x=7-x, y=y+1;
     ]], {
         -- <check-6.5>
-        1, "CHECK constraint failed: T1"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T1"
         -- </check-6.5>
     })
 
@@ -603,7 +603,7 @@ test:do_catchsql_test(
         INSERT OR ROLLBACK INTO t1 VALUES(8,40.0, 10);
     ]], {
         -- <check-6.7>
-        1, "CHECK constraint failed: T1"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T1"
         -- </check-6.7>
     })
 
@@ -613,7 +613,7 @@ test:do_catchsql_test(
         COMMIT;
     ]], {
         -- <check-6.8>
-        1, "cannot commit - no transaction is active"
+        1, "Error during execution of VDBE byte-code: cannot commit - no transaction is active"
         -- </check-6.8>
     })
 
@@ -636,7 +636,7 @@ test:do_catchsql_test(
         REPLACE INTO t1 VALUES(6,7, 11);
     ]], {
         -- <check-6.12>
-        1, "CHECK constraint failed: T1"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T1"
         -- </check-6.12>
     })
 
@@ -700,7 +700,7 @@ test:do_catchsql_test(
     7.3,
     " INSERT INTO t6 VALUES(11) ", {
         -- <7.3>
-        1, "CHECK constraint failed: T6"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T6"
         -- </7.3>
     })
 
diff --git a/test/sql-tap/delete1.test.lua b/test/sql-tap/delete1.test.lua
index d6d4762..bfed3ba 100755
--- a/test/sql-tap/delete1.test.lua
+++ b/test/sql-tap/delete1.test.lua
@@ -151,7 +151,7 @@ test:do_test(
 test:do_test(
     "delete1-6.1.1",
     function()
-        box.sql.execute([[delete from "t" where "id"=2]])
+        box.execute([[delete from "t" where "id"=2]])
         return s:count()
     end,
     2)
@@ -159,7 +159,7 @@ test:do_test(
 test:do_test(
     "delete1-6.1",
     function()
-        box.sql.execute([[delete from "t"]])
+        box.execute([[delete from "t"]])
 	return s:count()
     end,
     0)
diff --git a/test/sql-tap/distinct.test.lua b/test/sql-tap/distinct.test.lua
index c663751..e697008 100755
--- a/test/sql-tap/distinct.test.lua
+++ b/test/sql-tap/distinct.test.lua
@@ -25,14 +25,14 @@ local function is_distinct_noop(sql)
     local sql2 = string.gsub(sql, "DISTINCT", "")
     local program1 = {  }
     local program2 = {  }
-    local r = box.sql.execute("EXPLAIN "..sql1)
+    local r = box.execute("EXPLAIN "..sql1).rows
     for _, val in ipairs(r) do
         local opcode = val[2]
         if opcode ~= "Noop" then
             table.insert(program1, opcode)
         end
     end
-    r = box.sql.execute("EXPLAIN "..sql2)
+    r = box.execute("EXPLAIN "..sql2).rows
     for _, val in ipairs(r) do
         local opcode = val[2]
         if opcode ~= "Noop" then
@@ -63,7 +63,7 @@ local function do_temptables_test(tn, sql, temptables)
         tn,
         function()
             local ret = {}
-            local r = box.sql.execute("EXPLAIN "..sql)
+            local r = box.execute("EXPLAIN "..sql).rows
             for _, val in ipairs(r) do
                 local opcode = val[2]
                 local p5 = val[7]
diff --git a/test/sql-tap/fkey1.test.lua b/test/sql-tap/fkey1.test.lua
index 0464f2d..f7c473f 100755
--- a/test/sql-tap/fkey1.test.lua
+++ b/test/sql-tap/fkey1.test.lua
@@ -158,7 +158,7 @@ test:do_catchsql_test(
         INSERT OR REPLACE INTO t11 VALUES (2, 3);
     ]], {
         -- <fkey1-5.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey1-5.2>
     })
 
@@ -194,7 +194,7 @@ test:do_catchsql_test(
         INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 3, 'A-2-3');
     ]], {
         -- <fkey1-5.5>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey1-5.5>
     })
 
diff --git a/test/sql-tap/fkey2.test.lua b/test/sql-tap/fkey2.test.lua
index d347e5a..525ef2a 100755
--- a/test/sql-tap/fkey2.test.lua
+++ b/test/sql-tap/fkey2.test.lua
@@ -26,7 +26,7 @@ test:do_catchsql_test(
         INSERT INTO t2(c,d) VALUES(1, 3);
     ]], {
         -- <fkey2-1.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.2>
     })
 
@@ -56,7 +56,7 @@ test:do_catchsql_test(
         INSERT INTO t2(c,d) VALUES(2, 4);
     ]], {
         -- <fkey2-1.5>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.5>
     })
 
@@ -77,7 +77,7 @@ test:do_catchsql_test(
         UPDATE t2 SET c = 2 WHERE d = 4;
     ]], {
         -- <fkey2-1.7>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.7>
     })
 
@@ -98,7 +98,7 @@ test:do_catchsql_test(
         DELETE FROM t1 WHERE a = 1;
     ]], {
         -- <fkey2-1.9>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.9>
     })
 
@@ -109,7 +109,7 @@ test:do_catchsql_test(
         UPDATE t1 SET a = 2;
     ]], {
         -- <fkey2-1.10>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.10>
     })
 
@@ -131,7 +131,7 @@ test:do_catchsql_test(
         INSERT INTO t4(c,d) values (1,3);
     ]], {
         -- <fkey2-1.12>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.12>
     })
 
@@ -161,7 +161,7 @@ test:do_catchsql_test(
         INSERT INTO t8(c,d) values (1,3);
     ]], {
         -- <fkey2-1.15>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.15>
     })
 
@@ -191,7 +191,7 @@ test:do_catchsql_test(
         INSERT INTO t8(c,d) values (2,4);
     ]], {
         -- <fkey2-1.18>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.18>
     })
 
@@ -201,7 +201,7 @@ test:do_catchsql_test(
         INSERT INTO t8(c,d) values (6,4);
     ]], {
         -- <fkey2-1.19>
-        1,"FOREIGN KEY constraint failed"
+        1,"Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.19>
     })
 
@@ -241,7 +241,7 @@ test:do_catchsql_test(
         DELETE FROM t7 WHERE b = 1;
     ]], {
         -- <fkey2-1.23>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.23>
     })
 
@@ -251,7 +251,7 @@ test:do_catchsql_test(
         UPDATE t7 SET b = 2;
     ]], {
         -- <fkey2-1.24>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.24>
     })
 
@@ -271,7 +271,7 @@ test:do_catchsql_test(
         INSERT INTO t8(c,d) VALUES(666, 54644);
     ]], {
         -- <fkey2-1.26>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.26>
     })
 
@@ -281,7 +281,7 @@ test:do_catchsql_test(
         UPDATE t7 SET b = 5;
     ]], {
         -- <fkey2-1.27>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-1.27>
     })
 
@@ -333,7 +333,7 @@ test:do_catchsql_test(
         DELETE FROM i;
     ]], {
         -- <fkey2-2.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-2.2>
     })
 
@@ -362,7 +362,7 @@ test:do_catchsql_test(
         UPDATE ab SET a = 5;
     ]], {
         -- <fkey2-3.2>
-        1, "CHECK constraint failed: EF"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: EF"
         -- </fkey2-3.2>
     })
 
@@ -382,7 +382,7 @@ test:do_catchsql_test(
         UPDATE ab SET a = 5;
     ]], {
         -- <fkey2-3.4>
-        1, "CHECK constraint failed: EF"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: EF"
         -- </fkey2-3.4>
     })
 
@@ -403,7 +403,7 @@ test:do_catchsql_test(
         DELETE FROM ab;
     ]], {
         -- <fkey2-3.6>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-3.6>
     })
 
@@ -540,7 +540,7 @@ test:do_catchsql_test(
         INSERT INTO t2(c,b) VALUES(1, 'A');
     ]], {
         -- <fkey2-5.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-5.2>
     })
 
@@ -562,7 +562,7 @@ test:do_catchsql_test(
         UPDATE t2 SET c = 3;
     ]], {
         -- <fkey2-5.4>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-5.4>
     })
 
@@ -572,7 +572,7 @@ test:do_catchsql_test(
         DELETE FROM t1 WHERE a = 2;
     ]], {
         -- <fkey2-5.5>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-5.5>
     })
 
@@ -591,7 +591,7 @@ test:do_catchsql_test(
         UPDATE t1 SET a = 3;
     ]], {
         -- <fkey2-5.7>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-5.7>
     })
 
@@ -656,7 +656,7 @@ test:do_catchsql_test(
         DELETE FROM t1;
     ]], {
         -- <fkey2-6.5>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-6.5>
     })
 
@@ -808,7 +808,7 @@ test:do_catchsql_test(
       UPDATE t1 SET b = 'five' WHERE b = 'two';
     ]], {
         -- <fkey2-9.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-9.2>
     })
 
@@ -818,7 +818,7 @@ test:do_catchsql_test(
         DELETE FROM t1 WHERE b = 'two';
     ]], {
         -- <fkey2-9.3>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-9.3>
     })
 
@@ -828,7 +828,7 @@ test:do_catchsql_test(
         INSERT INTO t2 VALUES('five');
     ]], {
         -- <fkey2-9.4>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-9.4>
     })
 
@@ -885,7 +885,7 @@ test:do_catchsql_test(
         DELETE FROM t1;
     ]], {
         -- <fkey2-9.8>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-9.8>
     })
 
@@ -942,7 +942,7 @@ test:do_catchsql_test(
         INSERT INTO down(c39, c38) VALUES('yes', 'no');
     ]], {
         -- <fkey2-9.12>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-9.12>
     })
 
@@ -954,7 +954,7 @@ test:do_catchsql_test(
         DELETE FROM up WHERE c34 = 'yes';
     ]], {
         -- <fkey2-9.13>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-9.13>
     })
 
@@ -1007,7 +1007,7 @@ test:do_execsql_test(
 --         INSERT INTO t3 VALUES(1, 2, 3);
 --     ]], {
 --         -- <fkey2-10.2>
---         1, "FOREIGN KEY constraint failed"
+--         1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
 --         -- </fkey2-10.2>
 --     })
 
@@ -1027,7 +1027,7 @@ test:do_execsql_test(
 --         UPDATE t4 SET b = 5;
 --     ]], {
 --         -- <fkey2-10.4>
---         1, "FOREIGN KEY constraint failed"
+--         1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
 --         -- </fkey2-10.4>
 --     })
 
@@ -1183,7 +1183,7 @@ test:do_catchsql_test(
         UPDATE self SET b = 15;
     ]], {
         -- <fkey2-11.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-11.2>
     })
 
@@ -1193,7 +1193,7 @@ test:do_catchsql_test(
         UPDATE self SET a = 15;
     ]], {
         -- <fkey2-11.3>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-11.3>
     })
 
@@ -1203,7 +1203,7 @@ test:do_catchsql_test(
         UPDATE self SET a = 15, b = 16;
     ]], {
         -- <fkey2-11.4>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-11.4>
     })
 
@@ -1231,7 +1231,7 @@ test:do_catchsql_test(
         INSERT INTO self(a,b) VALUES(20, 21);
     ]], {
         -- <fkey2-11.7>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-11.7>
     })
 
@@ -1253,7 +1253,7 @@ test:do_catchsql_test(
         UPDATE self SET b = 15;
     ]], {
         -- <fkey2-11.9>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-11.9>
     })
 
@@ -1263,7 +1263,7 @@ test:do_catchsql_test(
         UPDATE self SET a = 15;
     ]], {
         -- <fkey2-11.10>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-11.10>
     })
 
@@ -1273,7 +1273,7 @@ test:do_catchsql_test(
         UPDATE self SET a = 15, b = 16;
     ]], {
         -- <fkey2-11.11>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-11.11>
     })
 
@@ -1301,7 +1301,7 @@ test:do_catchsql_test(
         INSERT INTO self(a,b) VALUES(20, 21);
     ]], {
         -- <fkey2-11.14>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-11.14>
     })
 
@@ -1328,7 +1328,7 @@ test:do_catchsql_test(
         DELETE FROM tdd08;
     ]], {
         -- <fkey2-12.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-12.2>
     })
 
@@ -1348,7 +1348,7 @@ test:do_catchsql_test(
         INSERT INTO tdd08_b(w,x,y) VALUES(400,500,300);
     ]], {
         -- <fkey2-12.4>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-12.4>
     })
 
@@ -1358,7 +1358,7 @@ test:do_catchsql_test(
         UPDATE tdd08_b SET x=x+1;
     ]], {
         -- <fkey2-12.5>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-12.5>
     })
 
@@ -1368,7 +1368,7 @@ test:do_catchsql_test(
         UPDATE tdd08 SET a=a+1;
     ]], {
         -- <fkey2-12.6>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-12.6>
     })
 
@@ -1394,7 +1394,7 @@ test:do_catchsql_test(
         UPDATE tce71 set b = 201 where a = 100;
     ]], {
         -- <fkey2-13.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-13.2>
     })
 
@@ -1404,7 +1404,7 @@ test:do_catchsql_test(
         UPDATE tce71 set a = 101 where a = 100;
     ]], {
         -- <fkey2-13.3>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-13.3>
     })
 
@@ -1429,7 +1429,7 @@ test:do_catchsql_test(
         UPDATE tce73 set b = 201 where a = 100;
     ]], {
         -- <fkey2-14.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-14.2>
     })
 
@@ -1439,7 +1439,7 @@ test:do_catchsql_test(
         UPDATE tce71 set a = 101 where a = 100;
     ]], {
         -- <fkey2-14.3>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey2-14.3>
     })
 
diff --git a/test/sql-tap/fkey3.test.lua b/test/sql-tap/fkey3.test.lua
index 011402d..c66b5e0 100755
--- a/test/sql-tap/fkey3.test.lua
+++ b/test/sql-tap/fkey3.test.lua
@@ -122,7 +122,7 @@ test:do_catchsql_test(
         INSERT INTO t3 VALUES(2, 2, 5, 2);
     ]], {
         -- <fkey3-3.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey3-3.2>
     })
 
@@ -132,7 +132,7 @@ test:do_catchsql_test(
         INSERT INTO t3 VALUES(2, 3, 5, 2);
     ]], {
         -- <fkey3-3.3>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey3-3.3>
     })
 
@@ -151,7 +151,7 @@ test:do_catchsql_test(
         INSERT INTO t4 VALUES(2, 1);
     ]], {
         -- <fkey3-3.5>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey3-3.5>
     })
 
@@ -175,7 +175,7 @@ test:do_catchsql_test(
         INSERT INTO t6(a,b,c,d) VALUES(4, 'a', 65, 'a');
     ]], {
         -- <fkey3-3.7>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey3-3.7>
     })
 
@@ -197,7 +197,7 @@ test:do_catchsql_test(
         UPDATE t6 SET c = 1, d = 'a' WHERE a = 100;
     ]], {
         -- <fkey3-3.9>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey3-3.9>
     })
 
@@ -219,7 +219,7 @@ test:do_catchsql_test(
         INSERT INTO t7 VALUES('x', 450, 'x', 4);
     ]], {
         -- <fkey3-3.11>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey3-3.11>
     })
 
@@ -229,7 +229,7 @@ test:do_catchsql_test(
         INSERT INTO t7 VALUES('x', 450, 'x', 451);
     ]], {
         -- <fkey3-3.12>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey3-3.12>
     })
 
@@ -253,7 +253,7 @@ test:do_catchsql_test(
         UPDATE t8 SET d = 2;
     ]], {
         -- <fkey3-6.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey3-6.2>
     })
 
@@ -282,7 +282,7 @@ test:do_catchsql_test(
         UPDATE TestTable SET parent_id=1000 WHERE id=2;
     ]], {
         -- <fkey3-6.4>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey3-6.4>
     })
 
diff --git a/test/sql-tap/fkey4.test.lua b/test/sql-tap/fkey4.test.lua
index 13fd308..3a03cd5 100755
--- a/test/sql-tap/fkey4.test.lua
+++ b/test/sql-tap/fkey4.test.lua
@@ -30,7 +30,7 @@ test:do_catchsql_test(
         DELETE FROM p1 WHERE a = 2;
     ]], {
         -- <fkey8-1.2>
-        1, "NOT NULL constraint failed: C1.B"
+        1, "Error during execution of VDBE byte-code: NOT NULL constraint failed: C1.B"
         -- </fkey8-1.2>
     })
 
@@ -83,7 +83,7 @@ test:do_catchsql_test(
         DELETE FROM p1 WHERE a = 2;
     ]], {
         -- <fkey8-1.5>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey8-1.5>
     })
 
@@ -159,7 +159,7 @@ test:do_catchsql_test(
         UPDATE OR IGNORE p1 SET a = 4 WHERE a = 2;
     ]], {
         -- <fkey8-1.9>
-        1, "NOT NULL constraint failed: C1.B"
+        1, "Error during execution of VDBE byte-code: NOT NULL constraint failed: C1.B"
         -- </fkey8-1.9>
     })
 
@@ -203,7 +203,7 @@ test:do_catchsql_test(
         INSERT OR REPLACE INTO p1 VALUES(2, 'two');
     ]], {
         -- <fkey8-2.2>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey8-2.2>
     })
 
@@ -278,7 +278,7 @@ test:do_catchsql_test(
         DELETE FROM p3 WHERE a=1;
     ]], {
         -- <fkey8-4.3>
-        1, "FOREIGN KEY constraint failed"
+        1, "Error during execution of VDBE byte-code: FOREIGN KEY constraint failed"
         -- </fkey8-4.3>
     })
 
diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua
index 889fc58..a7fff6e 100755
--- a/test/sql-tap/func.test.lua
+++ b/test/sql-tap/func.test.lua
@@ -1598,7 +1598,7 @@ test:do_catchsql_test(
         SELECT sum(x) - ((1<<62)*2.0+1) from t6;
     ]], {
         -- <func-18.12>
-        1, "integer overflow"
+        1, "Error during execution of VDBE byte-code: integer overflow"
         -- </func-18.12>
     })
 
@@ -1653,7 +1653,7 @@ test:do_catchsql_test(
             SELECT 10 AS x);
     ]], {
         -- <func-18.15>
-        1, "integer overflow"
+        1, "Error during execution of VDBE byte-code: integer overflow"
         -- </func-18.15>
     })
 
@@ -1665,7 +1665,7 @@ test:do_catchsql_test(
             SELECT -10 AS x);
     ]], {
         -- <func-18.18>
-        1, "integer overflow"
+        1, "Error during execution of VDBE byte-code: integer overflow"
         -- </func-18.18>
     })
 
@@ -1730,7 +1730,7 @@ test:do_catchsql_test(
         SELECT abs(-9223372036854775807-1);
     ]], {
         -- <func-18.32>
-        1, "integer overflow"
+        1, "Error during execution of VDBE byte-code: integer overflow"
         -- </func-18.32>
     })
 
@@ -1752,7 +1752,7 @@ test:do_catchsql_test(
         SELECT 'abc' MATCH 'xyz';
     ]], {
         -- <func-19.2>
-        1, "unable to use function MATCH in the requested context"
+        1, "Error during execution of VDBE byte-code: unable to use function MATCH in the requested context"
         -- </func-19.2>
     })
 
@@ -1762,7 +1762,7 @@ test:do_catchsql_test(
         SELECT 'abc' NOT MATCH 'xyz';
     ]], {
         -- <func-19.3>
-        1, "unable to use function MATCH in the requested context"
+        1, "Error during execution of VDBE byte-code: unable to use function MATCH in the requested context"
         -- </func-19.3>
     })
 
diff --git a/test/sql-tap/gh-2723-concurrency.test.lua b/test/sql-tap/gh-2723-concurrency.test.lua
index 21912a0..842142d 100755
--- a/test/sql-tap/gh-2723-concurrency.test.lua
+++ b/test/sql-tap/gh-2723-concurrency.test.lua
@@ -11,11 +11,11 @@ for id = 1, N do
     fiber.create(
         function ()
             local table_name = "table2723"..id
-            box.sql.execute("create table "..table_name.."(id INT primary key, a integer unique, b INT)")
-            box.sql.execute("insert into "..table_name.." values(1, 2, 3)")
-            box.sql.execute("insert into "..table_name.." values(3, 4, 3)")
-            pcall( function() box.sql.execute("insert into "..table_name.." values(3, 4, 3)") end)
-            box.sql.execute("drop table "..table_name)
+            box.execute("create table "..table_name.."(id INT primary key, a integer unique, b INT)")
+            box.execute("insert into "..table_name.." values(1, 2, 3)")
+            box.execute("insert into "..table_name.." values(3, 4, 3)")
+            pcall( function() box.execute("insert into "..table_name.." values(3, 4, 3)") end)
+            box.execute("drop table "..table_name)
             ch:put(1)
         end
     )
@@ -32,16 +32,16 @@ test:do_test(
     0)
 
 ch = fiber.channel(N)
-box.sql.execute("create table t1(id INT primary key, a integer unique, b INT);")
-box.sql.execute("create index i1 on t1(b);")
+box.execute("create table t1(id INT primary key, a integer unique, b INT);")
+box.execute("create index i1 on t1(b);")
 for id = 1, N do
     fiber.create(
         function ()
-            box.sql.execute(string.format("insert into t1 values(%s, %s, 3)", id, id))
-            box.sql.execute(string.format("insert into t1 values(%s, %s, 3)", id+N, id+N))
-            box.sql.execute(string.format("delete from t1 where id = %s", id+N))
-            box.sql.execute(string.format("insert into t1 values(%s, %s, 3)", id+2*N, id+2*N))
-            box.sql.execute(string.format("delete from t1 where id = %s", id+2*N))
+            box.execute(string.format("insert into t1 values(%s, %s, 3)", id, id))
+            box.execute(string.format("insert into t1 values(%s, %s, 3)", id+N, id+N))
+            box.execute(string.format("delete from t1 where id = %s", id+N))
+            box.execute(string.format("insert into t1 values(%s, %s, 3)", id+2*N, id+2*N))
+            box.execute(string.format("delete from t1 where id = %s", id+2*N))
             ch:put(1)
         end
     )
@@ -55,19 +55,19 @@ test:do_test(
         return test:execsql("select count(*) from (select distinct * from t1);")[1]
     end,
     N)
-box.sql.execute("drop table t1;")
+box.execute("drop table t1;")
 
 
 ch = fiber.channel(N)
-box.sql.execute("create table t1(id INT primary key, a integer unique, b INT);")
-box.sql.execute("create index i1 on t1(b);")
+box.execute("create table t1(id INT primary key, a integer unique, b INT);")
+box.execute("create index i1 on t1(b);")
 for id = 1, N*N do
-    box.sql.execute(string.format("insert into t1 values(%s, %s, 3)", id, id))
+    box.execute(string.format("insert into t1 values(%s, %s, 3)", id, id))
 end
 for id = 1, N do
     fiber.create(
         function ()
-            box.sql.execute("delete from t1")
+            box.execute("delete from t1")
             ch:put(1)
         end
     )
@@ -81,6 +81,6 @@ test:do_test(
         return test:execsql("select count(*) from t1;")[1]
     end,
     0)
-box.sql.execute("drop table t1;")
+box.execute("drop table t1;")
 
 test:finish_test()
diff --git a/test/sql-tap/gh-2931-savepoints.test.lua b/test/sql-tap/gh-2931-savepoints.test.lua
index 2ce4145..85dc7a1 100755
--- a/test/sql-tap/gh-2931-savepoints.test.lua
+++ b/test/sql-tap/gh-2931-savepoints.test.lua
@@ -38,7 +38,7 @@ local testcases = {
 		{0,{1,1}}},
 	{"5",
 		[[rollback to savepoint s1_2;]],
-		{1, "no such savepoint: S1_2"}},
+		{1, "Error during execution of VDBE byte-code: no such savepoint: S1_2"}},
 	{"6",
 		[[insert into t1 values(2);
 		select * from t1 union all select * from t2;]],
@@ -80,13 +80,13 @@ local testcases = {
 		{0,{1,2,10,11,1,2,4,10,11}}},
 	{"14",
 		[[insert into t1 values(4);]],
-		{1,"Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}},
+		{1,"Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}},
 	{"15",
 		[[select * from t1 union all select * from t2;]],
 		{0,{1,2,10,11,1,2,4,10,11}}},
 	{"16",
 		[[insert or rollback into t1 values(4);]],
-		{1,"Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}},
+		{1,"Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}},
 	{"17",  -- should work as transaction is rolled back
 		[[insert or rollback into t1 values(4);
 		select * from t1 union all select * from t2;]],
diff --git a/test/sql-tap/gh-3083-ephemeral-unref-tuples.test.lua b/test/sql-tap/gh-3083-ephemeral-unref-tuples.test.lua
index de57e38..3807ba6 100755
--- a/test/sql-tap/gh-3083-ephemeral-unref-tuples.test.lua
+++ b/test/sql-tap/gh-3083-ephemeral-unref-tuples.test.lua
@@ -9,11 +9,11 @@ test:do_test(
 		test:execsql "CREATE TABLE test(id integer, k integer, primary key (id))"
 
 		for i = 1, 1000 do
-			box.sql.execute("insert into test(id, k) values(" .. i .. "," .. i .. ")")
+			box.execute("insert into test(id, k) values(" .. i .. "," .. i .. ")")
 		end
 
 		for i = 1, 10000 do
-			box.sql.execute("SELECT id, k FROM test WHERE k IN (5849, 4986, 4997, 5020, 5044, 4990, 5013, 4983)")
+			box.execute("SELECT id, k FROM test WHERE k IN (5849, 4986, 4997, 5020, 5044, 4990, 5013, 4983)")
 		end
 	end, {
 		-- <unref_before_delete-1.1>
diff --git a/test/sql-tap/gh-3251-string-pattern-comparison.test.lua b/test/sql-tap/gh-3251-string-pattern-comparison.test.lua
index 3d35743..0e0a003 100755
--- a/test/sql-tap/gh-3251-string-pattern-comparison.test.lua
+++ b/test/sql-tap/gh-3251-string-pattern-comparison.test.lua
@@ -142,17 +142,17 @@ for i, tested_string in ipairs(invalid_testcases) do
     local test_name = prefix .. "2." .. tostring(i)
     local test_itself = "SELECT 'abc' LIKE 'ab" .. tested_string .. "';"
     test:do_catchsql_test(test_name, test_itself,
-                          {1, "LIKE pattern can only contain UTF-8 characters"})
+                          {1, "Error during execution of VDBE byte-code: LIKE pattern can only contain UTF-8 characters"})
 
     test_name = prefix .. "3." .. tostring(i)
     test_itself = "SELECT 'abc' LIKE 'abc" .. tested_string .. "';"
     test:do_catchsql_test(test_name, test_itself,
-                          {1, "LIKE pattern can only contain UTF-8 characters"})
+                          {1, "Error during execution of VDBE byte-code: LIKE pattern can only contain UTF-8 characters"})
 
     test_name = prefix .. "4." .. tostring(i)
     test_itself = "SELECT 'abc' LIKE 'ab" .. tested_string .. "c';"
     test:do_catchsql_test(test_name, test_itself,
-                          {1, "LIKE pattern can only contain UTF-8 characters"})
+                          {1, "Error during execution of VDBE byte-code: LIKE pattern can only contain UTF-8 characters"})
 
     -- Just skipping if row value predicand contains invalid character.
 
diff --git a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua
index 57fbca6..eec7b53 100755
--- a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua
+++ b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua
@@ -139,7 +139,7 @@ test:do_catchsql_xfer_test(
         INSERT INTO t2 SELECT * FROM t1;
     ]], {
         -- <xfer-optimization-1.9>
-        1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
         -- <xfer-optimization-1.9>
     }, {
         exp_xfer_count = 0
@@ -210,7 +210,7 @@ test:do_catchsql_xfer_test(
             INSERT INTO t2 SELECT * FROM t1;
     ]], {
         -- <xfer-optimization-1.13>
-        1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
         -- <xfer-optimization-1.13>
     }, {
         exp_xfer_count = 0
@@ -245,7 +245,7 @@ test:do_catchsql_xfer_test(
             INSERT OR ABORT INTO t2 SELECT * FROM t1;
     ]], {
         -- <xfer-optimization-1.20>
-        1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
         -- <xfer-optimization-1.20>
     }, {
         exp_xfer_count = 1
@@ -313,7 +313,7 @@ test:do_catchsql_xfer_test(
             INSERT OR ROLLBACK INTO t2 SELECT * FROM t1;
     ]], {
         -- <xfer-optimization-1.24>
-        1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
         -- <xfer-optimization-1.24>
     }, {
         exp_xfer_count = 0
@@ -381,7 +381,7 @@ test:do_catchsql_xfer_test(
             INSERT OR FAIL INTO t2 SELECT * FROM t1;
     ]], {
         -- <xfer-optimization-1.28>
-        1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"
         -- <xfer-optimization-1.28>
     }, {
         exp_xfer_count = 1
diff --git a/test/sql-tap/gh-3332-tuple-format-leak.test.lua b/test/sql-tap/gh-3332-tuple-format-leak.test.lua
index f19b7bc..84e67b7 100755
--- a/test/sql-tap/gh-3332-tuple-format-leak.test.lua
+++ b/test/sql-tap/gh-3332-tuple-format-leak.test.lua
@@ -5,13 +5,13 @@ test:plan(2)
 test:do_test(
     "format-leak-prep",
     function()
-        box.sql.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY,\
+        box.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY,\
                          max_players INTEGER, n_players INTEGER, flags INTEGER);");
-        box.sql.execute("CREATE INDEX IDX_MAX_PLAYERS ON t1(max_players);");
-        box.sql.execute("CREATE INDEX IDX_N_PLAYERS ON t1(n_players);");
-        box.sql.execute("CREATE INDEX IDX_FLAGS ON t1(flags);");
+        box.execute("CREATE INDEX IDX_MAX_PLAYERS ON t1(max_players);");
+        box.execute("CREATE INDEX IDX_N_PLAYERS ON t1(n_players);");
+        box.execute("CREATE INDEX IDX_FLAGS ON t1(flags);");
         for i = 1, 10 do
-            box.sql.execute(string.format("INSERT INTO t1 VALUES (%s, %s, %s, %s);",
+            box.execute(string.format("INSERT INTO t1 VALUES (%s, %s, %s, %s);",
                                           i, 15, 6, 3));
         end
     end, {
@@ -22,7 +22,7 @@ test:do_test(
     "format-leak",
     function()
         for i = 1, 100000 do
-            box.sql.execute("SELECT id FROM t1 WHERE flags=3 ORDER BY id LIMIT 2");
+            box.execute("SELECT id FROM t1 WHERE flags=3 ORDER BY id LIMIT 2");
         end
     end, {
 
diff --git a/test/sql-tap/gh2140-trans.test.lua b/test/sql-tap/gh2140-trans.test.lua
index fe978d1..3843c97 100755
--- a/test/sql-tap/gh2140-trans.test.lua
+++ b/test/sql-tap/gh2140-trans.test.lua
@@ -2,14 +2,14 @@
 test = require("sqltester")
 test:plan(10)
 
-box.sql.execute("DROP TABLE IF EXISTS t1")
-box.sql.execute("DROP TABLE IF EXISTS t2")
+box.execute("DROP TABLE IF EXISTS t1")
+box.execute("DROP TABLE IF EXISTS t2")
 
-box.sql.execute("CREATE TABLE t1 (s0 INT PRIMARY KEY, s1 INT UNIQUE, s2 INT);")
-box.sql.execute("CREATE TABLE t2 (s0 INT PRIMARY KEY, s1 INT UNIQUE, s2 INT);")
+box.execute("CREATE TABLE t1 (s0 INT PRIMARY KEY, s1 INT UNIQUE, s2 INT);")
+box.execute("CREATE TABLE t2 (s0 INT PRIMARY KEY, s1 INT UNIQUE, s2 INT);")
 
-box.sql.execute("INSERT INTO t1 VALUES (1,1,1);")
-box.sql.execute("INSERT INTO t2 VALUES (1,1,1);")
+box.execute("INSERT INTO t1 VALUES (1,1,1);")
+box.execute("INSERT INTO t2 VALUES (1,1,1);")
 
 test:do_execsql_test('commit1_check',
                      [[START TRANSACTION;
@@ -28,8 +28,8 @@ test:do_execsql_test('rollback1_check',
                      {1, 1, 2, 2})
 
 for _, verb in ipairs({'ROLLBACK', 'ABORT'}) do
-    box.sql.execute('DELETE FROM t2')
-    answer = "Duplicate key exists in unique index 'unique_unnamed_T1_2' in space 'T1'"
+    box.execute('DELETE FROM t2')
+    answer = "/Duplicate key exists in unique index 'unique_unnamed_T1_2' in space 'T1'/"
     test:do_catchsql_test('insert1_'..verb,
                           [[START TRANSACTION;
                             INSERT INTO t2 VALUES (20, 2, 2);
@@ -39,13 +39,13 @@ for _, verb in ipairs({'ROLLBACK', 'ABORT'}) do
 
     local expect = {}
     if verb == 'ABORT' then
-         box.sql.execute('COMMIT')
+         box.execute('COMMIT')
          expect = {20, 2, 2}
     end
     test:do_execsql_test('insert1_'..verb..'_check',
                          'SELECT * FROM t2', expect)
 
-    box.sql.execute('DELETE FROM t2')
+    box.execute('DELETE FROM t2')
     test:do_catchsql_test('update1_'..verb,
                           [[START TRANSACTION;
                             INSERT INTO t2 VALUES (20, 2, 2);
@@ -57,9 +57,9 @@ for _, verb in ipairs({'ROLLBACK', 'ABORT'}) do
                          'SELECT * FROM t2', expect)
 end
 
-box.sql.execute('COMMIT')
+box.execute('COMMIT')
 -- Cleanup
-box.sql.execute('DROP TABLE t1')
-box.sql.execute('DROP TABLE t2')
+box.execute('DROP TABLE t1')
+box.execute('DROP TABLE t2')
 
 test:finish_test()
diff --git a/test/sql-tap/gh2250-trigger-chain-limit.test.lua b/test/sql-tap/gh2250-trigger-chain-limit.test.lua
index e38f286..0a8a6c5 100755
--- a/test/sql-tap/gh2250-trigger-chain-limit.test.lua
+++ b/test/sql-tap/gh2250-trigger-chain-limit.test.lua
@@ -7,23 +7,23 @@ for _, table_count in ipairs({30, 31}) do
     for i = 1,table_count do
         -- First table for uniform triggers check
         drop_string = 'DROP TABLE IF EXISTS t' .. i .. ';'
-        box.sql.execute(drop_string)
+        box.execute(drop_string)
 
         create_string = 'CREATE TABLE t' .. i .. ' (s1 INT UNIQUE, s2 INT, s3 INT PRIMARY KEY);'
-        box.sql.execute(create_string)
+        box.execute(create_string)
 
         insert_string = 'INSERT INTO t' .. i .. ' VALUES (0,' .. i .. ', 0);'
-        box.sql.execute(insert_string)
+        box.execute(insert_string)
 
         -- Second table for triggers mixture check
         drop_string = 'DROP TABLE IF EXISTS tt' .. i .. ';'
-        box.sql.execute(drop_string)
+        box.execute(drop_string)
 
         create_string = 'CREATE TABLE tt' .. i .. ' (s1 INT UNIQUE, s2 INT, s3 INT PRIMARY KEY);'
-        box.sql.execute(create_string)
+        box.execute(create_string)
 
         insert_string = 'INSERT INTO tt' .. i .. ' VALUES (0,' .. i .. ', 0);'
-        box.sql.execute(insert_string)
+        box.execute(insert_string)
     end
 
     -- And ON DELETE|UPDATE|INSERT triggers
@@ -33,21 +33,21 @@ for _, table_count in ipairs({30, 31}) do
             .. ' FOR EACH ROW '
         create_string = create_string .. ' BEGIN DELETE FROM t' .. i+1
             .. '; END'
-        box.sql.execute(create_string)
+        box.execute(create_string)
 
         create_string = 'CREATE TRIGGER tu' .. i
         create_string = create_string .. ' BEFORE UPDATE ON t' .. i
             .. ' FOR EACH ROW '
         create_string = create_string .. ' BEGIN UPDATE t' .. i+1 ..
             ' SET s1=s1+1; END'
-        box.sql.execute(create_string)
+        box.execute(create_string)
 
         create_string = 'CREATE TRIGGER ti' .. i
         create_string = create_string .. ' BEFORE INSERT ON t' .. i
             .. ' FOR EACH ROW '
         create_string = create_string .. ' BEGIN INSERT INTO t' .. i+1
             .. ' (s1) SELECT max(s1)+1 FROM t' .. i+1 .. '; END'
-        box.sql.execute(create_string)
+        box.execute(create_string)
 
         -- Try triggers mixture: DELETE triggers UPDATE, which triggers
         -- INSERT, which triggers DELETE etc.
@@ -70,12 +70,13 @@ for _, table_count in ipairs({30, 31}) do
                     ' SET s1=s1+1; END'
             end
         end
-        box.sql.execute(create_string)
+        box.execute(create_string)
     end
 
     function check(sql)
         msg = ''
         local _, msg = pcall(function () test:execsql(sql) end)
+        msg = tostring(msg)
         test:do_test(sql,
                      function()
                          return true
diff --git a/test/sql-tap/gh2259-in-stmt-trans.test.lua b/test/sql-tap/gh2259-in-stmt-trans.test.lua
index 95e0398..1ac0d53 100755
--- a/test/sql-tap/gh2259-in-stmt-trans.test.lua
+++ b/test/sql-tap/gh2259-in-stmt-trans.test.lua
@@ -2,23 +2,23 @@
 test = require("sqltester")
 test:plan(20)
 
-box.sql.execute("DROP TABLE IF EXISTS t1")
-box.sql.execute("DROP TABLE IF EXISTS t2")
+box.execute("DROP TABLE IF EXISTS t1")
+box.execute("DROP TABLE IF EXISTS t2")
 
-box.sql.execute("CREATE TABLE t1 (s1 INT UNIQUE, s2 INT PRIMARY KEY);")
-box.sql.execute("CREATE TABLE t2 (s1 INT UNIQUE, s2 INT PRIMARY KEY);")
+box.execute("CREATE TABLE t1 (s1 INT UNIQUE, s2 INT PRIMARY KEY);")
+box.execute("CREATE TABLE t2 (s1 INT UNIQUE, s2 INT PRIMARY KEY);")
 
-box.sql.execute("INSERT INTO t2 VALUES (1,1);")
-box.sql.execute("INSERT INTO t1 VALUES (3,3);")
+box.execute("INSERT INTO t2 VALUES (1,1);")
+box.execute("INSERT INTO t1 VALUES (3,3);")
 
 for _, prefix in pairs({"BEFORE", "AFTER"}) do
-    box.sql.execute('DROP TRIGGER IF EXISTS t1i')
-    box.sql.execute('CREATE TRIGGER t1i '..prefix..' INSERT ON t1 FOR EACH ROW \
+    box.execute('DROP TRIGGER IF EXISTS t1i')
+    box.execute('CREATE TRIGGER t1i '..prefix..' INSERT ON t1 FOR EACH ROW \
                      BEGIN INSERT INTO t2 VALUES (1,1); END')
 
     test:do_catchsql_test(prefix..'_insert1',
                           'INSERT INTO t1 VALUES(1, 2)',
-                          {1,"Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
+                          {1,"Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
 
     test:do_execsql_test(prefix..'_insert1_check1',
                          'SELECT *  FROM t1',
@@ -28,13 +28,13 @@ for _, prefix in pairs({"BEFORE", "AFTER"}) do
                          'SELECT *  FROM t2',
                          {1, 1})
 
-    box.sql.execute('DROP TRIGGER IF EXISTS t1u')
-    box.sql.execute('CREATE TRIGGER t1u '..prefix..' UPDATE ON t1 FOR EACH ROW \
+    box.execute('DROP TRIGGER IF EXISTS t1u')
+    box.execute('CREATE TRIGGER t1u '..prefix..' UPDATE ON t1 FOR EACH ROW \
                      BEGIN INSERT INTO t2 VALUES (1,1); END')
 
     test:do_catchsql_test(prefix..'_update1',
                           'UPDATE t1 SET s1=1',
-                          {1,"Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
+                          {1,"Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
 
     test:do_execsql_test(prefix..'_update1_check1',
                          'SELECT *  FROM t1',
@@ -44,15 +44,15 @@ for _, prefix in pairs({"BEFORE", "AFTER"}) do
                          'SELECT *  FROM t2',
                          {1, 1})
 
-    box.sql.execute('DROP TRIGGER IF EXISTS t1ds')
+    box.execute('DROP TRIGGER IF EXISTS t1ds')
     -- FOR EACH STATEMENT
-    box.sql.execute('CREATE TRIGGER t1ds '..prefix..' DELETE ON t1 FOR EACH ROW\
+    box.execute('CREATE TRIGGER t1ds '..prefix..' DELETE ON t1 FOR EACH ROW\
                        BEGIN INSERT INTO t2 VALUES (2,2); \
                              INSERT INTO t2 VALUES (2,2); END')
 
     test:do_catchsql_test(prefix..'delete1',
                           'DELETE FROM t1;',
-                          {1, "Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
+                          {1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
 
     -- Nothing should be inserted due to abort
     test:do_execsql_test('delete1_check1',
@@ -69,16 +69,16 @@ end
 -- Check multi-insert
 test:do_catchsql_test('insert2',
                       'INSERT INTO t1 VALUES (5, 6), (6, 7)',
-                      {1, "Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
+                      {1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_2' in space 'T2'"})
 test:do_execsql_test('insert2_check',
                      'SELECT * FROM t1;',
                      {3, 3})
 
 -- Cleanup
-box.sql.execute('DROP TRIGGER IF EXISTS t1i')
-box.sql.execute('DROP TRIGGER IF EXISTS t1u')
-box.sql.execute('DROP TRIGGER IF EXISTS t1ds')
-box.sql.execute('DROP TABLE t1')
-box.sql.execute('DROP TABLE t2')
+box.execute('DROP TRIGGER IF EXISTS t1i')
+box.execute('DROP TRIGGER IF EXISTS t1u')
+box.execute('DROP TRIGGER IF EXISTS t1ds')
+box.execute('DROP TABLE t1')
+box.execute('DROP TABLE t2')
 
 test:finish_test()
diff --git a/test/sql-tap/gh2548-select-compound-limit.test.lua b/test/sql-tap/gh2548-select-compound-limit.test.lua
index 5494a66..3881932 100755
--- a/test/sql-tap/gh2548-select-compound-limit.test.lua
+++ b/test/sql-tap/gh2548-select-compound-limit.test.lua
@@ -14,41 +14,41 @@ for _, term in ipairs({'UNION', 'UNION ALL', 'INTERSECT', 'EXCEPT'}) do
                  function()
                      for i = 1,table_count do
                          drop_string = 'DROP TABLE IF EXISTS t' .. i .. ';\n'
-                         box.sql.execute(drop_string)
+                         box.execute(drop_string)
                      end
 
                      for i = 1,table_count do
                          create_string = 'CREATE TABLE t' .. i .. ' (s1 int primary key, s2 int);\n'
-                         box.sql.execute(create_string)
+                         box.execute(create_string)
                      end
 
                      for i = 1,table_count do
                          insert_string = 'INSERT INTO t' .. i .. ' VALUES (0,' .. i .. ');\n'
-                         box.sql.execute(insert_string)
+                         box.execute(insert_string)
                      end
 
                      for i = 1,table_count-1 do
                          if i > 1 then select_string = select_string .. ' ' .. term .. ' ' end
                          select_string = select_string .. 'SELECT * FROM t' .. i
                      end
-                     return pcall( function() box.sql.execute(select_string) end)
+                     return pcall( function() box.execute(select_string) end)
                  end,
                  true)
     test:do_test("Negative COMPOUND "..term,
                  function()
                      select_string = select_string .. ' ' .. term ..' ' .. 'SELECT * FROM t' .. table_count
-                     return  pcall(function() box.sql.execute(select_string) end)
+                     return  pcall(function() box.execute(select_string) end)
                  end,
                  false)
 
     select_string_last = select_string
 
---    if not pcall(function() box.sql.execute(select_string) end) then
+--    if not pcall(function() box.execute(select_string) end) then
 --        print('not ok')
 --    end
 
 --    select_string = select_string .. ' ' .. term ..' ' .. 'SELECT * FROM t' .. table_count
---    if pcall(function() box.sql.execute(select_string) end) then
+--    if pcall(function() box.execute(select_string) end) then
 --        print('not ok')
 --    end
 end
diff --git a/test/sql-tap/gh2964-abort.test.lua b/test/sql-tap/gh2964-abort.test.lua
index d4fcebc..82aa3e4 100755
--- a/test/sql-tap/gh2964-abort.test.lua
+++ b/test/sql-tap/gh2964-abort.test.lua
@@ -12,7 +12,7 @@ test:do_catchsql_test(
     test_prefix.."1.0.2",
     "CREATE TABLE t2 (a int primary key);")
 
-local insert_err = {1, "Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}
+local insert_err = {1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T2_1' in space 'T2'"}
 local data = {
 --id|TRIG TYPE|INSERT TYPE|insert error|commit error| result
  {1, "AFTER", "or abort",   insert_err, {0},          {1,1,2}},
diff --git a/test/sql-tap/index1.test.lua b/test/sql-tap/index1.test.lua
index b23e9b3..b6943a5 100755
--- a/test/sql-tap/index1.test.lua
+++ b/test/sql-tap/index1.test.lua
@@ -112,7 +112,7 @@ test:do_test(
             end)
         v = v == true and {0} or {1}
         test:execsql("DROP TABLE test1")
-        return table.insert(v,msg) or v
+        return table.insert(v,tostring(msg)) or v
     end, {
         -- <index-2.2>
         1, "Can’t resolve field 'F4'"
diff --git a/test/sql-tap/intpkey.test.lua b/test/sql-tap/intpkey.test.lua
index bec2670..3ec3771 100755
--- a/test/sql-tap/intpkey.test.lua
+++ b/test/sql-tap/intpkey.test.lua
@@ -96,7 +96,7 @@ test:do_catchsql_test(
         INSERT INTO t1 VALUES(5,'second','entry');
     ]], {
         -- <intpkey-1.6>
-        1, "Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
         -- </intpkey-1.6>
     })
 
diff --git a/test/sql-tap/limit.test.lua b/test/sql-tap/limit.test.lua
index a0c9c9f..632c634 100755
--- a/test/sql-tap/limit.test.lua
+++ b/test/sql-tap/limit.test.lua
@@ -731,12 +731,10 @@ test:do_test(
     "limit-10.4",
     function()
         local limit = 1.5
-        return {pcall(function()
-            return test:execsql("SELECT x FROM t1 WHERE x<10 LIMIT "..limit)
-        end)}
+        return test:catchsql("SELECT x FROM t1 WHERE x<10 LIMIT "..limit)
     end, {
         -- <limit-10.4>
-        0, "Only positive integers are allowed in the LIMIT clause"
+        1, "Only positive integers are allowed in the LIMIT clause"
         -- </limit-10.4>
     })
 
@@ -744,12 +742,10 @@ test:do_test(
     "limit-10.5",
     function()
         local limit = "'hello world'"
-        return {pcall(function()
-            return test:execsql("SELECT x FROM t1 WHERE x<10 LIMIT "..limit)
-        end)}
+        return test:catchsql("SELECT x FROM t1 WHERE x<10 LIMIT "..limit)
     end, {
         -- <limit-10.5>
-        0, "Only positive integers are allowed in the LIMIT clause"
+        1, "Only positive integers are allowed in the LIMIT clause"
         -- </limit-10.5>
     })
 
diff --git a/test/sql-tap/lua/sqltester.lua b/test/sql-tap/lua/sqltester.lua
index 63c5d9b..cb77bc4 100644
--- a/test/sql-tap/lua/sqltester.lua
+++ b/test/sql-tap/lua/sqltester.lua
@@ -16,6 +16,8 @@ local function flatten(arr)
         for _, v in ipairs(arr) do
             if type(v) == "table" then
                 flatten(v)
+            elseif box.tuple.is(v) then
+                flatten(v:totable())
             else
                 table.insert(result, v)
             end
@@ -169,11 +171,16 @@ test.do_test = do_test
 
 local function execsql_one_by_one(sql)
     local queries = sql_tokenizer.split_sql(sql)
-    local last_res = nil
+    local last_res_rows = nil
+    local last_res_metadata = nil
     for _, query in pairs(queries) do
-        last_res = box.sql.execute(query) or last_res
+        local new_res = box.execute(query)
+        if new_res ~= nil and new_res.rows ~= nil then
+            last_res_rows = new_res.rows
+            last_res_metadata = new_res.metadata
+        end
     end
-    return last_res
+    return last_res_rows, last_res_metadata
 end
 
 local function execsql(self, sql)
@@ -196,6 +203,9 @@ local function catchsql(self, sql, expect)
         r[1] = 0
     else
         r[1] = 1
+        if type(r[2]) == 'cdata' then
+            r[2] = tostring(r[2])
+        end
     end
     return r
 end
@@ -221,12 +231,11 @@ local function do_execsql2_test(self, label, sql, expect)
 end
 test.do_execsql2_test = do_execsql2_test
 
-local function flattern_with_column_names(result)
+local function flattern_with_column_names(result, metadata)
     local ret = {}
-    local columns = result[0]
     for i = 1, #result, 1 do
-        for j = 1, #columns, 1 do
-            table.insert(ret, columns[j])
+        for j = 1, #metadata, 1 do
+            table.insert(ret, metadata[j].name)
             table.insert(ret, result[i][j])
         end
     end
@@ -252,10 +261,10 @@ function test.do_catchsql_set_test(self, testcases, prefix)
 end
 
 local function execsql2(self, sql)
-    local result = execsql_one_by_one(sql)
+    local result, metadata = execsql_one_by_one(sql)
     if type(result) ~= 'table' then return end
     -- shift rows down, revealing column names
-    result = flattern_with_column_names(result)
+    result = flattern_with_column_names(result, metadata)
     return result
 end
 test.execsql2 = execsql2
@@ -272,6 +281,9 @@ local function catchsql2(self, sql)
     -- 0 means ok
     -- 1 means not ok
     r[1] = r[1] == true and 0 or 1
+    if r[1] == 1 then
+        r[2] = tostring(r[2])
+    end
     return r
 end
 test.catchsql2 = catchsql2
@@ -403,7 +415,16 @@ test.do_eqp_test = function (self, label, sql, result)
     test:do_test(
         label,
         function()
-            return execsql_one_by_one("EXPLAIN QUERY PLAN "..sql)
+            local result = execsql_one_by_one("EXPLAIN QUERY PLAN "..sql)
+            local res = {}
+            for k,v in pairs(result) do
+                res[k] = {}
+                res[k][1] = v[1]
+                res[k][2] = v[2]
+                res[k][3] = v[3]
+                res[k][4] = tostring(v[4])
+            end
+            return res
         end,
         result)
 end
@@ -424,7 +445,7 @@ box.cfg{
 }
 
 local engine = test_run and test_run:get_cfg('engine') or 'memtx'
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 function test.engine(self)
     return engine
diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index 1b288da..55c0c13 100755
--- a/test/sql-tap/misc1.test.lua
+++ b/test/sql-tap/misc1.test.lua
@@ -383,7 +383,7 @@ test:do_catchsql_test(
         INSERT INTO t5 VALUES(1,2,4);
     ]], {
         -- <misc1-7.4>
-        1, "Duplicate key exists in unique index 'pk_unnamed_T5_1' in space 'T5'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T5_1' in space 'T5'"
         -- </misc1-7.4>
     })
 
diff --git a/test/sql-tap/orderby9.test.lua b/test/sql-tap/orderby9.test.lua
index 191c21b..13f9ec6 100755
--- a/test/sql-tap/orderby9.test.lua
+++ b/test/sql-tap/orderby9.test.lua
@@ -41,6 +41,7 @@ test:do_test(
         -- separately for the result set and the ORDER BY clause, then the output
         -- order will be random.
         local l1 = test:execsql("SELECT random() AS y FROM t1 ORDER BY 1;")
+        for k,_ in pairs(l1) do l1[k] = tonumber(l1[k]) end
         local l2 = table.deepcopy(l1)
         table.sort(l1)
         return test.is_deeply_regex(l1, l2)
@@ -50,6 +51,7 @@ test:do_test(
     1.1,
     function()
         local l1 = test:execsql("SELECT random() AS y FROM t1 ORDER BY random();")
+        for k,_ in pairs(l1) do l1[k] = tonumber(l1[k]) end
         local l2 = table.deepcopy(l1)
         table.sort(l1)
         return test.is_deeply_regex(l1, l2)
diff --git a/test/sql-tap/pragma.test.lua b/test/sql-tap/pragma.test.lua
index 14d622f..8221d36 100755
--- a/test/sql-tap/pragma.test.lua
+++ b/test/sql-tap/pragma.test.lua
@@ -86,10 +86,10 @@ test:do_execsql_test(
 test:do_test(
 	"pragma-3.3",
 	function()
-		old_value = box.sql.execute('PRAGMA case_sensitive_like')
-		box.sql.execute('PRAGMA case_sensitive_like = 1')
-		new_value = box.sql.execute('PRAGMA case_sensitive_like')
-		box.sql.execute('PRAGMA case_sensitive_like = '.. old_value[1][1])
+		old_value = box.execute('PRAGMA case_sensitive_like').rows
+		box.execute('PRAGMA case_sensitive_like = 1')
+		new_value = box.execute('PRAGMA case_sensitive_like').rows
+		box.execute('PRAGMA case_sensitive_like = '.. old_value[1][1])
 		return new_value[1][1]
 	end,
 	-- <pragma-3.3>
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index d73429a..31955e3 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -1567,22 +1567,20 @@ test:do_execsql_test(
 test:do_test(
     "select1-9.2",
     function()
-        local r = box.sql.execute "SELECT * FROM test1 WHERE f1<0"
-        return r[0]
+        return box.execute("SELECT * FROM test1 WHERE f1<0").metadata
     end, {
         -- <select1-9.2>
-        "F1", "F2"
+        {name = F1, type = INTEGER},{name = F2, type = INTEGER}
         -- </select1-9.2>
     })
 
 test:do_test(
         "select1-9.3",
         function()
-            local r = box.sql.execute "SELECT * FROM test1 WHERE f1<(select count(*) from test2)"
-            return r[0]
+            return box.execute("SELECT * FROM test1 WHERE f1<(select count(*) from test2)").metadata
         end, {
             -- <select1-9.3>
-            "F1", "F2"
+            {name = F1, type = INTEGER},{name = F2, type = INTEGER}
             -- </select1-9.3>
         })
 
@@ -1591,22 +1589,20 @@ test:do_test(
 test:do_test(
     "select1-9.4",
     function()
-        local r = box.sql.execute "SELECT * FROM test1 ORDER BY f1"
-        return r[0]
+        return box.execute("SELECT * FROM test1 ORDER BY f1").metadata
     end, {
         -- <select1-9.4>
-        "F1", "F2"
+        {name = F1, type = INTEGER},{name = F2, type = INTEGER}
         -- </select1-9.4>
     })
 
 test:do_test(
     "select1-9.5",
     function()
-        local r = box.sql.execute "SELECT * FROM test1 WHERE f1<0 ORDER BY f1"
-        return r[0]
+        return box.execute("SELECT * FROM test1 WHERE f1<0 ORDER BY f1").metadata
     end, {
         -- <select1-9.5>
-        "F1", "F2"
+        {name = F1, type = INTEGER},{name = F2, type = INTEGER}
         -- </select1-9.5>
     })
 
diff --git a/test/sql-tap/select9.test.lua b/test/sql-tap/select9.test.lua
index d1883e9..a54010f 100755
--- a/test/sql-tap/select9.test.lua
+++ b/test/sql-tap/select9.test.lua
@@ -61,8 +61,9 @@ end
 
 local function test_compound_select(testname, sql, result)
     local nCol = 1
-    local A = box.sql.execute(sql) --test.box(sql)
-    nCol = #A[0]
+    local A = box.execute(sql) --test.box(sql)
+    nCol = #A.metadata
+    A = A.rows
     local nRow = #result / nCol
     local compound_sql = sql
     test:do_execsql_test(
diff --git a/test/sql-tap/selectB.test.lua b/test/sql-tap/selectB.test.lua
index 7f57cd2..56d4b9d 100755
--- a/test/sql-tap/selectB.test.lua
+++ b/test/sql-tap/selectB.test.lua
@@ -25,11 +25,11 @@ local function test_transform(testname, sql1, sql2, results)
     -- opcodes only (line[2]) of explain command)
     local vdbe1 = {  }
     local vdbe2 = {  }
-    local data = box.sql.execute("explain "..sql1)
+    local data = box.execute("explain "..sql1)
     for i, line in ipairs(data) do
         table.insert(vdbe1, line[2])
     end
-    data = box.sql.execute("explain "..sql2)
+    data = box.execute("explain "..sql2)
     for i, line in ipairs(data) do
         table.insert(vdbe2, line[2])
     end
diff --git a/test/sql-tap/table.test.lua b/test/sql-tap/table.test.lua
index c89d890..4470bce 100755
--- a/test/sql-tap/table.test.lua
+++ b/test/sql-tap/table.test.lua
@@ -722,7 +722,7 @@ test:do_catchsql_test(
         INSERT INTO t6 VALUES(NULL);
     ]], {
         -- <table-10.1>
-        1, "NOT NULL constraint failed: T6.A"
+        1, "Error during execution of VDBE byte-code: NOT NULL constraint failed: T6.A"
         -- </table-10.1>
     })
 
@@ -977,7 +977,7 @@ end
 -- MUST_WORK_TEST database should be locked #2554
 if 0>0 then
 local function try_drop_t9()
-    box.sql.execute("DROP TABLE t9;")
+    box.execute("DROP TABLE t9;")
     return 1
 end
 box.internal.sql_create_function("try_drop_t9", try_drop_t9)
@@ -1211,7 +1211,7 @@ test:do_catchsql_test(
         INSERT INTO T21 VALUES(1, 2, 2);
     ]], {
         -- <table-21.2>
-        1, "Duplicate key exists in unique index 'pk_unnamed_T21_1' in space 'T21'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T21_1' in space 'T21'"
         -- </table-21.2>
     })
 
@@ -1221,7 +1221,7 @@ test:do_catchsql_test(
         INSERT INTO T21 VALUES(1, -1, 1);
     ]], {
         -- <table-21.3>
-        1, "CHECK constraint failed: T21"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T21"
         -- </table-21.3>
     })
 
@@ -1231,7 +1231,7 @@ test:do_catchsql_test(
         INSERT INTO T21 VALUES(1, 1, -1);
     ]], {
         -- <table-21.4>
-        1, "CHECK constraint failed: T21"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: T21"
         -- </table-21.4>
     })
 
@@ -1283,7 +1283,7 @@ test:do_catchsql_test(
         INSERT INTO T22 VALUES(2, 1, 1);
     ]], {
         -- <table-22.3>
-        1,"Duplicate key exists in unique index 'unique_ONE_2' in space 'T22'"
+        1,"Error during execution of VDBE byte-code: Duplicate key exists in unique index 'unique_ONE_2' in space 'T22'"
         -- </table-22.3>
     })
 
@@ -1308,7 +1308,7 @@ test:do_catchsql_test(
         INSERT INTO T24 VALUES(2, 1, 1);
     ]], {
         -- <table-22.5>
-        1, "Duplicate key exists in unique index 'unique_TWO_2' in space 'T24'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'unique_TWO_2' in space 'T24'"
         -- </table-22.5>
     })
 
@@ -1362,7 +1362,7 @@ test:do_catchsql_test(
         INSERT INTO T28 VALUES(11);
     ]], {
         -- <table-22.9>
-        1,"Duplicate key exists in unique index 'pk_unnamed_T28_1' in space 'T28'"
+        1,"Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T28_1' in space 'T28'"
         -- </table-22.9>
     })
 
@@ -1372,7 +1372,7 @@ test:do_catchsql_test(
         INSERT INTO T28 VALUES(0);
     ]], {
         -- <table-22.10>
-        1, "CHECK constraint failed: CHECK1"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: CHECK1"
         -- </table-22.10>
     })
 
@@ -1382,7 +1382,7 @@ test:do_catchsql_test(
         INSERT INTO T28 VALUES(9);
     ]], {
         -- <table-22.11>
-        1, "CHECK constraint failed: CHECK2"
+        1, "Error during execution of VDBE byte-code: CHECK constraint failed: CHECK2"
         -- </table-22.11>
     })
 
diff --git a/test/sql-tap/tkt-4a03edc4c8.test.lua b/test/sql-tap/tkt-4a03edc4c8.test.lua
index cb7a982..703bf74 100755
--- a/test/sql-tap/tkt-4a03edc4c8.test.lua
+++ b/test/sql-tap/tkt-4a03edc4c8.test.lua
@@ -38,7 +38,7 @@ test:do_test(
         ]]
     end, {
         -- <tkt-4a03ed-1.1>
-        1, "Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
         -- </tkt-4a03ed-1.1>
     })
 
diff --git a/test/sql-tap/trigger1.test.lua b/test/sql-tap/trigger1.test.lua
index 2984d4c..bf1857f 100755
--- a/test/sql-tap/trigger1.test.lua
+++ b/test/sql-tap/trigger1.test.lua
@@ -251,7 +251,7 @@ test:do_catchsql_test(
         end;
     ]], {
         -- <trigger1-1.12>
-        1, "SQL error: cannot create INSTEAD OF trigger on space: T1"
+        1, "Error during execution of VDBE byte-code: SQL error: cannot create INSTEAD OF trigger on space: T1"
         -- </trigger1-1.12>
     })
 
@@ -265,7 +265,7 @@ test:do_catchsql_test(
         end;
     ]], {
         -- <trigger1-1.13>
-        1, "SQL error: cannot create BEFORE trigger on view: V1"
+        1, "Error during execution of VDBE byte-code: SQL error: cannot create BEFORE trigger on view: V1"
         -- </trigger1-1.13>
     })
 
@@ -280,7 +280,7 @@ test:do_catchsql_test(
         end;
     ]], {
         -- <trigger1-1.14>
-        1, "SQL error: cannot create AFTER trigger on view: V1"
+        1, "Error during execution of VDBE byte-code: SQL error: cannot create AFTER trigger on view: V1"
         -- </trigger1-1.14>
     })
 
@@ -495,7 +495,7 @@ test:do_catchsql_test(
         DELETE FROM t2
     ]], {
         -- <trigger1-6.3>
-        1, "deletes are not permitted"
+        1, "Error during execution of VDBE byte-code: deletes are not permitted"
         -- </trigger1-6.3>
     })
 
@@ -857,7 +857,7 @@ test:do_catchsql_test(
             INSERT INTO t16 values(1);
           END;
    ]], {
-        1, [[Space _trigger does not support multi-statement transactions]]
+        1, [[Error during execution of VDBE byte-code: Space _trigger does not support multi-statement transactions]]
 })
 
 test:execsql [[
@@ -870,7 +870,7 @@ test:do_catchsql_test(
         START TRANSACTION;
           DROP TRIGGER t16err3;
    ]], {
-        1, [[Space _trigger does not support multi-statement transactions]]
+        1, [[Error during execution of VDBE byte-code: Space _trigger does not support multi-statement transactions]]
 })
 -- MUST_WORK_TEST
 -- #-------------------------------------------------------------------------
diff --git a/test/sql-tap/triggerC.test.lua b/test/sql-tap/triggerC.test.lua
index c0ef605..76558f1 100755
--- a/test/sql-tap/triggerC.test.lua
+++ b/test/sql-tap/triggerC.test.lua
@@ -165,7 +165,7 @@ test:do_test(
         return test:catchsql " DELETE FROM t4 "
     end, {
         -- <triggerC-1.9>
-        1, "delete is not supported"
+        1, "Error during execution of VDBE byte-code: delete is not supported"
         -- </triggerC-1.9>
     })
 
@@ -199,7 +199,7 @@ test:do_catchsql_test(
         UPDATE OR REPLACE t5 SET a = 4 WHERE a = 1
     ]], {
         -- <triggerC-1.12>
-        1, "too many levels of trigger recursion"
+        1, "Error during execution of VDBE byte-code: too many levels of trigger recursion"
         -- </triggerC-1.12>
     })
 
@@ -285,7 +285,7 @@ tests =   { {[[ CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
 
             {[[ CREATE TRIGGER t2_trig BEFORE INSERT ON t2 BEGIN
                   INSERT INTO t2 VALUES(new.a - 1);
-                END;]], {1, "too many levels of trigger recursion"}},
+                END;]], {1, "Error during execution of VDBE byte-code: too many levels of trigger recursion"}},
 
             {[[ CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
                   INSERT OR IGNORE INTO t2 VALUES(new.a);
@@ -293,7 +293,7 @@ tests =   { {[[ CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
 
             {[[  CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN
                    INSERT OR IGNORE INTO t2 VALUES(new.a);
-                 END;]], {1, "too many levels of trigger recursion"}}}
+                 END;]], {1, "Error during execution of VDBE byte-code: too many levels of trigger recursion"}}}
 
 for n, v in ipairs(tests) do
     test:do_test(
@@ -382,7 +382,7 @@ test:do_catchsql_test(
         INSERT INTO t3 VALUES(0,0)
     ]], {
         -- <triggerC-3.1.2>
-        1, "too many levels of trigger recursion"
+        1, "Error during execution of VDBE byte-code: too many levels of trigger recursion"
         -- </triggerC-3.1.2>
     })
 
@@ -411,7 +411,7 @@ test:do_catchsql_test(
         INSERT INTO t3b VALUES(1);
     ]], {
         -- <triggerC-3.1.3>
-        1, "too many levels of trigger recursion"
+        1, "Error during execution of VDBE byte-code: too many levels of trigger recursion"
         -- </triggerC-3.1.3>
     })
 
@@ -908,7 +908,7 @@ test:do_catchsql_test(
         UPDATE t12 SET a=a+1, b=b+1;
     ]], {
         -- <triggerC-13.2>
-        1, "too many levels of trigger recursion"
+        1, "Error during execution of VDBE byte-code: too many levels of trigger recursion"
         -- </triggerC-13.2>
     })
 
diff --git a/test/sql-tap/unique.test.lua b/test/sql-tap/unique.test.lua
index 56ac74a..927c419 100755
--- a/test/sql-tap/unique.test.lua
+++ b/test/sql-tap/unique.test.lua
@@ -70,7 +70,7 @@ test:do_catchsql_test(
         INSERT INTO t1(a,b,c) VALUES(1,3,4)
     ]], {
         -- <unique-1.3>
-        1, "Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'pk_unnamed_T1_1' in space 'T1'"
         -- </unique-1.3>
     })
 
@@ -91,7 +91,7 @@ test:do_catchsql_test(
         INSERT INTO t1(a,b,c) VALUES(3,2,4)
     ]], {
         -- <unique-1.5>
-        1, "Duplicate key exists in unique index 'unique_unnamed_T1_2' in space 'T1'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'unique_unnamed_T1_2' in space 'T1'"
         -- </unique-1.5>
     })
 
@@ -167,7 +167,7 @@ test:do_catchsql_test(
         INSERT INTO t2 VALUES(3, 1,5);
     ]], {
         -- <unique-2.3>
-        1, "Duplicate key exists in unique index 'I2' in space 'T2'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'I2' in space 'T2'"
         -- </unique-2.3>
     })
 
@@ -287,7 +287,7 @@ test:do_catchsql_test(
         SELECT a,b,c,d FROM t3 ORDER BY a,b,c,d;
     ]], {
         -- <unique-3.4>
-        1, "Duplicate key exists in unique index 'unique_unnamed_T3_2' in space 'T3'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'unique_unnamed_T3_2' in space 'T3'"
         -- </unique-3.4>
     })
 
@@ -444,7 +444,7 @@ test:do_catchsql_test(
         INSERT INTO t5 VALUES(2, 1,2,3,4,5,6);
     ]], {
         -- <unique-5.2>
-        1, "Duplicate key exists in unique index 'unique_unnamed_T5_2' in space 'T5'"
+        1, "Error during execution of VDBE byte-code: Duplicate key exists in unique index 'unique_unnamed_T5_2' in space 'T5'"
         -- </unique-5.2>
     })
 
diff --git a/test/sql/check-clear-ephemeral.result b/test/sql/check-clear-ephemeral.result
index 6fb0357..9fd6b87 100644
--- a/test/sql/check-clear-ephemeral.result
+++ b/test/sql/check-clear-ephemeral.result
@@ -4,24 +4,31 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
 -- create space
-box.sql.execute("CREATE TABLE t1(a INT,b INT,c INT,PRIMARY KEY(b,c));")
+box.execute("CREATE TABLE t1(a INT,b INT,c INT,PRIMARY KEY(b,c));")
 ---
+- rowcount: 1
 ...
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 -- Seed entries
-box.sql.execute("WITH RECURSIVE cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<1000) INSERT INTO t1 SELECT x, x%40, x/40 FROM cnt;")
+box.execute("WITH RECURSIVE cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<1000) INSERT INTO t1 SELECT x, x%40, x/40 FROM cnt;")
 ---
+- rowcount: 1000
 ...
 -- Ephemeral table is not belong to Tarantool, so must be cleared sql-way.
-box.sql.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
+box.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
 ---
-- - [840]
+- metadata:
+  - name: A
+    type: BLOB
+  rows:
+  - [840]
   - [880]
   - [920]
   - [960]
@@ -33,8 +40,9 @@ box.sql.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
   - [161]
 ...
 -- Cleanup
-box.sql.execute("DROP TABLE t1")
+box.execute("DROP TABLE t1")
 ---
+- rowcount: 1
 ...
 -- Debug
 -- require("console").start()
diff --git a/test/sql/check-clear-ephemeral.test.lua b/test/sql/check-clear-ephemeral.test.lua
index d6fb3a2..929a6c9 100644
--- a/test/sql/check-clear-ephemeral.test.lua
+++ b/test/sql/check-clear-ephemeral.test.lua
@@ -1,22 +1,22 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 -- box.cfg()
 
 -- create space
-box.sql.execute("CREATE TABLE t1(a INT,b INT,c INT,PRIMARY KEY(b,c));")
+box.execute("CREATE TABLE t1(a INT,b INT,c INT,PRIMARY KEY(b,c));")
 
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 
 -- Seed entries
-box.sql.execute("WITH RECURSIVE cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<1000) INSERT INTO t1 SELECT x, x%40, x/40 FROM cnt;")
+box.execute("WITH RECURSIVE cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<1000) INSERT INTO t1 SELECT x, x%40, x/40 FROM cnt;")
 
 -- Ephemeral table is not belong to Tarantool, so must be cleared sql-way.
-box.sql.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
+box.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
 
 -- Cleanup
-box.sql.execute("DROP TABLE t1")
+box.execute("DROP TABLE t1")
 
 -- Debug
 -- require("console").start()
diff --git a/test/sql/checks.result b/test/sql/checks.result
index 42df657..108fea6 100644
--- a/test/sql/checks.result
+++ b/test/sql/checks.result
@@ -11,8 +11,9 @@ test_run:cmd("push filter ".."'\\.lua.*:[0-9]+: ' to '.lua...\"]:<line>: '")
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 --
 -- gh-3272: Move SQL CHECK into server
@@ -109,18 +110,18 @@ s = box.space._space:insert(t)
 --
 -- gh-3611: Segfault on table creation with check referencing this table
 --
-box.sql.execute("CREATE TABLE w2 (s1 INT PRIMARY KEY, CHECK ((SELECT COUNT(*) FROM w2) = 0));")
+box.execute("CREATE TABLE w2 (s1 INT PRIMARY KEY, CHECK ((SELECT COUNT(*) FROM w2) = 0));")
 ---
 - error: 'Failed to create space ''W2'': Space ''W2'' does not exist'
 ...
-box.sql.execute("DROP TABLE w2;")
+box.execute("DROP TABLE w2;")
 ---
 - error: Space 'W2' does not exist
 ...
 --
 -- gh-3653: Dissallow bindings for DDL
 --
-box.sql.execute("CREATE TABLE t5(x INT PRIMARY KEY, y INT, CHECK( x*y < ? ));")
+box.execute("CREATE TABLE t5(x INT PRIMARY KEY, y INT, CHECK( x*y < ? ));")
 ---
 - error: 'Wrong space options (field 5): invalid expression specified (bindings are
     not allowed in DDL)'
diff --git a/test/sql/checks.test.lua b/test/sql/checks.test.lua
index 0582bbb..5bfcf12 100644
--- a/test/sql/checks.test.lua
+++ b/test/sql/checks.test.lua
@@ -2,7 +2,7 @@ env = require('test_run')
 test_run = env.new()
 test_run:cmd("push filter ".."'\\.lua.*:[0-9]+: ' to '.lua...\"]:<line>: '")
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 --
 -- gh-3272: Move SQL CHECK into server
@@ -47,13 +47,13 @@ s = box.space._space:insert(t)
 --
 -- gh-3611: Segfault on table creation with check referencing this table
 --
-box.sql.execute("CREATE TABLE w2 (s1 INT PRIMARY KEY, CHECK ((SELECT COUNT(*) FROM w2) = 0));")
-box.sql.execute("DROP TABLE w2;")
+box.execute("CREATE TABLE w2 (s1 INT PRIMARY KEY, CHECK ((SELECT COUNT(*) FROM w2) = 0));")
+box.execute("DROP TABLE w2;")
 
 --
 -- gh-3653: Dissallow bindings for DDL
 --
-box.sql.execute("CREATE TABLE t5(x INT PRIMARY KEY, y INT, CHECK( x*y < ? ));")
+box.execute("CREATE TABLE t5(x INT PRIMARY KEY, y INT, CHECK( x*y < ? ));")
 
 opts = {checks = {{expr = '?>5', name = 'ONE'}}}
 format = {{name = 'X', type = 'unsigned'}}
diff --git a/test/sql/clear.result b/test/sql/clear.result
index 9d4e9d3..0694a1e 100644
--- a/test/sql/clear.result
+++ b/test/sql/clear.result
@@ -4,27 +4,40 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
 -- create space
-box.sql.execute("CREATE TABLE zoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
+box.execute("CREATE TABLE zoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE UNIQUE INDEX zoobar2 ON zoobar(c1, c4)")
+box.execute("CREATE UNIQUE INDEX zoobar2 ON zoobar(c1, c4)")
 ---
+- rowcount: 1
 ...
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON;")
+-- box.execute("PRAGMA vdbe_debug=ON;")
 -- Seed entry
-for i=1, 100 do box.sql.execute(string.format("INSERT INTO zoobar VALUES (%d, %d, 'c3', 444)", i+i, i)) end
+for i=1, 100 do box.execute(string.format("INSERT INTO zoobar VALUES (%d, %d, 'c3', 444)", i+i, i)) end
 ---
 ...
 -- Check table is not empty
-box.sql.execute("SELECT * FROM zoobar")
+box.execute("SELECT * FROM zoobar")
 ---
-- - [2, 1, 'c3', 444]
+- metadata:
+  - name: C1
+    type: INTEGER
+  - name: C2
+    type: INTEGER
+  - name: C3
+    type: TEXT
+  - name: C4
+    type: INTEGER
+  rows:
+  - [2, 1, 'c3', 444]
   - [4, 2, 'c3', 444]
   - [6, 3, 'c3', 444]
   - [8, 4, 'c3', 444]
@@ -126,20 +139,32 @@ box.sql.execute("SELECT * FROM zoobar")
   - [200, 100, 'c3', 444]
 ...
 -- Do clean up
-box.sql.execute("DELETE FROM zoobar")
+box.execute("DELETE FROM zoobar")
 ---
+- rowcount: 100
 ...
 -- Make sure table is empty
-box.sql.execute("SELECT * from zoobar")
+box.execute("SELECT * from zoobar")
 ---
-- []
+- metadata:
+  - name: C1
+    type: INTEGER
+  - name: C2
+    type: INTEGER
+  - name: C3
+    type: TEXT
+  - name: C4
+    type: INTEGER
+  rows: []
 ...
 -- Cleanup
-box.sql.execute("DROP INDEX zoobar2 ON zoobar")
+box.execute("DROP INDEX zoobar2 ON zoobar")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE zoobar")
+box.execute("DROP TABLE zoobar")
 ---
+- rowcount: 1
 ...
 -- Debug
 -- require("console").start()
diff --git a/test/sql/clear.test.lua b/test/sql/clear.test.lua
index 78923f1..c67a447 100644
--- a/test/sql/clear.test.lua
+++ b/test/sql/clear.test.lua
@@ -1,31 +1,31 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- box.cfg()
 
 -- create space
-box.sql.execute("CREATE TABLE zoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
-box.sql.execute("CREATE UNIQUE INDEX zoobar2 ON zoobar(c1, c4)")
+box.execute("CREATE TABLE zoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
+box.execute("CREATE UNIQUE INDEX zoobar2 ON zoobar(c1, c4)")
 
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON;")
+-- box.execute("PRAGMA vdbe_debug=ON;")
 
 -- Seed entry
-for i=1, 100 do box.sql.execute(string.format("INSERT INTO zoobar VALUES (%d, %d, 'c3', 444)", i+i, i)) end
+for i=1, 100 do box.execute(string.format("INSERT INTO zoobar VALUES (%d, %d, 'c3', 444)", i+i, i)) end
 
 -- Check table is not empty
-box.sql.execute("SELECT * FROM zoobar")
+box.execute("SELECT * FROM zoobar")
 
 -- Do clean up
-box.sql.execute("DELETE FROM zoobar")
+box.execute("DELETE FROM zoobar")
 
 -- Make sure table is empty
-box.sql.execute("SELECT * from zoobar")
+box.execute("SELECT * from zoobar")
 
 -- Cleanup
-box.sql.execute("DROP INDEX zoobar2 ON zoobar")
-box.sql.execute("DROP TABLE zoobar")
+box.execute("DROP INDEX zoobar2 ON zoobar")
+box.execute("DROP TABLE zoobar")
 
 -- Debug
 -- require("console").start()
diff --git a/test/sql/collation.result b/test/sql/collation.result
index 10872ca..cc1b1a9 100644
--- a/test/sql/collation.result
+++ b/test/sql/collation.result
@@ -7,63 +7,85 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- gh-3010: COLLATE after LIMIT should throw an error
 -- All of these tests should throw error "near "COLLATE": syntax error"
-box.sql.execute("SELECT 1 LIMIT 1 COLLATE BINARY;")
+box.execute("SELECT 1 LIMIT 1 COLLATE BINARY;")
 ---
 - error: Syntax error near 'COLLATE'
 ...
-box.sql.execute("SELECT 1 LIMIT 1 COLLATE BINARY OFFSET 1;")
+box.execute("SELECT 1 LIMIT 1 COLLATE BINARY OFFSET 1;")
 ---
 - error: Syntax error near 'COLLATE'
 ...
-box.sql.execute("SELECT 1 LIMIT 1 OFFSET 1 COLLATE BINARY;")
+box.execute("SELECT 1 LIMIT 1 OFFSET 1 COLLATE BINARY;")
 ---
 - error: Syntax error near 'COLLATE'
 ...
-box.sql.execute("SELECT 1 LIMIT 1, 1 COLLATE BINARY;")
+box.execute("SELECT 1 LIMIT 1, 1 COLLATE BINARY;")
 ---
 - error: Syntax error near 'COLLATE'
 ...
-box.sql.execute("SELECT 1 LIMIT 1 COLLATE BINARY, 1;")
+box.execute("SELECT 1 LIMIT 1 COLLATE BINARY, 1;")
 ---
 - error: Syntax error near 'COLLATE'
 ...
 -- gh-3052: upper/lower support only default locale
 -- For tr-TR result depends on collation
-box.sql.execute([[CREATE TABLE tu (descriptor VARCHAR(50) PRIMARY KEY, letter VARCHAR(50))]]);
+box.execute([[CREATE TABLE tu (descriptor VARCHAR(50) PRIMARY KEY, letter VARCHAR(50))]]);
 ---
+- rowcount: 1
 ...
 box.internal.collation.create('TURKISH', 'ICU', 'tr-TR', {strength='primary'});
 ---
 ...
-box.sql.execute([[INSERT INTO tu VALUES ('Latin Capital Letter I U+0049','I');]])
+box.execute([[INSERT INTO tu VALUES ('Latin Capital Letter I U+0049','I');]])
 ---
+- rowcount: 1
 ...
-box.sql.execute([[INSERT INTO tu VALUES ('Latin Small Letter I U+0069','i');]])
+box.execute([[INSERT INTO tu VALUES ('Latin Small Letter I U+0069','i');]])
 ---
+- rowcount: 1
 ...
-box.sql.execute([[INSERT INTO tu VALUES ('Latin Capital Letter I With Dot Above U+0130','İ');]])
+box.execute([[INSERT INTO tu VALUES ('Latin Capital Letter I With Dot Above U+0130','İ');]])
 ---
+- rowcount: 1
 ...
-box.sql.execute([[INSERT INTO tu VALUES ('Latin Small Letter Dotless I U+0131','ı');]])
+box.execute([[INSERT INTO tu VALUES ('Latin Small Letter Dotless I U+0131','ı');]])
 ---
+- rowcount: 1
 ...
 -- Without collation
-box.sql.execute([[SELECT descriptor, upper(letter) AS upper,lower(letter) AS lower FROM tu;]])
----
-- - ['Latin Capital Letter I U+0049', 'I', 'i']
+box.execute([[SELECT descriptor, upper(letter) AS upper,lower(letter) AS lower FROM tu;]])
+---
+- metadata:
+  - name: DESCRIPTOR
+    type: TEXT
+  - name: UPPER
+    type: TEXT
+  - name: LOWER
+    type: TEXT
+  rows:
+  - ['Latin Capital Letter I U+0049', 'I', 'i']
   - ['Latin Capital Letter I With Dot Above U+0130', 'İ', 'i̇']
   - ['Latin Small Letter Dotless I U+0131', 'I', 'ı']
   - ['Latin Small Letter I U+0069', 'I', 'i']
 ...
 -- With collation
-box.sql.execute([[SELECT descriptor, upper(letter COLLATE "TURKISH") AS upper,lower(letter COLLATE "TURKISH") AS lower FROM tu;]])
----
-- - ['Latin Capital Letter I U+0049', 'I', 'ı']
+box.execute([[SELECT descriptor, upper(letter COLLATE "TURKISH") AS upper,lower(letter COLLATE "TURKISH") AS lower FROM tu;]])
+---
+- metadata:
+  - name: DESCRIPTOR
+    type: TEXT
+  - name: UPPER
+    type: TEXT
+  - name: LOWER
+    type: TEXT
+  rows:
+  - ['Latin Capital Letter I U+0049', 'I', 'ı']
   - ['Latin Capital Letter I With Dot Above U+0130', 'İ', 'i']
   - ['Latin Small Letter Dotless I U+0131', 'I', 'ı']
   - ['Latin Small Letter I U+0069', 'İ', 'i']
@@ -75,24 +97,42 @@ box.internal.collation.drop('TURKISH')
 box.internal.collation.create('GERMAN', 'ICU', 'de-DE', {strength='primary'});
 ---
 ...
-box.sql.execute([[INSERT INTO tu VALUES ('German Small Letter Sharp S U+00DF','ß');]])
+box.execute([[INSERT INTO tu VALUES ('German Small Letter Sharp S U+00DF','ß');]])
 ---
+- rowcount: 1
 ...
 -- Without collation
-box.sql.execute([[SELECT descriptor, upper(letter), letter FROM tu where UPPER(letter) = 'SS';]])
----
-- - ['German Small Letter Sharp S U+00DF', 'SS', 'ß']
+box.execute([[SELECT descriptor, upper(letter), letter FROM tu where UPPER(letter) = 'SS';]])
+---
+- metadata:
+  - name: DESCRIPTOR
+    type: TEXT
+  - name: upper(letter)
+    type: TEXT
+  - name: LETTER
+    type: TEXT
+  rows:
+  - ['German Small Letter Sharp S U+00DF', 'SS', 'ß']
 ...
 -- With collation
-box.sql.execute([[SELECT descriptor, upper(letter COLLATE "GERMAN"), letter FROM tu where UPPER(letter COLLATE "GERMAN") = 'SS';]])
----
-- - ['German Small Letter Sharp S U+00DF', 'SS', 'ß']
+box.execute([[SELECT descriptor, upper(letter COLLATE "GERMAN"), letter FROM tu where UPPER(letter COLLATE "GERMAN") = 'SS';]])
+---
+- metadata:
+  - name: DESCRIPTOR
+    type: TEXT
+  - name: upper(letter COLLATE "GERMAN")
+    type: TEXT
+  - name: LETTER
+    type: TEXT
+  rows:
+  - ['German Small Letter Sharp S U+00DF', 'SS', 'ß']
 ...
 box.internal.collation.drop('GERMAN')
 ---
 ...
-box.sql.execute(([[DROP TABLE tu]]))
+box.execute(([[DROP TABLE tu]]))
 ---
+- rowcount: 1
 ...
 box.schema.user.grant('guest','read,write,execute', 'universe')
 ---
@@ -109,8 +149,9 @@ cn:close()
 ...
 -- Explicitly set BINARY collation is predifined and has ID.
 --
-box.sql.execute("CREATE TABLE t (id INT PRIMARY KEY, a TEXT, b TEXT COLLATE \"binary\");")
+box.execute("CREATE TABLE t (id INT PRIMARY KEY, a TEXT, b TEXT COLLATE \"binary\");")
 ---
+- rowcount: 1
 ...
 box.space.T:format()[2]['collation']
 ---
@@ -120,8 +161,9 @@ box.space.T:format()[3]['collation']
 ---
 - 3
 ...
-box.sql.execute("DROP TABLE t;")
+box.execute("DROP TABLE t;")
 ---
+- rowcount: 1
 ...
 -- BINARY collation works in the same way as there is no collation
 -- at all.
@@ -179,66 +221,116 @@ box.space._collation:delete{0}
 ...
 -- gh-3185: collations of LHS and RHS must be compatible.
 --
-box.sql.execute("CREATE TABLE t (id INT PRIMARY KEY, a TEXT, b TEXT COLLATE \"binary\", c TEXT COLLATE \"unicode_ci\");")
----
-...
-box.sql.execute("SELECT * FROM t WHERE a = b;")
----
-- []
-...
-box.sql.execute("SELECT * FROM t WHERE a COLLATE \"binary\" = b;")
----
-- []
-...
-box.sql.execute("SELECT * FROM t WHERE b = c;")
+box.execute("CREATE TABLE t (id INT PRIMARY KEY, a TEXT, b TEXT COLLATE \"binary\", c TEXT COLLATE \"unicode_ci\");")
+---
+- rowcount: 1
+...
+box.execute("SELECT * FROM t WHERE a = b;")
+---
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: TEXT
+  - name: B
+    type: TEXT
+  - name: C
+    type: TEXT
+  rows: []
+...
+box.execute("SELECT * FROM t WHERE a COLLATE \"binary\" = b;")
+---
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: TEXT
+  - name: B
+    type: TEXT
+  - name: C
+    type: TEXT
+  rows: []
+...
+box.execute("SELECT * FROM t WHERE b = c;")
 ---
 - error: Illegal mix of collations
 ...
-box.sql.execute("SELECT * FROM t WHERE b COLLATE \"binary\" = c;")
----
-- []
-...
-box.sql.execute("SELECT * FROM t WHERE a = c;")
----
-- []
-...
-box.sql.execute("SELECT * FROM t WHERE a COLLATE \"binary\" = c COLLATE \"unicode\";")
+box.execute("SELECT * FROM t WHERE b COLLATE \"binary\" = c;")
+---
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: TEXT
+  - name: B
+    type: TEXT
+  - name: C
+    type: TEXT
+  rows: []
+...
+box.execute("SELECT * FROM t WHERE a = c;")
+---
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: TEXT
+  - name: B
+    type: TEXT
+  - name: C
+    type: TEXT
+  rows: []
+...
+box.execute("SELECT * FROM t WHERE a COLLATE \"binary\" = c COLLATE \"unicode\";")
 ---
 - error: Illegal mix of collations
 ...
 -- Compound queries perform implicit comparisons between values.
 -- Hence, rules for collations compatibilities are the same.
 --
-box.sql.execute("SELECT 'abc' COLLATE \"binary\" UNION SELECT 'ABC' COLLATE \"unicode_ci\"")
+box.execute("SELECT 'abc' COLLATE \"binary\" UNION SELECT 'ABC' COLLATE \"unicode_ci\"")
 ---
 - error: Illegal mix of collations
 ...
-box.sql.execute("SELECT 'abc' COLLATE \"unicode_ci\" UNION SELECT 'ABC' COLLATE binary")
+box.execute("SELECT 'abc' COLLATE \"unicode_ci\" UNION SELECT 'ABC' COLLATE binary")
 ---
 - error: Illegal mix of collations
 ...
-box.sql.execute("SELECT c FROM t UNION SELECT b FROM t;")
+box.execute("SELECT c FROM t UNION SELECT b FROM t;")
 ---
 - error: Illegal mix of collations
 ...
-box.sql.execute("SELECT b FROM t UNION SELECT a FROM t;")
+box.execute("SELECT b FROM t UNION SELECT a FROM t;")
 ---
-- []
+- metadata:
+  - name: B
+    type: TEXT
+  rows: []
 ...
-box.sql.execute("SELECT a FROM t UNION SELECT c FROM t;")
+box.execute("SELECT a FROM t UNION SELECT c FROM t;")
 ---
-- []
+- metadata:
+  - name: A
+    type: TEXT
+  rows: []
 ...
-box.sql.execute("SELECT c COLLATE \"binary\" FROM t UNION SELECT a FROM t;")
+box.execute("SELECT c COLLATE \"binary\" FROM t UNION SELECT a FROM t;")
 ---
-- []
+- metadata:
+  - name: c COLLATE "binary"
+    type: TEXT
+  rows: []
 ...
-box.sql.execute("SELECT b COLLATE \"unicode\" FROM t UNION SELECT a FROM t;")
+box.execute("SELECT b COLLATE \"unicode\" FROM t UNION SELECT a FROM t;")
 ---
-- []
+- metadata:
+  - name: b COLLATE "unicode"
+    type: TEXT
+  rows: []
 ...
-box.sql.execute("DROP TABLE t;")
+box.execute("DROP TABLE t;")
 ---
+- rowcount: 1
 ...
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 ---
@@ -251,7 +343,7 @@ box.session.su('tmp')
 ---
 ...
 -- Error: read access to space is denied.
-box.sql.execute("pragma collation_list")
+box.execute("pragma collation_list")
 ---
 - error: Read access to space '_collation' is denied for user 'tmp'
 ...
@@ -263,160 +355,237 @@ box.schema.user.drop('tmp')
 ...
 -- gh-3644 Foreign key update fails with "unicode_ci".
 -- Check that foreign key update doesn't fail with "unicode_ci".
-box.sql.execute('CREATE TABLE t0 (s1 VARCHAR(5) COLLATE "unicode_ci" UNIQUE, id INT PRIMARY KEY AUTOINCREMENT);')
+box.execute('CREATE TABLE t0 (s1 VARCHAR(5) COLLATE "unicode_ci" UNIQUE, id INT PRIMARY KEY AUTOINCREMENT);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE TABLE t1 (s1 INT PRIMARY KEY, s0 VARCHAR(5) COLLATE "unicode_ci" REFERENCES t0(s1));')
+box.execute('CREATE TABLE t1 (s1 INT PRIMARY KEY, s0 VARCHAR(5) COLLATE "unicode_ci" REFERENCES t0(s1));')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t0(s1) VALUES ('a');")
+box.execute("INSERT INTO t0(s1) VALUES ('a');")
 ---
+- autoincrement_ids:
+  - 1
+  rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES (1,'a');")
+box.execute("INSERT INTO t1 VALUES (1,'a');")
 ---
+- rowcount: 1
 ...
 -- Should't fail.
-box.sql.execute("UPDATE t0 SET s1 = 'A';")
+box.execute("UPDATE t0 SET s1 = 'A';")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT s1 FROM t0;")
+box.execute("SELECT s1 FROM t0;")
 ---
-- - ['A']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['A']
 ...
-box.sql.execute("SELECT * FROM t1;")
+box.execute("SELECT * FROM t1;")
 ---
-- - [1, 'a']
+- metadata:
+  - name: S1
+    type: INTEGER
+  - name: S0
+    type: TEXT
+  rows:
+  - [1, 'a']
 ...
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t0;")
+box.execute("DROP TABLE t0;")
 ---
+- rowcount: 1
 ...
 -- Check that foreign key update fails with default collation.
-box.sql.execute('CREATE TABLE t0 (s1 VARCHAR(5) UNIQUE, id INT PRIMARY KEY AUTOINCREMENT);')
+box.execute('CREATE TABLE t0 (s1 VARCHAR(5) UNIQUE, id INT PRIMARY KEY AUTOINCREMENT);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE TABLE t1 (s1 INT PRIMARY KEY, s0 VARCHAR(5) REFERENCES t0(s1));')
+box.execute('CREATE TABLE t1 (s1 INT PRIMARY KEY, s0 VARCHAR(5) REFERENCES t0(s1));')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t0(s1) VALUES ('a');")
+box.execute("INSERT INTO t0(s1) VALUES ('a');")
 ---
+- autoincrement_ids:
+  - 1
+  rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES (1,'a');")
+box.execute("INSERT INTO t1 VALUES (1,'a');")
 ---
+- rowcount: 1
 ...
 -- Should fail.
-box.sql.execute("UPDATE t0 SET s1 = 'A';")
+box.execute("UPDATE t0 SET s1 = 'A';")
 ---
-- error: FOREIGN KEY constraint failed
+- error: 'Error during execution of VDBE byte-code: FOREIGN KEY constraint failed'
 ...
-box.sql.execute("SELECT * FROM t1;")
+box.execute("SELECT * FROM t1;")
 ---
-- - [1, 'a']
+- metadata:
+  - name: S1
+    type: INTEGER
+  - name: S0
+    type: TEXT
+  rows:
+  - [1, 'a']
 ...
-box.sql.execute("SELECT s1 FROM t0;")
+box.execute("SELECT s1 FROM t0;")
 ---
-- - ['a']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['a']
 ...
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t0;")
+box.execute("DROP TABLE t0;")
 ---
+- rowcount: 1
 ...
 -- gh-3937: result of concatination has derived collation.
 --
-box.sql.execute("CREATE TABLE t4a(a TEXT COLLATE \"unicode\", b TEXT COLLATE \"unicode_ci\", c INT PRIMARY KEY);")
+box.execute("CREATE TABLE t4a(a TEXT COLLATE \"unicode\", b TEXT COLLATE \"unicode_ci\", c INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t4a VALUES('ABC','abc',1);")
+box.execute("INSERT INTO t4a VALUES('ABC','abc',1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t4a VALUES('ghi','ghi',3);")
+box.execute("INSERT INTO t4a VALUES('ghi','ghi',3);")
 ---
+- rowcount: 1
 ...
 -- Only LHS of concatenation has implicitly set collation.
 -- Hence, no collation is used.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a||'') = b;")
+box.execute("SELECT c FROM t4a WHERE (a||'') = b;")
 ---
-- - [1]
+- metadata:
+  - name: C
+    type: INTEGER
+  rows:
+  - [1]
   - [3]
 ...
 -- BINARY collation is forced for comparison operator as
 -- a derivation from concatenation.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'') = b;")
+box.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'') = b;")
 ---
-- - [3]
+- metadata:
+  - name: C
+    type: INTEGER
+  rows:
+  - [3]
 ...
 -- Both operands of concatenation have explicit but different
 -- collations.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'' COLLATE \"unicode_ci\") = b;")
+box.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'' COLLATE \"unicode_ci\") = b;")
 ---
 - error: Illegal mix of collations
 ...
-box.sql.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'') = b COLLATE \"unicode\";")
+box.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'') = b COLLATE \"unicode\";")
 ---
 - error: Illegal mix of collations
 ...
 -- No collation is used since LHS and RHS of concatenation
 -- operator have different implicit collations.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a||'')=(b||'');")
+box.execute("SELECT c FROM t4a WHERE (a||'')=(b||'');")
 ---
-- - [3]
+- metadata:
+  - name: C
+    type: INTEGER
+  rows:
+  - [3]
 ...
-box.sql.execute("SELECT c FROM t4a WHERE (a||b)=(b||a);")
+box.execute("SELECT c FROM t4a WHERE (a||b)=(b||a);")
 ---
-- - [3]
+- metadata:
+  - name: C
+    type: INTEGER
+  rows:
+  - [3]
 ...
-box.sql.execute("CREATE TABLE t4b(a TEXT COLLATE \"unicode_ci\", b TEXT COLLATE \"unicode_ci\", c INT PRIMARY KEY);")
+box.execute("CREATE TABLE t4b(a TEXT COLLATE \"unicode_ci\", b TEXT COLLATE \"unicode_ci\", c INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t4b VALUES('BCD','bcd',1);")
+box.execute("INSERT INTO t4b VALUES('BCD','bcd',1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t4b VALUES('ghi','ghi',3);")
+box.execute("INSERT INTO t4b VALUES('ghi','ghi',3);")
 ---
+- rowcount: 1
 ...
 -- Operands have the same implicit collation, so it is derived.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a||b)=(b||a);")
+box.execute("SELECT c FROM t4a WHERE (a||b)=(b||a);")
 ---
-- - [3]
+- metadata:
+  - name: C
+    type: INTEGER
+  rows:
+  - [3]
 ...
 -- Couple of other possible combinations.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a||b COLLATE \"binary\")=(b||a);")
+box.execute("SELECT c FROM t4a WHERE (a||b COLLATE \"binary\")=(b||a);")
 ---
-- - [3]
+- metadata:
+  - name: C
+    type: INTEGER
+  rows:
+  - [3]
 ...
-box.sql.execute("SELECT c FROM t4a WHERE (a||b COLLATE \"binary\")=(b COLLATE \"unicode_ci\"||a);")
+box.execute("SELECT c FROM t4a WHERE (a||b COLLATE \"binary\")=(b COLLATE \"unicode_ci\"||a);")
 ---
 - error: Illegal mix of collations
 ...
-box.sql.execute("INSERT INTO t4b VALUES('abc', 'xxx', 2);")
+box.execute("INSERT INTO t4b VALUES('abc', 'xxx', 2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t4b VALUES('gHz', 'xxx', 4);")
+box.execute("INSERT INTO t4b VALUES('gHz', 'xxx', 4);")
 ---
+- rowcount: 1
 ...
 -- Results are sorted with case-insensitive order.
 -- Otherwise capital latters come first.
 --
-box.sql.execute("SELECT a FROM t4b ORDER BY a COLLATE \"unicode_ci\" || ''")
+box.execute("SELECT a FROM t4b ORDER BY a COLLATE \"unicode_ci\" || ''")
 ---
-- - ['abc']
+- metadata:
+  - name: A
+    type: TEXT
+  rows:
+  - ['abc']
   - ['BCD']
   - ['ghi']
   - ['gHz']
 ...
-box.sql.execute("SELECT a FROM t4b ORDER BY a || b")
+box.execute("SELECT a FROM t4b ORDER BY a || b")
 ---
-- - ['abc']
+- metadata:
+  - name: A
+    type: TEXT
+  rows:
+  - ['abc']
   - ['BCD']
   - ['ghi']
   - ['gHz']
@@ -429,358 +598,536 @@ box.space.T4B:drop()
 ...
 -- gh-3537 Duplicate key error for an index that is not unique
 -- pk - default, sc - unicode_ci
-box.sql.execute('CREATE TABLE t3 (s1 VARCHAR(5) PRIMARY KEY);')
+box.execute('CREATE TABLE t3 (s1 VARCHAR(5) PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3 ON t3 (s1 collate "unicode_ci");')
+box.execute('CREATE INDEX i3 ON t3 (s1 collate "unicode_ci");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3 VALUES ('a');")
+box.execute("INSERT INTO t3 VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3 VALUES ('A');")
+box.execute("INSERT INTO t3 VALUES ('A');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t3;")
+box.execute("SELECT * FROM t3;")
 ---
-- - ['A']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['A']
   - ['a']
 ...
-box.sql.execute("DROP TABLE t3;")
+box.execute("DROP TABLE t3;")
 ---
+- rowcount: 1
 ...
 -- pk - binary, sc - unicode
-box.sql.execute('CREATE TABLE t3b (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
+box.execute('CREATE TABLE t3b (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3b ON t3b (s1 collate "unicode");')
+box.execute('CREATE INDEX i3b ON t3b (s1 collate "unicode");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3b VALUES ('a');")
+box.execute("INSERT INTO t3b VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3b VALUES ('A');")
+box.execute("INSERT INTO t3b VALUES ('A');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t3b;")
+box.execute("SELECT * FROM t3b;")
 ---
-- - ['A']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['A']
   - ['a']
 ...
-box.sql.execute("DROP TABLE t3b;")
+box.execute("DROP TABLE t3b;")
 ---
+- rowcount: 1
 ...
 -- pk - binary, sc - unicode (make dup)
-box.sql.execute('CREATE TABLE t3b (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
+box.execute('CREATE TABLE t3b (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3b ON t3b (s1 collate "unicode");')
+box.execute('CREATE INDEX i3b ON t3b (s1 collate "unicode");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3b VALUES ('a');")
+box.execute("INSERT INTO t3b VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3b VALUES ('A');")
+box.execute("INSERT INTO t3b VALUES ('A');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3b VALUES ('a');")
+box.execute("INSERT INTO t3b VALUES ('a');")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_T3B_1' in space 'T3B'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_T3B_1'' in space ''T3B'''
 ...
-box.sql.execute("SELECT * FROM t3b;")
+box.execute("SELECT * FROM t3b;")
 ---
-- - ['A']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['A']
   - ['a']
 ...
-box.sql.execute("DROP TABLE t3b;")
+box.execute("DROP TABLE t3b;")
 ---
+- rowcount: 1
 ...
 -- pk - unicode, sc - binary
-box.sql.execute('CREATE TABLE t3c (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
+box.execute('CREATE TABLE t3c (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3c ON t3c (s1 collate "binary");')
+box.execute('CREATE INDEX i3c ON t3c (s1 collate "binary");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3c VALUES ('a');")
+box.execute("INSERT INTO t3c VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3c VALUES ('A');")
+box.execute("INSERT INTO t3c VALUES ('A');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t3c;")
+box.execute("SELECT * FROM t3c;")
 ---
-- - ['a']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['a']
   - ['A']
 ...
-box.sql.execute("DROP TABLE t3c;")
+box.execute("DROP TABLE t3c;")
 ---
+- rowcount: 1
 ...
 -- pk - unicode, sc - binary (make dup)
-box.sql.execute('CREATE TABLE t3c (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
+box.execute('CREATE TABLE t3c (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3c ON t3c (s1 collate "binary");')
+box.execute('CREATE INDEX i3c ON t3c (s1 collate "binary");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3c VALUES ('a');")
+box.execute("INSERT INTO t3c VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3c VALUES ('A');")
+box.execute("INSERT INTO t3c VALUES ('A');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3c VALUES ('a');")
+box.execute("INSERT INTO t3c VALUES ('a');")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_T3C_1' in space 'T3C'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_T3C_1'' in space ''T3C'''
 ...
-box.sql.execute("SELECT * FROM t3c;")
+box.execute("SELECT * FROM t3c;")
 ---
-- - ['a']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['a']
   - ['A']
 ...
-box.sql.execute("DROP TABLE t3c;")
+box.execute("DROP TABLE t3c;")
 ---
+- rowcount: 1
 ...
 -- pk - binary, sc - unicode_ci
-box.sql.execute('CREATE TABLE t3d (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
+box.execute('CREATE TABLE t3d (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3d ON t3d (s1 collate "unicode_ci");')
+box.execute('CREATE INDEX i3d ON t3d (s1 collate "unicode_ci");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3d VALUES ('a');")
+box.execute("INSERT INTO t3d VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3d VALUES ('A');")
+box.execute("INSERT INTO t3d VALUES ('A');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t3d;")
+box.execute("SELECT * FROM t3d;")
 ---
-- - ['A']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['A']
   - ['a']
 ...
-box.sql.execute("DROP TABLE t3d;")
+box.execute("DROP TABLE t3d;")
 ---
+- rowcount: 1
 ...
 -- pk - binary, sc - unicode_ci (make dup)
-box.sql.execute('CREATE TABLE t3d (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
+box.execute('CREATE TABLE t3d (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3d ON t3d (s1 collate "unicode_ci");')
+box.execute('CREATE INDEX i3d ON t3d (s1 collate "unicode_ci");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3d VALUES ('a');")
+box.execute("INSERT INTO t3d VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3d VALUES ('A');")
+box.execute("INSERT INTO t3d VALUES ('A');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3d VALUES ('a');")
+box.execute("INSERT INTO t3d VALUES ('a');")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_T3D_1' in space 'T3D'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_T3D_1'' in space ''T3D'''
 ...
-box.sql.execute("SELECT * FROM t3d;")
+box.execute("SELECT * FROM t3d;")
 ---
-- - ['A']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['A']
   - ['a']
 ...
-box.sql.execute("DROP TABLE t3d;")
+box.execute("DROP TABLE t3d;")
 ---
+- rowcount: 1
 ...
 -- pk - unicode_ci, sc - binary (should fail)
-box.sql.execute('CREATE TABLE t3e (s1 VARCHAR(5) collate "unicode_ci" PRIMARY KEY);')
+box.execute('CREATE TABLE t3e (s1 VARCHAR(5) collate "unicode_ci" PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3e ON t3e (s1 collate "binary");')
+box.execute('CREATE INDEX i3e ON t3e (s1 collate "binary");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3e VALUES ('a');")
+box.execute("INSERT INTO t3e VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3e VALUES ('A');")
+box.execute("INSERT INTO t3e VALUES ('A');")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_T3E_1' in space 'T3E'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_T3E_1'' in space ''T3E'''
 ...
-box.sql.execute("SELECT * FROM t3e;")
+box.execute("SELECT * FROM t3e;")
 ---
-- - ['a']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['a']
 ...
-box.sql.execute("DROP TABLE t3e;")
+box.execute("DROP TABLE t3e;")
 ---
+- rowcount: 1
 ...
 -- pk - unicode, sc - unicode_ci
-box.sql.execute('CREATE TABLE t3f (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
+box.execute('CREATE TABLE t3f (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3f ON t3f (s1 collate "unicode_ci");')
+box.execute('CREATE INDEX i3f ON t3f (s1 collate "unicode_ci");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3f VALUES ('a');")
+box.execute("INSERT INTO t3f VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3f VALUES ('A');")
+box.execute("INSERT INTO t3f VALUES ('A');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t3f;")
+box.execute("SELECT * FROM t3f;")
 ---
-- - ['a']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['a']
   - ['A']
 ...
-box.sql.execute("DROP TABLE t3f;")
+box.execute("DROP TABLE t3f;")
 ---
+- rowcount: 1
 ...
 -- pk - unicode, sc - unicode_ci (make dup)
-box.sql.execute('CREATE TABLE t3f (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
+box.execute('CREATE TABLE t3f (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3f ON t3f (s1 collate "unicode_ci");')
+box.execute('CREATE INDEX i3f ON t3f (s1 collate "unicode_ci");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3f VALUES ('a');")
+box.execute("INSERT INTO t3f VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3f VALUES ('A');")
+box.execute("INSERT INTO t3f VALUES ('A');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3f VALUES ('a');")
+box.execute("INSERT INTO t3f VALUES ('a');")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_T3F_1' in space 'T3F'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_T3F_1'' in space ''T3F'''
 ...
-box.sql.execute("SELECT * FROM t3f;")
+box.execute("SELECT * FROM t3f;")
 ---
-- - ['a']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['a']
   - ['A']
 ...
-box.sql.execute("DROP TABLE t3f;")
+box.execute("DROP TABLE t3f;")
 ---
+- rowcount: 1
 ...
 -- pk - unicode_ci, sc - unicode (should fail)
-box.sql.execute('CREATE TABLE t3g (s1 VARCHAR(5) collate "unicode_ci" PRIMARY KEY);')
+box.execute('CREATE TABLE t3g (s1 VARCHAR(5) collate "unicode_ci" PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i3g ON t3g (s1 collate "unicode");')
+box.execute('CREATE INDEX i3g ON t3g (s1 collate "unicode");')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3g VALUES ('a');")
+box.execute("INSERT INTO t3g VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3g VALUES ('A');")
+box.execute("INSERT INTO t3g VALUES ('A');")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_T3G_1' in space 'T3G'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_T3G_1'' in space ''T3G'''
 ...
-box.sql.execute("SELECT * FROM t3g;")
+box.execute("SELECT * FROM t3g;")
 ---
-- - ['a']
+- metadata:
+  - name: S1
+    type: TEXT
+  rows:
+  - ['a']
 ...
-box.sql.execute("DROP TABLE t3g;")
+box.execute("DROP TABLE t3g;")
 ---
+- rowcount: 1
 ...
 -- pk - default, sc - multipart
-box.sql.execute('CREATE TABLE qms1 (w VARCHAR(5) PRIMARY KEY, n VARCHAR(5), q VARCHAR(5), s INTEGER);')
+box.execute('CREATE TABLE qms1 (w VARCHAR(5) PRIMARY KEY, n VARCHAR(5), q VARCHAR(5), s INTEGER);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX iqms1 ON qms1 (w collate "unicode_ci", n);')
+box.execute('CREATE INDEX iqms1 ON qms1 (w collate "unicode_ci", n);')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO qms1 VALUES ('www', 'nnn', 'qqq', 1);")
+box.execute("INSERT INTO qms1 VALUES ('www', 'nnn', 'qqq', 1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO qms1 VALUES ('WWW', 'nnn', 'qqq', 2);")
+box.execute("INSERT INTO qms1 VALUES ('WWW', 'nnn', 'qqq', 2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM qms1;")
+box.execute("SELECT * FROM qms1;")
 ---
-- - ['WWW', 'nnn', 'qqq', 2]
+- metadata:
+  - name: W
+    type: TEXT
+  - name: N
+    type: TEXT
+  - name: Q
+    type: TEXT
+  - name: S
+    type: INTEGER
+  rows:
+  - ['WWW', 'nnn', 'qqq', 2]
   - ['www', 'nnn', 'qqq', 1]
 ...
-box.sql.execute("DROP TABLE qms1;")
+box.execute("DROP TABLE qms1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE TABLE qms2 (w VARCHAR(5) PRIMARY KEY, n VARCHAR(5), q VARCHAR(5), s INTEGER);')
+box.execute('CREATE TABLE qms2 (w VARCHAR(5) PRIMARY KEY, n VARCHAR(5), q VARCHAR(5), s INTEGER);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX iqms2 ON qms2 (w collate "unicode", n);')
+box.execute('CREATE INDEX iqms2 ON qms2 (w collate "unicode", n);')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO qms2 VALUES ('www', 'nnn', 'qqq', 1);")
+box.execute("INSERT INTO qms2 VALUES ('www', 'nnn', 'qqq', 1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO qms2 VALUES ('WWW', 'nnn', 'qqq', 2);")
+box.execute("INSERT INTO qms2 VALUES ('WWW', 'nnn', 'qqq', 2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM qms2;")
+box.execute("SELECT * FROM qms2;")
 ---
-- - ['WWW', 'nnn', 'qqq', 2]
+- metadata:
+  - name: W
+    type: TEXT
+  - name: N
+    type: TEXT
+  - name: Q
+    type: TEXT
+  - name: S
+    type: INTEGER
+  rows:
+  - ['WWW', 'nnn', 'qqq', 2]
   - ['www', 'nnn', 'qqq', 1]
 ...
-box.sql.execute("DROP TABLE qms2;")
+box.execute("DROP TABLE qms2;")
 ---
+- rowcount: 1
 ...
 -- pk - multipart, sc overlaps with pk
-box.sql.execute('CREATE TABLE qms3 (w VARCHAR(5), n VARCHAR(5), q VARCHAR(5), s INTEGER, CONSTRAINT pk_qms3 PRIMARY KEY(w, n, q));')
+box.execute('CREATE TABLE qms3 (w VARCHAR(5), n VARCHAR(5), q VARCHAR(5), s INTEGER, CONSTRAINT pk_qms3 PRIMARY KEY(w, n, q));')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX iqms3 ON qms3 (w collate "unicode_ci", s);')
+box.execute('CREATE INDEX iqms3 ON qms3 (w collate "unicode_ci", s);')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO qms3 VALUES ('www', 'nnn', 'qqq', 1);")
+box.execute("INSERT INTO qms3 VALUES ('www', 'nnn', 'qqq', 1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO qms3 VALUES ('WWW', 'nnn', 'qqq', 2);")
+box.execute("INSERT INTO qms3 VALUES ('WWW', 'nnn', 'qqq', 2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM qms3;")
+box.execute("SELECT * FROM qms3;")
 ---
-- - ['WWW', 'nnn', 'qqq', 2]
+- metadata:
+  - name: W
+    type: TEXT
+  - name: N
+    type: TEXT
+  - name: Q
+    type: TEXT
+  - name: S
+    type: INTEGER
+  rows:
+  - ['WWW', 'nnn', 'qqq', 2]
   - ['www', 'nnn', 'qqq', 1]
 ...
-box.sql.execute("DROP TABLE qms3;")
+box.execute("DROP TABLE qms3;")
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE TABLE qms4 (w VARCHAR(5), n VARCHAR(5), q VARCHAR(5), s INTEGER, CONSTRAINT pk_qms4 PRIMARY KEY(w, n, q));')
+box.execute('CREATE TABLE qms4 (w VARCHAR(5), n VARCHAR(5), q VARCHAR(5), s INTEGER, CONSTRAINT pk_qms4 PRIMARY KEY(w, n, q));')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX iqms4 ON qms4 (w collate "unicode", s);')
+box.execute('CREATE INDEX iqms4 ON qms4 (w collate "unicode", s);')
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO qms4 VALUES ('www', 'nnn', 'qqq', 1);")
+box.execute("INSERT INTO qms4 VALUES ('www', 'nnn', 'qqq', 1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO qms4 VALUES ('WWW', 'nnn', 'qqq', 2);")
+box.execute("INSERT INTO qms4 VALUES ('WWW', 'nnn', 'qqq', 2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM qms4;")
+box.execute("SELECT * FROM qms4;")
 ---
-- - ['WWW', 'nnn', 'qqq', 2]
+- metadata:
+  - name: W
+    type: TEXT
+  - name: N
+    type: TEXT
+  - name: Q
+    type: TEXT
+  - name: S
+    type: INTEGER
+  rows:
+  - ['WWW', 'nnn', 'qqq', 2]
   - ['www', 'nnn', 'qqq', 1]
 ...
-box.sql.execute("DROP TABLE qms4;")
+box.execute("DROP TABLE qms4;")
 ---
+- rowcount: 1
 ...
 -- gh-3932: make sure set build-in functions derive collation
 -- from their arguments.
 --
-box.sql.execute("CREATE TABLE jj (s1 INT PRIMARY KEY, s2 VARCHAR(3) COLLATE \"unicode_ci\");")
+box.execute("CREATE TABLE jj (s1 INT PRIMARY KEY, s2 VARCHAR(3) COLLATE \"unicode_ci\");")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO jj VALUES (1,'A'), (2,'a')")
+box.execute("INSERT INTO jj VALUES (1,'A'), (2,'a')")
 ---
+- rowcount: 2
 ...
-box.sql.execute("SELECT DISTINCT trim(s2) FROM jj;")
+box.execute("SELECT DISTINCT trim(s2) FROM jj;")
 ---
-- - ['A']
+- metadata:
+  - name: trim(s2)
+    type: TEXT
+  rows:
+  - ['A']
 ...
-box.sql.execute("INSERT INTO jj VALUES (3, 'aS'), (4, 'AS');")
+box.execute("INSERT INTO jj VALUES (3, 'aS'), (4, 'AS');")
 ---
+- rowcount: 2
 ...
-box.sql.execute("SELECT DISTINCT replace(s2, 'S', 's') FROM jj;")
+box.execute("SELECT DISTINCT replace(s2, 'S', 's') FROM jj;")
 ---
-- - ['A']
+- metadata:
+  - name: replace(s2, 'S', 's')
+    type: TEXT
+  rows:
+  - ['A']
   - ['as']
 ...
-box.sql.execute("SELECT DISTINCT substr(s2, 1, 1) FROM jj;")
+box.execute("SELECT DISTINCT substr(s2, 1, 1) FROM jj;")
 ---
-- - ['A']
+- metadata:
+  - name: substr(s2, 1, 1)
+    type: TEXT
+  rows:
+  - ['A']
 ...
 box.space.JJ:drop()
 ---
diff --git a/test/sql/collation.test.lua b/test/sql/collation.test.lua
index eba83e8..3a3f322 100644
--- a/test/sql/collation.test.lua
+++ b/test/sql/collation.test.lua
@@ -1,40 +1,40 @@
 remote = require('net.box')
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- gh-3010: COLLATE after LIMIT should throw an error
 
 -- All of these tests should throw error "near "COLLATE": syntax error"
-box.sql.execute("SELECT 1 LIMIT 1 COLLATE BINARY;")
-box.sql.execute("SELECT 1 LIMIT 1 COLLATE BINARY OFFSET 1;")
-box.sql.execute("SELECT 1 LIMIT 1 OFFSET 1 COLLATE BINARY;")
-box.sql.execute("SELECT 1 LIMIT 1, 1 COLLATE BINARY;")
-box.sql.execute("SELECT 1 LIMIT 1 COLLATE BINARY, 1;")
+box.execute("SELECT 1 LIMIT 1 COLLATE BINARY;")
+box.execute("SELECT 1 LIMIT 1 COLLATE BINARY OFFSET 1;")
+box.execute("SELECT 1 LIMIT 1 OFFSET 1 COLLATE BINARY;")
+box.execute("SELECT 1 LIMIT 1, 1 COLLATE BINARY;")
+box.execute("SELECT 1 LIMIT 1 COLLATE BINARY, 1;")
 
 -- gh-3052: upper/lower support only default locale
 -- For tr-TR result depends on collation
-box.sql.execute([[CREATE TABLE tu (descriptor VARCHAR(50) PRIMARY KEY, letter VARCHAR(50))]]);
+box.execute([[CREATE TABLE tu (descriptor VARCHAR(50) PRIMARY KEY, letter VARCHAR(50))]]);
 box.internal.collation.create('TURKISH', 'ICU', 'tr-TR', {strength='primary'});
-box.sql.execute([[INSERT INTO tu VALUES ('Latin Capital Letter I U+0049','I');]])
-box.sql.execute([[INSERT INTO tu VALUES ('Latin Small Letter I U+0069','i');]])
-box.sql.execute([[INSERT INTO tu VALUES ('Latin Capital Letter I With Dot Above U+0130','İ');]])
-box.sql.execute([[INSERT INTO tu VALUES ('Latin Small Letter Dotless I U+0131','ı');]])
+box.execute([[INSERT INTO tu VALUES ('Latin Capital Letter I U+0049','I');]])
+box.execute([[INSERT INTO tu VALUES ('Latin Small Letter I U+0069','i');]])
+box.execute([[INSERT INTO tu VALUES ('Latin Capital Letter I With Dot Above U+0130','İ');]])
+box.execute([[INSERT INTO tu VALUES ('Latin Small Letter Dotless I U+0131','ı');]])
 -- Without collation
-box.sql.execute([[SELECT descriptor, upper(letter) AS upper,lower(letter) AS lower FROM tu;]])
+box.execute([[SELECT descriptor, upper(letter) AS upper,lower(letter) AS lower FROM tu;]])
 -- With collation
-box.sql.execute([[SELECT descriptor, upper(letter COLLATE "TURKISH") AS upper,lower(letter COLLATE "TURKISH") AS lower FROM tu;]])
+box.execute([[SELECT descriptor, upper(letter COLLATE "TURKISH") AS upper,lower(letter COLLATE "TURKISH") AS lower FROM tu;]])
 box.internal.collation.drop('TURKISH')
 
 -- For de-DE result is actually the same
 box.internal.collation.create('GERMAN', 'ICU', 'de-DE', {strength='primary'});
-box.sql.execute([[INSERT INTO tu VALUES ('German Small Letter Sharp S U+00DF','ß');]])
+box.execute([[INSERT INTO tu VALUES ('German Small Letter Sharp S U+00DF','ß');]])
 -- Without collation
-box.sql.execute([[SELECT descriptor, upper(letter), letter FROM tu where UPPER(letter) = 'SS';]])
+box.execute([[SELECT descriptor, upper(letter), letter FROM tu where UPPER(letter) = 'SS';]])
 -- With collation
-box.sql.execute([[SELECT descriptor, upper(letter COLLATE "GERMAN"), letter FROM tu where UPPER(letter COLLATE "GERMAN") = 'SS';]])
+box.execute([[SELECT descriptor, upper(letter COLLATE "GERMAN"), letter FROM tu where UPPER(letter COLLATE "GERMAN") = 'SS';]])
 box.internal.collation.drop('GERMAN')
-box.sql.execute(([[DROP TABLE tu]]))
+box.execute(([[DROP TABLE tu]]))
 
 box.schema.user.grant('guest','read,write,execute', 'universe')
 cn = remote.connect(box.cfg.listen)
@@ -45,10 +45,10 @@ cn:close()
 
 -- Explicitly set BINARY collation is predifined and has ID.
 --
-box.sql.execute("CREATE TABLE t (id INT PRIMARY KEY, a TEXT, b TEXT COLLATE \"binary\");")
+box.execute("CREATE TABLE t (id INT PRIMARY KEY, a TEXT, b TEXT COLLATE \"binary\");")
 box.space.T:format()[2]['collation']
 box.space.T:format()[3]['collation']
-box.sql.execute("DROP TABLE t;")
+box.execute("DROP TABLE t;")
 
 -- BINARY collation works in the same way as there is no collation
 -- at all.
@@ -73,236 +73,236 @@ box.space._collation:delete{0}
 
 -- gh-3185: collations of LHS and RHS must be compatible.
 --
-box.sql.execute("CREATE TABLE t (id INT PRIMARY KEY, a TEXT, b TEXT COLLATE \"binary\", c TEXT COLLATE \"unicode_ci\");")
-box.sql.execute("SELECT * FROM t WHERE a = b;")
-box.sql.execute("SELECT * FROM t WHERE a COLLATE \"binary\" = b;")
-box.sql.execute("SELECT * FROM t WHERE b = c;")
-box.sql.execute("SELECT * FROM t WHERE b COLLATE \"binary\" = c;")
-box.sql.execute("SELECT * FROM t WHERE a = c;")
-box.sql.execute("SELECT * FROM t WHERE a COLLATE \"binary\" = c COLLATE \"unicode\";")
+box.execute("CREATE TABLE t (id INT PRIMARY KEY, a TEXT, b TEXT COLLATE \"binary\", c TEXT COLLATE \"unicode_ci\");")
+box.execute("SELECT * FROM t WHERE a = b;")
+box.execute("SELECT * FROM t WHERE a COLLATE \"binary\" = b;")
+box.execute("SELECT * FROM t WHERE b = c;")
+box.execute("SELECT * FROM t WHERE b COLLATE \"binary\" = c;")
+box.execute("SELECT * FROM t WHERE a = c;")
+box.execute("SELECT * FROM t WHERE a COLLATE \"binary\" = c COLLATE \"unicode\";")
 
 -- Compound queries perform implicit comparisons between values.
 -- Hence, rules for collations compatibilities are the same.
 --
-box.sql.execute("SELECT 'abc' COLLATE \"binary\" UNION SELECT 'ABC' COLLATE \"unicode_ci\"")
-box.sql.execute("SELECT 'abc' COLLATE \"unicode_ci\" UNION SELECT 'ABC' COLLATE binary")
-box.sql.execute("SELECT c FROM t UNION SELECT b FROM t;")
-box.sql.execute("SELECT b FROM t UNION SELECT a FROM t;")
-box.sql.execute("SELECT a FROM t UNION SELECT c FROM t;")
-box.sql.execute("SELECT c COLLATE \"binary\" FROM t UNION SELECT a FROM t;")
-box.sql.execute("SELECT b COLLATE \"unicode\" FROM t UNION SELECT a FROM t;")
-
-box.sql.execute("DROP TABLE t;")
+box.execute("SELECT 'abc' COLLATE \"binary\" UNION SELECT 'ABC' COLLATE \"unicode_ci\"")
+box.execute("SELECT 'abc' COLLATE \"unicode_ci\" UNION SELECT 'ABC' COLLATE binary")
+box.execute("SELECT c FROM t UNION SELECT b FROM t;")
+box.execute("SELECT b FROM t UNION SELECT a FROM t;")
+box.execute("SELECT a FROM t UNION SELECT c FROM t;")
+box.execute("SELECT c COLLATE \"binary\" FROM t UNION SELECT a FROM t;")
+box.execute("SELECT b COLLATE \"unicode\" FROM t UNION SELECT a FROM t;")
+
+box.execute("DROP TABLE t;")
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 
 -- gh-3857 "PRAGMA collation_list" invokes segmentation fault.
 box.schema.user.create('tmp')
 box.session.su('tmp')
 -- Error: read access to space is denied.
-box.sql.execute("pragma collation_list")
+box.execute("pragma collation_list")
 box.session.su('admin')
 box.schema.user.drop('tmp')
 
 -- gh-3644 Foreign key update fails with "unicode_ci".
 -- Check that foreign key update doesn't fail with "unicode_ci".
-box.sql.execute('CREATE TABLE t0 (s1 VARCHAR(5) COLLATE "unicode_ci" UNIQUE, id INT PRIMARY KEY AUTOINCREMENT);')
-box.sql.execute('CREATE TABLE t1 (s1 INT PRIMARY KEY, s0 VARCHAR(5) COLLATE "unicode_ci" REFERENCES t0(s1));')
-box.sql.execute("INSERT INTO t0(s1) VALUES ('a');")
-box.sql.execute("INSERT INTO t1 VALUES (1,'a');")
+box.execute('CREATE TABLE t0 (s1 VARCHAR(5) COLLATE "unicode_ci" UNIQUE, id INT PRIMARY KEY AUTOINCREMENT);')
+box.execute('CREATE TABLE t1 (s1 INT PRIMARY KEY, s0 VARCHAR(5) COLLATE "unicode_ci" REFERENCES t0(s1));')
+box.execute("INSERT INTO t0(s1) VALUES ('a');")
+box.execute("INSERT INTO t1 VALUES (1,'a');")
 -- Should't fail.
-box.sql.execute("UPDATE t0 SET s1 = 'A';")
-box.sql.execute("SELECT s1 FROM t0;")
-box.sql.execute("SELECT * FROM t1;")
-box.sql.execute("DROP TABLE t1;")
-box.sql.execute("DROP TABLE t0;")
+box.execute("UPDATE t0 SET s1 = 'A';")
+box.execute("SELECT s1 FROM t0;")
+box.execute("SELECT * FROM t1;")
+box.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t0;")
 -- Check that foreign key update fails with default collation.
-box.sql.execute('CREATE TABLE t0 (s1 VARCHAR(5) UNIQUE, id INT PRIMARY KEY AUTOINCREMENT);')
-box.sql.execute('CREATE TABLE t1 (s1 INT PRIMARY KEY, s0 VARCHAR(5) REFERENCES t0(s1));')
-box.sql.execute("INSERT INTO t0(s1) VALUES ('a');")
-box.sql.execute("INSERT INTO t1 VALUES (1,'a');")
+box.execute('CREATE TABLE t0 (s1 VARCHAR(5) UNIQUE, id INT PRIMARY KEY AUTOINCREMENT);')
+box.execute('CREATE TABLE t1 (s1 INT PRIMARY KEY, s0 VARCHAR(5) REFERENCES t0(s1));')
+box.execute("INSERT INTO t0(s1) VALUES ('a');")
+box.execute("INSERT INTO t1 VALUES (1,'a');")
 -- Should fail.
-box.sql.execute("UPDATE t0 SET s1 = 'A';")
-box.sql.execute("SELECT * FROM t1;")
-box.sql.execute("SELECT s1 FROM t0;")
-box.sql.execute("DROP TABLE t1;")
-box.sql.execute("DROP TABLE t0;")
+box.execute("UPDATE t0 SET s1 = 'A';")
+box.execute("SELECT * FROM t1;")
+box.execute("SELECT s1 FROM t0;")
+box.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t0;")
 
 -- gh-3937: result of concatination has derived collation.
 --
-box.sql.execute("CREATE TABLE t4a(a TEXT COLLATE \"unicode\", b TEXT COLLATE \"unicode_ci\", c INT PRIMARY KEY);")
-box.sql.execute("INSERT INTO t4a VALUES('ABC','abc',1);")
-box.sql.execute("INSERT INTO t4a VALUES('ghi','ghi',3);")
+box.execute("CREATE TABLE t4a(a TEXT COLLATE \"unicode\", b TEXT COLLATE \"unicode_ci\", c INT PRIMARY KEY);")
+box.execute("INSERT INTO t4a VALUES('ABC','abc',1);")
+box.execute("INSERT INTO t4a VALUES('ghi','ghi',3);")
 -- Only LHS of concatenation has implicitly set collation.
 -- Hence, no collation is used.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a||'') = b;")
+box.execute("SELECT c FROM t4a WHERE (a||'') = b;")
 -- BINARY collation is forced for comparison operator as
 -- a derivation from concatenation.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'') = b;")
+box.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'') = b;")
 -- Both operands of concatenation have explicit but different
 -- collations.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'' COLLATE \"unicode_ci\") = b;")
-box.sql.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'') = b COLLATE \"unicode\";")
+box.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'' COLLATE \"unicode_ci\") = b;")
+box.execute("SELECT c FROM t4a WHERE (a COLLATE \"binary\"||'') = b COLLATE \"unicode\";")
 -- No collation is used since LHS and RHS of concatenation
 -- operator have different implicit collations.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a||'')=(b||'');")
-box.sql.execute("SELECT c FROM t4a WHERE (a||b)=(b||a);")
+box.execute("SELECT c FROM t4a WHERE (a||'')=(b||'');")
+box.execute("SELECT c FROM t4a WHERE (a||b)=(b||a);")
 
-box.sql.execute("CREATE TABLE t4b(a TEXT COLLATE \"unicode_ci\", b TEXT COLLATE \"unicode_ci\", c INT PRIMARY KEY);")
-box.sql.execute("INSERT INTO t4b VALUES('BCD','bcd',1);")
-box.sql.execute("INSERT INTO t4b VALUES('ghi','ghi',3);")
+box.execute("CREATE TABLE t4b(a TEXT COLLATE \"unicode_ci\", b TEXT COLLATE \"unicode_ci\", c INT PRIMARY KEY);")
+box.execute("INSERT INTO t4b VALUES('BCD','bcd',1);")
+box.execute("INSERT INTO t4b VALUES('ghi','ghi',3);")
 -- Operands have the same implicit collation, so it is derived.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a||b)=(b||a);")
+box.execute("SELECT c FROM t4a WHERE (a||b)=(b||a);")
 -- Couple of other possible combinations.
 --
-box.sql.execute("SELECT c FROM t4a WHERE (a||b COLLATE \"binary\")=(b||a);")
-box.sql.execute("SELECT c FROM t4a WHERE (a||b COLLATE \"binary\")=(b COLLATE \"unicode_ci\"||a);")
+box.execute("SELECT c FROM t4a WHERE (a||b COLLATE \"binary\")=(b||a);")
+box.execute("SELECT c FROM t4a WHERE (a||b COLLATE \"binary\")=(b COLLATE \"unicode_ci\"||a);")
 
-box.sql.execute("INSERT INTO t4b VALUES('abc', 'xxx', 2);")
-box.sql.execute("INSERT INTO t4b VALUES('gHz', 'xxx', 4);")
+box.execute("INSERT INTO t4b VALUES('abc', 'xxx', 2);")
+box.execute("INSERT INTO t4b VALUES('gHz', 'xxx', 4);")
 -- Results are sorted with case-insensitive order.
 -- Otherwise capital latters come first.
 --
-box.sql.execute("SELECT a FROM t4b ORDER BY a COLLATE \"unicode_ci\" || ''")
-box.sql.execute("SELECT a FROM t4b ORDER BY a || b")
+box.execute("SELECT a FROM t4b ORDER BY a COLLATE \"unicode_ci\" || ''")
+box.execute("SELECT a FROM t4b ORDER BY a || b")
 
 box.space.T4A:drop()
 box.space.T4B:drop()
 
 -- gh-3537 Duplicate key error for an index that is not unique
 -- pk - default, sc - unicode_ci
-box.sql.execute('CREATE TABLE t3 (s1 VARCHAR(5) PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3 ON t3 (s1 collate "unicode_ci");')
-box.sql.execute("INSERT INTO t3 VALUES ('a');")
-box.sql.execute("INSERT INTO t3 VALUES ('A');")
-box.sql.execute("SELECT * FROM t3;")
-box.sql.execute("DROP TABLE t3;")
+box.execute('CREATE TABLE t3 (s1 VARCHAR(5) PRIMARY KEY);')
+box.execute('CREATE INDEX i3 ON t3 (s1 collate "unicode_ci");')
+box.execute("INSERT INTO t3 VALUES ('a');")
+box.execute("INSERT INTO t3 VALUES ('A');")
+box.execute("SELECT * FROM t3;")
+box.execute("DROP TABLE t3;")
 
 -- pk - binary, sc - unicode
-box.sql.execute('CREATE TABLE t3b (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3b ON t3b (s1 collate "unicode");')
-box.sql.execute("INSERT INTO t3b VALUES ('a');")
-box.sql.execute("INSERT INTO t3b VALUES ('A');")
-box.sql.execute("SELECT * FROM t3b;")
-box.sql.execute("DROP TABLE t3b;")
+box.execute('CREATE TABLE t3b (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
+box.execute('CREATE INDEX i3b ON t3b (s1 collate "unicode");')
+box.execute("INSERT INTO t3b VALUES ('a');")
+box.execute("INSERT INTO t3b VALUES ('A');")
+box.execute("SELECT * FROM t3b;")
+box.execute("DROP TABLE t3b;")
 
 -- pk - binary, sc - unicode (make dup)
-box.sql.execute('CREATE TABLE t3b (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3b ON t3b (s1 collate "unicode");')
-box.sql.execute("INSERT INTO t3b VALUES ('a');")
-box.sql.execute("INSERT INTO t3b VALUES ('A');")
-box.sql.execute("INSERT INTO t3b VALUES ('a');")
-box.sql.execute("SELECT * FROM t3b;")
-box.sql.execute("DROP TABLE t3b;")
+box.execute('CREATE TABLE t3b (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
+box.execute('CREATE INDEX i3b ON t3b (s1 collate "unicode");')
+box.execute("INSERT INTO t3b VALUES ('a');")
+box.execute("INSERT INTO t3b VALUES ('A');")
+box.execute("INSERT INTO t3b VALUES ('a');")
+box.execute("SELECT * FROM t3b;")
+box.execute("DROP TABLE t3b;")
 
 -- pk - unicode, sc - binary
-box.sql.execute('CREATE TABLE t3c (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3c ON t3c (s1 collate "binary");')
-box.sql.execute("INSERT INTO t3c VALUES ('a');")
-box.sql.execute("INSERT INTO t3c VALUES ('A');")
-box.sql.execute("SELECT * FROM t3c;")
-box.sql.execute("DROP TABLE t3c;")
+box.execute('CREATE TABLE t3c (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
+box.execute('CREATE INDEX i3c ON t3c (s1 collate "binary");')
+box.execute("INSERT INTO t3c VALUES ('a');")
+box.execute("INSERT INTO t3c VALUES ('A');")
+box.execute("SELECT * FROM t3c;")
+box.execute("DROP TABLE t3c;")
 
 -- pk - unicode, sc - binary (make dup)
-box.sql.execute('CREATE TABLE t3c (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3c ON t3c (s1 collate "binary");')
-box.sql.execute("INSERT INTO t3c VALUES ('a');")
-box.sql.execute("INSERT INTO t3c VALUES ('A');")
-box.sql.execute("INSERT INTO t3c VALUES ('a');")
-box.sql.execute("SELECT * FROM t3c;")
-box.sql.execute("DROP TABLE t3c;")
+box.execute('CREATE TABLE t3c (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
+box.execute('CREATE INDEX i3c ON t3c (s1 collate "binary");')
+box.execute("INSERT INTO t3c VALUES ('a');")
+box.execute("INSERT INTO t3c VALUES ('A');")
+box.execute("INSERT INTO t3c VALUES ('a');")
+box.execute("SELECT * FROM t3c;")
+box.execute("DROP TABLE t3c;")
 
 -- pk - binary, sc - unicode_ci
-box.sql.execute('CREATE TABLE t3d (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3d ON t3d (s1 collate "unicode_ci");')
-box.sql.execute("INSERT INTO t3d VALUES ('a');")
-box.sql.execute("INSERT INTO t3d VALUES ('A');")
-box.sql.execute("SELECT * FROM t3d;")
-box.sql.execute("DROP TABLE t3d;")
+box.execute('CREATE TABLE t3d (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
+box.execute('CREATE INDEX i3d ON t3d (s1 collate "unicode_ci");')
+box.execute("INSERT INTO t3d VALUES ('a');")
+box.execute("INSERT INTO t3d VALUES ('A');")
+box.execute("SELECT * FROM t3d;")
+box.execute("DROP TABLE t3d;")
 
 -- pk - binary, sc - unicode_ci (make dup)
-box.sql.execute('CREATE TABLE t3d (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3d ON t3d (s1 collate "unicode_ci");')
-box.sql.execute("INSERT INTO t3d VALUES ('a');")
-box.sql.execute("INSERT INTO t3d VALUES ('A');")
-box.sql.execute("INSERT INTO t3d VALUES ('a');")
-box.sql.execute("SELECT * FROM t3d;")
-box.sql.execute("DROP TABLE t3d;")
+box.execute('CREATE TABLE t3d (s1 VARCHAR(5) collate "binary" PRIMARY KEY);')
+box.execute('CREATE INDEX i3d ON t3d (s1 collate "unicode_ci");')
+box.execute("INSERT INTO t3d VALUES ('a');")
+box.execute("INSERT INTO t3d VALUES ('A');")
+box.execute("INSERT INTO t3d VALUES ('a');")
+box.execute("SELECT * FROM t3d;")
+box.execute("DROP TABLE t3d;")
 
 -- pk - unicode_ci, sc - binary (should fail)
-box.sql.execute('CREATE TABLE t3e (s1 VARCHAR(5) collate "unicode_ci" PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3e ON t3e (s1 collate "binary");')
-box.sql.execute("INSERT INTO t3e VALUES ('a');")
-box.sql.execute("INSERT INTO t3e VALUES ('A');")
-box.sql.execute("SELECT * FROM t3e;")
-box.sql.execute("DROP TABLE t3e;")
+box.execute('CREATE TABLE t3e (s1 VARCHAR(5) collate "unicode_ci" PRIMARY KEY);')
+box.execute('CREATE INDEX i3e ON t3e (s1 collate "binary");')
+box.execute("INSERT INTO t3e VALUES ('a');")
+box.execute("INSERT INTO t3e VALUES ('A');")
+box.execute("SELECT * FROM t3e;")
+box.execute("DROP TABLE t3e;")
 
 -- pk - unicode, sc - unicode_ci
-box.sql.execute('CREATE TABLE t3f (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3f ON t3f (s1 collate "unicode_ci");')
-box.sql.execute("INSERT INTO t3f VALUES ('a');")
-box.sql.execute("INSERT INTO t3f VALUES ('A');")
-box.sql.execute("SELECT * FROM t3f;")
-box.sql.execute("DROP TABLE t3f;")
+box.execute('CREATE TABLE t3f (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
+box.execute('CREATE INDEX i3f ON t3f (s1 collate "unicode_ci");')
+box.execute("INSERT INTO t3f VALUES ('a');")
+box.execute("INSERT INTO t3f VALUES ('A');")
+box.execute("SELECT * FROM t3f;")
+box.execute("DROP TABLE t3f;")
 
 -- pk - unicode, sc - unicode_ci (make dup)
-box.sql.execute('CREATE TABLE t3f (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3f ON t3f (s1 collate "unicode_ci");')
-box.sql.execute("INSERT INTO t3f VALUES ('a');")
-box.sql.execute("INSERT INTO t3f VALUES ('A');")
-box.sql.execute("INSERT INTO t3f VALUES ('a');")
-box.sql.execute("SELECT * FROM t3f;")
-box.sql.execute("DROP TABLE t3f;")
+box.execute('CREATE TABLE t3f (s1 VARCHAR(5) collate "unicode" PRIMARY KEY);')
+box.execute('CREATE INDEX i3f ON t3f (s1 collate "unicode_ci");')
+box.execute("INSERT INTO t3f VALUES ('a');")
+box.execute("INSERT INTO t3f VALUES ('A');")
+box.execute("INSERT INTO t3f VALUES ('a');")
+box.execute("SELECT * FROM t3f;")
+box.execute("DROP TABLE t3f;")
 
 -- pk - unicode_ci, sc - unicode (should fail)
-box.sql.execute('CREATE TABLE t3g (s1 VARCHAR(5) collate "unicode_ci" PRIMARY KEY);')
-box.sql.execute('CREATE INDEX i3g ON t3g (s1 collate "unicode");')
-box.sql.execute("INSERT INTO t3g VALUES ('a');")
-box.sql.execute("INSERT INTO t3g VALUES ('A');")
-box.sql.execute("SELECT * FROM t3g;")
-box.sql.execute("DROP TABLE t3g;")
+box.execute('CREATE TABLE t3g (s1 VARCHAR(5) collate "unicode_ci" PRIMARY KEY);')
+box.execute('CREATE INDEX i3g ON t3g (s1 collate "unicode");')
+box.execute("INSERT INTO t3g VALUES ('a');")
+box.execute("INSERT INTO t3g VALUES ('A');")
+box.execute("SELECT * FROM t3g;")
+box.execute("DROP TABLE t3g;")
 
 -- pk - default, sc - multipart
-box.sql.execute('CREATE TABLE qms1 (w VARCHAR(5) PRIMARY KEY, n VARCHAR(5), q VARCHAR(5), s INTEGER);')
-box.sql.execute('CREATE INDEX iqms1 ON qms1 (w collate "unicode_ci", n);')
-box.sql.execute("INSERT INTO qms1 VALUES ('www', 'nnn', 'qqq', 1);")
-box.sql.execute("INSERT INTO qms1 VALUES ('WWW', 'nnn', 'qqq', 2);")
-box.sql.execute("SELECT * FROM qms1;")
-box.sql.execute("DROP TABLE qms1;")
-
-box.sql.execute('CREATE TABLE qms2 (w VARCHAR(5) PRIMARY KEY, n VARCHAR(5), q VARCHAR(5), s INTEGER);')
-box.sql.execute('CREATE INDEX iqms2 ON qms2 (w collate "unicode", n);')
-box.sql.execute("INSERT INTO qms2 VALUES ('www', 'nnn', 'qqq', 1);")
-box.sql.execute("INSERT INTO qms2 VALUES ('WWW', 'nnn', 'qqq', 2);")
-box.sql.execute("SELECT * FROM qms2;")
-box.sql.execute("DROP TABLE qms2;")
+box.execute('CREATE TABLE qms1 (w VARCHAR(5) PRIMARY KEY, n VARCHAR(5), q VARCHAR(5), s INTEGER);')
+box.execute('CREATE INDEX iqms1 ON qms1 (w collate "unicode_ci", n);')
+box.execute("INSERT INTO qms1 VALUES ('www', 'nnn', 'qqq', 1);")
+box.execute("INSERT INTO qms1 VALUES ('WWW', 'nnn', 'qqq', 2);")
+box.execute("SELECT * FROM qms1;")
+box.execute("DROP TABLE qms1;")
+
+box.execute('CREATE TABLE qms2 (w VARCHAR(5) PRIMARY KEY, n VARCHAR(5), q VARCHAR(5), s INTEGER);')
+box.execute('CREATE INDEX iqms2 ON qms2 (w collate "unicode", n);')
+box.execute("INSERT INTO qms2 VALUES ('www', 'nnn', 'qqq', 1);")
+box.execute("INSERT INTO qms2 VALUES ('WWW', 'nnn', 'qqq', 2);")
+box.execute("SELECT * FROM qms2;")
+box.execute("DROP TABLE qms2;")
 
 -- pk - multipart, sc overlaps with pk
-box.sql.execute('CREATE TABLE qms3 (w VARCHAR(5), n VARCHAR(5), q VARCHAR(5), s INTEGER, CONSTRAINT pk_qms3 PRIMARY KEY(w, n, q));')
-box.sql.execute('CREATE INDEX iqms3 ON qms3 (w collate "unicode_ci", s);')
-box.sql.execute("INSERT INTO qms3 VALUES ('www', 'nnn', 'qqq', 1);")
-box.sql.execute("INSERT INTO qms3 VALUES ('WWW', 'nnn', 'qqq', 2);")
-box.sql.execute("SELECT * FROM qms3;")
-box.sql.execute("DROP TABLE qms3;")
-
-box.sql.execute('CREATE TABLE qms4 (w VARCHAR(5), n VARCHAR(5), q VARCHAR(5), s INTEGER, CONSTRAINT pk_qms4 PRIMARY KEY(w, n, q));')
-box.sql.execute('CREATE INDEX iqms4 ON qms4 (w collate "unicode", s);')
-box.sql.execute("INSERT INTO qms4 VALUES ('www', 'nnn', 'qqq', 1);")
-box.sql.execute("INSERT INTO qms4 VALUES ('WWW', 'nnn', 'qqq', 2);")
-box.sql.execute("SELECT * FROM qms4;")
-box.sql.execute("DROP TABLE qms4;")
+box.execute('CREATE TABLE qms3 (w VARCHAR(5), n VARCHAR(5), q VARCHAR(5), s INTEGER, CONSTRAINT pk_qms3 PRIMARY KEY(w, n, q));')
+box.execute('CREATE INDEX iqms3 ON qms3 (w collate "unicode_ci", s);')
+box.execute("INSERT INTO qms3 VALUES ('www', 'nnn', 'qqq', 1);")
+box.execute("INSERT INTO qms3 VALUES ('WWW', 'nnn', 'qqq', 2);")
+box.execute("SELECT * FROM qms3;")
+box.execute("DROP TABLE qms3;")
+
+box.execute('CREATE TABLE qms4 (w VARCHAR(5), n VARCHAR(5), q VARCHAR(5), s INTEGER, CONSTRAINT pk_qms4 PRIMARY KEY(w, n, q));')
+box.execute('CREATE INDEX iqms4 ON qms4 (w collate "unicode", s);')
+box.execute("INSERT INTO qms4 VALUES ('www', 'nnn', 'qqq', 1);")
+box.execute("INSERT INTO qms4 VALUES ('WWW', 'nnn', 'qqq', 2);")
+box.execute("SELECT * FROM qms4;")
+box.execute("DROP TABLE qms4;")
 
 -- gh-3932: make sure set build-in functions derive collation
 -- from their arguments.
 --
-box.sql.execute("CREATE TABLE jj (s1 INT PRIMARY KEY, s2 VARCHAR(3) COLLATE \"unicode_ci\");")
-box.sql.execute("INSERT INTO jj VALUES (1,'A'), (2,'a')")
-box.sql.execute("SELECT DISTINCT trim(s2) FROM jj;")
-box.sql.execute("INSERT INTO jj VALUES (3, 'aS'), (4, 'AS');")
-box.sql.execute("SELECT DISTINCT replace(s2, 'S', 's') FROM jj;")
-box.sql.execute("SELECT DISTINCT substr(s2, 1, 1) FROM jj;")
+box.execute("CREATE TABLE jj (s1 INT PRIMARY KEY, s2 VARCHAR(3) COLLATE \"unicode_ci\");")
+box.execute("INSERT INTO jj VALUES (1,'A'), (2,'a')")
+box.execute("SELECT DISTINCT trim(s2) FROM jj;")
+box.execute("INSERT INTO jj VALUES (3, 'aS'), (4, 'AS');")
+box.execute("SELECT DISTINCT replace(s2, 'S', 's') FROM jj;")
+box.execute("SELECT DISTINCT substr(s2, 1, 1) FROM jj;")
 box.space.JJ:drop()
diff --git a/test/sql/delete-multiple-idx.result b/test/sql/delete-multiple-idx.result
index 27c352a..9614ead 100644
--- a/test/sql/delete-multiple-idx.result
+++ b/test/sql/delete-multiple-idx.result
@@ -4,47 +4,65 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
 -- Create space.
-box.sql.execute("CREATE TABLE t3(id INT primary key,x INT,y INT);");
+box.execute("CREATE TABLE t3(id INT primary key,x INT,y INT);");
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE UNIQUE INDEX t3y ON t3(y);");
+box.execute("CREATE UNIQUE INDEX t3y ON t3(y);");
 ---
+- rowcount: 1
 ...
 -- Debug.
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 -- Seed entries.
-box.sql.execute("INSERT INTO t3 VALUES (1, 1, NULL);");
+box.execute("INSERT INTO t3 VALUES (1, 1, NULL);");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3 VALUES(2,9,NULL);");
+box.execute("INSERT INTO t3 VALUES(2,9,NULL);");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3 VALUES(3,5,NULL);");
+box.execute("INSERT INTO t3 VALUES(3,5,NULL);");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3 VALUES(6, 234,567);");
+box.execute("INSERT INTO t3 VALUES(6, 234,567);");
 ---
+- rowcount: 1
 ...
 -- Delete should be done from both trees..
-box.sql.execute("DELETE FROM t3 WHERE y IS NULL;");
+box.execute("DELETE FROM t3 WHERE y IS NULL;");
 ---
+- rowcount: 3
 ...
 -- Verify.
-box.sql.execute("SELECT * FROM t3;");
+box.execute("SELECT * FROM t3;");
 ---
-- - [6, 234, 567]
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: X
+    type: INTEGER
+  - name: Y
+    type: INTEGER
+  rows:
+  - [6, 234, 567]
 ...
 -- Cleanup.
-box.sql.execute("DROP INDEX t3y ON t3");
+box.execute("DROP INDEX t3y ON t3");
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t3;");
+box.execute("DROP TABLE t3;");
 ---
+- rowcount: 1
 ...
 -- Debug.
 -- require("console").start()
diff --git a/test/sql/delete-multiple-idx.test.lua b/test/sql/delete-multiple-idx.test.lua
index 4ce7f2d..a81cccc 100644
--- a/test/sql/delete-multiple-idx.test.lua
+++ b/test/sql/delete-multiple-idx.test.lua
@@ -1,32 +1,32 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- box.cfg()
 
 -- Create space.
-box.sql.execute("CREATE TABLE t3(id INT primary key,x INT,y INT);");
-box.sql.execute("CREATE UNIQUE INDEX t3y ON t3(y);");
+box.execute("CREATE TABLE t3(id INT primary key,x INT,y INT);");
+box.execute("CREATE UNIQUE INDEX t3y ON t3(y);");
 
 -- Debug.
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 
 -- Seed entries.
-box.sql.execute("INSERT INTO t3 VALUES (1, 1, NULL);");
-box.sql.execute("INSERT INTO t3 VALUES(2,9,NULL);");
-box.sql.execute("INSERT INTO t3 VALUES(3,5,NULL);");
-box.sql.execute("INSERT INTO t3 VALUES(6, 234,567);");
+box.execute("INSERT INTO t3 VALUES (1, 1, NULL);");
+box.execute("INSERT INTO t3 VALUES(2,9,NULL);");
+box.execute("INSERT INTO t3 VALUES(3,5,NULL);");
+box.execute("INSERT INTO t3 VALUES(6, 234,567);");
 
 
 -- Delete should be done from both trees..
-box.sql.execute("DELETE FROM t3 WHERE y IS NULL;");
+box.execute("DELETE FROM t3 WHERE y IS NULL;");
 
 -- Verify.
-box.sql.execute("SELECT * FROM t3;");
+box.execute("SELECT * FROM t3;");
 
 -- Cleanup.
-box.sql.execute("DROP INDEX t3y ON t3");
-box.sql.execute("DROP TABLE t3;");
+box.execute("DROP INDEX t3y ON t3");
+box.execute("DROP TABLE t3;");
 
 -- Debug.
 -- require("console").start()
diff --git a/test/sql/delete.result b/test/sql/delete.result
index e024dd6..60eb6c3 100644
--- a/test/sql/delete.result
+++ b/test/sql/delete.result
@@ -4,134 +4,174 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
 -- create space
-box.sql.execute("CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a, b));");
+box.execute("CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a, b));");
 ---
+- rowcount: 1
 ...
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 -- Seed entries
-box.sql.execute("INSERT INTO t1 VALUES(1, 2);");
+box.execute("INSERT INTO t1 VALUES(1, 2);");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES(2, 4);");
+box.execute("INSERT INTO t1 VALUES(2, 4);");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES(1, 5);");
+box.execute("INSERT INTO t1 VALUES(1, 5);");
 ---
+- rowcount: 1
 ...
 -- Two rows to be removed.
-box.sql.execute("DELETE FROM t1 WHERE a=1;");
+box.execute("DELETE FROM t1 WHERE a=1;");
 ---
+- rowcount: 2
 ...
 -- Verify
-box.sql.execute("SELECT * FROM t1;");
+box.execute("SELECT * FROM t1;");
 ---
-- - [2, 4]
+- metadata:
+  - name: A
+    type: INTEGER
+  - name: B
+    type: INTEGER
+  rows:
+  - [2, 4]
 ...
 -- Cleanup
-box.sql.execute("DROP TABLE t1;");
+box.execute("DROP TABLE t1;");
 ---
+- rowcount: 1
 ...
 -- Debug
 -- require("console").start()
 --
 -- gh-3535: Assertion with trigger and non existent table
 --
-box.sql.execute("DELETE FROM t1;")
+box.execute("DELETE FROM t1;")
 ---
 - error: Space 'T1' does not exist
 ...
-box.sql.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);")
+box.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER t2 BEFORE INSERT ON t2 BEGIN DELETE FROM t1; END;")
+box.execute("CREATE TRIGGER t2 BEFORE INSERT ON t2 BEGIN DELETE FROM t1; END;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t2 VALUES (0);")
+box.execute("INSERT INTO t2 VALUES (0);")
 ---
 - error: Space 'T1' does not exist
 ...
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t2;")
 ---
+- rowcount: 1
 ...
 --
 -- gh-2201: TRUNCATE TABLE operation.
 --
 -- can't truncate system table.
-box.sql.execute("TRUNCATE TABLE \"_sql_stat1\";")
+box.execute("TRUNCATE TABLE \"_sql_stat1\";")
 ---
 - error: Can't truncate a system space, space '_sql_stat1'
 ...
-box.sql.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT, b TEXT);")
+box.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT, b TEXT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES(1, 1, 'one');")
+box.execute("INSERT INTO t1 VALUES(1, 1, 'one');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES(2, 2, 'two');")
+box.execute("INSERT INTO t1 VALUES(2, 2, 'two');")
 ---
+- rowcount: 1
 ...
 -- Can't truncate in transaction.
-box.sql.execute("START TRANSACTION")
+box.execute("START TRANSACTION")
 ---
+- rowcount: 0
 ...
-box.sql.execute("TRUNCATE TABLE t1;")
+box.execute("TRUNCATE TABLE t1;")
 ---
 - error: DDL does not support multi-statement transactions
 ...
-box.sql.execute("ROLLBACK")
+box.execute("ROLLBACK")
 ---
+- rowcount: 0
 ...
 -- Can't truncate view.
-box.sql.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
+box.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("TRUNCATE TABLE v1;")
+box.execute("TRUNCATE TABLE v1;")
 ---
 - error: 'SQL error: can not truncate space ''V1'' because it is a view'
 ...
 -- Can't truncate table with FK.
-box.sql.execute("CREATE TABLE t2(x INT PRIMARY KEY REFERENCES t1(id));")
+box.execute("CREATE TABLE t2(x INT PRIMARY KEY REFERENCES t1(id));")
 ---
+- rowcount: 1
 ...
-box.sql.execute("TRUNCATE TABLE t1;")
+box.execute("TRUNCATE TABLE t1;")
 ---
 - error: 'SQL error: can not truncate space ''T1'' because other objects depend on
     it'
 ...
 -- Table triggers should be ignored.
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t2;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2(x INT PRIMARY KEY);")
+box.execute("CREATE TABLE t2(x INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN INSERT INTO t2 VALUES(old.x); END;")
+box.execute("CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN INSERT INTO t2 VALUES(old.x); END;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("TRUNCATE TABLE t1;")
+box.execute("TRUNCATE TABLE t1;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("SELECT * FROM t1;")
+box.execute("SELECT * FROM t1;")
 ---
-- []
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: INTEGER
+  - name: B
+    type: TEXT
+  rows: []
 ...
-box.sql.execute("SELECT * FROM t2;")
+box.execute("SELECT * FROM t2;")
 ---
-- []
+- metadata:
+  - name: X
+    type: INTEGER
+  rows: []
 ...
 -- Cleanup.
-box.sql.execute("DROP VIEW v1");
+box.execute("DROP VIEW v1");
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t2;")
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/delete.test.lua b/test/sql/delete.test.lua
index 5a08130..5c72296 100644
--- a/test/sql/delete.test.lua
+++ b/test/sql/delete.test.lua
@@ -1,28 +1,28 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- box.cfg()
 
 -- create space
-box.sql.execute("CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a, b));");
+box.execute("CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a, b));");
 
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 
 -- Seed entries
-box.sql.execute("INSERT INTO t1 VALUES(1, 2);");
-box.sql.execute("INSERT INTO t1 VALUES(2, 4);");
-box.sql.execute("INSERT INTO t1 VALUES(1, 5);");
+box.execute("INSERT INTO t1 VALUES(1, 2);");
+box.execute("INSERT INTO t1 VALUES(2, 4);");
+box.execute("INSERT INTO t1 VALUES(1, 5);");
 
 -- Two rows to be removed.
-box.sql.execute("DELETE FROM t1 WHERE a=1;");
+box.execute("DELETE FROM t1 WHERE a=1;");
 
 -- Verify
-box.sql.execute("SELECT * FROM t1;");
+box.execute("SELECT * FROM t1;");
 
 -- Cleanup
-box.sql.execute("DROP TABLE t1;");
+box.execute("DROP TABLE t1;");
 
 -- Debug
 -- require("console").start()
@@ -30,13 +30,13 @@ box.sql.execute("DROP TABLE t1;");
 --
 -- gh-3535: Assertion with trigger and non existent table
 --
-box.sql.execute("DELETE FROM t1;")
+box.execute("DELETE FROM t1;")
 
-box.sql.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);")
-box.sql.execute("CREATE TRIGGER t2 BEFORE INSERT ON t2 BEGIN DELETE FROM t1; END;")
-box.sql.execute("INSERT INTO t2 VALUES (0);")
+box.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);")
+box.execute("CREATE TRIGGER t2 BEFORE INSERT ON t2 BEGIN DELETE FROM t1; END;")
+box.execute("INSERT INTO t2 VALUES (0);")
 
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t2;")
 
 
 --
@@ -44,34 +44,34 @@ box.sql.execute("DROP TABLE t2;")
 --
 
 -- can't truncate system table.
-box.sql.execute("TRUNCATE TABLE \"_sql_stat1\";")
+box.execute("TRUNCATE TABLE \"_sql_stat1\";")
 
-box.sql.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT, b TEXT);")
-box.sql.execute("INSERT INTO t1 VALUES(1, 1, 'one');")
-box.sql.execute("INSERT INTO t1 VALUES(2, 2, 'two');")
+box.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT, b TEXT);")
+box.execute("INSERT INTO t1 VALUES(1, 1, 'one');")
+box.execute("INSERT INTO t1 VALUES(2, 2, 'two');")
 
 -- Can't truncate in transaction.
-box.sql.execute("START TRANSACTION")
-box.sql.execute("TRUNCATE TABLE t1;")
-box.sql.execute("ROLLBACK")
+box.execute("START TRANSACTION")
+box.execute("TRUNCATE TABLE t1;")
+box.execute("ROLLBACK")
 
 -- Can't truncate view.
-box.sql.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
-box.sql.execute("TRUNCATE TABLE v1;")
+box.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
+box.execute("TRUNCATE TABLE v1;")
 
 -- Can't truncate table with FK.
-box.sql.execute("CREATE TABLE t2(x INT PRIMARY KEY REFERENCES t1(id));")
-box.sql.execute("TRUNCATE TABLE t1;")
+box.execute("CREATE TABLE t2(x INT PRIMARY KEY REFERENCES t1(id));")
+box.execute("TRUNCATE TABLE t1;")
 
 -- Table triggers should be ignored.
-box.sql.execute("DROP TABLE t2;")
-box.sql.execute("CREATE TABLE t2(x INT PRIMARY KEY);")
-box.sql.execute("CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN INSERT INTO t2 VALUES(old.x); END;")
-box.sql.execute("TRUNCATE TABLE t1;")
-box.sql.execute("SELECT * FROM t1;")
-box.sql.execute("SELECT * FROM t2;")
+box.execute("DROP TABLE t2;")
+box.execute("CREATE TABLE t2(x INT PRIMARY KEY);")
+box.execute("CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN INSERT INTO t2 VALUES(old.x); END;")
+box.execute("TRUNCATE TABLE t1;")
+box.execute("SELECT * FROM t1;")
+box.execute("SELECT * FROM t2;")
 
 -- Cleanup.
-box.sql.execute("DROP VIEW v1");
-box.sql.execute("DROP TABLE t1;")
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP VIEW v1");
+box.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t2;")
diff --git a/test/sql/drop-index.result b/test/sql/drop-index.result
index 2590b74..7693f9e 100644
--- a/test/sql/drop-index.result
+++ b/test/sql/drop-index.result
@@ -4,46 +4,57 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
 -- create space
-box.sql.execute("CREATE TABLE zzoobar (c1 FLOAT, c2 INT PRIMARY KEY, c3 TEXT, c4 FLOAT)")
+box.execute("CREATE TABLE zzoobar (c1 FLOAT, c2 INT PRIMARY KEY, c3 TEXT, c4 FLOAT)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE UNIQUE INDEX zoobar2 ON zzoobar(c1, c4)")
+box.execute("CREATE UNIQUE INDEX zoobar2 ON zzoobar(c1, c4)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE        INDEX zoobar3 ON zzoobar(c3)")
+box.execute("CREATE        INDEX zoobar3 ON zzoobar(c3)")
 ---
+- rowcount: 1
 ...
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zzoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zzoobar VALUES (111, 222, 'c3', 444)")
 -- Dummy entry
-box.sql.execute("INSERT INTO zzoobar VALUES (111, 222, 'c3', 444)")
+box.execute("INSERT INTO zzoobar VALUES (111, 222, 'c3', 444)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP INDEX zoobar2 ON zzoobar")
+box.execute("DROP INDEX zoobar2 ON zzoobar")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP INDEX zoobar3 On zzoobar")
+box.execute("DROP INDEX zoobar3 On zzoobar")
 ---
+- rowcount: 1
 ...
 -- zoobar2 is dropped - should be OK
-box.sql.execute("INSERT INTO zzoobar VALUES (111, 223, 'c3', 444)")
+box.execute("INSERT INTO zzoobar VALUES (111, 223, 'c3', 444)")
 ---
+- rowcount: 1
 ...
 -- zoobar2 was dropped. Re-creation should  be OK
-box.sql.execute("CREATE INDEX zoobar2 ON zzoobar(c3)")
+box.execute("CREATE INDEX zoobar2 ON zzoobar(c3)")
 ---
+- rowcount: 1
 ...
 -- Cleanup
-box.sql.execute("DROP INDEX zoobar2 ON zzoobar")
+box.execute("DROP INDEX zoobar2 ON zzoobar")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE zzoobar")
+box.execute("DROP TABLE zzoobar")
 ---
+- rowcount: 1
 ...
 -- Debug
 -- require("console").start()
diff --git a/test/sql/drop-index.test.lua b/test/sql/drop-index.test.lua
index 2493299..9ce3da0 100644
--- a/test/sql/drop-index.test.lua
+++ b/test/sql/drop-index.test.lua
@@ -1,33 +1,33 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- box.cfg()
 
 -- create space
-box.sql.execute("CREATE TABLE zzoobar (c1 FLOAT, c2 INT PRIMARY KEY, c3 TEXT, c4 FLOAT)")
+box.execute("CREATE TABLE zzoobar (c1 FLOAT, c2 INT PRIMARY KEY, c3 TEXT, c4 FLOAT)")
 
-box.sql.execute("CREATE UNIQUE INDEX zoobar2 ON zzoobar(c1, c4)")
-box.sql.execute("CREATE        INDEX zoobar3 ON zzoobar(c3)")
+box.execute("CREATE UNIQUE INDEX zoobar2 ON zzoobar(c1, c4)")
+box.execute("CREATE        INDEX zoobar3 ON zzoobar(c3)")
 
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zzoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zzoobar VALUES (111, 222, 'c3', 444)")
 
 -- Dummy entry
-box.sql.execute("INSERT INTO zzoobar VALUES (111, 222, 'c3', 444)")
+box.execute("INSERT INTO zzoobar VALUES (111, 222, 'c3', 444)")
 
-box.sql.execute("DROP INDEX zoobar2 ON zzoobar")
-box.sql.execute("DROP INDEX zoobar3 On zzoobar")
+box.execute("DROP INDEX zoobar2 ON zzoobar")
+box.execute("DROP INDEX zoobar3 On zzoobar")
 
 -- zoobar2 is dropped - should be OK
-box.sql.execute("INSERT INTO zzoobar VALUES (111, 223, 'c3', 444)")
+box.execute("INSERT INTO zzoobar VALUES (111, 223, 'c3', 444)")
 
 -- zoobar2 was dropped. Re-creation should  be OK
-box.sql.execute("CREATE INDEX zoobar2 ON zzoobar(c3)")
+box.execute("CREATE INDEX zoobar2 ON zzoobar(c3)")
 
 -- Cleanup
-box.sql.execute("DROP INDEX zoobar2 ON zzoobar")
-box.sql.execute("DROP TABLE zzoobar")
+box.execute("DROP INDEX zoobar2 ON zzoobar")
+box.execute("DROP TABLE zzoobar")
 
 -- Debug
 -- require("console").start()
diff --git a/test/sql/drop-table.result b/test/sql/drop-table.result
index 0e14d8a..f752a92 100644
--- a/test/sql/drop-table.result
+++ b/test/sql/drop-table.result
@@ -4,47 +4,57 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
 -- create space
-box.sql.execute("CREATE TABLE zzzoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
+box.execute("CREATE TABLE zzzoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
 ---
+- rowcount: 1
 ...
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
-box.sql.execute("CREATE INDEX zb ON zzzoobar(c1, c3)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
+box.execute("CREATE INDEX zb ON zzzoobar(c1, c3)")
 ---
+- rowcount: 1
 ...
 -- Dummy entry
-box.sql.execute("INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
+box.execute("INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE zzzoobar")
+box.execute("DROP TABLE zzzoobar")
 ---
+- rowcount: 1
 ...
 -- Table does not exist anymore. Should error here.
-box.sql.execute("INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
+box.execute("INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
 ---
 - error: Space 'ZZZOOBAR' does not exist
 ...
 -- gh-3712: if space features sequence, data from _sequence_data
 -- must be deleted before space is dropped.
 --
-box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY AUTOINCREMENT);")
+box.execute("CREATE TABLE t1 (id INT PRIMARY KEY AUTOINCREMENT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES (NULL);")
+box.execute("INSERT INTO t1 VALUES (NULL);")
 ---
+- autoincrement_ids:
+  - 1
+  rowcount: 1
 ...
 box.snapshot()
 ---
 - ok
 ...
 test_run:cmd('restart server default')
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 1
 ...
 -- Cleanup
 -- DROP TABLE should do the job
@@ -85,12 +95,12 @@ box.session.su('tmp')
 -- Error: user do not have rights to write in box.space._index.
 -- Space that was already created should be automatically dropped.
 --
-box.sql.execute('CREATE TABLE t1 (id INT PRIMARY KEY, a INT)')
+box.execute('CREATE TABLE t1 (id INT PRIMARY KEY, a INT)')
 ---
 - error: Write access to space '_index' is denied for user 'tmp'
 ...
 -- Error: no such table.
-box.sql.execute('DROP TABLE t1')
+box.execute('DROP TABLE t1')
 ---
 - error: Space 'T1' does not exist
 ...
@@ -126,7 +136,7 @@ box.session.su('tmp')
 --
 -- Error: user do not have rights to write in _sequence.
 --
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY AUTOINCREMENT, a INT UNIQUE, b INT UNIQUE, c INT UNIQUE, d INT UNIQUE)')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY AUTOINCREMENT, a INT UNIQUE, b INT UNIQUE, c INT UNIQUE, d INT UNIQUE)')
 ---
 - error: Write access to space '_sequence' is denied for user 'tmp'
 ...
@@ -161,19 +171,21 @@ box.schema.user.grant('tmp', 'write', 'space')
 box.session.su('tmp')
 ---
 ...
-box.sql.execute('CREATE TABLE t3(a INTEGER PRIMARY KEY);')
+box.execute('CREATE TABLE t3(a INTEGER PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
 --
 -- Error: Failed to create foreign key constraint.
 --
-box.sql.execute('CREATE TABLE t4(x INTEGER PRIMARY KEY REFERENCES t3, a INT UNIQUE, c TEXT REFERENCES t3);')
+box.execute('CREATE TABLE t4(x INTEGER PRIMARY KEY REFERENCES t3, a INT UNIQUE, c TEXT REFERENCES t3);')
 ---
 - error: 'Failed to create foreign key constraint ''FK_CONSTRAINT_2_T4'': field type
     mismatch'
 ...
-box.sql.execute('DROP TABLE t3;')
+box.execute('DROP TABLE t3;')
 ---
+- rowcount: 1
 ...
 --
 -- Check that _space, _index and _sequence have the same number of
diff --git a/test/sql/drop-table.test.lua b/test/sql/drop-table.test.lua
index 808e8fe..a310db1 100644
--- a/test/sql/drop-table.test.lua
+++ b/test/sql/drop-table.test.lua
@@ -1,33 +1,33 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- box.cfg()
 
 -- create space
-box.sql.execute("CREATE TABLE zzzoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
+box.execute("CREATE TABLE zzzoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
 
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
 
-box.sql.execute("CREATE INDEX zb ON zzzoobar(c1, c3)")
+box.execute("CREATE INDEX zb ON zzzoobar(c1, c3)")
 
 -- Dummy entry
-box.sql.execute("INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
+box.execute("INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
 
-box.sql.execute("DROP TABLE zzzoobar")
+box.execute("DROP TABLE zzzoobar")
 
 -- Table does not exist anymore. Should error here.
-box.sql.execute("INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
+box.execute("INSERT INTO zzzoobar VALUES (111, 222, 'c3', 444)")
 
 -- gh-3712: if space features sequence, data from _sequence_data
 -- must be deleted before space is dropped.
 --
-box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY AUTOINCREMENT);")
-box.sql.execute("INSERT INTO t1 VALUES (NULL);")
+box.execute("CREATE TABLE t1 (id INT PRIMARY KEY AUTOINCREMENT);")
+box.execute("INSERT INTO t1 VALUES (NULL);")
 box.snapshot()
 test_run:cmd('restart server default')
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 
 -- Cleanup
 -- DROP TABLE should do the job
@@ -56,9 +56,9 @@ box.session.su('tmp')
 -- Error: user do not have rights to write in box.space._index.
 -- Space that was already created should be automatically dropped.
 --
-box.sql.execute('CREATE TABLE t1 (id INT PRIMARY KEY, a INT)')
+box.execute('CREATE TABLE t1 (id INT PRIMARY KEY, a INT)')
 -- Error: no such table.
-box.sql.execute('DROP TABLE t1')
+box.execute('DROP TABLE t1')
 
 box.session.su('admin')
 
@@ -80,7 +80,7 @@ box.session.su('tmp')
 --
 -- Error: user do not have rights to write in _sequence.
 --
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY AUTOINCREMENT, a INT UNIQUE, b INT UNIQUE, c INT UNIQUE, d INT UNIQUE)')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY AUTOINCREMENT, a INT UNIQUE, b INT UNIQUE, c INT UNIQUE, d INT UNIQUE)')
 
 box.session.su('admin')
 
@@ -100,12 +100,12 @@ fk_constraint_count = #box.space._fk_constraint:select()
 box.schema.user.grant('tmp', 'write', 'space')
 box.session.su('tmp')
 
-box.sql.execute('CREATE TABLE t3(a INTEGER PRIMARY KEY);')
+box.execute('CREATE TABLE t3(a INTEGER PRIMARY KEY);')
 --
 -- Error: Failed to create foreign key constraint.
 --
-box.sql.execute('CREATE TABLE t4(x INTEGER PRIMARY KEY REFERENCES t3, a INT UNIQUE, c TEXT REFERENCES t3);')
-box.sql.execute('DROP TABLE t3;')
+box.execute('CREATE TABLE t4(x INTEGER PRIMARY KEY REFERENCES t3, a INT UNIQUE, c TEXT REFERENCES t3);')
+box.execute('DROP TABLE t3;')
 
 --
 -- Check that _space, _index and _sequence have the same number of
diff --git a/test/sql/engine.result b/test/sql/engine.result
index 935383a..bfbde14 100644
--- a/test/sql/engine.result
+++ b/test/sql/engine.result
@@ -4,20 +4,25 @@ env = require('test_run')
 test_run = env.new()
 ---
 ...
-box.sql.execute("pragma sql_default_engine='vinyl'")
+box.execute("pragma sql_default_engine='vinyl'")
 ---
+- rowcount: 0
 ...
-box.sql.execute("CREATE TABLE t1_vinyl(a INT PRIMARY KEY, b INT, c INT);")
+box.execute("CREATE TABLE t1_vinyl(a INT PRIMARY KEY, b INT, c INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2_vinyl(a INT PRIMARY KEY, b INT, c INT);")
+box.execute("CREATE TABLE t2_vinyl(a INT PRIMARY KEY, b INT, c INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("pragma sql_default_engine='memtx'")
+box.execute("pragma sql_default_engine='memtx'")
 ---
+- rowcount: 0
 ...
-box.sql.execute("CREATE TABLE t3_memtx(a INT PRIMARY KEY, b INT, c INT);")
+box.execute("CREATE TABLE t3_memtx(a INT PRIMARY KEY, b INT, c INT);")
 ---
+- rowcount: 1
 ...
 assert(box.space.T1_VINYL.engine == 'vinyl')
 ---
@@ -31,12 +36,15 @@ assert(box.space.T3_MEMTX.engine == 'memtx')
 ---
 - true
 ...
-box.sql.execute("DROP TABLE t1_vinyl;")
+box.execute("DROP TABLE t1_vinyl;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t2_vinyl;")
+box.execute("DROP TABLE t2_vinyl;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t3_memtx;")
+box.execute("DROP TABLE t3_memtx;")
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/engine.test.lua b/test/sql/engine.test.lua
index 2f34b24..51d6939 100644
--- a/test/sql/engine.test.lua
+++ b/test/sql/engine.test.lua
@@ -1,17 +1,17 @@
 env = require('test_run')
 test_run = env.new()
 
-box.sql.execute("pragma sql_default_engine='vinyl'")
-box.sql.execute("CREATE TABLE t1_vinyl(a INT PRIMARY KEY, b INT, c INT);")
-box.sql.execute("CREATE TABLE t2_vinyl(a INT PRIMARY KEY, b INT, c INT);")
+box.execute("pragma sql_default_engine='vinyl'")
+box.execute("CREATE TABLE t1_vinyl(a INT PRIMARY KEY, b INT, c INT);")
+box.execute("CREATE TABLE t2_vinyl(a INT PRIMARY KEY, b INT, c INT);")
 
-box.sql.execute("pragma sql_default_engine='memtx'")
-box.sql.execute("CREATE TABLE t3_memtx(a INT PRIMARY KEY, b INT, c INT);")
+box.execute("pragma sql_default_engine='memtx'")
+box.execute("CREATE TABLE t3_memtx(a INT PRIMARY KEY, b INT, c INT);")
 
 assert(box.space.T1_VINYL.engine == 'vinyl')
 assert(box.space.T2_VINYL.engine == 'vinyl')
 assert(box.space.T3_MEMTX.engine == 'memtx')
 
-box.sql.execute("DROP TABLE t1_vinyl;")
-box.sql.execute("DROP TABLE t2_vinyl;")
-box.sql.execute("DROP TABLE t3_memtx;")
+box.execute("DROP TABLE t1_vinyl;")
+box.execute("DROP TABLE t2_vinyl;")
+box.execute("DROP TABLE t3_memtx;")
diff --git a/test/sql/errinj.result b/test/sql/errinj.result
index a1e7cc4..4b26560 100644
--- a/test/sql/errinj.result
+++ b/test/sql/errinj.result
@@ -7,8 +7,9 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 errinj = box.error.injection
 ---
@@ -18,17 +19,21 @@ fiber = require('fiber')
 ...
 -- gh-3924 Check that tuple_formats of ephemeral spaces are
 -- reused.
-box.sql.execute("CREATE TABLE t4 (id INTEGER PRIMARY KEY, a INTEGER);")
+box.execute("CREATE TABLE t4 (id INTEGER PRIMARY KEY, a INTEGER);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t4 VALUES (1,1)")
+box.execute("INSERT INTO t4 VALUES (1,1)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t4 VALUES (2,1)")
+box.execute("INSERT INTO t4 VALUES (2,1)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t4 VALUES (3,2)")
+box.execute("INSERT INTO t4 VALUES (3,2)")
 ---
+- rowcount: 1
 ...
 errinj.set('ERRINJ_TUPLE_FORMAT_COUNT', 200)
 ---
@@ -38,7 +43,7 @@ errinj.set('ERRINJ_MEMTX_DELAY_GC', true)
 ---
 - ok
 ...
-for i = 1, 201 do box.sql.execute("SELECT DISTINCT a FROM t4") end
+for i = 1, 201 do box.execute("SELECT DISTINCT a FROM t4") end
 ---
 ...
 errinj.set('ERRINJ_MEMTX_DELAY_GC', false)
@@ -49,11 +54,13 @@ errinj.set('ERRINJ_TUPLE_FORMAT_COUNT', -1)
 ---
 - ok
 ...
-box.sql.execute('DROP TABLE t4')
+box.execute('DROP TABLE t4')
 ---
+- rowcount: 1
 ...
-box.sql.execute('create table test (id int primary key, a float, b text)')
+box.execute('create table test (id int primary key, a float, b text)')
 ---
+- rowcount: 1
 ...
 box.schema.user.grant('guest','read,write,execute', 'universe')
 ---
@@ -122,16 +129,18 @@ select_res
 cn:close()
 ---
 ...
-box.sql.execute('drop table test')
+box.execute('drop table test')
 ---
+- rowcount: 1
 ...
 --
 -- gh-3326: after the iproto start using new buffers rotation
 -- policy, SQL responses could be corrupted, when DDL/DML is mixed
 -- with DQL. Same as gh-3255.
 --
-box.sql.execute('CREATE TABLE test (id integer primary key)')
+box.execute('CREATE TABLE test (id integer primary key)')
 ---
+- rowcount: 1
 ...
 cn = remote.connect(box.cfg.listen)
 ---
@@ -156,8 +165,9 @@ errinj.set("ERRINJ_IPROTO_TX_DELAY", false)
 ---
 - ok
 ...
-box.sql.execute('DROP TABLE test')
+box.execute('DROP TABLE test')
 ---
+- rowcount: 1
 ...
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 ---
@@ -165,21 +175,23 @@ box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 ----
 ---- gh-3273: Move SQL TRIGGERs into server.
 ----
-box.sql.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER);");
+box.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER);");
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2(id INTEGER PRIMARY KEY, a INTEGER);");
+box.execute("CREATE TABLE t2(id INTEGER PRIMARY KEY, a INTEGER);");
 ---
+- rowcount: 1
 ...
 box.error.injection.set("ERRINJ_WAL_IO", true)
 ---
 - ok
 ...
-box.sql.execute("CREATE TRIGGER t1t INSERT ON t1 BEGIN INSERT INTO t2 VALUES (1, 1); END;")
+box.execute("CREATE TRIGGER t1t INSERT ON t1 BEGIN INSERT INTO t2 VALUES (1, 1); END;")
 ---
-- error: Failed to write to disk
+- error: 'Error during execution of VDBE byte-code: Failed to write to disk'
 ...
-box.sql.execute("CREATE INDEX t1a ON t1(a);")
+box.execute("CREATE INDEX t1a ON t1(a);")
 ---
 - error: Failed to write to disk
 ...
@@ -187,19 +199,33 @@ box.error.injection.set("ERRINJ_WAL_IO", false)
 ---
 - ok
 ...
-box.sql.execute("CREATE TRIGGER t1t INSERT ON t1 BEGIN INSERT INTO t2 VALUES (1, 1); END;")
+box.execute("CREATE TRIGGER t1t INSERT ON t1 BEGIN INSERT INTO t2 VALUES (1, 1); END;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES (3, 3);")
+box.execute("INSERT INTO t1 VALUES (3, 3);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * from t1");
+box.execute("SELECT * from t1");
 ---
-- - [3, 3]
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: INTEGER
+  rows:
+  - [3, 3]
 ...
-box.sql.execute("SELECT * from t2");
+box.execute("SELECT * from t2");
 ---
-- - [1, 1]
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: INTEGER
+  rows:
+  - [1, 1]
 ...
 box.error.injection.set("ERRINJ_WAL_IO", true)
 ---
@@ -229,42 +255,60 @@ box.error.injection.set("ERRINJ_WAL_IO", true)
 ---
 - ok
 ...
-box.sql.execute("DROP TRIGGER t1t;")
+box.execute("DROP TRIGGER t1t;")
 ---
-- error: Failed to write to disk
+- error: 'Error during execution of VDBE byte-code: Failed to write to disk'
 ...
 box.error.injection.set("ERRINJ_WAL_IO", false)
 ---
 - ok
 ...
-box.sql.execute("DELETE FROM t1;")
+box.execute("DELETE FROM t1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DELETE FROM t2;")
+box.execute("DELETE FROM t2;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES (3, 3);")
+box.execute("INSERT INTO t1 VALUES (3, 3);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * from t1");
+box.execute("SELECT * from t1");
 ---
-- - [3, 3]
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: INTEGER
+  rows:
+  - [3, 3]
 ...
-box.sql.execute("SELECT * from t2");
+box.execute("SELECT * from t2");
 ---
-- - [1, 1]
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: INTEGER
+  rows:
+  - [1, 1]
 ...
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t2;")
 ---
+- rowcount: 1
 ...
 -- Tests which are aimed at verifying work of commit/rollback
 -- triggers on _fk_constraint space.
 --
-box.sql.execute("CREATE TABLE t3 (id FLOAT PRIMARY KEY, a INT REFERENCES t3, b INT UNIQUE);")
+box.execute("CREATE TABLE t3 (id FLOAT PRIMARY KEY, a INT REFERENCES t3, b INT UNIQUE);")
 ---
+- rowcount: 1
 ...
 t = box.space._fk_constraint:select{}[1]:totable()
 ---
@@ -288,15 +332,15 @@ errinj.set("ERRINJ_WAL_IO", false)
 ---
 - ok
 ...
-box.sql.execute("INSERT INTO t3 VALUES (1, 2, 2);")
+box.execute("INSERT INTO t3 VALUES (1, 2, 2);")
 ---
-- error: FOREIGN KEY constraint failed
+- error: 'Error during execution of VDBE byte-code: FOREIGN KEY constraint failed'
 ...
 errinj.set("ERRINJ_WAL_IO", true)
 ---
 - ok
 ...
-box.sql.execute("ALTER TABLE t3 ADD CONSTRAINT fk1 FOREIGN KEY (b) REFERENCES t3;")
+box.execute("ALTER TABLE t3 ADD CONSTRAINT fk1 FOREIGN KEY (b) REFERENCES t3;")
 ---
 - error: Failed to write to disk
 ...
@@ -304,41 +348,45 @@ errinj.set("ERRINJ_WAL_IO", false)
 ---
 - ok
 ...
-box.sql.execute("INSERT INTO t3 VALUES(1, 1, 3);")
+box.execute("INSERT INTO t3 VALUES(1, 1, 3);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DELETE FROM t3;")
+box.execute("DELETE FROM t3;")
 ---
+- rowcount: 1
 ...
 box.snapshot()
 ---
 - ok
 ...
-box.sql.execute("ALTER TABLE t3 ADD CONSTRAINT fk1 FOREIGN KEY (b) REFERENCES t3;")
+box.execute("ALTER TABLE t3 ADD CONSTRAINT fk1 FOREIGN KEY (b) REFERENCES t3;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("INSERT INTO t3 VALUES(1, 1, 3);")
+box.execute("INSERT INTO t3 VALUES(1, 1, 3);")
 ---
-- error: FOREIGN KEY constraint failed
+- error: 'Error during execution of VDBE byte-code: FOREIGN KEY constraint failed'
 ...
 errinj.set("ERRINJ_WAL_IO", true)
 ---
 - ok
 ...
-box.sql.execute("ALTER TABLE t3 DROP CONSTRAINT fk1;")
+box.execute("ALTER TABLE t3 DROP CONSTRAINT fk1;")
 ---
-- error: Failed to write to disk
+- error: 'Error during execution of VDBE byte-code: Failed to write to disk'
 ...
-box.sql.execute("INSERT INTO t3 VALUES(1, 1, 3);")
+box.execute("INSERT INTO t3 VALUES(1, 1, 3);")
 ---
-- error: FOREIGN KEY constraint failed
+- error: 'Error during execution of VDBE byte-code: FOREIGN KEY constraint failed'
 ...
 errinj.set("ERRINJ_WAL_IO", false)
 ---
 - ok
 ...
-box.sql.execute("DROP TABLE t3;")
+box.execute("DROP TABLE t3;")
 ---
+- rowcount: 1
 ...
 -- gh-3780: space without PK raises error if
 -- it is used in SQL queries.
@@ -349,11 +397,13 @@ errinj = box.error.injection
 fiber = require('fiber')
 ---
 ...
-box.sql.execute("CREATE TABLE t (id INT PRIMARY KEY);")
+box.execute("CREATE TABLE t (id INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t VALUES (1);")
+box.execute("INSERT INTO t VALUES (1);")
 ---
+- rowcount: 1
 ...
 errinj.set("ERRINJ_WAL_DELAY", true)
 ---
@@ -365,21 +415,21 @@ errinj.set("ERRINJ_WAL_DELAY", true)
 -- in yield, all operations on space will be blocked due to
 -- absence of primary key.
 --
-function drop_table_yield() box.sql.execute("DROP TABLE t;") end
+function drop_table_yield() box.execute("DROP TABLE t;") end
 ---
 ...
 f = fiber.create(drop_table_yield)
 ---
 ...
-box.sql.execute("SELECT * FROM t;")
+box.execute("SELECT * FROM t;")
 ---
 - error: SQL does not support spaces without primary key
 ...
-box.sql.execute("INSERT INTO t VALUES (2);")
+box.execute("INSERT INTO t VALUES (2);")
 ---
 - error: SQL does not support spaces without primary key
 ...
-box.sql.execute("UPDATE t SET id = 2;")
+box.execute("UPDATE t SET id = 2;")
 ---
 - error: SQL does not support spaces without primary key
 ...
diff --git a/test/sql/errinj.test.lua b/test/sql/errinj.test.lua
index d8833fe..c0c2531 100644
--- a/test/sql/errinj.test.lua
+++ b/test/sql/errinj.test.lua
@@ -1,24 +1,24 @@
 remote = require('net.box')
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 errinj = box.error.injection
 fiber = require('fiber')
 
 -- gh-3924 Check that tuple_formats of ephemeral spaces are
 -- reused.
-box.sql.execute("CREATE TABLE t4 (id INTEGER PRIMARY KEY, a INTEGER);")
-box.sql.execute("INSERT INTO t4 VALUES (1,1)")
-box.sql.execute("INSERT INTO t4 VALUES (2,1)")
-box.sql.execute("INSERT INTO t4 VALUES (3,2)")
+box.execute("CREATE TABLE t4 (id INTEGER PRIMARY KEY, a INTEGER);")
+box.execute("INSERT INTO t4 VALUES (1,1)")
+box.execute("INSERT INTO t4 VALUES (2,1)")
+box.execute("INSERT INTO t4 VALUES (3,2)")
 errinj.set('ERRINJ_TUPLE_FORMAT_COUNT', 200)
 errinj.set('ERRINJ_MEMTX_DELAY_GC', true)
-for i = 1, 201 do box.sql.execute("SELECT DISTINCT a FROM t4") end
+for i = 1, 201 do box.execute("SELECT DISTINCT a FROM t4") end
 errinj.set('ERRINJ_MEMTX_DELAY_GC', false)
 errinj.set('ERRINJ_TUPLE_FORMAT_COUNT', -1)
-box.sql.execute('DROP TABLE t4')
+box.execute('DROP TABLE t4')
 
-box.sql.execute('create table test (id int primary key, a float, b text)')
+box.execute('create table test (id int primary key, a float, b text)')
 box.schema.user.grant('guest','read,write,execute', 'universe')
 cn = remote.connect(box.cfg.listen)
 cn:ping()
@@ -41,14 +41,14 @@ insert_res
 select_res
 
 cn:close()
-box.sql.execute('drop table test')
+box.execute('drop table test')
 
 --
 -- gh-3326: after the iproto start using new buffers rotation
 -- policy, SQL responses could be corrupted, when DDL/DML is mixed
 -- with DQL. Same as gh-3255.
 --
-box.sql.execute('CREATE TABLE test (id integer primary key)')
+box.execute('CREATE TABLE test (id integer primary key)')
 cn = remote.connect(box.cfg.listen)
 
 ch = fiber.channel(200)
@@ -58,22 +58,22 @@ for i = 1, 100 do fiber.create(function() for j = 1, 10 do cn.space.TEST:get{1}
 for i = 1, 200 do ch:get() end
 errinj.set("ERRINJ_IPROTO_TX_DELAY", false)
 
-box.sql.execute('DROP TABLE test')
+box.execute('DROP TABLE test')
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 
 ----
 ---- gh-3273: Move SQL TRIGGERs into server.
 ----
-box.sql.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER);");
-box.sql.execute("CREATE TABLE t2(id INTEGER PRIMARY KEY, a INTEGER);");
+box.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER);");
+box.execute("CREATE TABLE t2(id INTEGER PRIMARY KEY, a INTEGER);");
 box.error.injection.set("ERRINJ_WAL_IO", true)
-box.sql.execute("CREATE TRIGGER t1t INSERT ON t1 BEGIN INSERT INTO t2 VALUES (1, 1); END;")
-box.sql.execute("CREATE INDEX t1a ON t1(a);")
+box.execute("CREATE TRIGGER t1t INSERT ON t1 BEGIN INSERT INTO t2 VALUES (1, 1); END;")
+box.execute("CREATE INDEX t1a ON t1(a);")
 box.error.injection.set("ERRINJ_WAL_IO", false)
-box.sql.execute("CREATE TRIGGER t1t INSERT ON t1 BEGIN INSERT INTO t2 VALUES (1, 1); END;")
-box.sql.execute("INSERT INTO t1 VALUES (3, 3);")
-box.sql.execute("SELECT * from t1");
-box.sql.execute("SELECT * from t2");
+box.execute("CREATE TRIGGER t1t INSERT ON t1 BEGIN INSERT INTO t2 VALUES (1, 1); END;")
+box.execute("INSERT INTO t1 VALUES (3, 3);")
+box.execute("SELECT * from t1");
+box.execute("SELECT * from t2");
 box.error.injection.set("ERRINJ_WAL_IO", true)
 t = box.space._trigger:get('T1T')
 t_new = t:totable()
@@ -82,20 +82,20 @@ _ = box.space._trigger:replace(t, t_new)
 box.error.injection.set("ERRINJ_WAL_IO", false)
 _ = box.space._trigger:replace(t, t_new)
 box.error.injection.set("ERRINJ_WAL_IO", true)
-box.sql.execute("DROP TRIGGER t1t;")
+box.execute("DROP TRIGGER t1t;")
 box.error.injection.set("ERRINJ_WAL_IO", false)
-box.sql.execute("DELETE FROM t1;")
-box.sql.execute("DELETE FROM t2;")
-box.sql.execute("INSERT INTO t1 VALUES (3, 3);")
-box.sql.execute("SELECT * from t1");
-box.sql.execute("SELECT * from t2");
-box.sql.execute("DROP TABLE t1;")
-box.sql.execute("DROP TABLE t2;")
+box.execute("DELETE FROM t1;")
+box.execute("DELETE FROM t2;")
+box.execute("INSERT INTO t1 VALUES (3, 3);")
+box.execute("SELECT * from t1");
+box.execute("SELECT * from t2");
+box.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t2;")
 
 -- Tests which are aimed at verifying work of commit/rollback
 -- triggers on _fk_constraint space.
 --
-box.sql.execute("CREATE TABLE t3 (id FLOAT PRIMARY KEY, a INT REFERENCES t3, b INT UNIQUE);")
+box.execute("CREATE TABLE t3 (id FLOAT PRIMARY KEY, a INT REFERENCES t3, b INT UNIQUE);")
 t = box.space._fk_constraint:select{}[1]:totable()
 errinj = box.error.injection
 errinj.set("ERRINJ_WAL_IO", true)
@@ -103,28 +103,28 @@ errinj.set("ERRINJ_WAL_IO", true)
 t[9] = {2}
 box.space._fk_constraint:replace(t)
 errinj.set("ERRINJ_WAL_IO", false)
-box.sql.execute("INSERT INTO t3 VALUES (1, 2, 2);")
+box.execute("INSERT INTO t3 VALUES (1, 2, 2);")
 errinj.set("ERRINJ_WAL_IO", true)
-box.sql.execute("ALTER TABLE t3 ADD CONSTRAINT fk1 FOREIGN KEY (b) REFERENCES t3;")
+box.execute("ALTER TABLE t3 ADD CONSTRAINT fk1 FOREIGN KEY (b) REFERENCES t3;")
 errinj.set("ERRINJ_WAL_IO", false)
-box.sql.execute("INSERT INTO t3 VALUES(1, 1, 3);")
-box.sql.execute("DELETE FROM t3;")
+box.execute("INSERT INTO t3 VALUES(1, 1, 3);")
+box.execute("DELETE FROM t3;")
 box.snapshot()
-box.sql.execute("ALTER TABLE t3 ADD CONSTRAINT fk1 FOREIGN KEY (b) REFERENCES t3;")
-box.sql.execute("INSERT INTO t3 VALUES(1, 1, 3);")
+box.execute("ALTER TABLE t3 ADD CONSTRAINT fk1 FOREIGN KEY (b) REFERENCES t3;")
+box.execute("INSERT INTO t3 VALUES(1, 1, 3);")
 errinj.set("ERRINJ_WAL_IO", true)
-box.sql.execute("ALTER TABLE t3 DROP CONSTRAINT fk1;")
-box.sql.execute("INSERT INTO t3 VALUES(1, 1, 3);")
+box.execute("ALTER TABLE t3 DROP CONSTRAINT fk1;")
+box.execute("INSERT INTO t3 VALUES(1, 1, 3);")
 errinj.set("ERRINJ_WAL_IO", false)
-box.sql.execute("DROP TABLE t3;")
+box.execute("DROP TABLE t3;")
 
 -- gh-3780: space without PK raises error if
 -- it is used in SQL queries.
 --
 errinj = box.error.injection
 fiber = require('fiber')
-box.sql.execute("CREATE TABLE t (id INT PRIMARY KEY);")
-box.sql.execute("INSERT INTO t VALUES (1);")
+box.execute("CREATE TABLE t (id INT PRIMARY KEY);")
+box.execute("INSERT INTO t VALUES (1);")
 errinj.set("ERRINJ_WAL_DELAY", true)
 -- DROP TABLE consists of several steps: firstly indexes
 -- are deleted, then space itself. Lets make sure that if
@@ -132,10 +132,10 @@ errinj.set("ERRINJ_WAL_DELAY", true)
 -- in yield, all operations on space will be blocked due to
 -- absence of primary key.
 --
-function drop_table_yield() box.sql.execute("DROP TABLE t;") end
+function drop_table_yield() box.execute("DROP TABLE t;") end
 f = fiber.create(drop_table_yield)
-box.sql.execute("SELECT * FROM t;")
-box.sql.execute("INSERT INTO t VALUES (2);")
-box.sql.execute("UPDATE t SET id = 2;")
+box.execute("SELECT * FROM t;")
+box.execute("INSERT INTO t VALUES (2);")
+box.execute("UPDATE t SET id = 2;")
 -- Finish drop space.
 errinj.set("ERRINJ_WAL_DELAY", false)
diff --git a/test/sql/foreign-keys.result b/test/sql/foreign-keys.result
index 3c6464e..293492e 100644
--- a/test/sql/foreign-keys.result
+++ b/test/sql/foreign-keys.result
@@ -8,17 +8,21 @@ test_run:cmd('restart server default with cleanup=1')
 -- Check that tuple inserted into _fk_constraint is FK constrains
 -- valid data.
 --
-box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b INT);")
+box.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE UNIQUE INDEX i1 ON t1(a);")
+box.execute("CREATE UNIQUE INDEX i1 ON t1(a);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2 (a INT, b INT, id INT PRIMARY KEY);")
+box.execute("CREATE TABLE t2 (a INT, b INT, id INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
+box.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
 ---
+- rowcount: 1
 ...
 -- Parent and child spaces must exist.
 --
@@ -56,8 +60,9 @@ box.space._fk_constraint:insert(t)
 - error: 'Failed to create foreign key constraint ''fk_1'': referencing space can''t
     be VIEW'
 ...
-box.sql.execute("DROP VIEW v1;")
+box.execute("DROP VIEW v1;")
 ---
+- rowcount: 1
 ...
 -- Match clause can be only one of: simple, partial, full.
 --
@@ -87,8 +92,9 @@ box.space._fk_constraint:insert(t)
 -- Temporary restriction (until SQL triggers work from Lua):
 -- referencing space must be empty.
 --
-box.sql.execute("INSERT INTO t2 VALUES (1, 2, 3);")
+box.execute("INSERT INTO t2 VALUES (1, 2, 3);")
 ---
+- rowcount: 1
 ...
 t = {'fk_1', child_id, parent_id, false, 'simple', 'restrict', 'restrict', {2}, {1}}
 ---
@@ -98,8 +104,9 @@ box.space._fk_constraint:insert(t)
 - error: 'Failed to create foreign key constraint ''fk_1'': referencing space must
     be empty'
 ...
-box.sql.execute("DELETE FROM t2;")
+box.execute("DELETE FROM t2;")
 ---
+- rowcount: 1
 ...
 -- Links must be specififed correctly.
 --
@@ -172,9 +179,10 @@ t = box.space._fk_constraint:insert(t)
 -- Implicitly referenced index can't be dropped,
 -- ergo - space can't be dropped until it is referenced.
 --
-box.sql.execute("DROP INDEX i1 on t1;")
+box.execute("DROP INDEX i1 on t1;")
 ---
-- error: 'Can''t modify space ''T1'': can not drop a referenced index'
+- error: 'Error during execution of VDBE byte-code: Can''t modify space ''T1'': can
+    not drop a referenced index'
 ...
 -- Referenced index can't be altered as well, if alter leads to
 -- rebuild of index (e.g. index still can be renamed).
@@ -213,11 +221,13 @@ box.space.T1:drop()
 -- Create several constraints to make sure that they are held
 -- as linked lists correctly including self-referencing constraints.
 --
-box.sql.execute("CREATE TABLE child (id INT PRIMARY KEY, a INT);")
+box.execute("CREATE TABLE child (id INT PRIMARY KEY, a INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE parent (a INT, id INT PRIMARY KEY);")
+box.execute("CREATE TABLE parent (a INT, id INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
 parent_id = box.space._space.index.name:select('PARENT')[1]['id']
 ---
@@ -330,14 +340,17 @@ box.space.PARENT:drop()
 -- Check that parser correctly handles MATCH, ON DELETE and
 -- ON UPDATE clauses.
 --
-box.sql.execute('CREATE TABLE tp (id INT PRIMARY KEY, a INT UNIQUE)')
+box.execute('CREATE TABLE tp (id INT PRIMARY KEY, a INT UNIQUE)')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE TABLE tc (id INT PRIMARY KEY, a INT REFERENCES tp(a) MATCH FULL ON DELETE SET NULL)')
+box.execute('CREATE TABLE tc (id INT PRIMARY KEY, a INT REFERENCES tp(a) MATCH FULL ON DELETE SET NULL)')
 ---
+- rowcount: 1
 ...
-box.sql.execute('ALTER TABLE tc ADD CONSTRAINT fk1 FOREIGN KEY (id) REFERENCES tp(id) MATCH PARTIAL ON DELETE CASCADE ON UPDATE SET NULL')
+box.execute('ALTER TABLE tc ADD CONSTRAINT fk1 FOREIGN KEY (id) REFERENCES tp(id) MATCH PARTIAL ON DELETE CASCADE ON UPDATE SET NULL')
 ---
+- rowcount: 0
 ...
 box.space._fk_constraint:select{}
 ---
@@ -345,32 +358,35 @@ box.space._fk_constraint:select{}
   - ['FK_CONSTRAINT_1_TC', 518, 517, false, 'full', 'set_null', 'no_action', [1],
     [1]]
 ...
-box.sql.execute('DROP TABLE tc')
+box.execute('DROP TABLE tc')
 ---
+- rowcount: 1
 ...
-box.sql.execute('DROP TABLE tp')
+box.execute('DROP TABLE tp')
 ---
+- rowcount: 1
 ...
 -- gh-3475: ON UPDATE and ON DELETE clauses must appear once;
 -- MATCH clause must come first.
-box.sql.execute('CREATE TABLE t1 (id INT PRIMARY KEY);')
+box.execute('CREATE TABLE t1 (id INT PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON DELETE RESTRICT);')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON DELETE RESTRICT);')
 ---
 - error: Keyword 'DELETE' is reserved. Please use double quotes if 'DELETE' is an
     identifier.
 ...
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON DELETE CASCADE);')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON DELETE CASCADE);')
 ---
 - error: Keyword 'DELETE' is reserved. Please use double quotes if 'DELETE' is an
     identifier.
 ...
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON UPDATE RESTRICT ON DELETE RESTRICT);')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON UPDATE RESTRICT ON DELETE RESTRICT);')
 ---
 - error: Keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.
 ...
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE MATCH FULL);')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE MATCH FULL);')
 ---
 - error: Keyword 'MATCH' is reserved. Please use double quotes if 'MATCH' is an identifier.
 ...
diff --git a/test/sql/foreign-keys.test.lua b/test/sql/foreign-keys.test.lua
index 3fb7cab..da0986d 100644
--- a/test/sql/foreign-keys.test.lua
+++ b/test/sql/foreign-keys.test.lua
@@ -6,10 +6,10 @@ test_run:cmd('restart server default with cleanup=1')
 -- Check that tuple inserted into _fk_constraint is FK constrains
 -- valid data.
 --
-box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b INT);")
-box.sql.execute("CREATE UNIQUE INDEX i1 ON t1(a);")
-box.sql.execute("CREATE TABLE t2 (a INT, b INT, id INT PRIMARY KEY);")
-box.sql.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
+box.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b INT);")
+box.execute("CREATE UNIQUE INDEX i1 ON t1(a);")
+box.execute("CREATE TABLE t2 (a INT, b INT, id INT PRIMARY KEY);")
+box.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
 
 -- Parent and child spaces must exist.
 --
@@ -26,7 +26,7 @@ t = {'fk_1', child_id, view_id, false, 'simple', 'restrict', 'restrict', {0}, {1
 box.space._fk_constraint:insert(t)
 t = {'fk_1', view_id, parent_id, false, 'simple', 'restrict', 'restrict', {0}, {1}}
 box.space._fk_constraint:insert(t)
-box.sql.execute("DROP VIEW v1;")
+box.execute("DROP VIEW v1;")
 
 -- Match clause can be only one of: simple, partial, full.
 --
@@ -43,10 +43,10 @@ box.space._fk_constraint:insert(t)
 -- Temporary restriction (until SQL triggers work from Lua):
 -- referencing space must be empty.
 --
-box.sql.execute("INSERT INTO t2 VALUES (1, 2, 3);")
+box.execute("INSERT INTO t2 VALUES (1, 2, 3);")
 t = {'fk_1', child_id, parent_id, false, 'simple', 'restrict', 'restrict', {2}, {1}}
 box.space._fk_constraint:insert(t)
-box.sql.execute("DELETE FROM t2;")
+box.execute("DELETE FROM t2;")
 
 -- Links must be specififed correctly.
 --
@@ -84,7 +84,7 @@ t = box.space._fk_constraint:insert(t)
 -- Implicitly referenced index can't be dropped,
 -- ergo - space can't be dropped until it is referenced.
 --
-box.sql.execute("DROP INDEX i1 on t1;")
+box.execute("DROP INDEX i1 on t1;")
 
 -- Referenced index can't be altered as well, if alter leads to
 -- rebuild of index (e.g. index still can be renamed).
@@ -108,8 +108,8 @@ box.space.T1:drop()
 -- Create several constraints to make sure that they are held
 -- as linked lists correctly including self-referencing constraints.
 --
-box.sql.execute("CREATE TABLE child (id INT PRIMARY KEY, a INT);")
-box.sql.execute("CREATE TABLE parent (a INT, id INT PRIMARY KEY);")
+box.execute("CREATE TABLE child (id INT PRIMARY KEY, a INT);")
+box.execute("CREATE TABLE parent (a INT, id INT PRIMARY KEY);")
 
 parent_id = box.space._space.index.name:select('PARENT')[1]['id']
 child_id = box.space._space.index.name:select('CHILD')[1]['id']
@@ -153,20 +153,20 @@ box.space.PARENT:drop()
 -- Check that parser correctly handles MATCH, ON DELETE and
 -- ON UPDATE clauses.
 --
-box.sql.execute('CREATE TABLE tp (id INT PRIMARY KEY, a INT UNIQUE)')
-box.sql.execute('CREATE TABLE tc (id INT PRIMARY KEY, a INT REFERENCES tp(a) MATCH FULL ON DELETE SET NULL)')
-box.sql.execute('ALTER TABLE tc ADD CONSTRAINT fk1 FOREIGN KEY (id) REFERENCES tp(id) MATCH PARTIAL ON DELETE CASCADE ON UPDATE SET NULL')
+box.execute('CREATE TABLE tp (id INT PRIMARY KEY, a INT UNIQUE)')
+box.execute('CREATE TABLE tc (id INT PRIMARY KEY, a INT REFERENCES tp(a) MATCH FULL ON DELETE SET NULL)')
+box.execute('ALTER TABLE tc ADD CONSTRAINT fk1 FOREIGN KEY (id) REFERENCES tp(id) MATCH PARTIAL ON DELETE CASCADE ON UPDATE SET NULL')
 box.space._fk_constraint:select{}
-box.sql.execute('DROP TABLE tc')
-box.sql.execute('DROP TABLE tp')
+box.execute('DROP TABLE tc')
+box.execute('DROP TABLE tp')
 
 -- gh-3475: ON UPDATE and ON DELETE clauses must appear once;
 -- MATCH clause must come first.
-box.sql.execute('CREATE TABLE t1 (id INT PRIMARY KEY);')
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON DELETE RESTRICT);')
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON DELETE CASCADE);')
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON UPDATE RESTRICT ON DELETE RESTRICT);')
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE MATCH FULL);')
+box.execute('CREATE TABLE t1 (id INT PRIMARY KEY);')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON DELETE RESTRICT);')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON DELETE CASCADE);')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE ON UPDATE RESTRICT ON DELETE RESTRICT);')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY REFERENCES t2 ON DELETE CASCADE MATCH FULL);')
 box.space.T1:drop()
 
 --- Clean-up SQL DD hash.
diff --git a/test/sql/func-recreate.result b/test/sql/func-recreate.result
index 22e169b..85c2c9c 100644
--- a/test/sql/func-recreate.result
+++ b/test/sql/func-recreate.result
@@ -4,8 +4,9 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- Check errors during function create process
 fiber = require('fiber')
@@ -17,7 +18,7 @@ box.internal.sql_create_function('WAITFOR', 'INT', function (n) fiber.sleep(n) r
 ch = fiber.channel(1)
 ---
 ...
-_ = fiber.create(function () ch:put(box.sql.execute('select WAITFOR(0.2)')) end)
+_ = fiber.create(function () ch:put(box.execute('select WAITFOR(0.2)')) end)
 ---
 ...
 fiber.sleep(0.1)
@@ -29,7 +30,11 @@ box.internal.sql_create_function('WAITFOR', 'INT', function (n) require('fiber')
 ...
 ch:get()
 ---
-- - [0.2]
+- metadata:
+  - name: WAITFOR(0.2)
+    type: INTEGER
+  rows:
+  - [0.2]
 ...
 box.internal.sql_create_function('WAITFOR', 'INT', function (n) require('fiber').sleep(n) return n end)
 ---
diff --git a/test/sql/func-recreate.test.lua b/test/sql/func-recreate.test.lua
index b4e1fbe..753e9ca 100644
--- a/test/sql/func-recreate.test.lua
+++ b/test/sql/func-recreate.test.lua
@@ -1,6 +1,6 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- Check errors during function create process
 fiber = require('fiber')
@@ -8,7 +8,7 @@ box.internal.sql_create_function('WAITFOR', 'INT', function (n) fiber.sleep(n) r
 
 ch = fiber.channel(1)
 
-_ = fiber.create(function () ch:put(box.sql.execute('select WAITFOR(0.2)')) end)
+_ = fiber.create(function () ch:put(box.execute('select WAITFOR(0.2)')) end)
 fiber.sleep(0.1)
 
 box.internal.sql_create_function('WAITFOR', 'INT', function (n) require('fiber').sleep(n) return n end)
diff --git a/test/sql/gh-2347-max-int-literals.result b/test/sql/gh-2347-max-int-literals.result
index c289a80..635a9bc 100644
--- a/test/sql/gh-2347-max-int-literals.result
+++ b/test/sql/gh-2347-max-int-literals.result
@@ -4,25 +4,34 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 box.cfg{}
 ---
 ...
-box.sql.execute("select (9223372036854775807)")
+box.execute("select (9223372036854775807)")
 ---
-- - [9223372036854775807]
+- metadata:
+  - name: (9223372036854775807)
+    type: INTEGER
+  rows:
+  - [9223372036854775807]
 ...
-box.sql.execute("select (-9223372036854775808)")
+box.execute("select (-9223372036854775808)")
 ---
-- - [-9223372036854775808]
+- metadata:
+  - name: (-9223372036854775808)
+    type: NUMERIC
+  rows:
+  - [-9223372036854775808]
 ...
-box.sql.execute("select (9223372036854775808)")
+box.execute("select (9223372036854775808)")
 ---
 - error: 'oversized integer: 9223372036854775808'
 ...
-box.sql.execute("select (-9223372036854775809)")
+box.execute("select (-9223372036854775809)")
 ---
 - error: 'oversized integer: -9223372036854775809'
 ...
diff --git a/test/sql/gh-2347-max-int-literals.test.lua b/test/sql/gh-2347-max-int-literals.test.lua
index 4b1ef0d..8331f03 100644
--- a/test/sql/gh-2347-max-int-literals.test.lua
+++ b/test/sql/gh-2347-max-int-literals.test.lua
@@ -1,11 +1,11 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 box.cfg{}
 
-box.sql.execute("select (9223372036854775807)")
-box.sql.execute("select (-9223372036854775808)")
+box.execute("select (9223372036854775807)")
+box.execute("select (-9223372036854775808)")
 
-box.sql.execute("select (9223372036854775808)")
-box.sql.execute("select (-9223372036854775809)")
+box.execute("select (9223372036854775808)")
+box.execute("select (-9223372036854775809)")
diff --git a/test/sql/gh-2362-select-access-rights.result b/test/sql/gh-2362-select-access-rights.result
index 8f1ecfa..c6026c1 100644
--- a/test/sql/gh-2362-select-access-rights.result
+++ b/test/sql/gh-2362-select-access-rights.result
@@ -7,20 +7,25 @@ engine = test_run:get_cfg('engine')
 nb = require('net.box')
 ---
 ...
-box.sql.execute("PRAGMA sql_default_engine='"..engine.."'")
+box.execute("PRAGMA sql_default_engine='"..engine.."'")
 ---
+- rowcount: 0
 ...
-box.sql.execute("CREATE TABLE t1 (s1 INT PRIMARY KEY, s2 INT UNIQUE);")
+box.execute("CREATE TABLE t1 (s1 INT PRIMARY KEY, s2 INT UNIQUE);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);")
+box.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES (1, 1);")
+box.execute("INSERT INTO t1 VALUES (1, 1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t2 VALUES (1);")
+box.execute("INSERT INTO t2 VALUES (1);")
 ---
+- rowcount: 1
 ...
 box.schema.user.grant('guest','read', 'space', 'T1')
 ---
@@ -58,8 +63,9 @@ c:execute('SELECT * FROM t1, t2 WHERE t1.s1 = t2.s1')
 ---
 - error: Read access to space 'T1' is denied for user 'guest'
 ...
-box.sql.execute("CREATE VIEW v AS SELECT * FROM t1")
+box.execute("CREATE VIEW v AS SELECT * FROM t1")
 ---
+- rowcount: 1
 ...
 box.schema.user.grant('guest','read', 'space', 'V')
 ---
@@ -71,8 +77,9 @@ c:execute('SELECT * FROM v')
 ---
 - error: Read access to space 'T1' is denied for user 'guest'
 ...
-box.sql.execute('CREATE TABLE t3 (s1 INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES t1(s2))')
+box.execute('CREATE TABLE t3 (s1 INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES t1(s2))')
 ---
+- rowcount: 1
 ...
 box.schema.user.grant('guest','read','space', 'T3')
 ---
@@ -94,15 +101,19 @@ box.schema.user.revoke('guest','read','space', 'T2')
 box.schema.user.revoke('guest','read','space', 'T3')
 ---
 ...
-box.sql.execute('DROP VIEW v')
+box.execute('DROP VIEW v')
 ---
+- rowcount: 1
 ...
-box.sql.execute('DROP TABLE t3')
+box.execute('DROP TABLE t3')
 ---
+- rowcount: 1
 ...
-box.sql.execute('DROP TABLE t2')
+box.execute('DROP TABLE t2')
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t1")
+box.execute("DROP TABLE t1")
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/gh-2362-select-access-rights.test.lua b/test/sql/gh-2362-select-access-rights.test.lua
index 9c50e19..f2b66b6 100644
--- a/test/sql/gh-2362-select-access-rights.test.lua
+++ b/test/sql/gh-2362-select-access-rights.test.lua
@@ -2,11 +2,11 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 nb = require('net.box')
 
-box.sql.execute("PRAGMA sql_default_engine='"..engine.."'")
-box.sql.execute("CREATE TABLE t1 (s1 INT PRIMARY KEY, s2 INT UNIQUE);")
-box.sql.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);")
-box.sql.execute("INSERT INTO t1 VALUES (1, 1);")
-box.sql.execute("INSERT INTO t2 VALUES (1);")
+box.execute("PRAGMA sql_default_engine='"..engine.."'")
+box.execute("CREATE TABLE t1 (s1 INT PRIMARY KEY, s2 INT UNIQUE);")
+box.execute("CREATE TABLE t2 (s1 INT PRIMARY KEY);")
+box.execute("INSERT INTO t1 VALUES (1, 1);")
+box.execute("INSERT INTO t2 VALUES (1);")
 
 box.schema.user.grant('guest','read', 'space', 'T1')
 c = nb.connect(box.cfg.listen)
@@ -20,13 +20,13 @@ box.schema.user.grant('guest','read', 'space', 'T2')
 c = nb.connect(box.cfg.listen)
 c:execute('SELECT * FROM t1, t2 WHERE t1.s1 = t2.s1')
 
-box.sql.execute("CREATE VIEW v AS SELECT * FROM t1")
+box.execute("CREATE VIEW v AS SELECT * FROM t1")
 
 box.schema.user.grant('guest','read', 'space', 'V')
 v = nb.connect(box.cfg.listen)
 c:execute('SELECT * FROM v')
 
-box.sql.execute('CREATE TABLE t3 (s1 INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES t1(s2))')
+box.execute('CREATE TABLE t3 (s1 INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES t1(s2))')
 box.schema.user.grant('guest','read','space', 'T3')
 v = nb.connect(box.cfg.listen)
 c:execute('INSERT INTO t3 VALUES (1, 1)')
@@ -36,7 +36,7 @@ box.schema.user.revoke('guest','read','space', 'V')
 box.schema.user.revoke('guest','read','space', 'T2')
 box.schema.user.revoke('guest','read','space', 'T3')
 
-box.sql.execute('DROP VIEW v')
-box.sql.execute('DROP TABLE t3')
-box.sql.execute('DROP TABLE t2')
-box.sql.execute("DROP TABLE t1")
+box.execute('DROP VIEW v')
+box.execute('DROP TABLE t3')
+box.execute('DROP TABLE t2')
+box.execute("DROP TABLE t1")
diff --git a/test/sql/gh-2929-primary-key.result b/test/sql/gh-2929-primary-key.result
index 4052665..1e01041 100644
--- a/test/sql/gh-2929-primary-key.result
+++ b/test/sql/gh-2929-primary-key.result
@@ -4,8 +4,9 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- All tables in SQL are now WITHOUT ROW ID, so if user
 -- tries to create table without a primary key, an appropriate error message
@@ -13,32 +14,34 @@ box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
 box.cfg{}
 ---
 ...
-box.sql.execute("CREATE TABLE t1(a INT PRIMARY KEY, b INT UNIQUE)")
+box.execute("CREATE TABLE t1(a INT PRIMARY KEY, b INT UNIQUE)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2(a INT UNIQUE, b INT)")
+box.execute("CREATE TABLE t2(a INT UNIQUE, b INT)")
 ---
 - error: PRIMARY KEY missing on table T2
 ...
-box.sql.execute("CREATE TABLE t3(a FLOAT)")
+box.execute("CREATE TABLE t3(a FLOAT)")
 ---
 - error: PRIMARY KEY missing on table T3
 ...
-box.sql.execute("CREATE TABLE t4(a FLOAT, b TEXT)")
+box.execute("CREATE TABLE t4(a FLOAT, b TEXT)")
 ---
 - error: PRIMARY KEY missing on table T4
 ...
-box.sql.execute("CREATE TABLE t5(a FLOAT, b FLOAT UNIQUE)")
+box.execute("CREATE TABLE t5(a FLOAT, b FLOAT UNIQUE)")
 ---
 - error: PRIMARY KEY missing on table T5
 ...
-box.sql.execute("DROP TABLE t1")
+box.execute("DROP TABLE t1")
 ---
+- rowcount: 1
 ...
 --
 -- gh-3522: invalid primary key name
 --
-box.sql.execute("CREATE TABLE tx (a INT, PRIMARY KEY (b));")
+box.execute("CREATE TABLE tx (a INT, PRIMARY KEY (b));")
 ---
 - error: Can’t resolve field 'B'
 ...
diff --git a/test/sql/gh-2929-primary-key.test.lua b/test/sql/gh-2929-primary-key.test.lua
index 6c2f0eb..870e65a 100644
--- a/test/sql/gh-2929-primary-key.test.lua
+++ b/test/sql/gh-2929-primary-key.test.lua
@@ -1,6 +1,6 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- All tables in SQL are now WITHOUT ROW ID, so if user
 -- tries to create table without a primary key, an appropriate error message
@@ -8,16 +8,16 @@ box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
 
 box.cfg{}
 
-box.sql.execute("CREATE TABLE t1(a INT PRIMARY KEY, b INT UNIQUE)")
-box.sql.execute("CREATE TABLE t2(a INT UNIQUE, b INT)")
+box.execute("CREATE TABLE t1(a INT PRIMARY KEY, b INT UNIQUE)")
+box.execute("CREATE TABLE t2(a INT UNIQUE, b INT)")
 
-box.sql.execute("CREATE TABLE t3(a FLOAT)")
-box.sql.execute("CREATE TABLE t4(a FLOAT, b TEXT)")
-box.sql.execute("CREATE TABLE t5(a FLOAT, b FLOAT UNIQUE)")
+box.execute("CREATE TABLE t3(a FLOAT)")
+box.execute("CREATE TABLE t4(a FLOAT, b TEXT)")
+box.execute("CREATE TABLE t5(a FLOAT, b FLOAT UNIQUE)")
 
-box.sql.execute("DROP TABLE t1")
+box.execute("DROP TABLE t1")
 
 --
 -- gh-3522: invalid primary key name
 --
-box.sql.execute("CREATE TABLE tx (a INT, PRIMARY KEY (b));")
+box.execute("CREATE TABLE tx (a INT, PRIMARY KEY (b));")
diff --git a/test/sql/gh-2981-check-autoinc.result b/test/sql/gh-2981-check-autoinc.result
index b0f55e6..00bfe91 100644
--- a/test/sql/gh-2981-check-autoinc.result
+++ b/test/sql/gh-2981-check-autoinc.result
@@ -4,55 +4,66 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 box.cfg{}
 ---
 ...
-box.sql.execute("CREATE TABLE t1 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 <> 19));");
+box.execute("CREATE TABLE t1 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 <> 19));");
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 <> 19 AND s1 <> 25));");
+box.execute("CREATE TABLE t2 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 <> 19 AND s1 <> 25));");
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t3 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 < 10));");
+box.execute("CREATE TABLE t3 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 < 10));");
 ---
+- rowcount: 1
 ...
-box.sql.execute("insert into t1 values (18, null);")
+box.execute("insert into t1 values (18, null);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("insert into t1(s2) values (null);")
+box.execute("insert into t1(s2) values (null);")
 ---
-- error: 'CHECK constraint failed: T1'
+- error: 'Error during execution of VDBE byte-code: CHECK constraint failed: T1'
 ...
-box.sql.execute("insert into t2 values (18, null);")
+box.execute("insert into t2 values (18, null);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("insert into t2(s2) values (null);")
+box.execute("insert into t2(s2) values (null);")
 ---
-- error: 'CHECK constraint failed: T2'
+- error: 'Error during execution of VDBE byte-code: CHECK constraint failed: T2'
 ...
-box.sql.execute("insert into t2 values (24, null);")
+box.execute("insert into t2 values (24, null);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("insert into t2(s2) values (null);")
+box.execute("insert into t2(s2) values (null);")
 ---
-- error: 'CHECK constraint failed: T2'
+- error: 'Error during execution of VDBE byte-code: CHECK constraint failed: T2'
 ...
-box.sql.execute("insert into t3 values (9, null)")
+box.execute("insert into t3 values (9, null)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("insert into t3(s2) values (null)")
+box.execute("insert into t3(s2) values (null)")
 ---
-- error: 'CHECK constraint failed: T3'
+- error: 'Error during execution of VDBE byte-code: CHECK constraint failed: T3'
 ...
-box.sql.execute("DROP TABLE t1")
+box.execute("DROP TABLE t1")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t2")
+box.execute("DROP TABLE t2")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t3")
+box.execute("DROP TABLE t3")
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/gh-2981-check-autoinc.test.lua b/test/sql/gh-2981-check-autoinc.test.lua
index 98a5fb4..0eb8f73 100644
--- a/test/sql/gh-2981-check-autoinc.test.lua
+++ b/test/sql/gh-2981-check-autoinc.test.lua
@@ -1,25 +1,25 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 box.cfg{}
 
-box.sql.execute("CREATE TABLE t1 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 <> 19));");
-box.sql.execute("CREATE TABLE t2 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 <> 19 AND s1 <> 25));");
-box.sql.execute("CREATE TABLE t3 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 < 10));");
+box.execute("CREATE TABLE t1 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 <> 19));");
+box.execute("CREATE TABLE t2 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 <> 19 AND s1 <> 25));");
+box.execute("CREATE TABLE t3 (s1 INTEGER PRIMARY KEY AUTOINCREMENT, s2 INTEGER, CHECK (s1 < 10));");
 
-box.sql.execute("insert into t1 values (18, null);")
-box.sql.execute("insert into t1(s2) values (null);")
+box.execute("insert into t1 values (18, null);")
+box.execute("insert into t1(s2) values (null);")
 
-box.sql.execute("insert into t2 values (18, null);")
-box.sql.execute("insert into t2(s2) values (null);")
-box.sql.execute("insert into t2 values (24, null);")
-box.sql.execute("insert into t2(s2) values (null);")
+box.execute("insert into t2 values (18, null);")
+box.execute("insert into t2(s2) values (null);")
+box.execute("insert into t2 values (24, null);")
+box.execute("insert into t2(s2) values (null);")
 
-box.sql.execute("insert into t3 values (9, null)")
-box.sql.execute("insert into t3(s2) values (null)")
+box.execute("insert into t3 values (9, null)")
+box.execute("insert into t3(s2) values (null)")
 
-box.sql.execute("DROP TABLE t1")
-box.sql.execute("DROP TABLE t2")
-box.sql.execute("DROP TABLE t3")
+box.execute("DROP TABLE t1")
+box.execute("DROP TABLE t2")
+box.execute("DROP TABLE t3")
 
diff --git a/test/sql/gh-3199-no-mem-leaks.result b/test/sql/gh-3199-no-mem-leaks.result
index fff6abf..759645b 100644
--- a/test/sql/gh-3199-no-mem-leaks.result
+++ b/test/sql/gh-3199-no-mem-leaks.result
@@ -4,8 +4,9 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 fiber = require('fiber')
 ---
@@ -14,57 +15,110 @@ fiber = require('fiber')
 -- executing SQL queries.
 --
 -- box.cfg()
-box.sql.execute('CREATE TABLE test (id INT PRIMARY KEY, x INTEGER, y INTEGER)')
+box.execute('CREATE TABLE test (id INT PRIMARY KEY, x INTEGER, y INTEGER)')
 ---
+- rowcount: 1
 ...
-box.sql.execute('INSERT INTO test VALUES (1, 1, 1), (2, 2, 2)')
+box.execute('INSERT INTO test VALUES (1, 1, 1), (2, 2, 2)')
 ---
+- rowcount: 2
 ...
-box.sql.execute('SELECT x, y, x + y FROM test ORDER BY y')
+box.execute('SELECT x, y, x + y FROM test ORDER BY y')
 ---
-- - [1, 1, 2]
+- metadata:
+  - name: X
+    type: INTEGER
+  - name: Y
+    type: BLOB
+  - name: x + y
+    type: NUMERIC
+  rows:
+  - [1, 1, 2]
   - [2, 2, 4]
 ...
 fiber.info()[fiber.self().id()].memory.used
 ---
 - 0
 ...
-box.sql.execute('SELECT x, y, x + y FROM test ORDER BY y')
----
-- - [1, 1, 2]
+box.execute('SELECT x, y, x + y FROM test ORDER BY y')
+---
+- metadata:
+  - name: X
+    type: INTEGER
+  - name: Y
+    type: BLOB
+  - name: x + y
+    type: NUMERIC
+  rows:
+  - [1, 1, 2]
   - [2, 2, 4]
 ...
-box.sql.execute('SELECT x, y, x + y FROM test ORDER BY y')
----
-- - [1, 1, 2]
+box.execute('SELECT x, y, x + y FROM test ORDER BY y')
+---
+- metadata:
+  - name: X
+    type: INTEGER
+  - name: Y
+    type: BLOB
+  - name: x + y
+    type: NUMERIC
+  rows:
+  - [1, 1, 2]
   - [2, 2, 4]
 ...
-box.sql.execute('SELECT x, y, x + y FROM test ORDER BY y')
----
-- - [1, 1, 2]
+box.execute('SELECT x, y, x + y FROM test ORDER BY y')
+---
+- metadata:
+  - name: X
+    type: INTEGER
+  - name: Y
+    type: BLOB
+  - name: x + y
+    type: NUMERIC
+  rows:
+  - [1, 1, 2]
   - [2, 2, 4]
 ...
-box.sql.execute('SELECT x, y, x + y FROM test ORDER BY y')
----
-- - [1, 1, 2]
+box.execute('SELECT x, y, x + y FROM test ORDER BY y')
+---
+- metadata:
+  - name: X
+    type: INTEGER
+  - name: Y
+    type: BLOB
+  - name: x + y
+    type: NUMERIC
+  rows:
+  - [1, 1, 2]
   - [2, 2, 4]
 ...
 fiber.info()[fiber.self().id()].memory.used
 ---
 - 0
 ...
-box.sql.execute('CREATE TABLE test2 (id INT PRIMARY KEY, a TEXT, b INTEGER)')
+box.execute('CREATE TABLE test2 (id INT PRIMARY KEY, a TEXT, b INTEGER)')
 ---
+- rowcount: 1
 ...
-box.sql.execute('INSERT INTO test2 VALUES (1, \'abc\', 1), (2, \'hello\', 2)')
+box.execute('INSERT INTO test2 VALUES (1, \'abc\', 1), (2, \'hello\', 2)')
 ---
+- rowcount: 2
 ...
-box.sql.execute('INSERT INTO test2 VALUES (3, \'test\', 3), (4, \'xx\', 4)')
+box.execute('INSERT INTO test2 VALUES (3, \'test\', 3), (4, \'xx\', 4)')
 ---
+- rowcount: 2
 ...
-box.sql.execute('SELECT a, id + 2, b FROM test2 WHERE b < id * 2 ORDER BY a ')
+box.execute('SELECT a, id + 2, b FROM test2 WHERE b < id * 2 ORDER BY a ')
 ---
-- - ['abc', 3, 1]
+- metadata:
+  - name: A
+    type: BLOB
+  - name: id + 2
+    type: NUMERIC
+  - name: B
+    type: INTEGER
+  rows:
+  - ['abc', 3, 1]
   - ['hello', 4, 2]
   - ['test', 5, 3]
   - ['xx', 6, 4]
@@ -73,23 +127,47 @@ fiber.info()[fiber.self().id()].memory.used
 ---
 - 0
 ...
-box.sql.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
----
-- - ['abc', 3, 'abc']
+box.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
+---
+- metadata:
+  - name: A
+    type: TEXT
+  - name: id + 2 * b
+    type: NUMERIC
+  - name: A
+    type: BLOB
+  rows:
+  - ['abc', 3, 'abc']
   - ['hello', 6, 'hello']
   - ['test', 9, 'test']
   - ['xx', 12, 'xx']
 ...
-box.sql.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
----
-- - ['abc', 3, 'abc']
+box.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
+---
+- metadata:
+  - name: A
+    type: TEXT
+  - name: id + 2 * b
+    type: NUMERIC
+  - name: A
+    type: BLOB
+  rows:
+  - ['abc', 3, 'abc']
   - ['hello', 6, 'hello']
   - ['test', 9, 'test']
   - ['xx', 12, 'xx']
 ...
-box.sql.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
----
-- - ['abc', 3, 'abc']
+box.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
+---
+- metadata:
+  - name: A
+    type: TEXT
+  - name: id + 2 * b
+    type: NUMERIC
+  - name: A
+    type: BLOB
+  rows:
+  - ['abc', 3, 'abc']
   - ['hello', 6, 'hello']
   - ['test', 9, 'test']
   - ['xx', 12, 'xx']
@@ -98,19 +176,43 @@ fiber.info()[fiber.self().id()].memory.used
 ---
 - 0
 ...
-box.sql.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
----
-- - [1, 4, 1]
+box.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
+---
+- metadata:
+  - name: X
+    type: INTEGER
+  - name: y + 3 * b
+    type: NUMERIC
+  - name: B
+    type: INTEGER
+  rows:
+  - [1, 4, 1]
   - [2, 8, 2]
 ...
-box.sql.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
----
-- - [1, 4, 1]
+box.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
+---
+- metadata:
+  - name: X
+    type: INTEGER
+  - name: y + 3 * b
+    type: NUMERIC
+  - name: B
+    type: INTEGER
+  rows:
+  - [1, 4, 1]
   - [2, 8, 2]
 ...
-box.sql.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
----
-- - [1, 4, 1]
+box.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
+---
+- metadata:
+  - name: X
+    type: INTEGER
+  - name: y + 3 * b
+    type: NUMERIC
+  - name: B
+    type: INTEGER
+  rows:
+  - [1, 4, 1]
   - [2, 8, 2]
 ...
 fiber.info()[fiber.self().id()].memory.used
@@ -118,9 +220,11 @@ fiber.info()[fiber.self().id()].memory.used
 - 0
 ...
 -- Cleanup
-box.sql.execute('DROP TABLE test')
+box.execute('DROP TABLE test')
 ---
+- rowcount: 1
 ...
-box.sql.execute('DROP TABLE test2')
+box.execute('DROP TABLE test2')
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/gh-3199-no-mem-leaks.test.lua b/test/sql/gh-3199-no-mem-leaks.test.lua
index 1954e34..54a6ce5 100644
--- a/test/sql/gh-3199-no-mem-leaks.test.lua
+++ b/test/sql/gh-3199-no-mem-leaks.test.lua
@@ -1,6 +1,6 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 fiber = require('fiber')
 
 -- This test checks that no leaks of region memory happens during
@@ -10,39 +10,39 @@ fiber = require('fiber')
 -- box.cfg()
 
 
-box.sql.execute('CREATE TABLE test (id INT PRIMARY KEY, x INTEGER, y INTEGER)')
-box.sql.execute('INSERT INTO test VALUES (1, 1, 1), (2, 2, 2)')
-box.sql.execute('SELECT x, y, x + y FROM test ORDER BY y')
+box.execute('CREATE TABLE test (id INT PRIMARY KEY, x INTEGER, y INTEGER)')
+box.execute('INSERT INTO test VALUES (1, 1, 1), (2, 2, 2)')
+box.execute('SELECT x, y, x + y FROM test ORDER BY y')
 
 fiber.info()[fiber.self().id()].memory.used
 
-box.sql.execute('SELECT x, y, x + y FROM test ORDER BY y')
-box.sql.execute('SELECT x, y, x + y FROM test ORDER BY y')
-box.sql.execute('SELECT x, y, x + y FROM test ORDER BY y')
-box.sql.execute('SELECT x, y, x + y FROM test ORDER BY y')
+box.execute('SELECT x, y, x + y FROM test ORDER BY y')
+box.execute('SELECT x, y, x + y FROM test ORDER BY y')
+box.execute('SELECT x, y, x + y FROM test ORDER BY y')
+box.execute('SELECT x, y, x + y FROM test ORDER BY y')
 
 fiber.info()[fiber.self().id()].memory.used
 
-box.sql.execute('CREATE TABLE test2 (id INT PRIMARY KEY, a TEXT, b INTEGER)')
-box.sql.execute('INSERT INTO test2 VALUES (1, \'abc\', 1), (2, \'hello\', 2)')
-box.sql.execute('INSERT INTO test2 VALUES (3, \'test\', 3), (4, \'xx\', 4)')
-box.sql.execute('SELECT a, id + 2, b FROM test2 WHERE b < id * 2 ORDER BY a ')
+box.execute('CREATE TABLE test2 (id INT PRIMARY KEY, a TEXT, b INTEGER)')
+box.execute('INSERT INTO test2 VALUES (1, \'abc\', 1), (2, \'hello\', 2)')
+box.execute('INSERT INTO test2 VALUES (3, \'test\', 3), (4, \'xx\', 4)')
+box.execute('SELECT a, id + 2, b FROM test2 WHERE b < id * 2 ORDER BY a ')
 
 fiber.info()[fiber.self().id()].memory.used
 
-box.sql.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
-box.sql.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
-box.sql.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
+box.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
+box.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
+box.execute('SELECT a, id + 2 * b, a FROM test2 WHERE b < id * 2 ORDER BY a ')
 
 fiber.info()[fiber.self().id()].memory.used
 
-box.sql.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
-box.sql.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
-box.sql.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
+box.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
+box.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
+box.execute('SELECT x, y + 3 * b, b FROM test2, test WHERE b = x')
 
 fiber.info()[fiber.self().id()].memory.used
 
 -- Cleanup
-box.sql.execute('DROP TABLE test')
-box.sql.execute('DROP TABLE test2')
+box.execute('DROP TABLE test')
+box.execute('DROP TABLE test2')
 
diff --git a/test/sql/gh-3613-idx-alter-update-2.result b/test/sql/gh-3613-idx-alter-update-2.result
index 234336c..d899121 100644
--- a/test/sql/gh-3613-idx-alter-update-2.result
+++ b/test/sql/gh-3613-idx-alter-update-2.result
@@ -4,25 +4,31 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
-box.sql.execute('CREATE TABLE t (s1 INT PRIMARY KEY)')
+box.execute('CREATE TABLE t (s1 INT PRIMARY KEY)')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i ON t (s1)')
+box.execute('CREATE INDEX i ON t (s1)')
 ---
+- rowcount: 1
 ...
-box.sql.execute('ALTER TABLE t RENAME TO j3')
+box.execute('ALTER TABLE t RENAME TO j3')
 ---
+- rowcount: 0
 ...
 -- After gh-3613 fix, bug in cmp_def was discovered.
 -- Comparison didn't take .opts.sql into account.
 test_run:cmd('restart server default')
-box.sql.execute('DROP INDEX i ON j3')
+box.execute('DROP INDEX i ON j3')
 ---
+- rowcount: 1
 ...
 -- Cleanup
-box.sql.execute('DROP TABLE j3')
+box.execute('DROP TABLE j3')
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/gh-3613-idx-alter-update-2.test.lua b/test/sql/gh-3613-idx-alter-update-2.test.lua
index e2beb7a..ff5b651 100644
--- a/test/sql/gh-3613-idx-alter-update-2.test.lua
+++ b/test/sql/gh-3613-idx-alter-update-2.test.lua
@@ -1,16 +1,16 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
-box.sql.execute('CREATE TABLE t (s1 INT PRIMARY KEY)')
-box.sql.execute('CREATE INDEX i ON t (s1)')
-box.sql.execute('ALTER TABLE t RENAME TO j3')
+box.execute('CREATE TABLE t (s1 INT PRIMARY KEY)')
+box.execute('CREATE INDEX i ON t (s1)')
+box.execute('ALTER TABLE t RENAME TO j3')
 
 -- After gh-3613 fix, bug in cmp_def was discovered.
 -- Comparison didn't take .opts.sql into account.
 test_run:cmd('restart server default')
 
-box.sql.execute('DROP INDEX i ON j3')
+box.execute('DROP INDEX i ON j3')
 
 -- Cleanup
-box.sql.execute('DROP TABLE j3')
+box.execute('DROP TABLE j3')
diff --git a/test/sql/gh-3613-idx-alter-update.result b/test/sql/gh-3613-idx-alter-update.result
index 2815428..85078df 100644
--- a/test/sql/gh-3613-idx-alter-update.result
+++ b/test/sql/gh-3613-idx-alter-update.result
@@ -4,21 +4,26 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
-box.sql.execute('CREATE TABLE t (s1 INT PRIMARY KEY)')
+box.execute('CREATE TABLE t (s1 INT PRIMARY KEY)')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE INDEX i ON t (s1)')
+box.execute('CREATE INDEX i ON t (s1)')
 ---
+- rowcount: 1
 ...
-box.sql.execute('ALTER TABLE t RENAME TO j3')
+box.execute('ALTER TABLE t RENAME TO j3')
 ---
+- rowcount: 0
 ...
 -- Due to gh-3613, next stmt caused segfault
-box.sql.execute('DROP INDEX i ON j3')
+box.execute('DROP INDEX i ON j3')
 ---
+- rowcount: 1
 ...
 -- Make sure that no artifacts remain after restart.
 box.snapshot()
@@ -26,12 +31,13 @@ box.snapshot()
 - ok
 ...
 test_run:cmd('restart server default')
-box.sql.execute('DROP INDEX i ON j3')
+box.execute('DROP INDEX i ON j3')
 ---
 - error: No index 'I' is defined in space 'J3'
 ...
-box.sql.execute('CREATE INDEX i ON j3 (s1)')
+box.execute('CREATE INDEX i ON j3 (s1)')
 ---
+- rowcount: 1
 ...
 -- Check that _index was altered properly
 box.snapshot()
@@ -39,10 +45,12 @@ box.snapshot()
 - ok
 ...
 test_run:cmd('restart server default')
-box.sql.execute('DROP INDEX i ON j3')
+box.execute('DROP INDEX i ON j3')
 ---
+- rowcount: 1
 ...
 -- Cleanup
-box.sql.execute('DROP TABLE j3')
+box.execute('DROP TABLE j3')
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/gh-3613-idx-alter-update.test.lua b/test/sql/gh-3613-idx-alter-update.test.lua
index 49b81d7..3027182 100644
--- a/test/sql/gh-3613-idx-alter-update.test.lua
+++ b/test/sql/gh-3613-idx-alter-update.test.lua
@@ -1,26 +1,26 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
-box.sql.execute('CREATE TABLE t (s1 INT PRIMARY KEY)')
-box.sql.execute('CREATE INDEX i ON t (s1)')
-box.sql.execute('ALTER TABLE t RENAME TO j3')
+box.execute('CREATE TABLE t (s1 INT PRIMARY KEY)')
+box.execute('CREATE INDEX i ON t (s1)')
+box.execute('ALTER TABLE t RENAME TO j3')
 
 -- Due to gh-3613, next stmt caused segfault
-box.sql.execute('DROP INDEX i ON j3')
+box.execute('DROP INDEX i ON j3')
 
 -- Make sure that no artifacts remain after restart.
 box.snapshot()
 test_run:cmd('restart server default')
-box.sql.execute('DROP INDEX i ON j3')
+box.execute('DROP INDEX i ON j3')
 
-box.sql.execute('CREATE INDEX i ON j3 (s1)')
+box.execute('CREATE INDEX i ON j3 (s1)')
 
 -- Check that _index was altered properly
 box.snapshot()
 test_run:cmd('restart server default')
 
-box.sql.execute('DROP INDEX i ON j3')
+box.execute('DROP INDEX i ON j3')
 
 -- Cleanup
-box.sql.execute('DROP TABLE j3')
+box.execute('DROP TABLE j3')
diff --git a/test/sql/gh-3888-values-blob-assert.result b/test/sql/gh-3888-values-blob-assert.result
index 611c10d..e7f3e38 100644
--- a/test/sql/gh-3888-values-blob-assert.result
+++ b/test/sql/gh-3888-values-blob-assert.result
@@ -10,52 +10,69 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- check 'VALUES' against typedef keywords (should fail)
-box.sql.execute('VALUES(scalar)')
+box.execute('VALUES(scalar)')
 ---
 - error: Syntax error near 'scalar'
 ...
-box.sql.execute('VALUES(float)')
+box.execute('VALUES(float)')
 ---
 - error: Syntax error near 'float'
 ...
 -- check 'SELECT' against typedef keywords (should fail)
-box.sql.execute('SELECT scalar')
+box.execute('SELECT scalar')
 ---
 - error: Syntax error near 'scalar'
 ...
-box.sql.execute('SELECT float')
+box.execute('SELECT float')
 ---
 - error: Syntax error near 'float'
 ...
 -- check 'VALUES' against ID (should fail)
-box.sql.execute('VALUES(TheColumnName)')
+box.execute('VALUES(TheColumnName)')
 ---
 - error: Can’t resolve field 'THECOLUMNNAME'
 ...
 -- check 'SELECT' against ID (should fail)
-box.sql.execute('SELECT TheColumnName')
+box.execute('SELECT TheColumnName')
 ---
 - error: Can’t resolve field 'THECOLUMNNAME'
 ...
 -- check 'VALUES' well-formed expression  (returns value)
-box.sql.execute('VALUES(-0.5e-2)')
+box.execute('VALUES(-0.5e-2)')
 ---
-- - [-0.005]
+- metadata:
+  - name: column1
+    type: NUMERIC
+  rows:
+  - [-0.005]
 ...
-box.sql.execute('SELECT X\'507265766564\'')
+box.execute('SELECT X\'507265766564\'')
 ---
-- - ['Preved']
+- metadata:
+  - name: X'507265766564'
+    type: BLOB
+  rows:
+  - ['Preved']
 ...
 -- check 'SELECT' well-formed expression  (return value)
-box.sql.execute('SELECT 3.14')
+box.execute('SELECT 3.14')
 ---
-- - [3.14]
+- metadata:
+  - name: '3.14'
+    type: INTEGER
+  rows:
+  - [3.14]
 ...
-box.sql.execute('SELECT X\'4D6564766564\'')
+box.execute('SELECT X\'4D6564766564\'')
 ---
-- - ['Medved']
+- metadata:
+  - name: X'4D6564766564'
+    type: BLOB
+  rows:
+  - ['Medved']
 ...
diff --git a/test/sql/gh-3888-values-blob-assert.test.lua b/test/sql/gh-3888-values-blob-assert.test.lua
index 6e916c2..0b7c385 100644
--- a/test/sql/gh-3888-values-blob-assert.test.lua
+++ b/test/sql/gh-3888-values-blob-assert.test.lua
@@ -6,28 +6,28 @@
 --
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- check 'VALUES' against typedef keywords (should fail)
-box.sql.execute('VALUES(scalar)')
-box.sql.execute('VALUES(float)')
+box.execute('VALUES(scalar)')
+box.execute('VALUES(float)')
 
 -- check 'SELECT' against typedef keywords (should fail)
-box.sql.execute('SELECT scalar')
-box.sql.execute('SELECT float')
+box.execute('SELECT scalar')
+box.execute('SELECT float')
 
 -- check 'VALUES' against ID (should fail)
-box.sql.execute('VALUES(TheColumnName)')
+box.execute('VALUES(TheColumnName)')
 
 -- check 'SELECT' against ID (should fail)
-box.sql.execute('SELECT TheColumnName')
+box.execute('SELECT TheColumnName')
 
 -- check 'VALUES' well-formed expression  (returns value)
-box.sql.execute('VALUES(-0.5e-2)')
-box.sql.execute('SELECT X\'507265766564\'')
+box.execute('VALUES(-0.5e-2)')
+box.execute('SELECT X\'507265766564\'')
 
 -- check 'SELECT' well-formed expression  (return value)
-box.sql.execute('SELECT 3.14')
-box.sql.execute('SELECT X\'4D6564766564\'')
+box.execute('SELECT 3.14')
+box.execute('SELECT X\'4D6564766564\'')
 
 
diff --git a/test/sql/gh2141-delete-trigger-drop-table.result b/test/sql/gh2141-delete-trigger-drop-table.result
index 82ff51a..f1fefc7 100644
--- a/test/sql/gh2141-delete-trigger-drop-table.result
+++ b/test/sql/gh2141-delete-trigger-drop-table.result
@@ -4,35 +4,49 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- create space
-box.sql.execute("CREATE TABLE t(id INT PRIMARY KEY)")
+box.execute("CREATE TABLE t(id INT PRIMARY KEY)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER tt_bu BEFORE UPDATE ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_bu BEFORE UPDATE ON t BEGIN SELECT 1; END")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER tt_au AFTER UPDATE ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_au AFTER UPDATE ON t BEGIN SELECT 1; END")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER tt_bi BEFORE INSERT ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_bi BEFORE INSERT ON t BEGIN SELECT 1; END")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER tt_ai AFTER INSERT ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_ai AFTER INSERT ON t BEGIN SELECT 1; END")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER tt_bd BEFORE DELETE ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_bd BEFORE DELETE ON t BEGIN SELECT 1; END")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER tt_ad AFTER DELETE ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_ad AFTER DELETE ON t BEGIN SELECT 1; END")
 ---
+- rowcount: 1
 ...
 -- check that these triggers exist
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
 ---
-- - ['TT_AD', {'sql': 'CREATE TRIGGER tt_ad AFTER DELETE ON t BEGIN SELECT 1; END'}]
+- metadata:
+  - name: name
+    type: TEXT
+  - name: opts
+    type: UNKNOWN
+  rows:
+  - ['TT_AD', {'sql': 'CREATE TRIGGER tt_ad AFTER DELETE ON t BEGIN SELECT 1; END'}]
   - ['TT_AI', {'sql': 'CREATE TRIGGER tt_ai AFTER INSERT ON t BEGIN SELECT 1; END'}]
   - ['TT_AU', {'sql': 'CREATE TRIGGER tt_au AFTER UPDATE ON t BEGIN SELECT 1; END'}]
   - ['TT_BD', {'sql': 'CREATE TRIGGER tt_bd BEFORE DELETE ON t BEGIN SELECT 1; END'}]
@@ -40,11 +54,17 @@ box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
   - ['TT_BU', {'sql': 'CREATE TRIGGER tt_bu BEFORE UPDATE ON t BEGIN SELECT 1; END'}]
 ...
 -- drop table
-box.sql.execute("DROP TABLE t")
+box.execute("DROP TABLE t")
 ---
+- rowcount: 1
 ...
 -- check that triggers were dropped with deleted table
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
 ---
-- []
+- metadata:
+  - name: name
+    type: TEXT
+  - name: opts
+    type: UNKNOWN
+  rows: []
 ...
diff --git a/test/sql/gh2141-delete-trigger-drop-table.test.lua b/test/sql/gh2141-delete-trigger-drop-table.test.lua
index be3adc3..6fc9d99 100644
--- a/test/sql/gh2141-delete-trigger-drop-table.test.lua
+++ b/test/sql/gh2141-delete-trigger-drop-table.test.lua
@@ -1,22 +1,22 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- create space
-box.sql.execute("CREATE TABLE t(id INT PRIMARY KEY)")
+box.execute("CREATE TABLE t(id INT PRIMARY KEY)")
 
-box.sql.execute("CREATE TRIGGER tt_bu BEFORE UPDATE ON t BEGIN SELECT 1; END")
-box.sql.execute("CREATE TRIGGER tt_au AFTER UPDATE ON t BEGIN SELECT 1; END")
-box.sql.execute("CREATE TRIGGER tt_bi BEFORE INSERT ON t BEGIN SELECT 1; END")
-box.sql.execute("CREATE TRIGGER tt_ai AFTER INSERT ON t BEGIN SELECT 1; END")
-box.sql.execute("CREATE TRIGGER tt_bd BEFORE DELETE ON t BEGIN SELECT 1; END")
-box.sql.execute("CREATE TRIGGER tt_ad AFTER DELETE ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_bu BEFORE UPDATE ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_au AFTER UPDATE ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_bi BEFORE INSERT ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_ai AFTER INSERT ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_bd BEFORE DELETE ON t BEGIN SELECT 1; END")
+box.execute("CREATE TRIGGER tt_ad AFTER DELETE ON t BEGIN SELECT 1; END")
 
 -- check that these triggers exist
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
 
 -- drop table
-box.sql.execute("DROP TABLE t")
+box.execute("DROP TABLE t")
 
 -- check that triggers were dropped with deleted table
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
diff --git a/test/sql/gh2251-multiple-update.result b/test/sql/gh2251-multiple-update.result
index e6380a0..cc1a4c8 100644
--- a/test/sql/gh2251-multiple-update.result
+++ b/test/sql/gh2251-multiple-update.result
@@ -5,49 +5,68 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
-box.sql.execute("CREATE TABLE t1(a integer primary key, b INT UNIQUE, e INT);")
+box.execute("CREATE TABLE t1(a integer primary key, b INT UNIQUE, e INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES(1,4,6);")
+box.execute("INSERT INTO t1 VALUES(1,4,6);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES(2,5,7);")
+box.execute("INSERT INTO t1 VALUES(2,5,7);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);")
+box.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);")
 ---
+- rowcount: 2
 ...
-box.sql.execute("SELECT e FROM t1")
+box.execute("SELECT e FROM t1")
 ---
-- - [7]
+- metadata:
+  - name: E
+    type: INTEGER
+  rows:
+  - [7]
   - [8]
 ...
-box.sql.execute("CREATE TABLE t2(a integer primary key, b INT UNIQUE, c FLOAT, d FLOAT, e INT,  UNIQUE(c,d));")
+box.execute("CREATE TABLE t2(a integer primary key, b INT UNIQUE, c FLOAT, d FLOAT, e INT,  UNIQUE(c,d));")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t2 VALUES(1,2,3,4,5);")
+box.execute("INSERT INTO t2 VALUES(1,2,3,4,5);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t2 VALUES(2,3,4,4,6);")
+box.execute("INSERT INTO t2 VALUES(2,3,4,4,6);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("UPDATE t2 SET e=e+1 WHERE b IN (SELECT b FROM t2);")
+box.execute("UPDATE t2 SET e=e+1 WHERE b IN (SELECT b FROM t2);")
 ---
+- rowcount: 2
 ...
-box.sql.execute("SELECT e FROM t2")
+box.execute("SELECT e FROM t2")
 ---
-- - [6]
+- metadata:
+  - name: E
+    type: INTEGER
+  rows:
+  - [6]
   - [7]
 ...
-box.sql.execute("DROP TABLE t1")
+box.execute("DROP TABLE t1")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t2")
+box.execute("DROP TABLE t2")
 ---
+- rowcount: 1
 ...
 -- Debug
 -- require("console").start()
diff --git a/test/sql/gh2251-multiple-update.test.lua b/test/sql/gh2251-multiple-update.test.lua
index 656ed72..a852c4b 100644
--- a/test/sql/gh2251-multiple-update.test.lua
+++ b/test/sql/gh2251-multiple-update.test.lua
@@ -1,28 +1,28 @@
 -- Regression test for #2251
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- box.cfg()
 
-box.sql.execute("CREATE TABLE t1(a integer primary key, b INT UNIQUE, e INT);")
-box.sql.execute("INSERT INTO t1 VALUES(1,4,6);")
-box.sql.execute("INSERT INTO t1 VALUES(2,5,7);")
+box.execute("CREATE TABLE t1(a integer primary key, b INT UNIQUE, e INT);")
+box.execute("INSERT INTO t1 VALUES(1,4,6);")
+box.execute("INSERT INTO t1 VALUES(2,5,7);")
 
-box.sql.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);")
+box.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);")
 
-box.sql.execute("SELECT e FROM t1")
+box.execute("SELECT e FROM t1")
 
-box.sql.execute("CREATE TABLE t2(a integer primary key, b INT UNIQUE, c FLOAT, d FLOAT, e INT,  UNIQUE(c,d));")
-box.sql.execute("INSERT INTO t2 VALUES(1,2,3,4,5);")
-box.sql.execute("INSERT INTO t2 VALUES(2,3,4,4,6);")
+box.execute("CREATE TABLE t2(a integer primary key, b INT UNIQUE, c FLOAT, d FLOAT, e INT,  UNIQUE(c,d));")
+box.execute("INSERT INTO t2 VALUES(1,2,3,4,5);")
+box.execute("INSERT INTO t2 VALUES(2,3,4,4,6);")
 
-box.sql.execute("UPDATE t2 SET e=e+1 WHERE b IN (SELECT b FROM t2);")
+box.execute("UPDATE t2 SET e=e+1 WHERE b IN (SELECT b FROM t2);")
 
-box.sql.execute("SELECT e FROM t2")
+box.execute("SELECT e FROM t2")
 
-box.sql.execute("DROP TABLE t1")
-box.sql.execute("DROP TABLE t2")
+box.execute("DROP TABLE t1")
+box.execute("DROP TABLE t2")
 
 -- Debug
 -- require("console").start()
diff --git a/test/sql/gh2483-remote-persistency-check.result b/test/sql/gh2483-remote-persistency-check.result
index 50e65f2..0a45db4 100644
--- a/test/sql/gh2483-remote-persistency-check.result
+++ b/test/sql/gh2483-remote-persistency-check.result
@@ -8,23 +8,30 @@ test_run = env.new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 box.schema.user.grant('guest', 'read,write,execute', 'universe')
 ---
 ...
 -- Create a table and insert a datum
-box.sql.execute([[CREATE TABLE t(id int PRIMARY KEY)]])
+box.execute([[CREATE TABLE t(id int PRIMARY KEY)]])
 ---
+- rowcount: 1
 ...
-box.sql.execute([[INSERT INTO t (id) VALUES (1)]])
+box.execute([[INSERT INTO t (id) VALUES (1)]])
 ---
+- rowcount: 1
 ...
 -- Sanity check
-box.sql.execute([[SELECT * FROM t]])
+box.execute([[SELECT * FROM t]])
 ---
-- - [1]
+- metadata:
+  - name: ID
+    type: INTEGER
+  rows:
+  - [1]
 ...
 test_run:cmd('restart server default');
 -- Connect to ourself
@@ -34,13 +41,14 @@ c = require('net.box').connect(os.getenv("LISTEN"))
 -- This segfaults due to gh-2483 since
 -- before the patch sql schema was read on-demand.
 -- Which could obviously lead to access denied error.
-c:eval([[ return box.sql.execute('SELECT * FROM t') ]])
+c:eval([[ return box.execute('SELECT * FROM t') ]])
 ---
-- [[1]]
+- {'metadata': [{'name': 'ID', 'type': 'INTEGER'}], 'rows': [[1]]}
 ...
 -- sql.execute([[SELECT * FROM t]])
-box.sql.execute([[DROP TABLE t]])
+box.execute([[DROP TABLE t]])
 ---
+- rowcount: 1
 ...
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 ---
diff --git a/test/sql/gh2483-remote-persistency-check.test.lua b/test/sql/gh2483-remote-persistency-check.test.lua
index b952f6b..7db1602 100644
--- a/test/sql/gh2483-remote-persistency-check.test.lua
+++ b/test/sql/gh2483-remote-persistency-check.test.lua
@@ -2,16 +2,16 @@
 env = require('test_run')
 test_run = env.new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 box.schema.user.grant('guest', 'read,write,execute', 'universe')
 
 -- Create a table and insert a datum
-box.sql.execute([[CREATE TABLE t(id int PRIMARY KEY)]])
-box.sql.execute([[INSERT INTO t (id) VALUES (1)]])
+box.execute([[CREATE TABLE t(id int PRIMARY KEY)]])
+box.execute([[INSERT INTO t (id) VALUES (1)]])
 
 -- Sanity check
-box.sql.execute([[SELECT * FROM t]])
+box.execute([[SELECT * FROM t]])
 
 test_run:cmd('restart server default');
 
@@ -21,8 +21,8 @@ c = require('net.box').connect(os.getenv("LISTEN"))
 -- This segfaults due to gh-2483 since
 -- before the patch sql schema was read on-demand.
 -- Which could obviously lead to access denied error.
-c:eval([[ return box.sql.execute('SELECT * FROM t') ]])
+c:eval([[ return box.execute('SELECT * FROM t') ]])
 -- sql.execute([[SELECT * FROM t]])
 
-box.sql.execute([[DROP TABLE t]])
+box.execute([[DROP TABLE t]])
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
diff --git a/test/sql/gh2808-inline-unique-persistency-check.result b/test/sql/gh2808-inline-unique-persistency-check.result
index 6754af6..d2440da 100644
--- a/test/sql/gh2808-inline-unique-persistency-check.result
+++ b/test/sql/gh2808-inline-unique-persistency-check.result
@@ -8,35 +8,52 @@ test_run = env.new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- Create a table and insert a datum
-box.sql.execute([[CREATE TABLE t1(a INT PRIMARY KEY, b INT, UNIQUE(b));]])
+box.execute([[CREATE TABLE t1(a INT PRIMARY KEY, b INT, UNIQUE(b));]])
 ---
+- rowcount: 1
 ...
-box.sql.execute([[INSERT INTO t1 VALUES(1,2);]])
+box.execute([[INSERT INTO t1 VALUES(1,2);]])
 ---
+- rowcount: 1
 ...
 -- Sanity check
-box.sql.execute([[SELECT * FROM t1]])
+box.execute([[SELECT * FROM t1]])
 ---
-- - [1, 2]
+- metadata:
+  - name: A
+    type: INTEGER
+  - name: B
+    type: INTEGER
+  rows:
+  - [1, 2]
 ...
 test_run:cmd('restart server default');
 -- This cmd should not fail
 -- before this fix, unique index was notrecovered
 -- correctly after restart (#2808)
-box.sql.execute([[INSERT INTO t1 VALUES(2,3);]])
+box.execute([[INSERT INTO t1 VALUES(2,3);]])
 ---
+- rowcount: 1
 ...
 -- Sanity check
-box.sql.execute([[SELECT * FROM t1]])
----
-- - [1, 2]
+box.execute([[SELECT * FROM t1]])
+---
+- metadata:
+  - name: A
+    type: INTEGER
+  - name: B
+    type: INTEGER
+  rows:
+  - [1, 2]
   - [2, 3]
 ...
 -- Cleanup
-box.sql.execute([[drop table t1;]])
+box.execute([[drop table t1;]])
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/gh2808-inline-unique-persistency-check.test.lua b/test/sql/gh2808-inline-unique-persistency-check.test.lua
index 81e2af5..26b646a 100644
--- a/test/sql/gh2808-inline-unique-persistency-check.test.lua
+++ b/test/sql/gh2808-inline-unique-persistency-check.test.lua
@@ -2,23 +2,23 @@
 env = require('test_run')
 test_run = env.new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- Create a table and insert a datum
-box.sql.execute([[CREATE TABLE t1(a INT PRIMARY KEY, b INT, UNIQUE(b));]])
-box.sql.execute([[INSERT INTO t1 VALUES(1,2);]])
+box.execute([[CREATE TABLE t1(a INT PRIMARY KEY, b INT, UNIQUE(b));]])
+box.execute([[INSERT INTO t1 VALUES(1,2);]])
 
 -- Sanity check
-box.sql.execute([[SELECT * FROM t1]])
+box.execute([[SELECT * FROM t1]])
 
 test_run:cmd('restart server default');
 -- This cmd should not fail
 -- before this fix, unique index was notrecovered
 -- correctly after restart (#2808)
-box.sql.execute([[INSERT INTO t1 VALUES(2,3);]])
+box.execute([[INSERT INTO t1 VALUES(2,3);]])
 
 -- Sanity check
-box.sql.execute([[SELECT * FROM t1]])
+box.execute([[SELECT * FROM t1]])
 
 -- Cleanup
-box.sql.execute([[drop table t1;]])
+box.execute([[drop table t1;]])
diff --git a/test/sql/icu-upper-lower.result b/test/sql/icu-upper-lower.result
index 61d6546..c062beb 100644
--- a/test/sql/icu-upper-lower.result
+++ b/test/sql/icu-upper-lower.result
@@ -4,15 +4,16 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 test_run:cmd("setopt delimiter ';'")
 ---
 - true
 ...
 upper_lower_test = function (str)
-    return box.sql.execute(string.format("select lower('%s'), upper('%s')", str, str))
+    return box.execute(string.format("select lower('%s'), upper('%s')", str, str))
 end;
 ---
 ...
@@ -22,14 +23,28 @@ upper_lower_test([[
     Zəfər, jaketini də, papağını da götür, bu axşam hava çox soyuq olacaq.
 ]]);
 ---
-- - ['     zəfər, jaketini də, papağını da götür, bu axşam hava çox soyuq olacaq. ',
+- metadata:
+  - name: lower('     Zəfər, jaketini də, papağını da götür, bu axşam hava çox soyuq
+      olacaq. ')
+    type: TEXT
+  - name: upper('     Zəfər, jaketini də, papağını da götür, bu axşam hava çox soyuq
+      olacaq. ')
+    type: TEXT
+  rows:
+  - ['     zəfər, jaketini də, papağını da götür, bu axşam hava çox soyuq olacaq. ',
     '     ZƏFƏR, JAKETINI DƏ, PAPAĞINI DA GÖTÜR, BU AXŞAM HAVA ÇOX SOYUQ OLACAQ. ']
 ...
 upper_lower_test([[
     The quick brown fox jumps over the lazy dog.
 ]]);
 ---
-- - ['     the quick brown fox jumps over the lazy dog. ', '     THE QUICK BROWN FOX
+- metadata:
+  - name: lower('     The quick brown fox jumps over the lazy dog. ')
+    type: TEXT
+  - name: upper('     The quick brown fox jumps over the lazy dog. ')
+    type: TEXT
+  rows:
+  - ['     the quick brown fox jumps over the lazy dog. ', '     THE QUICK BROWN FOX
       JUMPS OVER THE LAZY DOG. ']
 ...
 -- English
@@ -37,7 +52,13 @@ upper_lower_test([[
     The quick brown fox jumps over the lazy dog.
 ]]);
 ---
-- - ['     the quick brown fox jumps over the lazy dog. ', '     THE QUICK BROWN FOX
+- metadata:
+  - name: lower('     The quick brown fox jumps over the lazy dog. ')
+    type: TEXT
+  - name: upper('     The quick brown fox jumps over the lazy dog. ')
+    type: TEXT
+  rows:
+  - ['     the quick brown fox jumps over the lazy dog. ', '     THE QUICK BROWN FOX
       JUMPS OVER THE LAZY DOG. ']
 ...
 -- Armenian
@@ -45,7 +66,15 @@ upper_lower_test([[
     Բել դղյակի ձախ ժամն օֆ ազգությանը ցպահանջ չճշտած վնաս էր եւ փառք
 ]]);
 ---
-- - ['     բել դղյակի ձախ ժամն օֆ ազգությանը ցպահանջ չճշտած վնաս էր եւ փառք ', '     ԲԵԼ
+- metadata:
+  - name: lower('     Բել դղյակի ձախ ժամն օֆ ազգությանը ցպահանջ չճշտած վնաս էր եւ
+      փառք ')
+    type: TEXT
+  - name: upper('     Բել դղյակի ձախ ժամն օֆ ազգությանը ցպահանջ չճշտած վնաս էր եւ
+      փառք ')
+    type: TEXT
+  rows:
+  - ['     բել դղյակի ձախ ժամն օֆ ազգությանը ցպահանջ չճշտած վնաս էր եւ փառք ', '     ԲԵԼ
       ԴՂՅԱԿԻ ՁԱԽ ԺԱՄՆ ՕՖ ԱԶԳՈՒԹՅԱՆԸ ՑՊԱՀԱՆՋ ՉՃՇՏԱԾ ՎՆԱՍ ԷՐ ԵՒ ՓԱՌՔ ']
 ...
 -- Belarussian
@@ -53,7 +82,15 @@ upper_lower_test([[
     У Іўі худы жвавы чорт у зялёнай камізэльцы пабег пад’есці фаршу з юшкай
 ]]);
 ---
-- - ['     у іўі худы жвавы чорт у зялёнай камізэльцы пабег пад’есці фаршу з юшкай ',
+- metadata:
+  - name: lower('     У Іўі худы жвавы чорт у зялёнай камізэльцы пабег пад’есці фаршу
+      з юшкай ')
+    type: TEXT
+  - name: upper('     У Іўі худы жвавы чорт у зялёнай камізэльцы пабег пад’есці фаршу
+      з юшкай ')
+    type: TEXT
+  rows:
+  - ['     у іўі худы жвавы чорт у зялёнай камізэльцы пабег пад’есці фаршу з юшкай ',
     '     У ІЎІ ХУДЫ ЖВАВЫ ЧОРТ У ЗЯЛЁНАЙ КАМІЗЭЛЬЦЫ ПАБЕГ ПАД’ЕСЦІ ФАРШУ З ЮШКАЙ ']
 ...
 -- Greek
@@ -61,7 +98,15 @@ upper_lower_test([[
     Τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός
 ]]);
 ---
-- - ['     τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός ', '     ΤΆΧΙΣΤΗ
+- metadata:
+  - name: lower('     Τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός
+      ')
+    type: TEXT
+  - name: upper('     Τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός
+      ')
+    type: TEXT
+  rows:
+  - ['     τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός ', '     ΤΆΧΙΣΤΗ
       ΑΛΏΠΗΞ ΒΑΦΉΣ ΨΗΜΈΝΗ ΓΗ, ΔΡΑΣΚΕΛΊΖΕΙ ΥΠΈΡ ΝΩΘΡΟΎ ΚΥΝΌΣ ']
 ...
 -- Irish
@@ -69,7 +114,15 @@ upper_lower_test([[
     Chuaigh bé mhórshách le dlúthspád fíorfhinn trí hata mo dhea-phorcáin bhig
 ]]);
 ---
-- - ['     chuaigh bé mhórshách le dlúthspád fíorfhinn trí hata mo dhea-phorcáin bhig ',
+- metadata:
+  - name: lower('     Chuaigh bé mhórshách le dlúthspád fíorfhinn trí hata mo dhea-phorcáin
+      bhig ')
+    type: TEXT
+  - name: upper('     Chuaigh bé mhórshách le dlúthspád fíorfhinn trí hata mo dhea-phorcáin
+      bhig ')
+    type: TEXT
+  rows:
+  - ['     chuaigh bé mhórshách le dlúthspád fíorfhinn trí hata mo dhea-phorcáin bhig ',
     '     CHUAIGH BÉ MHÓRSHÁCH LE DLÚTHSPÁD FÍORFHINN TRÍ HATA MO DHEA-PHORCÁIN BHIG ']
 ...
 -- Spain
@@ -77,7 +130,13 @@ upper_lower_test([[
     Quiere la boca exhausta vid, kiwi, piña y fugaz jamón
 ]]);
 ---
-- - ['     quiere la boca exhausta vid, kiwi, piña y fugaz jamón ', '     QUIERE LA
+- metadata:
+  - name: lower('     Quiere la boca exhausta vid, kiwi, piña y fugaz jamón ')
+    type: TEXT
+  - name: upper('     Quiere la boca exhausta vid, kiwi, piña y fugaz jamón ')
+    type: TEXT
+  rows:
+  - ['     quiere la boca exhausta vid, kiwi, piña y fugaz jamón ', '     QUIERE LA
       BOCA EXHAUSTA VID, KIWI, PIÑA Y FUGAZ JAMÓN ']
 ...
 -- Korean
@@ -85,7 +144,13 @@ upper_lower_test([[
     키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다
 ]]);
 ---
-- - ['     키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다 ', '     키스의 고유조건은 입술끼리 만나야 하고 특별한
+- metadata:
+  - name: lower('     키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다 ')
+    type: TEXT
+  - name: upper('     키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다 ')
+    type: TEXT
+  rows:
+  - ['     키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다 ', '     키스의 고유조건은 입술끼리 만나야 하고 특별한
       기술은 필요치 않다 ']
 ...
 -- Latvian
@@ -93,7 +158,13 @@ upper_lower_test([[
     Glāžšķūņa rūķīši dzērumā čiepj Baha koncertflīģeļu vākus
 ]]);
 ---
-- - ['     glāžšķūņa rūķīši dzērumā čiepj baha koncertflīģeļu vākus ', '     GLĀŽŠĶŪŅA
+- metadata:
+  - name: lower('     Glāžšķūņa rūķīši dzērumā čiepj Baha koncertflīģeļu vākus ')
+    type: TEXT
+  - name: upper('     Glāžšķūņa rūķīši dzērumā čiepj Baha koncertflīģeļu vākus ')
+    type: TEXT
+  rows:
+  - ['     glāžšķūņa rūķīši dzērumā čiepj baha koncertflīģeļu vākus ', '     GLĀŽŠĶŪŅA
       RŪĶĪŠI DZĒRUMĀ ČIEPJ BAHA KONCERTFLĪĢEĻU VĀKUS ']
 ...
 -- German
@@ -101,7 +172,15 @@ upper_lower_test([[
     Zwölf große Boxkämpfer jagen Viktor quer über den Sylter Deich
 ]]);
 ---
-- - ['     zwölf große boxkämpfer jagen viktor quer über den sylter deich ', '     ZWÖLF
+- metadata:
+  - name: lower('     Zwölf große Boxkämpfer jagen Viktor quer über den Sylter Deich
+      ')
+    type: TEXT
+  - name: upper('     Zwölf große Boxkämpfer jagen Viktor quer über den Sylter Deich
+      ')
+    type: TEXT
+  rows:
+  - ['     zwölf große boxkämpfer jagen viktor quer über den sylter deich ', '     ZWÖLF
       GROSSE BOXKÄMPFER JAGEN VIKTOR QUER ÜBER DEN SYLTER DEICH ']
 ...
 -- Polish
@@ -109,7 +188,13 @@ upper_lower_test([[
     Pchnąć w tę łódź jeża lub ośm skrzyń fig.
 ]]);
 ---
-- - ['     pchnąć w tę łódź jeża lub ośm skrzyń fig. ', '     PCHNĄĆ W TĘ ŁÓDŹ JEŻA
+- metadata:
+  - name: lower('     Pchnąć w tę łódź jeża lub ośm skrzyń fig. ')
+    type: TEXT
+  - name: upper('     Pchnąć w tę łódź jeża lub ośm skrzyń fig. ')
+    type: TEXT
+  rows:
+  - ['     pchnąć w tę łódź jeża lub ośm skrzyń fig. ', '     PCHNĄĆ W TĘ ŁÓDŹ JEŻA
       LUB OŚM SKRZYŃ FIG. ']
 ...
 -- Ukrainian
@@ -117,7 +202,13 @@ upper_lower_test([[
     Чуєш їх, доцю, га? Кумедна ж ти, прощайся без ґольфів!
 ]]);
 ---
-- - ['     чуєш їх, доцю, га? кумедна ж ти, прощайся без ґольфів! ', '     ЧУЄШ ЇХ,
+- metadata:
+  - name: lower('     Чуєш їх, доцю, га? Кумедна ж ти, прощайся без ґольфів! ')
+    type: TEXT
+  - name: upper('     Чуєш їх, доцю, га? Кумедна ж ти, прощайся без ґольфів! ')
+    type: TEXT
+  rows:
+  - ['     чуєш їх, доцю, га? кумедна ж ти, прощайся без ґольфів! ', '     ЧУЄШ ЇХ,
       ДОЦЮ, ГА? КУМЕДНА Ж ТИ, ПРОЩАЙСЯ БЕЗ ҐОЛЬФІВ! ']
 ...
 -- Czech
@@ -125,7 +216,13 @@ upper_lower_test([[
     Příliš žluťoučký kůň úpěl ďábelské ódy
 ]]);
 ---
-- - ['     příliš žluťoučký kůň úpěl ďábelské ódy ', '     PŘÍLIŠ ŽLUŤOUČKÝ KŮŇ ÚPĚL
+- metadata:
+  - name: lower('     Příliš žluťoučký kůň úpěl ďábelské ódy ')
+    type: TEXT
+  - name: upper('     Příliš žluťoučký kůň úpěl ďábelské ódy ')
+    type: TEXT
+  rows:
+  - ['     příliš žluťoučký kůň úpěl ďábelské ódy ', '     PŘÍLIŠ ŽLUŤOUČKÝ KŮŇ ÚPĚL
       ĎÁBELSKÉ ÓDY ']
 ...
 -- Esperanto
@@ -133,7 +230,15 @@ upper_lower_test([[
     Laŭ Ludoviko Zamenhof bongustas freŝa ĉeĥa manĝaĵo kun spicoj
 ]]);
 ---
-- - ['     laŭ ludoviko zamenhof bongustas freŝa ĉeĥa manĝaĵo kun spicoj ', '     LAŬ
+- metadata:
+  - name: lower('     Laŭ Ludoviko Zamenhof bongustas freŝa ĉeĥa manĝaĵo kun spicoj
+      ')
+    type: TEXT
+  - name: upper('     Laŭ Ludoviko Zamenhof bongustas freŝa ĉeĥa manĝaĵo kun spicoj
+      ')
+    type: TEXT
+  rows:
+  - ['     laŭ ludoviko zamenhof bongustas freŝa ĉeĥa manĝaĵo kun spicoj ', '     LAŬ
       LUDOVIKO ZAMENHOF BONGUSTAS FREŜA ĈEĤA MANĜAĴO KUN SPICOJ ']
 ...
 -- Japanese
@@ -141,7 +246,13 @@ upper_lower_test([[
     いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす
 ]]);
 ---
-- - ['     いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす ', '     いろはにほへと
+- metadata:
+  - name: lower('     いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす ')
+    type: TEXT
+  - name: upper('     いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす ')
+    type: TEXT
+  rows:
+  - ['     いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす ', '     いろはにほへと
       ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす ']
 ...
 -- Turkish
@@ -149,7 +260,13 @@ upper_lower_test([[
     Pijamalı hasta yağız şoföre çabucak güvendi. EXTRA: İ
 ]]);
 ---
-- - ['     pijamalı hasta yağız şoföre çabucak güvendi. extra: i̇ ', '     PIJAMALI
+- metadata:
+  - name: 'lower(''     Pijamalı hasta yağız şoföre çabucak güvendi. EXTRA: İ '')'
+    type: TEXT
+  - name: 'upper(''     Pijamalı hasta yağız şoföre çabucak güvendi. EXTRA: İ '')'
+    type: TEXT
+  rows:
+  - ['     pijamalı hasta yağız şoföre çabucak güvendi. extra: i̇ ', '     PIJAMALI
       HASTA YAĞIZ ŞOFÖRE ÇABUCAK GÜVENDI. EXTRA: İ ']
 ...
 test_run:cmd("setopt delimiter ''");
@@ -157,15 +274,15 @@ test_run:cmd("setopt delimiter ''");
 - true
 ...
 -- Bad test cases
-box.sql.execute("select upper('1', 2)")
+box.execute("select upper('1', 2)")
 ---
 - error: wrong number of arguments to function UPPER()
 ...
-box.sql.execute("select upper(\"1\")")
+box.execute("select upper(\"1\")")
 ---
 - error: Can’t resolve field '1'
 ...
-box.sql.execute("select upper()")
+box.execute("select upper()")
 ---
 - error: wrong number of arguments to function UPPER()
 ...
diff --git a/test/sql/icu-upper-lower.test.lua b/test/sql/icu-upper-lower.test.lua
index 6629a74..00e9699 100644
--- a/test/sql/icu-upper-lower.test.lua
+++ b/test/sql/icu-upper-lower.test.lua
@@ -1,11 +1,11 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 test_run:cmd("setopt delimiter ';'")
 
 upper_lower_test = function (str)
-    return box.sql.execute(string.format("select lower('%s'), upper('%s')", str, str))
+    return box.execute(string.format("select lower('%s'), upper('%s')", str, str))
 end;
 
 -- Some pangrams
@@ -80,7 +80,7 @@ upper_lower_test([[
 test_run:cmd("setopt delimiter ''");
 
 -- Bad test cases
-box.sql.execute("select upper('1', 2)")
-box.sql.execute("select upper(\"1\")")
-box.sql.execute("select upper()")
+box.execute("select upper('1', 2)")
+box.execute("select upper(\"1\")")
+box.execute("select upper()")
 
diff --git a/test/sql/insert-unique.result b/test/sql/insert-unique.result
index adfa60f..a18f9ff 100644
--- a/test/sql/insert-unique.result
+++ b/test/sql/insert-unique.result
@@ -4,39 +4,47 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
 -- create space
-box.sql.execute("CREATE TABLE zoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
+box.execute("CREATE TABLE zoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE UNIQUE INDEX zoobar2 ON zoobar(c1, c4)")
+box.execute("CREATE UNIQUE INDEX zoobar2 ON zoobar(c1, c4)")
 ---
+- rowcount: 1
 ...
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 -- Seed entry
-box.sql.execute("INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+box.execute("INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 ---
+- rowcount: 1
 ...
 -- PK must be unique
-box.sql.execute("INSERT INTO zoobar VALUES (112, 222, 'c3', 444)")
+box.execute("INSERT INTO zoobar VALUES (112, 222, 'c3', 444)")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_ZOOBAR_1' in space 'ZOOBAR'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_ZOOBAR_1'' in space ''ZOOBAR'''
 ...
 -- Unique index must be respected
-box.sql.execute("INSERT INTO zoobar VALUES (111, 223, 'c3', 444)")
+box.execute("INSERT INTO zoobar VALUES (111, 223, 'c3', 444)")
 ---
-- error: Duplicate key exists in unique index 'ZOOBAR2' in space 'ZOOBAR'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''ZOOBAR2'' in space ''ZOOBAR'''
 ...
 -- Cleanup
-box.sql.execute("DROP INDEX zoobar2 ON zoobar")
+box.execute("DROP INDEX zoobar2 ON zoobar")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE zoobar")
+box.execute("DROP TABLE zoobar")
 ---
+- rowcount: 1
 ...
 -- Debug
 -- require("console").start()
diff --git a/test/sql/insert-unique.test.lua b/test/sql/insert-unique.test.lua
index b44a6e2..026bc9d 100644
--- a/test/sql/insert-unique.test.lua
+++ b/test/sql/insert-unique.test.lua
@@ -1,28 +1,28 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- box.cfg()
 
 -- create space
-box.sql.execute("CREATE TABLE zoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
-box.sql.execute("CREATE UNIQUE INDEX zoobar2 ON zoobar(c1, c4)")
+box.execute("CREATE TABLE zoobar (c1 INT, c2 INT PRIMARY KEY, c3 TEXT, c4 INT)")
+box.execute("CREATE UNIQUE INDEX zoobar2 ON zoobar(c1, c4)")
 
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 
 -- Seed entry
-box.sql.execute("INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+box.execute("INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 
 -- PK must be unique
-box.sql.execute("INSERT INTO zoobar VALUES (112, 222, 'c3', 444)")
+box.execute("INSERT INTO zoobar VALUES (112, 222, 'c3', 444)")
 
 -- Unique index must be respected
-box.sql.execute("INSERT INTO zoobar VALUES (111, 223, 'c3', 444)")
+box.execute("INSERT INTO zoobar VALUES (111, 223, 'c3', 444)")
 
 -- Cleanup
-box.sql.execute("DROP INDEX zoobar2 ON zoobar")
-box.sql.execute("DROP TABLE zoobar")
+box.execute("DROP INDEX zoobar2 ON zoobar")
+box.execute("DROP TABLE zoobar")
 
 -- Debug
 -- require("console").start()
diff --git a/test/sql/integer-overflow.result b/test/sql/integer-overflow.result
index 4754c04..2a9bbbd 100644
--- a/test/sql/integer-overflow.result
+++ b/test/sql/integer-overflow.result
@@ -4,45 +4,46 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- gh-3735: make sure that integer overflows errors are
 -- handled during VDBE execution.
 --
-box.sql.execute('SELECT (2147483647 * 2147483647 * 2147483647);')
+box.execute('SELECT (2147483647 * 2147483647 * 2147483647);')
 ---
 - error: 'Failed to execute SQL statement: integer is overflowed'
 ...
-box.sql.execute('SELECT (-9223372036854775808 / -1);')
+box.execute('SELECT (-9223372036854775808 / -1);')
 ---
 - error: 'Failed to execute SQL statement: integer is overflowed'
 ...
-box.sql.execute('SELECT (-9223372036854775808 - 1);')
+box.execute('SELECT (-9223372036854775808 - 1);')
 ---
 - error: 'Failed to execute SQL statement: integer is overflowed'
 ...
-box.sql.execute('SELECT (9223372036854775807 + 1);')
+box.execute('SELECT (9223372036854775807 + 1);')
 ---
 - error: 'Failed to execute SQL statement: integer is overflowed'
 ...
 -- Literals are checked right after parsing.
 --
-box.sql.execute('SELECT 9223372036854775808;')
+box.execute('SELECT 9223372036854775808;')
 ---
 - error: 'oversized integer: 9223372036854775808'
 ...
-box.sql.execute('SELECT -9223372036854775809;')
+box.execute('SELECT -9223372036854775809;')
 ---
 - error: 'oversized integer: -9223372036854775809'
 ...
-box.sql.execute('SELECT 9223372036854775808 - 1;')
+box.execute('SELECT 9223372036854775808 - 1;')
 ---
 - error: 'oversized integer: 9223372036854775808'
 ...
 -- Test that CAST may also leads to overflow.
 --
-box.sql.execute('SELECT CAST(\'9223372036854775808\' AS INTEGER);')
+box.execute('SELECT CAST(\'9223372036854775808\' AS INTEGER);')
 ---
 - error: 'Type mismatch: can not convert 9223372036854775808 to integer'
 ...
@@ -52,7 +53,7 @@ box.sql.execute('SELECT CAST(\'9223372036854775808\' AS INTEGER);')
 -- float 9223372036854775800 -> int (9223372036854775808),
 -- with error due to conversion = 8.
 --
-box.sql.execute('SELECT CAST(9223372036854775807.0 AS INTEGER);')
+box.execute('SELECT CAST(9223372036854775807.0 AS INTEGER);')
 ---
 - error: 'Type mismatch: can not convert 9.22337203685478e+18 to integer'
 ...
@@ -60,14 +61,15 @@ box.sql.execute('SELECT CAST(9223372036854775807.0 AS INTEGER);')
 -- [INT64_MAX, UINT64_MAX], they are handled inside SQL in a
 -- proper way, which now means that an error is raised.
 --
-box.sql.execute('CREATE TABLE t (id INT PRIMARY KEY);')
+box.execute('CREATE TABLE t (id INT PRIMARY KEY);')
 ---
+- rowcount: 1
 ...
 box.space.T:insert({9223372036854775809})
 ---
 - [9223372036854775808]
 ...
-box.sql.execute('SELECT * FROM t;')
+box.execute('SELECT * FROM t;')
 ---
 - error: 'Failed to execute SQL statement: integer is overflowed'
 ...
diff --git a/test/sql/integer-overflow.test.lua b/test/sql/integer-overflow.test.lua
index 45fc209..4339edf 100644
--- a/test/sql/integer-overflow.test.lua
+++ b/test/sql/integer-overflow.test.lua
@@ -1,34 +1,34 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- gh-3735: make sure that integer overflows errors are
 -- handled during VDBE execution.
 --
-box.sql.execute('SELECT (2147483647 * 2147483647 * 2147483647);')
-box.sql.execute('SELECT (-9223372036854775808 / -1);')
-box.sql.execute('SELECT (-9223372036854775808 - 1);')
-box.sql.execute('SELECT (9223372036854775807 + 1);')
+box.execute('SELECT (2147483647 * 2147483647 * 2147483647);')
+box.execute('SELECT (-9223372036854775808 / -1);')
+box.execute('SELECT (-9223372036854775808 - 1);')
+box.execute('SELECT (9223372036854775807 + 1);')
 -- Literals are checked right after parsing.
 --
-box.sql.execute('SELECT 9223372036854775808;')
-box.sql.execute('SELECT -9223372036854775809;')
-box.sql.execute('SELECT 9223372036854775808 - 1;')
+box.execute('SELECT 9223372036854775808;')
+box.execute('SELECT -9223372036854775809;')
+box.execute('SELECT 9223372036854775808 - 1;')
 -- Test that CAST may also leads to overflow.
 --
-box.sql.execute('SELECT CAST(\'9223372036854775808\' AS INTEGER);')
+box.execute('SELECT CAST(\'9223372036854775808\' AS INTEGER);')
 -- Due to inexact represantation of large integers in terms of
 -- floating point numbers, numerics with value < INT64_MAX
 -- have INT64_MAX + 1 value in integer representation:
 -- float 9223372036854775800 -> int (9223372036854775808),
 -- with error due to conversion = 8.
 --
-box.sql.execute('SELECT CAST(9223372036854775807.0 AS INTEGER);')
+box.execute('SELECT CAST(9223372036854775807.0 AS INTEGER);')
 -- gh-3810: make sure that if space contains integers in range
 -- [INT64_MAX, UINT64_MAX], they are handled inside SQL in a
 -- proper way, which now means that an error is raised.
 --
-box.sql.execute('CREATE TABLE t (id INT PRIMARY KEY);')
+box.execute('CREATE TABLE t (id INT PRIMARY KEY);')
 box.space.T:insert({9223372036854775809})
-box.sql.execute('SELECT * FROM t;')
+box.execute('SELECT * FROM t;')
 box.space.T:drop()
diff --git a/test/sql/iproto.result b/test/sql/iproto.result
index 7ad61e5..0ab8558 100644
--- a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -7,11 +7,13 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
-box.sql.execute('create table test (id int primary key, a float, b text)')
+box.execute('create table test (id int primary key, a float, b text)')
 ---
+- rowcount: 1
 ...
 space = box.space.TEST
 ---
@@ -28,9 +30,17 @@ space:replace{7, 8.5, '9'}
 ---
 - [7, 8.5, '9']
 ...
-box.sql.execute('select * from test')
+box.execute('select * from test')
 ---
-- - [1, 2, '3']
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: NUMERIC
+  - name: B
+    type: TEXT
+  rows:
+  - [1, 2, '3']
   - [4, 5, '6']
   - [7, 8.5, '9']
 ...
@@ -619,8 +629,9 @@ res.metadata
   - name: B
     type: TEXT
 ...
-box.sql.execute('drop table test')
+box.execute('drop table test')
 ---
+- rowcount: 1
 ...
 cn:close()
 ---
@@ -678,13 +689,15 @@ future4:wait_result()
 cn:close()
 ---
 ...
-box.sql.execute('drop table test')
+box.execute('drop table test')
 ---
+- rowcount: 1
 ...
 -- gh-2618 Return generated columns after INSERT in IPROTO.
 -- Return all ids generated in current INSERT statement.
-box.sql.execute('create table test (id integer primary key autoincrement, a integer)')
+box.execute('create table test (id integer primary key autoincrement, a integer)')
 ---
+- rowcount: 1
 ...
 cn = remote.connect(box.cfg.listen)
 ---
@@ -763,8 +776,9 @@ cn:execute('insert into test values (null, 1)')
   - 2
   rowcount: 1
 ...
-box.sql.execute('create table test3 (id int primary key autoincrement)')
+box.execute('create table test3 (id int primary key autoincrement)')
 ---
+- rowcount: 1
 ...
 box.schema.sequence.alter('TEST3', {min=-10000, step=-10})
 ---
@@ -778,8 +792,9 @@ cn:execute('insert into TEST3 values (null), (null), (null), (null)')
   - -29
   rowcount: 4
 ...
-box.sql.execute('drop table test')
+box.execute('drop table test')
 ---
+- rowcount: 1
 ...
 s:drop()
 ---
@@ -787,8 +802,9 @@ s:drop()
 sq:drop()
 ---
 ...
-box.sql.execute('drop table test3')
+box.execute('drop table test3')
 ---
+- rowcount: 1
 ...
 --
 -- Ensure that FK inside CREATE TABLE does not affect rowcount.
@@ -857,8 +873,9 @@ s:drop()
 cn = remote.connect(box.cfg.listen)
 ---
 ...
-box.sql.execute('CREATE TABLE t1(id INTEGER PRIMARY KEY AUTOINCREMENT)')
+box.execute('CREATE TABLE t1(id INTEGER PRIMARY KEY AUTOINCREMENT)')
 ---
+- rowcount: 1
 ...
 for i = 0, 1000 do cn:execute("INSERT INTO t1 VALUES (null)") end
 ---
@@ -866,15 +883,17 @@ for i = 0, 1000 do cn:execute("INSERT INTO t1 VALUES (null)") end
 _ = cn:execute("INSERT INTO t1 SELECT NULL from t1")
 ---
 ...
-box.sql.execute('DROP TABLE t1')
+box.execute('DROP TABLE t1')
 ---
+- rowcount: 1
 ...
 cn:close()
 ---
 ...
 -- gh-3832: Some statements do not return column type
-box.sql.execute('CREATE TABLE t1(id INTEGER PRIMARY KEY)')
+box.execute('CREATE TABLE t1(id INTEGER PRIMARY KEY)')
 ---
+- rowcount: 1
 ...
 cn = remote.connect(box.cfg.listen)
 ---
@@ -969,8 +988,9 @@ cn:execute("UPDATE t1 SET id = id + 100 WHERE id > 10;")
 cn:close()
 ---
 ...
-box.sql.execute('DROP TABLE t1')
+box.execute('DROP TABLE t1')
 ---
+- rowcount: 1
 ...
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 ---
diff --git a/test/sql/iproto.test.lua b/test/sql/iproto.test.lua
index 3b36cc3..6a6c24a 100644
--- a/test/sql/iproto.test.lua
+++ b/test/sql/iproto.test.lua
@@ -1,14 +1,14 @@
 remote = require('net.box')
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
-box.sql.execute('create table test (id int primary key, a float, b text)')
+box.execute('create table test (id int primary key, a float, b text)')
 space = box.space.TEST
 space:replace{1, 2, '3'}
 space:replace{4, 5, '6'}
 space:replace{7, 8.5, '9'}
-box.sql.execute('select * from test')
+box.execute('select * from test')
 box.schema.user.grant('guest','read,write,execute', 'universe')
 box.schema.user.grant('guest', 'create', 'space')
 cn = remote.connect(box.cfg.listen)
@@ -194,7 +194,7 @@ cn:execute('select * from test where id = :1', {1})
 _ = space:replace{1, 1, string.rep('a', 4 * 1024 * 1024)}
 res = cn:execute('select * from test')
 res.metadata
-box.sql.execute('drop table test')
+box.execute('drop table test')
 cn:close()
 
 --
@@ -212,11 +212,11 @@ future3:wait_result()
 future4 = cn:execute('select * from test', nil, nil, {is_async = true})
 future4:wait_result()
 cn:close()
-box.sql.execute('drop table test')
+box.execute('drop table test')
 
 -- gh-2618 Return generated columns after INSERT in IPROTO.
 -- Return all ids generated in current INSERT statement.
-box.sql.execute('create table test (id integer primary key autoincrement, a integer)')
+box.execute('create table test (id integer primary key autoincrement, a integer)')
 
 cn = remote.connect(box.cfg.listen)
 cn:execute('insert into test values (1, 1)')
@@ -233,14 +233,14 @@ function push_id() s:replace{box.NULL} s:replace{box.NULL} end
 _ = box.space.TEST:on_replace(push_id)
 cn:execute('insert into test values (null, 1)')
 
-box.sql.execute('create table test3 (id int primary key autoincrement)')
+box.execute('create table test3 (id int primary key autoincrement)')
 box.schema.sequence.alter('TEST3', {min=-10000, step=-10})
 cn:execute('insert into TEST3 values (null), (null), (null), (null)')
 
-box.sql.execute('drop table test')
+box.execute('drop table test')
 s:drop()
 sq:drop()
-box.sql.execute('drop table test3')
+box.execute('drop table test3')
 
 --
 -- Ensure that FK inside CREATE TABLE does not affect rowcount.
@@ -268,15 +268,15 @@ s:drop()
 
 -- Too many autogenerated ids leads to SEGFAULT.
 cn = remote.connect(box.cfg.listen)
-box.sql.execute('CREATE TABLE t1(id INTEGER PRIMARY KEY AUTOINCREMENT)')
+box.execute('CREATE TABLE t1(id INTEGER PRIMARY KEY AUTOINCREMENT)')
 for i = 0, 1000 do cn:execute("INSERT INTO t1 VALUES (null)") end
 _ = cn:execute("INSERT INTO t1 SELECT NULL from t1")
-box.sql.execute('DROP TABLE t1')
+box.execute('DROP TABLE t1')
 
 cn:close()
 
 -- gh-3832: Some statements do not return column type
-box.sql.execute('CREATE TABLE t1(id INTEGER PRIMARY KEY)')
+box.execute('CREATE TABLE t1(id INTEGER PRIMARY KEY)')
 cn = remote.connect(box.cfg.listen)
 
 -- PRAGMA:
@@ -298,7 +298,7 @@ cn:execute("REPLACE INTO t1 VALUES (2), (3), (4), (5);")
 cn:execute("UPDATE t1 SET id = id + 100 WHERE id > 10;")
 
 cn:close()
-box.sql.execute('DROP TABLE t1')
+box.execute('DROP TABLE t1')
 
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 box.schema.user.revoke('guest', 'create', 'space')
diff --git a/test/sql/max-on-index.result b/test/sql/max-on-index.result
index c4b5900..de1fbb3 100644
--- a/test/sql/max-on-index.result
+++ b/test/sql/max-on-index.result
@@ -4,62 +4,86 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
 -- create space
 -- scalar affinity
-box.sql.execute("CREATE TABLE test1 (f1 INT, f2 INT, PRIMARY KEY(f1))")
+box.execute("CREATE TABLE test1 (f1 INT, f2 INT, PRIMARY KEY(f1))")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE INDEX test1_index ON test1 (f2)")
+box.execute("CREATE INDEX test1_index ON test1 (f2)")
 ---
+- rowcount: 1
 ...
 -- integer affinity
-box.sql.execute("CREATE TABLE test2 (f1 INT, f2 INT, PRIMARY KEY(f1))")
+box.execute("CREATE TABLE test2 (f1 INT, f2 INT, PRIMARY KEY(f1))")
 ---
+- rowcount: 1
 ...
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 -- Seed entries
-box.sql.execute("INSERT INTO test1 VALUES(1, 2)");
+box.execute("INSERT INTO test1 VALUES(1, 2)");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO test1 VALUES(2, NULL)");
+box.execute("INSERT INTO test1 VALUES(2, NULL)");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO test1 VALUES(3, NULL)");
+box.execute("INSERT INTO test1 VALUES(3, NULL)");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO test1 VALUES(4, 3)");
+box.execute("INSERT INTO test1 VALUES(4, 3)");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO test2 VALUES(1, 2)");
+box.execute("INSERT INTO test2 VALUES(1, 2)");
 ---
+- rowcount: 1
 ...
 -- Select must return properly decoded `NULL`
-box.sql.execute("SELECT MAX(f1) FROM test1")
+box.execute("SELECT MAX(f1) FROM test1")
 ---
-- - [4]
+- metadata:
+  - name: MAX(f1)
+    type: BLOB
+  rows:
+  - [4]
 ...
-box.sql.execute("SELECT MAX(f2) FROM test1")
+box.execute("SELECT MAX(f2) FROM test1")
 ---
-- - [3]
+- metadata:
+  - name: MAX(f2)
+    type: BLOB
+  rows:
+  - [3]
 ...
-box.sql.execute("SELECT MAX(f1) FROM test2")
+box.execute("SELECT MAX(f1) FROM test2")
 ---
-- - [1]
+- metadata:
+  - name: MAX(f1)
+    type: BLOB
+  rows:
+  - [1]
 ...
 -- Cleanup
-box.sql.execute("DROP INDEX test1_index ON test1")
+box.execute("DROP INDEX test1_index ON test1")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE test1")
+box.execute("DROP TABLE test1")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE test2")
+box.execute("DROP TABLE test2")
 ---
+- rowcount: 1
 ...
 -- Debug
 -- require("console").start()
diff --git a/test/sql/max-on-index.test.lua b/test/sql/max-on-index.test.lua
index 7d89c3a..4cceaa7 100644
--- a/test/sql/max-on-index.test.lua
+++ b/test/sql/max-on-index.test.lua
@@ -1,38 +1,38 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- box.cfg()
 
 -- create space
 -- scalar affinity
-box.sql.execute("CREATE TABLE test1 (f1 INT, f2 INT, PRIMARY KEY(f1))")
-box.sql.execute("CREATE INDEX test1_index ON test1 (f2)")
+box.execute("CREATE TABLE test1 (f1 INT, f2 INT, PRIMARY KEY(f1))")
+box.execute("CREATE INDEX test1_index ON test1 (f2)")
 
 -- integer affinity
-box.sql.execute("CREATE TABLE test2 (f1 INT, f2 INT, PRIMARY KEY(f1))")
+box.execute("CREATE TABLE test2 (f1 INT, f2 INT, PRIMARY KEY(f1))")
 
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 
 -- Seed entries
-box.sql.execute("INSERT INTO test1 VALUES(1, 2)");
-box.sql.execute("INSERT INTO test1 VALUES(2, NULL)");
-box.sql.execute("INSERT INTO test1 VALUES(3, NULL)");
-box.sql.execute("INSERT INTO test1 VALUES(4, 3)");
+box.execute("INSERT INTO test1 VALUES(1, 2)");
+box.execute("INSERT INTO test1 VALUES(2, NULL)");
+box.execute("INSERT INTO test1 VALUES(3, NULL)");
+box.execute("INSERT INTO test1 VALUES(4, 3)");
 
-box.sql.execute("INSERT INTO test2 VALUES(1, 2)");
+box.execute("INSERT INTO test2 VALUES(1, 2)");
 
 -- Select must return properly decoded `NULL`
-box.sql.execute("SELECT MAX(f1) FROM test1")
-box.sql.execute("SELECT MAX(f2) FROM test1")
+box.execute("SELECT MAX(f1) FROM test1")
+box.execute("SELECT MAX(f2) FROM test1")
 
-box.sql.execute("SELECT MAX(f1) FROM test2")
+box.execute("SELECT MAX(f1) FROM test2")
 
 -- Cleanup
-box.sql.execute("DROP INDEX test1_index ON test1")
-box.sql.execute("DROP TABLE test1")
-box.sql.execute("DROP TABLE test2")
+box.execute("DROP INDEX test1_index ON test1")
+box.execute("DROP TABLE test1")
+box.execute("DROP TABLE test2")
 
 -- Debug
 -- require("console").start()
diff --git a/test/sql/message-func-indexes.result b/test/sql/message-func-indexes.result
index 5928a8e..04e7a52 100644
--- a/test/sql/message-func-indexes.result
+++ b/test/sql/message-func-indexes.result
@@ -4,44 +4,51 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- Creating tables.
-box.sql.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER)")
+box.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2(object INTEGER PRIMARY KEY, price INTEGER, count INTEGER)")
+box.execute("CREATE TABLE t2(object INTEGER PRIMARY KEY, price INTEGER, count INTEGER)")
 ---
+- rowcount: 1
 ...
 -- Expressions that're supposed to create functional indexes
 -- should return certain message.
-box.sql.execute("CREATE INDEX i1 ON t1(a+1)")
+box.execute("CREATE INDEX i1 ON t1(a+1)")
 ---
 - error: Tarantool does not support functional indexes
 ...
-box.sql.execute("CREATE INDEX i2 ON t1(a)")
+box.execute("CREATE INDEX i2 ON t1(a)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE INDEX i3 ON t2(price + 100)")
+box.execute("CREATE INDEX i3 ON t2(price + 100)")
 ---
 - error: Tarantool does not support functional indexes
 ...
-box.sql.execute("CREATE INDEX i4 ON t2(price)")
+box.execute("CREATE INDEX i4 ON t2(price)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE INDEX i5 ON t2(count + 1)")
+box.execute("CREATE INDEX i5 ON t2(count + 1)")
 ---
 - error: Tarantool does not support functional indexes
 ...
-box.sql.execute("CREATE INDEX i6 ON t2(count * price)")
+box.execute("CREATE INDEX i6 ON t2(count * price)")
 ---
 - error: Tarantool does not support functional indexes
 ...
 -- Cleaning up.
-box.sql.execute("DROP TABLE t1")
+box.execute("DROP TABLE t1")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t2")
+box.execute("DROP TABLE t2")
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/message-func-indexes.test.lua b/test/sql/message-func-indexes.test.lua
index e0eae76..9ac5f47 100644
--- a/test/sql/message-func-indexes.test.lua
+++ b/test/sql/message-func-indexes.test.lua
@@ -1,20 +1,20 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- Creating tables.
-box.sql.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER)")
-box.sql.execute("CREATE TABLE t2(object INTEGER PRIMARY KEY, price INTEGER, count INTEGER)")
+box.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER)")
+box.execute("CREATE TABLE t2(object INTEGER PRIMARY KEY, price INTEGER, count INTEGER)")
 
 -- Expressions that're supposed to create functional indexes
 -- should return certain message.
-box.sql.execute("CREATE INDEX i1 ON t1(a+1)")
-box.sql.execute("CREATE INDEX i2 ON t1(a)")
-box.sql.execute("CREATE INDEX i3 ON t2(price + 100)")
-box.sql.execute("CREATE INDEX i4 ON t2(price)")
-box.sql.execute("CREATE INDEX i5 ON t2(count + 1)")
-box.sql.execute("CREATE INDEX i6 ON t2(count * price)")
+box.execute("CREATE INDEX i1 ON t1(a+1)")
+box.execute("CREATE INDEX i2 ON t1(a)")
+box.execute("CREATE INDEX i3 ON t2(price + 100)")
+box.execute("CREATE INDEX i4 ON t2(price)")
+box.execute("CREATE INDEX i5 ON t2(count + 1)")
+box.execute("CREATE INDEX i6 ON t2(count * price)")
 
 -- Cleaning up.
-box.sql.execute("DROP TABLE t1")
-box.sql.execute("DROP TABLE t2")
+box.execute("DROP TABLE t1")
+box.execute("DROP TABLE t2")
diff --git a/test/sql/min-on-index.result b/test/sql/min-on-index.result
deleted file mode 100644
index 1b2aadf..0000000
--- a/test/sql/min-on-index.result
+++ /dev/null
@@ -1,59 +0,0 @@
-test_run = require('test_run').new()
----
-...
--- box.cfg()
--- create space
--- scalar affinity
-box.sql.execute("CREATE TABLE test1 (f1, f2 INT, PRIMARY KEY(f1))")
----
-...
-box.sql.execute("CREATE INDEX test1_index ON test1 (f2)")
----
-...
--- integer affinity
-box.sql.execute("CREATE TABLE test2 (f1 INT, f2 INT, PRIMARY KEY(f1))")
----
-...
--- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
--- Seed entries
-box.sql.execute("INSERT INTO test1 VALUES(1, 2)");
----
-...
-box.sql.execute("INSERT INTO test1 VALUES(2, NULL)");
----
-...
-box.sql.execute("INSERT INTO test1 VALUES(3, NULL)");
----
-...
-box.sql.execute("INSERT INTO test1 VALUES(4, 3)");
----
-...
-box.sql.execute("INSERT INTO test2 VALUES(1, 2)");
----
-...
--- Select must return properly decoded `NULL`
-box.sql.execute("SELECT MIN(f1) FROM test1")
----
-- - [1]
-...
-box.sql.execute("SELECT MIN(f2) FROM test1")
----
-- - [2]
-...
-box.sql.execute("SELECT MIN(f1) FROM test2")
----
-- - [1]
-...
--- Cleanup
-box.sql.execute("DROP INDEX test1_index")
----
-...
-box.sql.execute("DROP TABLE test1")
----
-...
-box.sql.execute("DROP TABLE test2")
----
-...
--- Debug
--- require("console").start()
diff --git a/test/sql/misc.result b/test/sql/misc.result
index 9a8aa8d..b20818d 100644
--- a/test/sql/misc.result
+++ b/test/sql/misc.result
@@ -4,20 +4,25 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- Forbid multistatement queries.
-box.sql.execute('select 1;')
+box.execute('select 1;')
 ---
-- - [1]
+- metadata:
+  - name: '1'
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute('select 1; select 2;')
+box.execute('select 1; select 2;')
 ---
 - error: Keyword 'select' is reserved. Please use double quotes if 'select' is an
     identifier.
 ...
-box.sql.execute('create table t1 (id INT primary key); select 100;')
+box.execute('create table t1 (id INT primary key); select 100;')
 ---
 - error: Keyword 'select' is reserved. Please use double quotes if 'select' is an
     identifier.
@@ -26,19 +31,19 @@ box.space.t1 == nil
 ---
 - true
 ...
-box.sql.execute(';')
+box.execute(';')
 ---
 - error: Failed to execute an empty SQL statement
 ...
-box.sql.execute('')
+box.execute('')
 ---
 - error: Failed to execute an empty SQL statement
 ...
-box.sql.execute('     ;')
+box.execute('     ;')
 ---
 - error: Failed to execute an empty SQL statement
 ...
-box.sql.execute('\n\n\n\t\t\t   ')
+box.execute('\n\n\n\t\t\t   ')
 ---
 - error: Failed to execute an empty SQL statement
 ...
diff --git a/test/sql/misc.test.lua b/test/sql/misc.test.lua
index 994e64f..1c2e6ce 100644
--- a/test/sql/misc.test.lua
+++ b/test/sql/misc.test.lua
@@ -1,13 +1,13 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- Forbid multistatement queries.
-box.sql.execute('select 1;')
-box.sql.execute('select 1; select 2;')
-box.sql.execute('create table t1 (id INT primary key); select 100;')
+box.execute('select 1;')
+box.execute('select 1; select 2;')
+box.execute('create table t1 (id INT primary key); select 100;')
 box.space.t1 == nil
-box.sql.execute(';')
-box.sql.execute('')
-box.sql.execute('     ;')
-box.sql.execute('\n\n\n\t\t\t   ')
+box.execute(';')
+box.execute('')
+box.execute('     ;')
+box.execute('\n\n\n\t\t\t   ')
diff --git a/test/sql/no-pk-space.result b/test/sql/no-pk-space.result
index 1d57d16..b270b1f 100644
--- a/test/sql/no-pk-space.result
+++ b/test/sql/no-pk-space.result
@@ -4,8 +4,9 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 format = {}
 ---
@@ -16,19 +17,19 @@ format[1] = {'id', 'integer'}
 s = box.schema.create_space('test', {format = format})
 ---
 ...
-box.sql.execute("SELECT * FROM \"test\";")
+box.execute("SELECT * FROM \"test\";")
 ---
 - error: SQL does not support spaces without primary key
 ...
-box.sql.execute("INSERT INTO \"test\" VALUES (1);")
+box.execute("INSERT INTO \"test\" VALUES (1);")
 ---
 - error: SQL does not support spaces without primary key
 ...
-box.sql.execute("DELETE FROM \"test\";")
+box.execute("DELETE FROM \"test\";")
 ---
 - error: SQL does not support spaces without primary key
 ...
-box.sql.execute("UPDATE \"test\" SET id = 3;")
+box.execute("UPDATE \"test\" SET id = 3;")
 ---
 - error: SQL does not support spaces without primary key
 ...
@@ -39,17 +40,19 @@ s:drop()
 -- after drop of indexes. So, if space:drop() fails due to being
 -- referenced by a view, space becomes unusable in SQL terms.
 --
-box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY);")
+box.execute("CREATE TABLE t1 (id INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
+box.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
 ---
+- rowcount: 1
 ...
 box.space.T1:drop()
 ---
 - error: 'Can''t drop space ''T1'': other views depend on this space'
 ...
-box.sql.execute("SELECT * FROM v1;")
+box.execute("SELECT * FROM v1;")
 ---
 - error: SQL does not support spaces without primary key
 ...
diff --git a/test/sql/no-pk-space.test.lua b/test/sql/no-pk-space.test.lua
index 2828777..318c2ac 100644
--- a/test/sql/no-pk-space.test.lua
+++ b/test/sql/no-pk-space.test.lua
@@ -1,14 +1,14 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 format = {}
 format[1] = {'id', 'integer'}
 s = box.schema.create_space('test', {format = format})
-box.sql.execute("SELECT * FROM \"test\";")
-box.sql.execute("INSERT INTO \"test\" VALUES (1);")
-box.sql.execute("DELETE FROM \"test\";")
-box.sql.execute("UPDATE \"test\" SET id = 3;")
+box.execute("SELECT * FROM \"test\";")
+box.execute("INSERT INTO \"test\" VALUES (1);")
+box.execute("DELETE FROM \"test\";")
+box.execute("UPDATE \"test\" SET id = 3;")
 
 s:drop()
 
@@ -16,9 +16,9 @@ s:drop()
 -- after drop of indexes. So, if space:drop() fails due to being
 -- referenced by a view, space becomes unusable in SQL terms.
 --
-box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY);")
-box.sql.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
+box.execute("CREATE TABLE t1 (id INT PRIMARY KEY);")
+box.execute("CREATE VIEW v1 AS SELECT * FROM t1;")
 box.space.T1:drop()
-box.sql.execute("SELECT * FROM v1;")
+box.execute("SELECT * FROM v1;")
 box.space.V1:drop()
 box.space.T1:drop()
diff --git a/test/sql/on-conflict.result b/test/sql/on-conflict.result
index 6d37e69..253b356 100644
--- a/test/sql/on-conflict.result
+++ b/test/sql/on-conflict.result
@@ -4,145 +4,195 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 --
 -- Check that original sql ON CONFLICT clause is really
 -- disabled.
 --
-box.sql.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT ABORT)")
+box.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT ABORT)")
 ---
 - error: Keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.
 ...
-box.sql.execute("CREATE TABLE q (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT FAIL)")
+box.execute("CREATE TABLE q (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT FAIL)")
 ---
 - error: Keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.
 ...
-box.sql.execute("CREATE TABLE p (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT IGNORE)")
+box.execute("CREATE TABLE p (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT IGNORE)")
 ---
 - error: Keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.
 ...
-box.sql.execute("CREATE TABLE g (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT REPLACE)")
+box.execute("CREATE TABLE g (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT REPLACE)")
 ---
 - error: Keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.
 ...
-box.sql.execute("CREATE TABLE e (id INTEGER PRIMARY KEY ON CONFLICT REPLACE, v INTEGER)")
+box.execute("CREATE TABLE e (id INTEGER PRIMARY KEY ON CONFLICT REPLACE, v INTEGER)")
 ---
 - error: Keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.
 ...
-box.sql.execute("CREATE TABLE t1(a INT PRIMARY KEY ON CONFLICT REPLACE)")
+box.execute("CREATE TABLE t1(a INT PRIMARY KEY ON CONFLICT REPLACE)")
 ---
 - error: Keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.
 ...
-box.sql.execute("CREATE TABLE t2(a INT PRIMARY KEY ON CONFLICT IGNORE)")
+box.execute("CREATE TABLE t2(a INT PRIMARY KEY ON CONFLICT IGNORE)")
 ---
 - error: Keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.
 ...
 -- CHECK constraint is illegal with REPLACE option.
 --
-box.sql.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, a INTEGER CHECK (a > 5) ON CONFLICT REPLACE);")
+box.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, a INTEGER CHECK (a > 5) ON CONFLICT REPLACE);")
 ---
 - error: Keyword 'ON' is reserved. Please use double quotes if 'ON' is an identifier.
 ...
 --
 -- gh-3473: Primary key can't be declared with NULL.
 --
-box.sql.execute("CREATE TABLE te17 (s1 INT NULL PRIMARY KEY NOT NULL);")
+box.execute("CREATE TABLE te17 (s1 INT NULL PRIMARY KEY NOT NULL);")
 ---
 - error: Primary index of the space 'TE17' can not contain nullable parts
 ...
-box.sql.execute("CREATE TABLE te17 (s1 INT NULL PRIMARY KEY);")
+box.execute("CREATE TABLE te17 (s1 INT NULL PRIMARY KEY);")
 ---
 - error: Primary index of the space 'TE17' can not contain nullable parts
 ...
-box.sql.execute("CREATE TABLE test (a int PRIMARY KEY, b int NULL ON CONFLICT IGNORE);")
+box.execute("CREATE TABLE test (a int PRIMARY KEY, b int NULL ON CONFLICT IGNORE);")
 ---
 - error: 'SQL error: NULL declaration for column ''B'' of table ''TEST'' has been
     already set to ''none'''
 ...
-box.sql.execute("CREATE TABLE test (a int, b int NULL, c int, PRIMARY KEY(a, b, c))")
+box.execute("CREATE TABLE test (a int, b int NULL, c int, PRIMARY KEY(a, b, c))")
 ---
 - error: Primary index of the space 'TEST' can not contain nullable parts
 ...
 -- Several NOT NULL REPLACE constraints work
 --
-box.sql.execute("CREATE TABLE a (id INT PRIMARY KEY, a INT NOT NULL ON CONFLICT REPLACE DEFAULT 1, b INT NOT NULL ON CONFLICT REPLACE DEFAULT 2);")
+box.execute("CREATE TABLE a (id INT PRIMARY KEY, a INT NOT NULL ON CONFLICT REPLACE DEFAULT 1, b INT NOT NULL ON CONFLICT REPLACE DEFAULT 2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO a VALUES(1, NULL, NULL);")
+box.execute("INSERT INTO a VALUES(1, NULL, NULL);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO a VALUES(2, NULL, NULL);")
+box.execute("INSERT INTO a VALUES(2, NULL, NULL);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM a;")
+box.execute("SELECT * FROM a;")
 ---
-- - [1, 1, 2]
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: INTEGER
+  - name: B
+    type: INTEGER
+  rows:
+  - [1, 1, 2]
   - [2, 1, 2]
 ...
-box.sql.execute("DROP TABLE a;")
+box.execute("DROP TABLE a;")
 ---
+- rowcount: 1
 ...
 -- gh-3566: UPDATE OR IGNORE causes deletion of old entry.
 --
-box.sql.execute("CREATE TABLE tj (s0 INT PRIMARY KEY, s1 INT UNIQUE, s2 INT);")
+box.execute("CREATE TABLE tj (s0 INT PRIMARY KEY, s1 INT UNIQUE, s2 INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO tj VALUES (1, 1, 2), (2, 2, 3);")
+box.execute("INSERT INTO tj VALUES (1, 1, 2), (2, 2, 3);")
 ---
+- rowcount: 2
 ...
-box.sql.execute("CREATE UNIQUE INDEX i ON tj (s2);")
+box.execute("CREATE UNIQUE INDEX i ON tj (s2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("UPDATE OR IGNORE tj SET s1 = s1 + 1;")
+box.execute("UPDATE OR IGNORE tj SET s1 = s1 + 1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT s1, s2 FROM tj;")
+box.execute("SELECT s1, s2 FROM tj;")
 ---
-- - [1, 2]
+- metadata:
+  - name: S1
+    type: INTEGER
+  - name: S2
+    type: INTEGER
+  rows:
+  - [1, 2]
   - [3, 3]
 ...
-box.sql.execute("UPDATE OR IGNORE tj SET s2 = s2 + 1;")
+box.execute("UPDATE OR IGNORE tj SET s2 = s2 + 1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT s1, s2 FROM tj;")
+box.execute("SELECT s1, s2 FROM tj;")
 ---
-- - [1, 2]
+- metadata:
+  - name: S1
+    type: INTEGER
+  - name: S2
+    type: INTEGER
+  rows:
+  - [1, 2]
   - [3, 4]
 ...
 -- gh-3565: INSERT OR REPLACE causes assertion fault.
 --
-box.sql.execute("DROP TABLE tj;")
+box.execute("DROP TABLE tj;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE tj (s1 INT PRIMARY KEY, s2 INT);")
+box.execute("CREATE TABLE tj (s1 INT PRIMARY KEY, s2 INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO tj VALUES (1, 2),(2, 3);")
+box.execute("INSERT INTO tj VALUES (1, 2),(2, 3);")
 ---
+- rowcount: 2
 ...
-box.sql.execute("CREATE UNIQUE INDEX i ON tj (s2);")
+box.execute("CREATE UNIQUE INDEX i ON tj (s2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("REPLACE INTO tj VALUES (1, 3);")
+box.execute("REPLACE INTO tj VALUES (1, 3);")
 ---
+- rowcount: 3
 ...
-box.sql.execute("SELECT * FROM tj;")
+box.execute("SELECT * FROM tj;")
 ---
-- - [1, 3]
+- metadata:
+  - name: S1
+    type: INTEGER
+  - name: S2
+    type: INTEGER
+  rows:
+  - [1, 3]
 ...
-box.sql.execute("INSERT INTO tj VALUES (2, 4), (3, 5);")
+box.execute("INSERT INTO tj VALUES (2, 4), (3, 5);")
 ---
+- rowcount: 2
 ...
-box.sql.execute("UPDATE OR REPLACE tj SET s2 = s2 + 1;")
+box.execute("UPDATE OR REPLACE tj SET s2 = s2 + 1;")
 ---
+- rowcount: 5
 ...
-box.sql.execute("SELECT * FROM tj;")
+box.execute("SELECT * FROM tj;")
 ---
-- - [1, 4]
+- metadata:
+  - name: S1
+    type: INTEGER
+  - name: S2
+    type: INTEGER
+  rows:
+  - [1, 4]
   - [3, 6]
 ...
-box.sql.execute("DROP TABLE tj;")
+box.execute("DROP TABLE tj;")
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/on-conflict.test.lua b/test/sql/on-conflict.test.lua
index 982612e..1aa4d1b 100644
--- a/test/sql/on-conflict.test.lua
+++ b/test/sql/on-conflict.test.lua
@@ -1,58 +1,58 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 --
 -- Check that original sql ON CONFLICT clause is really
 -- disabled.
 --
-box.sql.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT ABORT)")
-box.sql.execute("CREATE TABLE q (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT FAIL)")
-box.sql.execute("CREATE TABLE p (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT IGNORE)")
-box.sql.execute("CREATE TABLE g (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT REPLACE)")
-box.sql.execute("CREATE TABLE e (id INTEGER PRIMARY KEY ON CONFLICT REPLACE, v INTEGER)")
-box.sql.execute("CREATE TABLE t1(a INT PRIMARY KEY ON CONFLICT REPLACE)")
-box.sql.execute("CREATE TABLE t2(a INT PRIMARY KEY ON CONFLICT IGNORE)")
+box.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT ABORT)")
+box.execute("CREATE TABLE q (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT FAIL)")
+box.execute("CREATE TABLE p (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT IGNORE)")
+box.execute("CREATE TABLE g (id INTEGER PRIMARY KEY, v INTEGER UNIQUE ON CONFLICT REPLACE)")
+box.execute("CREATE TABLE e (id INTEGER PRIMARY KEY ON CONFLICT REPLACE, v INTEGER)")
+box.execute("CREATE TABLE t1(a INT PRIMARY KEY ON CONFLICT REPLACE)")
+box.execute("CREATE TABLE t2(a INT PRIMARY KEY ON CONFLICT IGNORE)")
 
 -- CHECK constraint is illegal with REPLACE option.
 --
-box.sql.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, a INTEGER CHECK (a > 5) ON CONFLICT REPLACE);")
+box.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, a INTEGER CHECK (a > 5) ON CONFLICT REPLACE);")
 
 --
 -- gh-3473: Primary key can't be declared with NULL.
 --
-box.sql.execute("CREATE TABLE te17 (s1 INT NULL PRIMARY KEY NOT NULL);")
-box.sql.execute("CREATE TABLE te17 (s1 INT NULL PRIMARY KEY);")
-box.sql.execute("CREATE TABLE test (a int PRIMARY KEY, b int NULL ON CONFLICT IGNORE);")
-box.sql.execute("CREATE TABLE test (a int, b int NULL, c int, PRIMARY KEY(a, b, c))")
+box.execute("CREATE TABLE te17 (s1 INT NULL PRIMARY KEY NOT NULL);")
+box.execute("CREATE TABLE te17 (s1 INT NULL PRIMARY KEY);")
+box.execute("CREATE TABLE test (a int PRIMARY KEY, b int NULL ON CONFLICT IGNORE);")
+box.execute("CREATE TABLE test (a int, b int NULL, c int, PRIMARY KEY(a, b, c))")
 
 -- Several NOT NULL REPLACE constraints work
 --
-box.sql.execute("CREATE TABLE a (id INT PRIMARY KEY, a INT NOT NULL ON CONFLICT REPLACE DEFAULT 1, b INT NOT NULL ON CONFLICT REPLACE DEFAULT 2);")
-box.sql.execute("INSERT INTO a VALUES(1, NULL, NULL);")
-box.sql.execute("INSERT INTO a VALUES(2, NULL, NULL);")
-box.sql.execute("SELECT * FROM a;")
-box.sql.execute("DROP TABLE a;")
+box.execute("CREATE TABLE a (id INT PRIMARY KEY, a INT NOT NULL ON CONFLICT REPLACE DEFAULT 1, b INT NOT NULL ON CONFLICT REPLACE DEFAULT 2);")
+box.execute("INSERT INTO a VALUES(1, NULL, NULL);")
+box.execute("INSERT INTO a VALUES(2, NULL, NULL);")
+box.execute("SELECT * FROM a;")
+box.execute("DROP TABLE a;")
 
 -- gh-3566: UPDATE OR IGNORE causes deletion of old entry.
 --
-box.sql.execute("CREATE TABLE tj (s0 INT PRIMARY KEY, s1 INT UNIQUE, s2 INT);")
-box.sql.execute("INSERT INTO tj VALUES (1, 1, 2), (2, 2, 3);")
-box.sql.execute("CREATE UNIQUE INDEX i ON tj (s2);")
-box.sql.execute("UPDATE OR IGNORE tj SET s1 = s1 + 1;")
-box.sql.execute("SELECT s1, s2 FROM tj;")
-box.sql.execute("UPDATE OR IGNORE tj SET s2 = s2 + 1;")
-box.sql.execute("SELECT s1, s2 FROM tj;")
+box.execute("CREATE TABLE tj (s0 INT PRIMARY KEY, s1 INT UNIQUE, s2 INT);")
+box.execute("INSERT INTO tj VALUES (1, 1, 2), (2, 2, 3);")
+box.execute("CREATE UNIQUE INDEX i ON tj (s2);")
+box.execute("UPDATE OR IGNORE tj SET s1 = s1 + 1;")
+box.execute("SELECT s1, s2 FROM tj;")
+box.execute("UPDATE OR IGNORE tj SET s2 = s2 + 1;")
+box.execute("SELECT s1, s2 FROM tj;")
 
 -- gh-3565: INSERT OR REPLACE causes assertion fault.
 --
-box.sql.execute("DROP TABLE tj;")
-box.sql.execute("CREATE TABLE tj (s1 INT PRIMARY KEY, s2 INT);")
-box.sql.execute("INSERT INTO tj VALUES (1, 2),(2, 3);")
-box.sql.execute("CREATE UNIQUE INDEX i ON tj (s2);")
-box.sql.execute("REPLACE INTO tj VALUES (1, 3);")
-box.sql.execute("SELECT * FROM tj;")
-box.sql.execute("INSERT INTO tj VALUES (2, 4), (3, 5);")
-box.sql.execute("UPDATE OR REPLACE tj SET s2 = s2 + 1;")
-box.sql.execute("SELECT * FROM tj;")
+box.execute("DROP TABLE tj;")
+box.execute("CREATE TABLE tj (s1 INT PRIMARY KEY, s2 INT);")
+box.execute("INSERT INTO tj VALUES (1, 2),(2, 3);")
+box.execute("CREATE UNIQUE INDEX i ON tj (s2);")
+box.execute("REPLACE INTO tj VALUES (1, 3);")
+box.execute("SELECT * FROM tj;")
+box.execute("INSERT INTO tj VALUES (2, 4), (3, 5);")
+box.execute("UPDATE OR REPLACE tj SET s2 = s2 + 1;")
+box.execute("SELECT * FROM tj;")
 
-box.sql.execute("DROP TABLE tj;")
+box.execute("DROP TABLE tj;")
diff --git a/test/sql/persistency.result b/test/sql/persistency.result
index 31c844f..9e5994b 100644
--- a/test/sql/persistency.result
+++ b/test/sql/persistency.result
@@ -7,159 +7,343 @@ test_run = env.new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- create space
-box.sql.execute("CREATE TABLE foobar (foo INT PRIMARY KEY, bar TEXT)")
+box.execute("CREATE TABLE foobar (foo INT PRIMARY KEY, bar TEXT)")
 ---
+- rowcount: 1
 ...
 -- prepare data
-box.sql.execute("INSERT INTO foobar VALUES (1, 'foo')")
+box.execute("INSERT INTO foobar VALUES (1, 'foo')")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO foobar VALUES (2, 'bar')")
+box.execute("INSERT INTO foobar VALUES (2, 'bar')")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO foobar VALUES (1000, 'foobar')")
+box.execute("INSERT INTO foobar VALUES (1000, 'foobar')")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO foobar VALUES (1, 'duplicate')")
+box.execute("INSERT INTO foobar VALUES (1, 'duplicate')")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_FOOBAR_1' in space 'FOOBAR'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_FOOBAR_1'' in space ''FOOBAR'''
 ...
 -- simple select
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
   - ['foobar', 1000, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar LIMIT 2")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar LIMIT 2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=2")
----
-- - ['bar', 2, 42, 'awesome']
-...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>2")
----
-- - ['foobar', 1000, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['bar', 2, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>=2")
----
-- - ['bar', 2, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
   - ['foobar', 1000, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=10000")
----
-- []
-...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>10000")
----
-- []
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>=2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['bar', 2, 42, 'awesome']
+  - ['foobar', 1000, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=10000")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows: []
+...
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>10000")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows: []
+...
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2.001")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2.001")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<=2")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<=2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<100")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<100")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE bar='foo'")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE bar='foo'")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
 ...
-box.sql.execute("SELECT count(*) FROM foobar")
+box.execute("SELECT count(*) FROM foobar")
 ---
-- - [3]
+- metadata:
+  - name: count(*)
+    type: INTEGER
+  rows:
+  - [3]
 ...
-box.sql.execute("SELECT count(*) FROM foobar WHERE bar='foo'")
+box.execute("SELECT count(*) FROM foobar WHERE bar='foo'")
 ---
-- - [1]
+- metadata:
+  - name: count(*)
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar")
----
-- - ['bar', 2, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar")
+---
+- metadata:
+  - name: BAR
+    type: BLOB
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['bar', 2, 42, 'awesome']
   - ['foo', 1, 42, 'awesome']
   - ['foobar', 1000, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar DESC")
----
-- - ['foobar', 1000, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar DESC")
+---
+- metadata:
+  - name: BAR
+    type: BLOB
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foobar', 1000, 42, 'awesome']
   - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
 ...
 -- updates
-box.sql.execute("REPLACE INTO foobar VALUES (1, 'cacodaemon')")
+box.execute("REPLACE INTO foobar VALUES (1, 'cacodaemon')")
 ---
+- rowcount: 2
 ...
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE foo=1")
+box.execute("SELECT COUNT(*) FROM foobar WHERE foo=1")
 ---
-- - [1]
+- metadata:
+  - name: COUNT(*)
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
+box.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
 ---
-- - [1]
+- metadata:
+  - name: COUNT(*)
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("DELETE FROM foobar WHERE bar='cacodaemon'")
+box.execute("DELETE FROM foobar WHERE bar='cacodaemon'")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
+box.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
 ---
-- - [0]
+- metadata:
+  - name: COUNT(*)
+    type: INTEGER
+  rows:
+  - [0]
 ...
 -- multi-index
 -- create space
-box.sql.execute("CREATE TABLE barfoo (bar TEXT, foo FLOAT PRIMARY KEY)")
+box.execute("CREATE TABLE barfoo (bar TEXT, foo FLOAT PRIMARY KEY)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE UNIQUE INDEX barfoo2 ON barfoo(bar)")
+box.execute("CREATE UNIQUE INDEX barfoo2 ON barfoo(bar)")
 ---
+- rowcount: 1
 ...
 -- prepare data
-box.sql.execute("INSERT INTO barfoo VALUES ('foo', 1)")
+box.execute("INSERT INTO barfoo VALUES ('foo', 1)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO barfoo VALUES ('bar', 2)")
+box.execute("INSERT INTO barfoo VALUES ('bar', 2)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO barfoo VALUES ('foobar', 1000)")
+box.execute("INSERT INTO barfoo VALUES ('foobar', 1000)")
 ---
+- rowcount: 1
 ...
 -- create a trigger
-box.sql.execute("CREATE TRIGGER tfoobar AFTER INSERT ON foobar BEGIN INSERT INTO barfoo VALUES ('trigger test', 9999); END")
+box.execute("CREATE TRIGGER tfoobar AFTER INSERT ON foobar BEGIN INSERT INTO barfoo VALUES ('trigger test', 9999); END")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
 ---
-- - ['TFOOBAR', {'sql': 'CREATE TRIGGER tfoobar AFTER INSERT ON foobar BEGIN INSERT
+- metadata:
+  - name: name
+    type: TEXT
+  - name: opts
+    type: UNKNOWN
+  rows:
+  - ['TFOOBAR', {'sql': 'CREATE TRIGGER tfoobar AFTER INSERT ON foobar BEGIN INSERT
         INTO barfoo VALUES (''trigger test'', 9999); END'}]
 ...
 -- Many entries
-box.sql.execute("CREATE TABLE t1(a INT,b INT,c INT,PRIMARY KEY(b,c));")
+box.execute("CREATE TABLE t1(a INT,b INT,c INT,PRIMARY KEY(b,c));")
 ---
+- rowcount: 1
 ...
-box.sql.execute("WITH RECURSIVE cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<1000) INSERT INTO t1 SELECT x, x%40, x/40 FROM cnt;")
+box.execute("WITH RECURSIVE cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<1000) INSERT INTO t1 SELECT x, x%40, x/40 FROM cnt;")
 ---
+- rowcount: 1000
 ...
-box.sql.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
+box.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
 ---
-- - [840]
+- metadata:
+  - name: A
+    type: BLOB
+  rows:
+  - [840]
   - [880]
   - [920]
   - [960]
@@ -172,59 +356,99 @@ box.sql.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
 ...
 test_run:cmd('restart server default');
 -- prove that trigger survived
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
----
-- - ['TFOOBAR', {'sql': 'CREATE TRIGGER tfoobar AFTER INSERT ON foobar BEGIN INSERT
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
+---
+- metadata:
+  - name: name
+    type: TEXT
+  - name: opts
+    type: UNKNOWN
+  rows:
+  - ['TFOOBAR', {'sql': 'CREATE TRIGGER tfoobar AFTER INSERT ON foobar BEGIN INSERT
         INTO barfoo VALUES (''trigger test'', 9999); END'}]
 ...
 -- ... functional
-box.sql.execute("INSERT INTO foobar VALUES ('foobar trigger test', 8888)")
+box.execute("INSERT INTO foobar VALUES ('foobar trigger test', 8888)")
 ---
 - error: 'Type mismatch: can not convert foobar trigger test to integer'
 ...
-box.sql.execute("SELECT * FROM barfoo WHERE foo = 9999");
+box.execute("SELECT * FROM barfoo WHERE foo = 9999");
 ---
-- []
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: NUMERIC
+  rows: []
 ...
 -- and still persistent
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
----
-- - ['TFOOBAR', {'sql': 'CREATE TRIGGER tfoobar AFTER INSERT ON foobar BEGIN INSERT
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
+---
+- metadata:
+  - name: name
+    type: TEXT
+  - name: opts
+    type: UNKNOWN
+  rows:
+  - ['TFOOBAR', {'sql': 'CREATE TRIGGER tfoobar AFTER INSERT ON foobar BEGIN INSERT
         INTO barfoo VALUES (''trigger test'', 9999); END'}]
 ...
 -- and can be dropped just once
-box.sql.execute("DROP TRIGGER tfoobar")
+box.execute("DROP TRIGGER tfoobar")
 ---
+- rowcount: 1
 ...
 -- Should error
-box.sql.execute("DROP TRIGGER tfoobar")
+box.execute("DROP TRIGGER tfoobar")
 ---
 - error: Trigger 'TFOOBAR' doesn't exist
 ...
 -- Should be empty
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
 ---
-- []
+- metadata:
+  - name: name
+    type: TEXT
+  - name: opts
+    type: UNKNOWN
+  rows: []
 ...
 -- prove barfoo2 still exists
-box.sql.execute("INSERT INTO barfoo VALUES ('xfoo', 1)")
+box.execute("INSERT INTO barfoo VALUES ('xfoo', 1)")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_BARFOO_1' in space 'BARFOO'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_BARFOO_1'' in space ''BARFOO'''
 ...
-box.sql.execute("SELECT * FROM barfoo")
+box.execute("SELECT * FROM barfoo")
 ---
-- - ['foo', 1]
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: NUMERIC
+  rows:
+  - ['foo', 1]
   - ['bar', 2]
   - ['foobar', 1000]
 ...
-box.sql.execute("SELECT * FROM foobar");
+box.execute("SELECT * FROM foobar");
 ---
-- - [2, 'bar']
+- metadata:
+  - name: FOO
+    type: INTEGER
+  - name: BAR
+    type: TEXT
+  rows:
+  - [2, 'bar']
   - [1000, 'foobar']
 ...
-box.sql.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
+box.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
 ---
-- - [840]
+- metadata:
+  - name: A
+    type: BLOB
+  rows:
+  - [840]
   - [880]
   - [920]
   - [960]
@@ -236,12 +460,15 @@ box.sql.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
   - [161]
 ...
 -- cleanup
-box.sql.execute("DROP TABLE foobar")
+box.execute("DROP TABLE foobar")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE barfoo")
+box.execute("DROP TABLE barfoo")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t1")
+box.execute("DROP TABLE t1")
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/persistency.test.lua b/test/sql/persistency.test.lua
index 67659e8..bad2d69 100644
--- a/test/sql/persistency.test.lua
+++ b/test/sql/persistency.test.lua
@@ -1,90 +1,90 @@
 env = require('test_run')
 test_run = env.new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- create space
-box.sql.execute("CREATE TABLE foobar (foo INT PRIMARY KEY, bar TEXT)")
+box.execute("CREATE TABLE foobar (foo INT PRIMARY KEY, bar TEXT)")
 
 -- prepare data
-box.sql.execute("INSERT INTO foobar VALUES (1, 'foo')")
-box.sql.execute("INSERT INTO foobar VALUES (2, 'bar')")
-box.sql.execute("INSERT INTO foobar VALUES (1000, 'foobar')")
+box.execute("INSERT INTO foobar VALUES (1, 'foo')")
+box.execute("INSERT INTO foobar VALUES (2, 'bar')")
+box.execute("INSERT INTO foobar VALUES (1000, 'foobar')")
 
-box.sql.execute("INSERT INTO foobar VALUES (1, 'duplicate')")
+box.execute("INSERT INTO foobar VALUES (1, 'duplicate')")
 
 -- simple select
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar LIMIT 2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>=2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=10000")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>10000")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2.001")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<=2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<100")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE bar='foo'")
-box.sql.execute("SELECT count(*) FROM foobar")
-box.sql.execute("SELECT count(*) FROM foobar WHERE bar='foo'")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar DESC")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar LIMIT 2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>=2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=10000")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>10000")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2.001")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<=2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<100")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE bar='foo'")
+box.execute("SELECT count(*) FROM foobar")
+box.execute("SELECT count(*) FROM foobar WHERE bar='foo'")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar DESC")
 
 -- updates
-box.sql.execute("REPLACE INTO foobar VALUES (1, 'cacodaemon')")
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE foo=1")
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
-box.sql.execute("DELETE FROM foobar WHERE bar='cacodaemon'")
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
+box.execute("REPLACE INTO foobar VALUES (1, 'cacodaemon')")
+box.execute("SELECT COUNT(*) FROM foobar WHERE foo=1")
+box.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
+box.execute("DELETE FROM foobar WHERE bar='cacodaemon'")
+box.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
 
 -- multi-index
 
 -- create space
-box.sql.execute("CREATE TABLE barfoo (bar TEXT, foo FLOAT PRIMARY KEY)")
-box.sql.execute("CREATE UNIQUE INDEX barfoo2 ON barfoo(bar)")
+box.execute("CREATE TABLE barfoo (bar TEXT, foo FLOAT PRIMARY KEY)")
+box.execute("CREATE UNIQUE INDEX barfoo2 ON barfoo(bar)")
 
 -- prepare data
-box.sql.execute("INSERT INTO barfoo VALUES ('foo', 1)")
-box.sql.execute("INSERT INTO barfoo VALUES ('bar', 2)")
-box.sql.execute("INSERT INTO barfoo VALUES ('foobar', 1000)")
+box.execute("INSERT INTO barfoo VALUES ('foo', 1)")
+box.execute("INSERT INTO barfoo VALUES ('bar', 2)")
+box.execute("INSERT INTO barfoo VALUES ('foobar', 1000)")
 
 -- create a trigger
-box.sql.execute("CREATE TRIGGER tfoobar AFTER INSERT ON foobar BEGIN INSERT INTO barfoo VALUES ('trigger test', 9999); END")
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
+box.execute("CREATE TRIGGER tfoobar AFTER INSERT ON foobar BEGIN INSERT INTO barfoo VALUES ('trigger test', 9999); END")
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
 
 -- Many entries
-box.sql.execute("CREATE TABLE t1(a INT,b INT,c INT,PRIMARY KEY(b,c));")
-box.sql.execute("WITH RECURSIVE cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<1000) INSERT INTO t1 SELECT x, x%40, x/40 FROM cnt;")
-box.sql.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
+box.execute("CREATE TABLE t1(a INT,b INT,c INT,PRIMARY KEY(b,c));")
+box.execute("WITH RECURSIVE cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<1000) INSERT INTO t1 SELECT x, x%40, x/40 FROM cnt;")
+box.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
 
 test_run:cmd('restart server default');
 
 -- prove that trigger survived
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
 
 -- ... functional
-box.sql.execute("INSERT INTO foobar VALUES ('foobar trigger test', 8888)")
-box.sql.execute("SELECT * FROM barfoo WHERE foo = 9999");
+box.execute("INSERT INTO foobar VALUES ('foobar trigger test', 8888)")
+box.execute("SELECT * FROM barfoo WHERE foo = 9999");
 
 -- and still persistent
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
 
 -- and can be dropped just once
-box.sql.execute("DROP TRIGGER tfoobar")
+box.execute("DROP TRIGGER tfoobar")
 -- Should error
-box.sql.execute("DROP TRIGGER tfoobar")
+box.execute("DROP TRIGGER tfoobar")
 -- Should be empty
-box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
+box.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"")
 
 -- prove barfoo2 still exists
-box.sql.execute("INSERT INTO barfoo VALUES ('xfoo', 1)")
+box.execute("INSERT INTO barfoo VALUES ('xfoo', 1)")
 
-box.sql.execute("SELECT * FROM barfoo")
-box.sql.execute("SELECT * FROM foobar");
-box.sql.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
+box.execute("SELECT * FROM barfoo")
+box.execute("SELECT * FROM foobar");
+box.execute("SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;");
 
 -- cleanup
-box.sql.execute("DROP TABLE foobar")
-box.sql.execute("DROP TABLE barfoo")
-box.sql.execute("DROP TABLE t1")
+box.execute("DROP TABLE foobar")
+box.execute("DROP TABLE barfoo")
+box.execute("DROP TABLE t1")
diff --git a/test/sql/row-count.result b/test/sql/row-count.result
index b75298f..fe48430 100644
--- a/test/sql/row-count.result
+++ b/test/sql/row-count.result
@@ -4,208 +4,338 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- Test cases concerning row count calculations.
 --
-box.sql.execute("CREATE TABLE t1 (s1 VARCHAR(10) PRIMARY KEY);")
+box.execute("CREATE TABLE t1 (s1 VARCHAR(10) PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [1]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [0]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [0]
 ...
-box.sql.execute("CREATE TABLE t2 (s1 VARCHAR(10) PRIMARY KEY, s2 VARCHAR(10) REFERENCES t1 ON DELETE CASCADE);")
+box.execute("CREATE TABLE t2 (s1 VARCHAR(10) PRIMARY KEY, s2 VARCHAR(10) REFERENCES t1 ON DELETE CASCADE);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [1]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("CREATE TABLE t3 (i1 INT UNIQUE, i2 INT, i3 INT PRIMARY KEY);")
+box.execute("CREATE TABLE t3 (i1 INT UNIQUE, i2 INT, i3 INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3 VALUES (0, 0, 0);")
+box.execute("INSERT INTO t3 VALUES (0, 0, 0);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [1]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("CREATE TRIGGER x AFTER DELETE ON t1 FOR EACH ROW BEGIN UPDATE t3 SET i1 = i1 + ROW_COUNT(); END;")
+box.execute("CREATE TRIGGER x AFTER DELETE ON t1 FOR EACH ROW BEGIN UPDATE t3 SET i1 = i1 + ROW_COUNT(); END;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [1]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("INSERT INTO t1 VALUES ('a');")
+box.execute("INSERT INTO t1 VALUES ('a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [1]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("INSERT INTO t2 VALUES ('a','a');")
+box.execute("INSERT INTO t2 VALUES ('a','a');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [1]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("INSERT INTO t1 VALUES ('b'), ('c'), ('d');")
+box.execute("INSERT INTO t1 VALUES ('b'), ('c'), ('d');")
 ---
+- rowcount: 3
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [3]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [3]
 ...
 -- REPLACE is accounted for two operations: DELETE + INSERT.
-box.sql.execute("REPLACE INTO t2 VALUES('a', 'c');")
+box.execute("REPLACE INTO t2 VALUES('a', 'c');")
 ---
+- rowcount: 2
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [2]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [2]
 ...
-box.sql.execute("DELETE FROM t1;")
+box.execute("DELETE FROM t1;")
 ---
+- rowcount: 4
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [4]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [4]
 ...
-box.sql.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
+box.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
 ---
+- rowcount: 3
 ...
-box.sql.execute("TRUNCATE TABLE t3;")
+box.execute("TRUNCATE TABLE t3;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [0]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [0]
 ...
-box.sql.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
+box.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
 ---
+- rowcount: 3
 ...
-box.sql.execute("UPDATE t3 SET i2 = 666;")
+box.execute("UPDATE t3 SET i2 = 666;")
 ---
+- rowcount: 3
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [3]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [3]
 ...
 -- gh-3816: DELETE optimization returns valid number of
 -- deleted tuples.
 --
-box.sql.execute("DELETE FROM t3 WHERE 0 = 0;")
+box.execute("DELETE FROM t3 WHERE 0 = 0;")
 ---
+- rowcount: 3
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [3]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [3]
 ...
-box.sql.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
+box.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
 ---
+- rowcount: 3
 ...
-box.sql.execute("DELETE FROM t3")
+box.execute("DELETE FROM t3")
 ---
+- rowcount: 3
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [3]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [3]
 ...
 -- But triggers still should't be accounted.
 --
-box.sql.execute("CREATE TABLE tt1 (id INT PRIMARY KEY);")
+box.execute("CREATE TABLE tt1 (id INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE tt2 (id INT PRIMARY KEY);")
+box.execute("CREATE TABLE tt2 (id INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER tr1 AFTER DELETE ON tt1 BEGIN DELETE FROM tt2; END;")
+box.execute("CREATE TRIGGER tr1 AFTER DELETE ON tt1 BEGIN DELETE FROM tt2; END;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO tt1 VALUES (1), (2), (3);")
+box.execute("INSERT INTO tt1 VALUES (1), (2), (3);")
 ---
+- rowcount: 3
 ...
-box.sql.execute("INSERT INTO tt2 VALUES (1), (2), (3);")
+box.execute("INSERT INTO tt2 VALUES (1), (2), (3);")
 ---
+- rowcount: 3
 ...
-box.sql.execute("DELETE FROM tt1 WHERE id = 2;")
+box.execute("DELETE FROM tt1 WHERE id = 2;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [1]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("SELECT * FROM tt2;")
+box.execute("SELECT * FROM tt2;")
 ---
-- []
+- metadata:
+  - name: ID
+    type: INTEGER
+  rows: []
 ...
-box.sql.execute("DROP TABLE tt1;")
+box.execute("DROP TABLE tt1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE tt2;")
+box.execute("DROP TABLE tt2;")
 ---
+- rowcount: 1
 ...
 -- All statements which are not accounted as DML should
 -- return 0 (zero) as a row count.
 --
-box.sql.execute("START TRANSACTION;")
+box.execute("START TRANSACTION;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [0]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [0]
 ...
-box.sql.execute("COMMIT;")
+box.execute("COMMIT;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [0]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [0]
 ...
-box.sql.execute("COMMIT;")
+box.execute("COMMIT;")
 ---
-- error: cannot commit - no transaction is active
+- error: 'Error during execution of VDBE byte-code: cannot commit - no transaction
+    is active'
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [0]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [0]
 ...
-box.sql.execute("ANALYZE;")
+box.execute("ANALYZE;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [0]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [0]
 ...
-box.sql.execute("EXPLAIN QUERY PLAN INSERT INTO t1 VALUES ('b'), ('c'), ('d');")
+box.execute("EXPLAIN QUERY PLAN INSERT INTO t1 VALUES ('b'), ('c'), ('d');")
 ---
-- - [0, 0, 0, 'SCAN TABLE T2']
+- metadata:
+  - name: selectid
+    type: INTEGER
+  - name: order
+    type: INTEGER
+  - name: from
+    type: INTEGER
+  - name: detail
+    type: TEXT
+  rows:
+  - [0, 0, 0, 'SCAN TABLE T2']
 ...
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
 ---
-- - [0]
+- metadata:
+  - name: ROW_COUNT()
+    type: INTEGER
+  rows:
+  - [0]
 ...
-box.sql.execute('PRAGMA recursive_triggers')
+box.execute('PRAGMA recursive_triggers')
 ---
-- - [1]
+- metadata:
+  - name: recursive_triggers
+    type: INTEGER
+  rows:
+  - [1]
 ...
 -- Clean-up.
 --
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t2;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t3;")
+box.execute("DROP TABLE t3;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/row-count.test.lua b/test/sql/row-count.test.lua
index 89476c7..590e5d0 100644
--- a/test/sql/row-count.test.lua
+++ b/test/sql/row-count.test.lua
@@ -1,75 +1,75 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- Test cases concerning row count calculations.
 --
-box.sql.execute("CREATE TABLE t1 (s1 VARCHAR(10) PRIMARY KEY);")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("CREATE TABLE t2 (s1 VARCHAR(10) PRIMARY KEY, s2 VARCHAR(10) REFERENCES t1 ON DELETE CASCADE);")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("CREATE TABLE t3 (i1 INT UNIQUE, i2 INT, i3 INT PRIMARY KEY);")
-box.sql.execute("INSERT INTO t3 VALUES (0, 0, 0);")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("CREATE TRIGGER x AFTER DELETE ON t1 FOR EACH ROW BEGIN UPDATE t3 SET i1 = i1 + ROW_COUNT(); END;")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("INSERT INTO t1 VALUES ('a');")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("INSERT INTO t2 VALUES ('a','a');")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("INSERT INTO t1 VALUES ('b'), ('c'), ('d');")
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("CREATE TABLE t1 (s1 VARCHAR(10) PRIMARY KEY);")
+box.execute("SELECT ROW_COUNT();")
+box.execute("SELECT ROW_COUNT();")
+box.execute("CREATE TABLE t2 (s1 VARCHAR(10) PRIMARY KEY, s2 VARCHAR(10) REFERENCES t1 ON DELETE CASCADE);")
+box.execute("SELECT ROW_COUNT();")
+box.execute("CREATE TABLE t3 (i1 INT UNIQUE, i2 INT, i3 INT PRIMARY KEY);")
+box.execute("INSERT INTO t3 VALUES (0, 0, 0);")
+box.execute("SELECT ROW_COUNT();")
+box.execute("CREATE TRIGGER x AFTER DELETE ON t1 FOR EACH ROW BEGIN UPDATE t3 SET i1 = i1 + ROW_COUNT(); END;")
+box.execute("SELECT ROW_COUNT();")
+box.execute("INSERT INTO t1 VALUES ('a');")
+box.execute("SELECT ROW_COUNT();")
+box.execute("INSERT INTO t2 VALUES ('a','a');")
+box.execute("SELECT ROW_COUNT();")
+box.execute("INSERT INTO t1 VALUES ('b'), ('c'), ('d');")
+box.execute("SELECT ROW_COUNT();")
 -- REPLACE is accounted for two operations: DELETE + INSERT.
-box.sql.execute("REPLACE INTO t2 VALUES('a', 'c');")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("DELETE FROM t1;")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
-box.sql.execute("TRUNCATE TABLE t3;")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
-box.sql.execute("UPDATE t3 SET i2 = 666;")
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("REPLACE INTO t2 VALUES('a', 'c');")
+box.execute("SELECT ROW_COUNT();")
+box.execute("DELETE FROM t1;")
+box.execute("SELECT ROW_COUNT();")
+box.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
+box.execute("TRUNCATE TABLE t3;")
+box.execute("SELECT ROW_COUNT();")
+box.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
+box.execute("UPDATE t3 SET i2 = 666;")
+box.execute("SELECT ROW_COUNT();")
 -- gh-3816: DELETE optimization returns valid number of
 -- deleted tuples.
 --
-box.sql.execute("DELETE FROM t3 WHERE 0 = 0;")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
-box.sql.execute("DELETE FROM t3")
-box.sql.execute("SELECT ROW_COUNT();")
+box.execute("DELETE FROM t3 WHERE 0 = 0;")
+box.execute("SELECT ROW_COUNT();")
+box.execute("INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);")
+box.execute("DELETE FROM t3")
+box.execute("SELECT ROW_COUNT();")
 -- But triggers still should't be accounted.
 --
-box.sql.execute("CREATE TABLE tt1 (id INT PRIMARY KEY);")
-box.sql.execute("CREATE TABLE tt2 (id INT PRIMARY KEY);")
-box.sql.execute("CREATE TRIGGER tr1 AFTER DELETE ON tt1 BEGIN DELETE FROM tt2; END;")
-box.sql.execute("INSERT INTO tt1 VALUES (1), (2), (3);")
-box.sql.execute("INSERT INTO tt2 VALUES (1), (2), (3);")
-box.sql.execute("DELETE FROM tt1 WHERE id = 2;")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("SELECT * FROM tt2;")
-box.sql.execute("DROP TABLE tt1;")
-box.sql.execute("DROP TABLE tt2;")
+box.execute("CREATE TABLE tt1 (id INT PRIMARY KEY);")
+box.execute("CREATE TABLE tt2 (id INT PRIMARY KEY);")
+box.execute("CREATE TRIGGER tr1 AFTER DELETE ON tt1 BEGIN DELETE FROM tt2; END;")
+box.execute("INSERT INTO tt1 VALUES (1), (2), (3);")
+box.execute("INSERT INTO tt2 VALUES (1), (2), (3);")
+box.execute("DELETE FROM tt1 WHERE id = 2;")
+box.execute("SELECT ROW_COUNT();")
+box.execute("SELECT * FROM tt2;")
+box.execute("DROP TABLE tt1;")
+box.execute("DROP TABLE tt2;")
 
 -- All statements which are not accounted as DML should
 -- return 0 (zero) as a row count.
 --
-box.sql.execute("START TRANSACTION;")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("COMMIT;")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("COMMIT;")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("ANALYZE;")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute("EXPLAIN QUERY PLAN INSERT INTO t1 VALUES ('b'), ('c'), ('d');")
-box.sql.execute("SELECT ROW_COUNT();")
-box.sql.execute('PRAGMA recursive_triggers')
+box.execute("START TRANSACTION;")
+box.execute("SELECT ROW_COUNT();")
+box.execute("COMMIT;")
+box.execute("SELECT ROW_COUNT();")
+box.execute("COMMIT;")
+box.execute("SELECT ROW_COUNT();")
+box.execute("ANALYZE;")
+box.execute("SELECT ROW_COUNT();")
+box.execute("EXPLAIN QUERY PLAN INSERT INTO t1 VALUES ('b'), ('c'), ('d');")
+box.execute("SELECT ROW_COUNT();")
+box.execute('PRAGMA recursive_triggers')
 
 -- Clean-up.
 --
-box.sql.execute("DROP TABLE t2;")
-box.sql.execute("DROP TABLE t3;")
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t3;")
+box.execute("DROP TABLE t1;")
 
diff --git a/test/sql/savepoints.result b/test/sql/savepoints.result
index 8553dd8..d378172 100644
--- a/test/sql/savepoints.result
+++ b/test/sql/savepoints.result
@@ -4,32 +4,33 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- These tests check that SQL savepoints properly work outside
 -- transactions as well as inside transactions started in Lua.
 -- gh-3313
 --
-box.sql.execute('SAVEPOINT t1;');
+box.execute('SAVEPOINT t1;');
 ---
 - error: Can not set a savepoint in absence of active transaction
 ...
-box.sql.execute('RELEASE SAVEPOINT t1;');
+box.execute('RELEASE SAVEPOINT t1;');
 ---
 - error: Can not set a savepoint in absence of active transaction
 ...
-box.sql.execute('ROLLBACK TO SAVEPOINT t1;');
+box.execute('ROLLBACK TO SAVEPOINT t1;');
 ---
 - error: Can not set a savepoint in absence of active transaction
 ...
-box.begin() box.sql.execute('SAVEPOINT t1;') box.sql.execute('RELEASE SAVEPOINT t1;') box.commit();
+box.begin() box.execute('SAVEPOINT t1;') box.execute('RELEASE SAVEPOINT t1;') box.commit();
 ---
 ...
-box.begin() box.sql.execute('SAVEPOINT t1;') box.sql.execute('ROLLBACK TO t1;') box.commit();
+box.begin() box.execute('SAVEPOINT t1;') box.execute('ROLLBACK TO t1;') box.commit();
 ---
 ...
-box.begin() box.sql.execute('SAVEPOINT t1;') box.commit();
+box.begin() box.execute('SAVEPOINT t1;') box.commit();
 ---
 ...
 box.commit();
@@ -43,8 +44,8 @@ test_run:cmd("setopt delimiter ';'")
 ...
 release_sv = function()
     box.begin()
-    box.sql.execute('SAVEPOINT t1;')
-    box.sql.execute('RELEASE SAVEPOINT t1;')
+    box.execute('SAVEPOINT t1;')
+    box.execute('RELEASE SAVEPOINT t1;')
 end;
 ---
 ...
@@ -56,17 +57,17 @@ box.commit();
 ...
 release_sv_fail = function()
     box.begin()
-    box.sql.execute('SAVEPOINT t1;')
-    box.sql.execute('SAVEPOINT t2;')
-    box.sql.execute('RELEASE SAVEPOINT t2;')
-    box.sql.execute('RELEASE SAVEPOINT t1;')
-    box.sql.execute('ROLLBACK TO t1;')
+    box.execute('SAVEPOINT t1;')
+    box.execute('SAVEPOINT t2;')
+    box.execute('RELEASE SAVEPOINT t2;')
+    box.execute('RELEASE SAVEPOINT t1;')
+    box.execute('ROLLBACK TO t1;')
 end;
 ---
 ...
 release_sv_fail();
 ---
-- error: 'no such savepoint: T1'
+- error: 'Error during execution of VDBE byte-code: no such savepoint: T1'
 ...
 box.commit();
 ---
diff --git a/test/sql/savepoints.test.lua b/test/sql/savepoints.test.lua
index a4ed061..b4c6fee 100644
--- a/test/sql/savepoints.test.lua
+++ b/test/sql/savepoints.test.lua
@@ -1,21 +1,21 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- These tests check that SQL savepoints properly work outside
 -- transactions as well as inside transactions started in Lua.
 -- gh-3313
 --
 
-box.sql.execute('SAVEPOINT t1;');
-box.sql.execute('RELEASE SAVEPOINT t1;');
-box.sql.execute('ROLLBACK TO SAVEPOINT t1;');
+box.execute('SAVEPOINT t1;');
+box.execute('RELEASE SAVEPOINT t1;');
+box.execute('ROLLBACK TO SAVEPOINT t1;');
 
-box.begin() box.sql.execute('SAVEPOINT t1;') box.sql.execute('RELEASE SAVEPOINT t1;') box.commit();
+box.begin() box.execute('SAVEPOINT t1;') box.execute('RELEASE SAVEPOINT t1;') box.commit();
 
-box.begin() box.sql.execute('SAVEPOINT t1;') box.sql.execute('ROLLBACK TO t1;') box.commit();
+box.begin() box.execute('SAVEPOINT t1;') box.execute('ROLLBACK TO t1;') box.commit();
 
-box.begin() box.sql.execute('SAVEPOINT t1;') box.commit();
+box.begin() box.execute('SAVEPOINT t1;') box.commit();
 
 box.commit();
 
@@ -25,19 +25,19 @@ test_run:cmd("setopt delimiter ';'")
 
 release_sv = function()
     box.begin()
-    box.sql.execute('SAVEPOINT t1;')
-    box.sql.execute('RELEASE SAVEPOINT t1;')
+    box.execute('SAVEPOINT t1;')
+    box.execute('RELEASE SAVEPOINT t1;')
 end;
 release_sv();
 box.commit();
 
 release_sv_fail = function()
     box.begin()
-    box.sql.execute('SAVEPOINT t1;')
-    box.sql.execute('SAVEPOINT t2;')
-    box.sql.execute('RELEASE SAVEPOINT t2;')
-    box.sql.execute('RELEASE SAVEPOINT t1;')
-    box.sql.execute('ROLLBACK TO t1;')
+    box.execute('SAVEPOINT t1;')
+    box.execute('SAVEPOINT t2;')
+    box.execute('RELEASE SAVEPOINT t2;')
+    box.execute('RELEASE SAVEPOINT t1;')
+    box.execute('ROLLBACK TO t1;')
 end;
 release_sv_fail();
 box.commit();
diff --git a/test/sql/select-null.result b/test/sql/select-null.result
index 5ea23d0..948d53d 100644
--- a/test/sql/select-null.result
+++ b/test/sql/select-null.result
@@ -4,32 +4,45 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
 -- create space
-box.sql.execute("CREATE TABLE t3(id INT, a text, b TEXT, PRIMARY KEY(id))")
+box.execute("CREATE TABLE t3(id INT, a text, b TEXT, PRIMARY KEY(id))")
 ---
+- rowcount: 1
 ...
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 -- Seed entries
-box.sql.execute("INSERT INTO t3 VALUES(1, 'abc',NULL)");
+box.execute("INSERT INTO t3 VALUES(1, 'abc',NULL)");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t3 VALUES(2, NULL,'xyz')");
+box.execute("INSERT INTO t3 VALUES(2, NULL,'xyz')");
 ---
+- rowcount: 1
 ...
 -- Select must return properly decoded `NULL`
-box.sql.execute("SELECT * FROM t3")
----
-- - [1, 'abc', null]
+box.execute("SELECT * FROM t3")
+---
+- metadata:
+  - name: ID
+    type: INTEGER
+  - name: A
+    type: TEXT
+  - name: B
+    type: TEXT
+  rows:
+  - [1, 'abc', null]
   - [2, null, 'xyz']
 ...
 -- Cleanup
-box.sql.execute("DROP TABLE t3")
+box.execute("DROP TABLE t3")
 ---
+- rowcount: 1
 ...
 -- Debug
 -- require("console").start()
diff --git a/test/sql/select-null.test.lua b/test/sql/select-null.test.lua
index ccbc030..a49eb43 100644
--- a/test/sql/select-null.test.lua
+++ b/test/sql/select-null.test.lua
@@ -1,24 +1,24 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- box.cfg()
 
 -- create space
-box.sql.execute("CREATE TABLE t3(id INT, a text, b TEXT, PRIMARY KEY(id))")
+box.execute("CREATE TABLE t3(id INT, a text, b TEXT, PRIMARY KEY(id))")
 
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 
 -- Seed entries
-box.sql.execute("INSERT INTO t3 VALUES(1, 'abc',NULL)");
-box.sql.execute("INSERT INTO t3 VALUES(2, NULL,'xyz')");
+box.execute("INSERT INTO t3 VALUES(1, 'abc',NULL)");
+box.execute("INSERT INTO t3 VALUES(2, NULL,'xyz')");
 
 -- Select must return properly decoded `NULL`
-box.sql.execute("SELECT * FROM t3")
+box.execute("SELECT * FROM t3")
 
 -- Cleanup
-box.sql.execute("DROP TABLE t3")
+box.execute("DROP TABLE t3")
 
 -- Debug
 -- require("console").start()
diff --git a/test/sql/sql-debug.result b/test/sql/sql-debug.result
index a857392..a2aca8b 100644
--- a/test/sql/sql-debug.result
+++ b/test/sql/sql-debug.result
@@ -8,25 +8,37 @@ test_run = require('test_run').new()
 -- gh-3832: Some statements do not return column type
 -- Check that "PRAGMA parser_trace" returns 0 or 1 if called
 -- without parameter.
-result = box.sql.execute('PRAGMA parser_trace')
+result = box.execute('PRAGMA parser_trace').rows
 ---
 ...
-box.sql.execute('PRAGMA parser_trace = 1')
+box.execute('PRAGMA parser_trace = 1')
 ---
+- rowcount: 0
 ...
-box.sql.execute('PRAGMA parser_trace')
+box.execute('PRAGMA parser_trace')
 ---
-- - [1]
+- metadata:
+  - name: parser_trace
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute('PRAGMA parser_trace = '.. result[1][1])
+box.execute('PRAGMA parser_trace = '.. result[1][1])
 ---
+- rowcount: 0
 ...
 --
 -- Make PRAGMA command return the result as a result set.
 --
-box.sql.execute('PRAGMA')
+box.execute('PRAGMA')
 ---
-- - ['case_sensitive_like', 0]
+- metadata:
+  - name: pragma_name
+    type: TEXT
+  - name: pragma_value
+    type: INTEGER
+  rows:
+  - ['case_sensitive_like', 0]
   - ['count_changes', 0]
   - ['defer_foreign_keys', 0]
   - ['full_column_names', 0]
diff --git a/test/sql/sql-debug.test.lua b/test/sql/sql-debug.test.lua
index e429c38..edd0ef4 100644
--- a/test/sql/sql-debug.test.lua
+++ b/test/sql/sql-debug.test.lua
@@ -6,12 +6,12 @@ test_run = require('test_run').new()
 
 -- Check that "PRAGMA parser_trace" returns 0 or 1 if called
 -- without parameter.
-result = box.sql.execute('PRAGMA parser_trace')
-box.sql.execute('PRAGMA parser_trace = 1')
-box.sql.execute('PRAGMA parser_trace')
-box.sql.execute('PRAGMA parser_trace = '.. result[1][1])
+result = box.execute('PRAGMA parser_trace').rows
+box.execute('PRAGMA parser_trace = 1')
+box.execute('PRAGMA parser_trace')
+box.execute('PRAGMA parser_trace = '.. result[1][1])
 
 --
 -- Make PRAGMA command return the result as a result set.
 --
-box.sql.execute('PRAGMA')
+box.execute('PRAGMA')
diff --git a/test/sql/sql-statN-index-drop.result b/test/sql/sql-statN-index-drop.result
index 7605951..0636cd9 100644
--- a/test/sql/sql-statN-index-drop.result
+++ b/test/sql/sql-statN-index-drop.result
@@ -4,130 +4,239 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- Initializing some things.
-box.sql.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT);")
+box.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2(id INT PRIMARY KEY, a INT);")
+box.execute("CREATE TABLE t2(id INT PRIMARY KEY, a INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE INDEX i1 ON t1(a);")
+box.execute("CREATE INDEX i1 ON t1(a);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE INDEX i1 ON t2(a);")
+box.execute("CREATE INDEX i1 ON t2(a);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES(1, 2);")
+box.execute("INSERT INTO t1 VALUES(1, 2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t2 VALUES(1, 2);")
+box.execute("INSERT INTO t2 VALUES(1, 2);")
 ---
+- rowcount: 1
 ...
 -- Analyze.
-box.sql.execute("ANALYZE;")
+box.execute("ANALYZE;")
 ---
+- rowcount: 0
 ...
 -- Checking the data.
-box.sql.execute("SELECT * FROM \"_sql_stat4\";")
----
-- - ['T1', 'I1', '1', '0', '0', !!binary kQI=]
+box.execute("SELECT * FROM \"_sql_stat4\";")
+---
+- metadata:
+  - name: tbl
+    type: TEXT
+  - name: idx
+    type: TEXT
+  - name: neq
+    type: TEXT
+  - name: nlt
+    type: TEXT
+  - name: ndlt
+    type: TEXT
+  - name: sample
+    type: BLOB
+  rows:
+  - ['T1', 'I1', '1', '0', '0', !!binary kQI=]
   - ['T1', 'T1', '1', '0', '0', !!binary kQE=]
   - ['T2', 'I1', '1', '0', '0', !!binary kQI=]
   - ['T2', 'T2', '1', '0', '0', !!binary kQE=]
 ...
-box.sql.execute("SELECT * FROM \"_sql_stat1\";")
----
-- - ['T1', 'I1', '1 1']
+box.execute("SELECT * FROM \"_sql_stat1\";")
+---
+- metadata:
+  - name: tbl
+    type: TEXT
+  - name: idx
+    type: TEXT
+  - name: stat
+    type: TEXT
+  rows:
+  - ['T1', 'I1', '1 1']
   - ['T1', 'T1', '1 1']
   - ['T2', 'I1', '1 1']
   - ['T2', 'T2', '1 1']
 ...
 -- Dropping an index.
-box.sql.execute("DROP INDEX i1 ON t1;")
+box.execute("DROP INDEX i1 ON t1;")
 ---
+- rowcount: 3
 ...
 -- Checking the DROP INDEX results.
-box.sql.execute("SELECT * FROM \"_sql_stat4\";")
----
-- - ['T1', 'T1', '1', '0', '0', !!binary kQE=]
+box.execute("SELECT * FROM \"_sql_stat4\";")
+---
+- metadata:
+  - name: tbl
+    type: TEXT
+  - name: idx
+    type: TEXT
+  - name: neq
+    type: TEXT
+  - name: nlt
+    type: TEXT
+  - name: ndlt
+    type: TEXT
+  - name: sample
+    type: BLOB
+  rows:
+  - ['T1', 'T1', '1', '0', '0', !!binary kQE=]
   - ['T2', 'I1', '1', '0', '0', !!binary kQI=]
   - ['T2', 'T2', '1', '0', '0', !!binary kQE=]
 ...
-box.sql.execute("SELECT * FROM \"_sql_stat1\";")
+box.execute("SELECT * FROM \"_sql_stat1\";")
 ---
-- - ['T1', 'T1', '1 1']
+- metadata:
+  - name: tbl
+    type: TEXT
+  - name: idx
+    type: TEXT
+  - name: stat
+    type: TEXT
+  rows:
+  - ['T1', 'T1', '1 1']
   - ['T2', 'I1', '1 1']
   - ['T2', 'T2', '1 1']
 ...
 --Cleaning up.
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 3
 ...
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t2;")
 ---
+- rowcount: 5
 ...
 -- Same test but dropping an INDEX ON t2.
-box.sql.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT);")
+box.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2(id INT PRIMARY KEY, a INT);")
+box.execute("CREATE TABLE t2(id INT PRIMARY KEY, a INT);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE INDEX i1 ON t1(a);")
+box.execute("CREATE INDEX i1 ON t1(a);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE INDEX i1 ON t2(a);")
+box.execute("CREATE INDEX i1 ON t2(a);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES(1, 2);")
+box.execute("INSERT INTO t1 VALUES(1, 2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t2 VALUES(1, 2);")
+box.execute("INSERT INTO t2 VALUES(1, 2);")
 ---
+- rowcount: 1
 ...
 -- Analyze.
-box.sql.execute("ANALYZE;")
+box.execute("ANALYZE;")
 ---
+- rowcount: 0
 ...
 -- Checking the data.
-box.sql.execute("SELECT * FROM \"_sql_stat4\";")
----
-- - ['T1', 'I1', '1', '0', '0', !!binary kQI=]
+box.execute("SELECT * FROM \"_sql_stat4\";")
+---
+- metadata:
+  - name: tbl
+    type: TEXT
+  - name: idx
+    type: TEXT
+  - name: neq
+    type: TEXT
+  - name: nlt
+    type: TEXT
+  - name: ndlt
+    type: TEXT
+  - name: sample
+    type: BLOB
+  rows:
+  - ['T1', 'I1', '1', '0', '0', !!binary kQI=]
   - ['T1', 'T1', '1', '0', '0', !!binary kQE=]
   - ['T2', 'I1', '1', '0', '0', !!binary kQI=]
   - ['T2', 'T2', '1', '0', '0', !!binary kQE=]
 ...
-box.sql.execute("SELECT * FROM \"_sql_stat1\";")
----
-- - ['T1', 'I1', '1 1']
+box.execute("SELECT * FROM \"_sql_stat1\";")
+---
+- metadata:
+  - name: tbl
+    type: TEXT
+  - name: idx
+    type: TEXT
+  - name: stat
+    type: TEXT
+  rows:
+  - ['T1', 'I1', '1 1']
   - ['T1', 'T1', '1 1']
   - ['T2', 'I1', '1 1']
   - ['T2', 'T2', '1 1']
 ...
 -- Dropping an index.
-box.sql.execute("DROP INDEX i1 ON t2;")
+box.execute("DROP INDEX i1 ON t2;")
 ---
+- rowcount: 3
 ...
 -- Checking the DROP INDEX results.
-box.sql.execute("SELECT * FROM \"_sql_stat4\";")
----
-- - ['T1', 'I1', '1', '0', '0', !!binary kQI=]
+box.execute("SELECT * FROM \"_sql_stat4\";")
+---
+- metadata:
+  - name: tbl
+    type: TEXT
+  - name: idx
+    type: TEXT
+  - name: neq
+    type: TEXT
+  - name: nlt
+    type: TEXT
+  - name: ndlt
+    type: TEXT
+  - name: sample
+    type: BLOB
+  rows:
+  - ['T1', 'I1', '1', '0', '0', !!binary kQI=]
   - ['T1', 'T1', '1', '0', '0', !!binary kQE=]
   - ['T2', 'T2', '1', '0', '0', !!binary kQE=]
 ...
-box.sql.execute("SELECT * FROM \"_sql_stat1\";")
----
-- - ['T1', 'I1', '1 1']
+box.execute("SELECT * FROM \"_sql_stat1\";")
+---
+- metadata:
+  - name: tbl
+    type: TEXT
+  - name: idx
+    type: TEXT
+  - name: stat
+    type: TEXT
+  rows:
+  - ['T1', 'I1', '1 1']
   - ['T1', 'T1', '1 1']
   - ['T2', 'T2', '1 1']
 ...
 --Cleaning up.
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 5
 ...
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t2;")
 ---
+- rowcount: 3
 ...
diff --git a/test/sql/sql-statN-index-drop.test.lua b/test/sql/sql-statN-index-drop.test.lua
index 35f2291..5477a2a 100644
--- a/test/sql/sql-statN-index-drop.test.lua
+++ b/test/sql/sql-statN-index-drop.test.lua
@@ -1,56 +1,56 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- Initializing some things.
-box.sql.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT);")
-box.sql.execute("CREATE TABLE t2(id INT PRIMARY KEY, a INT);")
-box.sql.execute("CREATE INDEX i1 ON t1(a);")
-box.sql.execute("CREATE INDEX i1 ON t2(a);")
-box.sql.execute("INSERT INTO t1 VALUES(1, 2);")
-box.sql.execute("INSERT INTO t2 VALUES(1, 2);")
+box.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT);")
+box.execute("CREATE TABLE t2(id INT PRIMARY KEY, a INT);")
+box.execute("CREATE INDEX i1 ON t1(a);")
+box.execute("CREATE INDEX i1 ON t2(a);")
+box.execute("INSERT INTO t1 VALUES(1, 2);")
+box.execute("INSERT INTO t2 VALUES(1, 2);")
 
 -- Analyze.
-box.sql.execute("ANALYZE;")
+box.execute("ANALYZE;")
 
 -- Checking the data.
-box.sql.execute("SELECT * FROM \"_sql_stat4\";")
-box.sql.execute("SELECT * FROM \"_sql_stat1\";")
+box.execute("SELECT * FROM \"_sql_stat4\";")
+box.execute("SELECT * FROM \"_sql_stat1\";")
 
 -- Dropping an index.
-box.sql.execute("DROP INDEX i1 ON t1;")
+box.execute("DROP INDEX i1 ON t1;")
 
 -- Checking the DROP INDEX results.
-box.sql.execute("SELECT * FROM \"_sql_stat4\";")
-box.sql.execute("SELECT * FROM \"_sql_stat1\";")
+box.execute("SELECT * FROM \"_sql_stat4\";")
+box.execute("SELECT * FROM \"_sql_stat1\";")
 
 --Cleaning up.
-box.sql.execute("DROP TABLE t1;")
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t2;")
 
 -- Same test but dropping an INDEX ON t2.
 
-box.sql.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT);")
-box.sql.execute("CREATE TABLE t2(id INT PRIMARY KEY, a INT);")
-box.sql.execute("CREATE INDEX i1 ON t1(a);")
-box.sql.execute("CREATE INDEX i1 ON t2(a);")
-box.sql.execute("INSERT INTO t1 VALUES(1, 2);")
-box.sql.execute("INSERT INTO t2 VALUES(1, 2);")
+box.execute("CREATE TABLE t1(id INT PRIMARY KEY, a INT);")
+box.execute("CREATE TABLE t2(id INT PRIMARY KEY, a INT);")
+box.execute("CREATE INDEX i1 ON t1(a);")
+box.execute("CREATE INDEX i1 ON t2(a);")
+box.execute("INSERT INTO t1 VALUES(1, 2);")
+box.execute("INSERT INTO t2 VALUES(1, 2);")
 
 -- Analyze.
-box.sql.execute("ANALYZE;")
+box.execute("ANALYZE;")
 
 -- Checking the data.
-box.sql.execute("SELECT * FROM \"_sql_stat4\";")
-box.sql.execute("SELECT * FROM \"_sql_stat1\";")
+box.execute("SELECT * FROM \"_sql_stat4\";")
+box.execute("SELECT * FROM \"_sql_stat1\";")
 
 -- Dropping an index.
-box.sql.execute("DROP INDEX i1 ON t2;")
+box.execute("DROP INDEX i1 ON t2;")
 
 -- Checking the DROP INDEX results.
-box.sql.execute("SELECT * FROM \"_sql_stat4\";")
-box.sql.execute("SELECT * FROM \"_sql_stat1\";")
+box.execute("SELECT * FROM \"_sql_stat4\";")
+box.execute("SELECT * FROM \"_sql_stat1\";")
 
 --Cleaning up.
-box.sql.execute("DROP TABLE t1;")
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t2;")
diff --git a/test/sql/tokenizer.result b/test/sql/tokenizer.result
index 95063b5..47fb9d4 100644
--- a/test/sql/tokenizer.result
+++ b/test/sql/tokenizer.result
@@ -7,8 +7,9 @@ test_run = env.new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 sql_tokenizer = require('sql_tokenizer')
 ---
diff --git a/test/sql/tokenizer.test.lua b/test/sql/tokenizer.test.lua
index 4a4e289..3f5dd12 100644
--- a/test/sql/tokenizer.test.lua
+++ b/test/sql/tokenizer.test.lua
@@ -1,7 +1,7 @@
 env = require('test_run')
 test_run = env.new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 sql_tokenizer = require('sql_tokenizer')
 
diff --git a/test/sql/transition.result b/test/sql/transition.result
index ea110c0..b348730 100644
--- a/test/sql/transition.result
+++ b/test/sql/transition.result
@@ -4,188 +4,395 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- create space
-box.sql.execute("CREATE TABLE foobar (foo INT PRIMARY KEY, bar TEXT)")
+box.execute("CREATE TABLE foobar (foo INT PRIMARY KEY, bar TEXT)")
 ---
+- rowcount: 1
 ...
 -- prepare data
-box.sql.execute("INSERT INTO foobar VALUES (1, 'foo')")
+box.execute("INSERT INTO foobar VALUES (1, 'foo')")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO foobar VALUES (2, 'bar')")
+box.execute("INSERT INTO foobar VALUES (2, 'bar')")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO foobar VALUES (1000, 'foobar')")
+box.execute("INSERT INTO foobar VALUES (1000, 'foobar')")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO foobar VALUES (1, 'duplicate')")
+box.execute("INSERT INTO foobar VALUES (1, 'duplicate')")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_FOOBAR_1' in space 'FOOBAR'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_FOOBAR_1'' in space ''FOOBAR'''
 ...
 -- simple select
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
   - ['foobar', 1000, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar LIMIT 2")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar LIMIT 2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=2")
----
-- - ['bar', 2, 42, 'awesome']
-...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>2")
----
-- - ['foobar', 1000, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['bar', 2, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>=2")
----
-- - ['bar', 2, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
   - ['foobar', 1000, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=10000")
----
-- []
-...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>10000")
----
-- []
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>=2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['bar', 2, 42, 'awesome']
+  - ['foobar', 1000, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=10000")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows: []
+...
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>10000")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows: []
+...
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2.001")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2.001")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<=2")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<=2")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<100")
----
-- - ['foo', 1, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<100")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE bar='foo'")
----
-- - ['foo', 1, 42, 'awesome']
-...
-box.sql.execute("SELECT count(*) FROM foobar")
----
-- - [3]
-...
-box.sql.execute("SELECT count(*) FROM foobar WHERE bar='foo'")
----
-- - [1]
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE bar='foo'")
+---
+- metadata:
+  - name: BAR
+    type: TEXT
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foo', 1, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar")
----
-- - ['bar', 2, 42, 'awesome']
+box.execute("SELECT count(*) FROM foobar")
+---
+- metadata:
+  - name: count(*)
+    type: INTEGER
+  rows:
+  - [3]
+...
+box.execute("SELECT count(*) FROM foobar WHERE bar='foo'")
+---
+- metadata:
+  - name: count(*)
+    type: INTEGER
+  rows:
+  - [1]
+...
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar")
+---
+- metadata:
+  - name: BAR
+    type: BLOB
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['bar', 2, 42, 'awesome']
   - ['foo', 1, 42, 'awesome']
   - ['foobar', 1000, 42, 'awesome']
 ...
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar DESC")
----
-- - ['foobar', 1000, 42, 'awesome']
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar DESC")
+---
+- metadata:
+  - name: BAR
+    type: BLOB
+  - name: FOO
+    type: INTEGER
+  - name: '42'
+    type: INTEGER
+  - name: '''awesome'''
+    type: TEXT
+  rows:
+  - ['foobar', 1000, 42, 'awesome']
   - ['foo', 1, 42, 'awesome']
   - ['bar', 2, 42, 'awesome']
 ...
 -- updates
-box.sql.execute("REPLACE INTO foobar VALUES (1, 'cacodaemon')")
+box.execute("REPLACE INTO foobar VALUES (1, 'cacodaemon')")
 ---
+- rowcount: 2
 ...
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE foo=1")
+box.execute("SELECT COUNT(*) FROM foobar WHERE foo=1")
 ---
-- - [1]
+- metadata:
+  - name: COUNT(*)
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
+box.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
 ---
-- - [1]
+- metadata:
+  - name: COUNT(*)
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("DELETE FROM foobar WHERE bar='cacodaemon'")
+box.execute("DELETE FROM foobar WHERE bar='cacodaemon'")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
+box.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
 ---
-- - [0]
+- metadata:
+  - name: COUNT(*)
+    type: INTEGER
+  rows:
+  - [0]
 ...
 -- multi-index
 -- create space
-box.sql.execute("CREATE TABLE barfoo (bar TEXT, foo FLOAT PRIMARY KEY)")
+box.execute("CREATE TABLE barfoo (bar TEXT, foo FLOAT PRIMARY KEY)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE UNIQUE INDEX barfoo2 ON barfoo(bar)")
+box.execute("CREATE UNIQUE INDEX barfoo2 ON barfoo(bar)")
 ---
+- rowcount: 1
 ...
 -- prepare data
-box.sql.execute("INSERT INTO barfoo VALUES ('foo', 1)")
+box.execute("INSERT INTO barfoo VALUES ('foo', 1)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO barfoo VALUES ('bar', 2)")
+box.execute("INSERT INTO barfoo VALUES ('bar', 2)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO barfoo VALUES ('foobar', 1000)")
+box.execute("INSERT INTO barfoo VALUES ('foobar', 1000)")
 ---
+- rowcount: 1
 ...
 -- prove barfoo2 was created
-box.sql.execute("INSERT INTO barfoo VALUES ('xfoo', 1)")
+box.execute("INSERT INTO barfoo VALUES ('xfoo', 1)")
 ---
-- error: Duplicate key exists in unique index 'pk_unnamed_BARFOO_1' in space 'BARFOO'
+- error: 'Error during execution of VDBE byte-code: Duplicate key exists in unique
+    index ''pk_unnamed_BARFOO_1'' in space ''BARFOO'''
 ...
-box.sql.execute("SELECT foo, bar FROM barfoo")
+box.execute("SELECT foo, bar FROM barfoo")
 ---
-- - [1, 'foo']
+- metadata:
+  - name: FOO
+    type: NUMERIC
+  - name: BAR
+    type: TEXT
+  rows:
+  - [1, 'foo']
   - [2, 'bar']
   - [1000, 'foobar']
 ...
-box.sql.execute("SELECT foo, bar FROM barfoo WHERE foo==2")
+box.execute("SELECT foo, bar FROM barfoo WHERE foo==2")
 ---
-- - [2, 'bar']
+- metadata:
+  - name: FOO
+    type: NUMERIC
+  - name: BAR
+    type: TEXT
+  rows:
+  - [2, 'bar']
 ...
-box.sql.execute("SELECT foo, bar FROM barfoo WHERE bar=='foobar'")
+box.execute("SELECT foo, bar FROM barfoo WHERE bar=='foobar'")
 ---
-- - [1000, 'foobar']
+- metadata:
+  - name: FOO
+    type: NUMERIC
+  - name: BAR
+    type: TEXT
+  rows:
+  - [1000, 'foobar']
 ...
-box.sql.execute("SELECT foo, bar FROM barfoo WHERE foo>=2")
+box.execute("SELECT foo, bar FROM barfoo WHERE foo>=2")
 ---
-- - [2, 'bar']
+- metadata:
+  - name: FOO
+    type: NUMERIC
+  - name: BAR
+    type: TEXT
+  rows:
+  - [2, 'bar']
   - [1000, 'foobar']
 ...
-box.sql.execute("SELECT foo, bar FROM barfoo WHERE foo<=2")
+box.execute("SELECT foo, bar FROM barfoo WHERE foo<=2")
 ---
-- - [1, 'foo']
+- metadata:
+  - name: FOO
+    type: NUMERIC
+  - name: BAR
+    type: TEXT
+  rows:
+  - [1, 'foo']
   - [2, 'bar']
 ...
 -- cleanup
-box.sql.execute("DROP INDEX barfoo2 ON barfoo")
+box.execute("DROP INDEX barfoo2 ON barfoo")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE foobar")
+box.execute("DROP TABLE foobar")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE barfoo")
+box.execute("DROP TABLE barfoo")
 ---
+- rowcount: 1
 ...
 -- attempt to create a table lacking PRIMARY KEY
-box.sql.execute("CREATE TABLE without_rowid_lacking_primary_key(x SCALAR)")
+box.execute("CREATE TABLE without_rowid_lacking_primary_key(x SCALAR)")
 ---
 - error: PRIMARY KEY missing on table WITHOUT_ROWID_LACKING_PRIMARY_KEY
 ...
 -- create a table with implicit indices (used to SEGFAULT)
-box.sql.execute("CREATE TABLE implicit_indices(a INT PRIMARY KEY,b INT,c INT,d TEXT UNIQUE)")
+box.execute("CREATE TABLE implicit_indices(a INT PRIMARY KEY,b INT,c INT,d TEXT UNIQUE)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE implicit_indices")
+box.execute("DROP TABLE implicit_indices")
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/transition.test.lua b/test/sql/transition.test.lua
index 2fbee62..c76ab93 100644
--- a/test/sql/transition.test.lua
+++ b/test/sql/transition.test.lua
@@ -1,70 +1,70 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- create space
-box.sql.execute("CREATE TABLE foobar (foo INT PRIMARY KEY, bar TEXT)")
+box.execute("CREATE TABLE foobar (foo INT PRIMARY KEY, bar TEXT)")
 
 -- prepare data
-box.sql.execute("INSERT INTO foobar VALUES (1, 'foo')")
-box.sql.execute("INSERT INTO foobar VALUES (2, 'bar')")
-box.sql.execute("INSERT INTO foobar VALUES (1000, 'foobar')")
+box.execute("INSERT INTO foobar VALUES (1, 'foo')")
+box.execute("INSERT INTO foobar VALUES (2, 'bar')")
+box.execute("INSERT INTO foobar VALUES (1000, 'foobar')")
 
-box.sql.execute("INSERT INTO foobar VALUES (1, 'duplicate')")
+box.execute("INSERT INTO foobar VALUES (1, 'duplicate')")
 
 -- simple select
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar LIMIT 2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>=2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=10000")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>10000")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2.001")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<=2")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<100")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE bar='foo'")
-box.sql.execute("SELECT count(*) FROM foobar")
-box.sql.execute("SELECT count(*) FROM foobar WHERE bar='foo'")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar")
-box.sql.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar DESC")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar LIMIT 2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>=2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo=10000")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo>10000")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<2.001")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<=2")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE foo<100")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar WHERE bar='foo'")
+box.execute("SELECT count(*) FROM foobar")
+box.execute("SELECT count(*) FROM foobar WHERE bar='foo'")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar")
+box.execute("SELECT bar, foo, 42, 'awesome' FROM foobar ORDER BY bar DESC")
 
 -- updates
-box.sql.execute("REPLACE INTO foobar VALUES (1, 'cacodaemon')")
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE foo=1")
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
-box.sql.execute("DELETE FROM foobar WHERE bar='cacodaemon'")
-box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
+box.execute("REPLACE INTO foobar VALUES (1, 'cacodaemon')")
+box.execute("SELECT COUNT(*) FROM foobar WHERE foo=1")
+box.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
+box.execute("DELETE FROM foobar WHERE bar='cacodaemon'")
+box.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
 
 -- multi-index
 
 -- create space
-box.sql.execute("CREATE TABLE barfoo (bar TEXT, foo FLOAT PRIMARY KEY)")
-box.sql.execute("CREATE UNIQUE INDEX barfoo2 ON barfoo(bar)")
+box.execute("CREATE TABLE barfoo (bar TEXT, foo FLOAT PRIMARY KEY)")
+box.execute("CREATE UNIQUE INDEX barfoo2 ON barfoo(bar)")
 
 -- prepare data
-box.sql.execute("INSERT INTO barfoo VALUES ('foo', 1)")
-box.sql.execute("INSERT INTO barfoo VALUES ('bar', 2)")
-box.sql.execute("INSERT INTO barfoo VALUES ('foobar', 1000)")
+box.execute("INSERT INTO barfoo VALUES ('foo', 1)")
+box.execute("INSERT INTO barfoo VALUES ('bar', 2)")
+box.execute("INSERT INTO barfoo VALUES ('foobar', 1000)")
 
 -- prove barfoo2 was created
-box.sql.execute("INSERT INTO barfoo VALUES ('xfoo', 1)")
+box.execute("INSERT INTO barfoo VALUES ('xfoo', 1)")
 
-box.sql.execute("SELECT foo, bar FROM barfoo")
-box.sql.execute("SELECT foo, bar FROM barfoo WHERE foo==2")
-box.sql.execute("SELECT foo, bar FROM barfoo WHERE bar=='foobar'")
-box.sql.execute("SELECT foo, bar FROM barfoo WHERE foo>=2")
-box.sql.execute("SELECT foo, bar FROM barfoo WHERE foo<=2")
+box.execute("SELECT foo, bar FROM barfoo")
+box.execute("SELECT foo, bar FROM barfoo WHERE foo==2")
+box.execute("SELECT foo, bar FROM barfoo WHERE bar=='foobar'")
+box.execute("SELECT foo, bar FROM barfoo WHERE foo>=2")
+box.execute("SELECT foo, bar FROM barfoo WHERE foo<=2")
 
 -- cleanup
-box.sql.execute("DROP INDEX barfoo2 ON barfoo")
-box.sql.execute("DROP TABLE foobar")
-box.sql.execute("DROP TABLE barfoo")
+box.execute("DROP INDEX barfoo2 ON barfoo")
+box.execute("DROP TABLE foobar")
+box.execute("DROP TABLE barfoo")
 
 -- attempt to create a table lacking PRIMARY KEY
-box.sql.execute("CREATE TABLE without_rowid_lacking_primary_key(x SCALAR)")
+box.execute("CREATE TABLE without_rowid_lacking_primary_key(x SCALAR)")
 
 -- create a table with implicit indices (used to SEGFAULT)
-box.sql.execute("CREATE TABLE implicit_indices(a INT PRIMARY KEY,b INT,c INT,d TEXT UNIQUE)")
-box.sql.execute("DROP TABLE implicit_indices")
+box.execute("CREATE TABLE implicit_indices(a INT PRIMARY KEY,b INT,c INT,d TEXT UNIQUE)")
+box.execute("DROP TABLE implicit_indices")
diff --git a/test/sql/transitive-transactions.result b/test/sql/transitive-transactions.result
index 88685b4..82e0406 100644
--- a/test/sql/transitive-transactions.result
+++ b/test/sql/transitive-transactions.result
@@ -4,8 +4,9 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute("pragma sql_default_engine=\'"..engine.."\'")
+box.execute("pragma sql_default_engine=\'"..engine.."\'")
 ---
+- rowcount: 0
 ...
 test_run:cmd("setopt delimiter ';'")
 ---
@@ -15,28 +16,30 @@ test_run:cmd("setopt delimiter ';'")
 -- between SQL and Lua. In particular, make sure that deferred foreign keys
 -- violations are passed correctly.
 --
-box.begin() box.sql.execute('COMMIT');
+box.begin() box.execute('COMMIT');
 ---
 ...
-box.begin() box.sql.execute('ROLLBACK');
+box.begin() box.execute('ROLLBACK');
 ---
 ...
-box.sql.execute('START TRANSACTION;') box.commit();
+box.execute('START TRANSACTION;') box.commit();
 ---
 ...
-box.sql.execute('START TRANSACTION;') box.rollback();
+box.execute('START TRANSACTION;') box.rollback();
 ---
 ...
-box.sql.execute('CREATE TABLE parent(id INT PRIMARY KEY, y INT UNIQUE);');
+box.execute('CREATE TABLE parent(id INT PRIMARY KEY, y INT UNIQUE);');
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE TABLE child(id INT PRIMARY KEY, x INT REFERENCES parent(y) DEFERRABLE INITIALLY DEFERRED);');
+box.execute('CREATE TABLE child(id INT PRIMARY KEY, x INT REFERENCES parent(y) DEFERRABLE INITIALLY DEFERRED);');
 ---
+- rowcount: 1
 ...
 fk_violation_1 = function()
     box.begin()
-    box.sql.execute('INSERT INTO child VALUES (1, 1);')
-    box.sql.execute('COMMIT;')
+    box.execute('INSERT INTO child VALUES (1, 1);')
+    box.execute('COMMIT;')
 end;
 ---
 ...
@@ -49,8 +52,8 @@ box.space.CHILD:select();
 - []
 ...
 fk_violation_2 = function()
-    box.sql.execute('START TRANSACTION;')
-    box.sql.execute('INSERT INTO child VALUES (1, 1);')
+    box.execute('START TRANSACTION;')
+    box.execute('INSERT INTO child VALUES (1, 1);')
     box.commit()
 end;
 ---
@@ -65,8 +68,8 @@ box.space.CHILD:select();
 ...
 fk_violation_3 = function()
     box.begin()
-    box.sql.execute('INSERT INTO child VALUES (1, 1);')
-    box.sql.execute('INSERT INTO parent VALUES (1, 1);')
+    box.execute('INSERT INTO child VALUES (1, 1);')
+    box.execute('INSERT INTO parent VALUES (1, 1);')
     box.commit()
 end;
 ---
@@ -84,20 +87,20 @@ box.space.PARENT:select();
 ...
 -- Make sure that 'PRAGMA defer_foreign_keys' works.
 --
-box.sql.execute('DROP TABLE child;')
-box.sql.execute('CREATE TABLE child(id INT PRIMARY KEY, x INT REFERENCES parent(y))')
+box.execute('DROP TABLE child;')
+box.execute('CREATE TABLE child(id INT PRIMARY KEY, x INT REFERENCES parent(y))')
 
 fk_defer = function()
     box.begin()
-    box.sql.execute('INSERT INTO child VALUES (1, 2);')
-    box.sql.execute('INSERT INTO parent VALUES (2, 2);')
+    box.execute('INSERT INTO child VALUES (1, 2);')
+    box.execute('INSERT INTO parent VALUES (2, 2);')
     box.commit()
 end;
 ---
 ...
 fk_defer();
 ---
-- error: FOREIGN KEY constraint failed
+- error: 'Error during execution of VDBE byte-code: FOREIGN KEY constraint failed'
 ...
 box.space.CHILD:select();
 ---
@@ -107,7 +110,7 @@ box.space.PARENT:select();
 ---
 - - [1, 1]
 ...
-box.sql.execute('PRAGMA defer_foreign_keys = 1;')
+box.execute('PRAGMA defer_foreign_keys = 1;')
 box.rollback()
 fk_defer();
 ---
@@ -122,11 +125,12 @@ box.space.PARENT:select();
   - [2, 2]
 ...
 -- Cleanup
-box.sql.execute('PRAGMA defer_foreign_keys = 0;')
+box.execute('PRAGMA defer_foreign_keys = 0;')
 
-box.sql.execute('DROP TABLE child;');
+box.execute('DROP TABLE child;');
 ---
 ...
-box.sql.execute('DROP TABLE parent;');
+box.execute('DROP TABLE parent;');
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/transitive-transactions.test.lua b/test/sql/transitive-transactions.test.lua
index 5127202..97b06e5 100644
--- a/test/sql/transitive-transactions.test.lua
+++ b/test/sql/transitive-transactions.test.lua
@@ -1,6 +1,6 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute("pragma sql_default_engine=\'"..engine.."\'")
+box.execute("pragma sql_default_engine=\'"..engine.."\'")
 test_run:cmd("setopt delimiter ';'")
 
 -- These tests are aimed at checking transitive transactions
@@ -8,25 +8,25 @@ test_run:cmd("setopt delimiter ';'")
 -- violations are passed correctly.
 --
 
-box.begin() box.sql.execute('COMMIT');
-box.begin() box.sql.execute('ROLLBACK');
-box.sql.execute('START TRANSACTION;') box.commit();
-box.sql.execute('START TRANSACTION;') box.rollback();
+box.begin() box.execute('COMMIT');
+box.begin() box.execute('ROLLBACK');
+box.execute('START TRANSACTION;') box.commit();
+box.execute('START TRANSACTION;') box.rollback();
 
-box.sql.execute('CREATE TABLE parent(id INT PRIMARY KEY, y INT UNIQUE);');
-box.sql.execute('CREATE TABLE child(id INT PRIMARY KEY, x INT REFERENCES parent(y) DEFERRABLE INITIALLY DEFERRED);');
+box.execute('CREATE TABLE parent(id INT PRIMARY KEY, y INT UNIQUE);');
+box.execute('CREATE TABLE child(id INT PRIMARY KEY, x INT REFERENCES parent(y) DEFERRABLE INITIALLY DEFERRED);');
 
 fk_violation_1 = function()
     box.begin()
-    box.sql.execute('INSERT INTO child VALUES (1, 1);')
-    box.sql.execute('COMMIT;')
+    box.execute('INSERT INTO child VALUES (1, 1);')
+    box.execute('COMMIT;')
 end;
 fk_violation_1();
 box.space.CHILD:select();
 
 fk_violation_2 = function()
-    box.sql.execute('START TRANSACTION;')
-    box.sql.execute('INSERT INTO child VALUES (1, 1);')
+    box.execute('START TRANSACTION;')
+    box.execute('INSERT INTO child VALUES (1, 1);')
     box.commit()
 end;
 fk_violation_2();
@@ -34,8 +34,8 @@ box.space.CHILD:select();
 
 fk_violation_3 = function()
     box.begin()
-    box.sql.execute('INSERT INTO child VALUES (1, 1);')
-    box.sql.execute('INSERT INTO parent VALUES (1, 1);')
+    box.execute('INSERT INTO child VALUES (1, 1);')
+    box.execute('INSERT INTO parent VALUES (1, 1);')
     box.commit()
 end;
 fk_violation_3();
@@ -44,26 +44,26 @@ box.space.PARENT:select();
 
 -- Make sure that 'PRAGMA defer_foreign_keys' works.
 --
-box.sql.execute('DROP TABLE child;')
-box.sql.execute('CREATE TABLE child(id INT PRIMARY KEY, x INT REFERENCES parent(y))')
+box.execute('DROP TABLE child;')
+box.execute('CREATE TABLE child(id INT PRIMARY KEY, x INT REFERENCES parent(y))')
 
 fk_defer = function()
     box.begin()
-    box.sql.execute('INSERT INTO child VALUES (1, 2);')
-    box.sql.execute('INSERT INTO parent VALUES (2, 2);')
+    box.execute('INSERT INTO child VALUES (1, 2);')
+    box.execute('INSERT INTO parent VALUES (2, 2);')
     box.commit()
 end;
 fk_defer();
 box.space.CHILD:select();
 box.space.PARENT:select();
-box.sql.execute('PRAGMA defer_foreign_keys = 1;')
+box.execute('PRAGMA defer_foreign_keys = 1;')
 box.rollback()
 fk_defer();
 box.space.CHILD:select();
 box.space.PARENT:select();
 
-box.sql.execute('PRAGMA defer_foreign_keys = 0;')
+box.execute('PRAGMA defer_foreign_keys = 0;')
 
 -- Cleanup
-box.sql.execute('DROP TABLE child;');
-box.sql.execute('DROP TABLE parent;');
+box.execute('DROP TABLE child;');
+box.execute('DROP TABLE parent;');
diff --git a/test/sql/triggers.result b/test/sql/triggers.result
index 826e998..3f0f388 100644
--- a/test/sql/triggers.result
+++ b/test/sql/triggers.result
@@ -7,8 +7,9 @@ test_run = env.new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- Get invariant part of the tuple; name and opts don't change.
  function immutable_part(data) local r = {} for i, l in pairs(data) do table.insert(r, {l.name, l.opts}) end return r end
@@ -17,14 +18,17 @@ box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
 --
 -- gh-3273: Move Triggers to server
 --
-box.sql.execute("CREATE TABLE t1(x INTEGER PRIMARY KEY);")
+box.execute("CREATE TABLE t1(x INTEGER PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t2(x INTEGER PRIMARY KEY);")
+box.execute("CREATE TABLE t2(x INTEGER PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute([[CREATE TRIGGER t1t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(1); END; ]])
+box.execute([[CREATE TRIGGER t1t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(1); END; ]])
 ---
+- rowcount: 1
 ...
 immutable_part(box.space._trigger:select())
 ---
@@ -64,18 +68,21 @@ immutable_part(box.space._trigger:select())
     - {'sql': 'CREATE TRIGGER t1t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(1);
         END; '}
 ...
-box.sql.execute("DROP TABLE T1;")
+box.execute("DROP TABLE T1;")
 ---
+- rowcount: 1
 ...
 immutable_part(box.space._trigger:select())
 ---
 - []
 ...
-box.sql.execute("CREATE TABLE t1(x INTEGER PRIMARY KEY);")
+box.execute("CREATE TABLE t1(x INTEGER PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute([[CREATE TRIGGER t1t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(1); END; ]])
+box.execute([[CREATE TRIGGER t1t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(1); END; ]])
 ---
+- rowcount: 1
 ...
 immutable_part(box.space._trigger:select())
 ---
@@ -87,15 +94,21 @@ space_id = box.space._space.index["name"]:get('T1').id
 ---
 ...
 -- Test, didn't trigger t1t degrade.
-box.sql.execute("INSERT INTO t1 VALUES(1);")
+box.execute("INSERT INTO t1 VALUES(1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t2;")
+box.execute("SELECT * FROM t2;")
 ---
-- - [1]
+- metadata:
+  - name: X
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("DELETE FROM t2;")
+box.execute("DELETE FROM t2;")
 ---
+- rowcount: 1
 ...
 -- Test triggers.
 tuple = {"T2T", space_id, {sql = "CREATE TRIGGER t2t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(2); END;"}}
@@ -122,21 +135,28 @@ immutable_part(box.space._trigger:select())
     - {'sql': 'CREATE TRIGGER t3t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(3);
         END;'}
 ...
-box.sql.execute("INSERT INTO t1 VALUES(2);")
+box.execute("INSERT INTO t1 VALUES(2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t2;")
+box.execute("SELECT * FROM t2;")
 ---
-- - [1]
+- metadata:
+  - name: X
+    type: INTEGER
+  rows:
+  - [1]
   - [2]
   - [3]
 ...
-box.sql.execute("DELETE FROM t2;")
+box.execute("DELETE FROM t2;")
 ---
+- rowcount: 3
 ...
 -- Test t1t after t2t and t3t drop.
-box.sql.execute("DROP TRIGGER T2T;")
+box.execute("DROP TRIGGER T2T;")
 ---
+- rowcount: 1
 ...
 _ = box.space._trigger:delete("T3T")
 ---
@@ -147,22 +167,30 @@ immutable_part(box.space._trigger:select())
     - {'sql': 'CREATE TRIGGER t1t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(1);
         END; '}
 ...
-box.sql.execute("INSERT INTO t1 VALUES(3);")
+box.execute("INSERT INTO t1 VALUES(3);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t2;")
+box.execute("SELECT * FROM t2;")
 ---
-- - [1]
+- metadata:
+  - name: X
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("DELETE FROM t2;")
+box.execute("DELETE FROM t2;")
 ---
+- rowcount: 1
 ...
 -- Insert new SQL t2t and t3t.
-box.sql.execute([[CREATE TRIGGER t2t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(2); END; ]])
+box.execute([[CREATE TRIGGER t2t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(2); END; ]])
 ---
+- rowcount: 1
 ...
-box.sql.execute([[CREATE TRIGGER t3t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(3); END; ]])
+box.execute([[CREATE TRIGGER t3t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(3); END; ]])
 ---
+- rowcount: 1
 ...
 immutable_part(box.space._trigger:select())
 ---
@@ -176,29 +204,37 @@ immutable_part(box.space._trigger:select())
     - {'sql': 'CREATE TRIGGER t3t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(3);
         END; '}
 ...
-box.sql.execute("INSERT INTO t1 VALUES(4);")
+box.execute("INSERT INTO t1 VALUES(4);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t2;")
+box.execute("SELECT * FROM t2;")
 ---
-- - [1]
+- metadata:
+  - name: X
+    type: INTEGER
+  rows:
+  - [1]
   - [2]
   - [3]
 ...
 -- Clean up.
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t2;")
 ---
+- rowcount: 1
 ...
 immutable_part(box.space._trigger:select())
 ---
 - []
 ...
 -- Test target tables restricts.
-box.sql.execute("CREATE TABLE t1(a INT PRIMARY KEY,b INT);")
+box.execute("CREATE TABLE t1(a INT PRIMARY KEY,b INT);")
 ---
+- rowcount: 1
 ...
 space_id = box.space.T1.id
 ---
@@ -210,8 +246,9 @@ box.space._trigger:insert(tuple)
 ---
 - error: 'SQL error: cannot create INSTEAD OF trigger on space: T1'
 ...
-box.sql.execute("CREATE VIEW V1 AS SELECT * FROM t1;")
+box.execute("CREATE VIEW V1 AS SELECT * FROM t1;")
 ---
+- rowcount: 1
 ...
 space_id = box.space.V1.id
 ---
@@ -240,165 +277,216 @@ box.space._trigger:insert(tuple)
 ---
 - error: 'SQL error: cannot create trigger on system table'
 ...
-box.sql.execute("DROP VIEW V1;")
+box.execute("DROP VIEW V1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE T1;")
+box.execute("DROP TABLE T1;")
 ---
+- rowcount: 1
 ...
 --
 -- 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.execute("PRAGMA sql_default_engine ('vinyl');")
 ---
+- rowcount: 0
 ...
-box.sql.execute("CREATE TABLE m (s0 INT PRIMARY KEY, s1 TEXT UNIQUE);")
+box.execute("CREATE TABLE m (s0 INT PRIMARY KEY, s1 TEXT UNIQUE);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = 'now'; END;")
+box.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = 'now'; END;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("PRAGMA sql_default_engine('memtx');")
+box.execute("PRAGMA sql_default_engine('memtx');")
 ---
+- rowcount: 0
 ...
-box.sql.execute("CREATE TABLE n (s0 INT PRIMARY KEY, s1 TEXT UNIQUE, s2 REAL);")
+box.execute("CREATE TABLE n (s0 INT PRIMARY KEY, s1 TEXT UNIQUE, s2 REAL);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO m VALUES (0, '0');")
+box.execute("INSERT INTO m VALUES (0, '0');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO n VALUES (0, '',null);")
+box.execute("INSERT INTO n VALUES (0, '',null);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("UPDATE m SET s1 = 'The Rain In Spain';")
+box.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.execute("ANALYZE m;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("DROP TABLE m;")
+box.execute("DROP TABLE m;")
 ---
+- rowcount: 5
 ...
-box.sql.execute("DROP TABLE n;")
+box.execute("DROP TABLE n;")
 ---
+- rowcount: 1
 ...
 -- Case 2: Src 'memtx' table; Dst 'vinyl' table
-box.sql.execute("PRAGMA sql_default_engine ('memtx');")
+box.execute("PRAGMA sql_default_engine ('memtx');")
 ---
+- rowcount: 0
 ...
-box.sql.execute("CREATE TABLE m (s0 INT PRIMARY KEY, s1 TEXT UNIQUE);")
+box.execute("CREATE TABLE m (s0 INT PRIMARY KEY, s1 TEXT UNIQUE);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = 'now'; END;")
+box.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = 'now'; END;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("PRAGMA sql_default_engine('vinyl');")
+box.execute("PRAGMA sql_default_engine('vinyl');")
 ---
+- rowcount: 0
 ...
-box.sql.execute("CREATE TABLE n (s0 INT PRIMARY KEY, s1 TEXT UNIQUE, s2 REAL);")
+box.execute("CREATE TABLE n (s0 INT PRIMARY KEY, s1 TEXT UNIQUE, s2 REAL);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO m VALUES (0, '0');")
+box.execute("INSERT INTO m VALUES (0, '0');")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO n VALUES (0, '',null);")
+box.execute("INSERT INTO n VALUES (0, '',null);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("UPDATE m SET s1 = 'The Rain In Spain';")
+box.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.execute("ANALYZE n;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("DROP TABLE m;")
+box.execute("DROP TABLE m;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE n;")
+box.execute("DROP TABLE n;")
 ---
+- rowcount: 5
 ...
 -- Test SQL Transaction with LUA
-box.sql.execute("PRAGMA sql_default_engine ('memtx');")
+box.execute("PRAGMA sql_default_engine ('memtx');")
 ---
+- rowcount: 0
 ...
-box.sql.execute("CREATE TABLE test (id INT PRIMARY KEY)")
+box.execute("CREATE TABLE test (id INT PRIMARY KEY)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("PRAGMA sql_default_engine='vinyl'")
+box.execute("PRAGMA sql_default_engine='vinyl'")
 ---
+- rowcount: 0
 ...
-box.sql.execute("CREATE TABLE test2 (id INT PRIMARY KEY)")
+box.execute("CREATE TABLE test2 (id INT PRIMARY KEY)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO test2 VALUES (2)")
+box.execute("INSERT INTO test2 VALUES (2)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("START TRANSACTION")
+box.execute("START TRANSACTION")
 ---
+- rowcount: 0
 ...
-box.sql.execute("INSERT INTO test VALUES (1)")
+box.execute("INSERT INTO test VALUES (1)")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM test2")
+box.execute("SELECT * FROM test2")
 ---
 - error: A multi-statement transaction can not use multiple storage engines
 ...
-box.sql.execute("ROLLBACK;")
+box.execute("ROLLBACK;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("DROP TABLE test;")
+box.execute("DROP TABLE test;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE test2;")
+box.execute("DROP TABLE test2;")
 ---
+- rowcount: 1
 ...
 --
 -- gh-3536: Some triggers cause error messages and/or half-finished updates
 --
-box.sql.execute("CREATE TABLE t (s1 INT, s2 INT, s3 INT, s4 INT PRIMARY KEY);")
+box.execute("CREATE TABLE t (s1 INT, s2 INT, s3 INT, s4 INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW v AS SELECT s1, s2 FROM t;")
+box.execute("CREATE VIEW v AS SELECT s1, s2 FROM t;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER tv INSTEAD OF UPDATE ON v BEGIN UPDATE t SET s3 = new.s1 WHERE s1 = old.s1; END;")
+box.execute("CREATE TRIGGER tv INSTEAD OF UPDATE ON v BEGIN UPDATE t SET s3 = new.s1 WHERE s1 = old.s1; END;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t VALUES (1,1,1,1);")
+box.execute("INSERT INTO t VALUES (1,1,1,1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("UPDATE v SET s2 = s1 + 1;")
+box.execute("UPDATE v SET s2 = s1 + 1;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("UPDATE v SET s1 = s1 + 5;")
+box.execute("UPDATE v SET s1 = s1 + 5;")
 ---
+- rowcount: 0
 ...
-box.sql.execute("SELECT * FROM t;")
+box.execute("SELECT * FROM t;")
 ---
-- - [1, 1, 6, 1]
+- metadata:
+  - name: S1
+    type: INTEGER
+  - name: S2
+    type: INTEGER
+  - name: S3
+    type: INTEGER
+  - name: S4
+    type: INTEGER
+  rows:
+  - [1, 1, 6, 1]
 ...
-box.sql.execute("DROP VIEW v;")
+box.execute("DROP VIEW v;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t;")
+box.execute("DROP TABLE t;")
 ---
+- rowcount: 1
 ...
 --
 -- gh-3653: Dissallow bindings for DDL
 --
-box.sql.execute("CREATE TABLE t1(a INT PRIMARY KEY, b INT);")
+box.execute("CREATE TABLE t1(a INT PRIMARY KEY, b INT);")
 ---
+- rowcount: 1
 ...
 space_id = box.space.T1.id
 ---
 ...
-box.sql.execute("CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.a = ? BEGIN SELECT 1; END;")
+box.execute("CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.a = ? BEGIN SELECT 1; END;")
 ---
-- error: bindings are not allowed in DDL
+- error: 'Error during execution of VDBE byte-code: bindings are not allowed in DDL'
 ...
 tuple = {"TR1", space_id, {sql = [[CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.a = ? BEGIN SELECT 1; END;]]}}
 ---
@@ -407,6 +495,7 @@ box.space._trigger:insert(tuple)
 ---
 - error: bindings are not allowed in DDL
 ...
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/triggers.test.lua b/test/sql/triggers.test.lua
index b22b4f9..8bd6633 100644
--- a/test/sql/triggers.test.lua
+++ b/test/sql/triggers.test.lua
@@ -1,7 +1,7 @@
 env = require('test_run')
 test_run = env.new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- Get invariant part of the tuple; name and opts don't change.
  function immutable_part(data) local r = {} for i, l in pairs(data) do table.insert(r, {l.name, l.opts}) end return r end
@@ -10,9 +10,9 @@ box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
 -- gh-3273: Move Triggers to server
 --
 
-box.sql.execute("CREATE TABLE t1(x INTEGER PRIMARY KEY);")
-box.sql.execute("CREATE TABLE t2(x INTEGER PRIMARY KEY);")
-box.sql.execute([[CREATE TRIGGER t1t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(1); END; ]])
+box.execute("CREATE TABLE t1(x INTEGER PRIMARY KEY);")
+box.execute("CREATE TABLE t2(x INTEGER PRIMARY KEY);")
+box.execute([[CREATE TRIGGER t1t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(1); END; ]])
 immutable_part(box.space._trigger:select())
 
 space_id = box.space._space.index["name"]:get('T1').id
@@ -28,19 +28,19 @@ tuple = {"T2T", box.space.T1.id + 1, {sql = "CREATE TRIGGER t2t AFTER INSERT ON
 box.space._trigger:insert(tuple)
 immutable_part(box.space._trigger:select())
 
-box.sql.execute("DROP TABLE T1;")
+box.execute("DROP TABLE T1;")
 immutable_part(box.space._trigger:select())
 
-box.sql.execute("CREATE TABLE t1(x INTEGER PRIMARY KEY);")
-box.sql.execute([[CREATE TRIGGER t1t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(1); END; ]])
+box.execute("CREATE TABLE t1(x INTEGER PRIMARY KEY);")
+box.execute([[CREATE TRIGGER t1t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(1); END; ]])
 immutable_part(box.space._trigger:select())
 
 space_id = box.space._space.index["name"]:get('T1').id
 
 -- Test, didn't trigger t1t degrade.
-box.sql.execute("INSERT INTO t1 VALUES(1);")
-box.sql.execute("SELECT * FROM t2;")
-box.sql.execute("DELETE FROM t2;")
+box.execute("INSERT INTO t1 VALUES(1);")
+box.execute("SELECT * FROM t2;")
+box.execute("DELETE FROM t2;")
 
 
 -- Test triggers.
@@ -49,38 +49,38 @@ _ = box.space._trigger:insert(tuple)
 tuple = {"T3T", space_id, {sql = "CREATE TRIGGER t3t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(3); END;"}}
 _ = box.space._trigger:insert(tuple)
 immutable_part(box.space._trigger:select())
-box.sql.execute("INSERT INTO t1 VALUES(2);")
-box.sql.execute("SELECT * FROM t2;")
-box.sql.execute("DELETE FROM t2;")
+box.execute("INSERT INTO t1 VALUES(2);")
+box.execute("SELECT * FROM t2;")
+box.execute("DELETE FROM t2;")
 
 -- Test t1t after t2t and t3t drop.
-box.sql.execute("DROP TRIGGER T2T;")
+box.execute("DROP TRIGGER T2T;")
 _ = box.space._trigger:delete("T3T")
 immutable_part(box.space._trigger:select())
-box.sql.execute("INSERT INTO t1 VALUES(3);")
-box.sql.execute("SELECT * FROM t2;")
-box.sql.execute("DELETE FROM t2;")
+box.execute("INSERT INTO t1 VALUES(3);")
+box.execute("SELECT * FROM t2;")
+box.execute("DELETE FROM t2;")
 
 -- Insert new SQL t2t and t3t.
-box.sql.execute([[CREATE TRIGGER t2t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(2); END; ]])
-box.sql.execute([[CREATE TRIGGER t3t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(3); END; ]])
+box.execute([[CREATE TRIGGER t2t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(2); END; ]])
+box.execute([[CREATE TRIGGER t3t AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(3); END; ]])
 immutable_part(box.space._trigger:select())
-box.sql.execute("INSERT INTO t1 VALUES(4);")
-box.sql.execute("SELECT * FROM t2;")
+box.execute("INSERT INTO t1 VALUES(4);")
+box.execute("SELECT * FROM t2;")
 
 -- Clean up.
-box.sql.execute("DROP TABLE t1;")
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t2;")
 immutable_part(box.space._trigger:select())
 
 -- Test target tables restricts.
-box.sql.execute("CREATE TABLE t1(a INT PRIMARY KEY,b INT);")
+box.execute("CREATE TABLE t1(a INT PRIMARY KEY,b INT);")
 space_id = box.space.T1.id
 
 tuple = {"T1T", space_id, {sql = [[create trigger t1t instead of update on t1 for each row begin delete from t1 WHERE a=old.a+2; end;]]}}
 box.space._trigger:insert(tuple)
 
-box.sql.execute("CREATE VIEW V1 AS SELECT * FROM t1;")
+box.execute("CREATE VIEW V1 AS SELECT * FROM t1;")
 space_id = box.space.V1.id
 
 tuple = {"V1T", space_id, {sql = [[create trigger v1t before update on v1 for each row begin delete from t1 WHERE a=old.a+2; end;]]}}
@@ -93,75 +93,75 @@ space_id =  box.space._sql_stat1.id
 tuple = {"T1T", space_id, {sql = [[create trigger t1t instead of update on "_sql_stat1" for each row begin delete from t1 WHERE a=old.a+2; end;]]}}
 box.space._trigger:insert(tuple)
 
-box.sql.execute("DROP VIEW V1;")
-box.sql.execute("DROP TABLE T1;")
+box.execute("DROP VIEW V1;")
+box.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 (s0 INT PRIMARY KEY, s1 TEXT UNIQUE);")
-box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = 'now'; END;")
-box.sql.execute("PRAGMA sql_default_engine('memtx');")
-box.sql.execute("CREATE TABLE n (s0 INT PRIMARY KEY, s1 TEXT UNIQUE, s2 REAL);")
-box.sql.execute("INSERT INTO m VALUES (0, '0');")
-box.sql.execute("INSERT INTO n VALUES (0, '',null);")
-box.sql.execute("UPDATE m SET s1 = 'The Rain In Spain';")
+box.execute("PRAGMA sql_default_engine ('vinyl');")
+box.execute("CREATE TABLE m (s0 INT PRIMARY KEY, s1 TEXT UNIQUE);")
+box.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = 'now'; END;")
+box.execute("PRAGMA sql_default_engine('memtx');")
+box.execute("CREATE TABLE n (s0 INT PRIMARY KEY, s1 TEXT UNIQUE, s2 REAL);")
+box.execute("INSERT INTO m VALUES (0, '0');")
+box.execute("INSERT INTO n VALUES (0, '',null);")
+box.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;")
+box.execute("ANALYZE m;")
+box.execute("DROP TABLE m;")
+box.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 (s0 INT PRIMARY KEY, s1 TEXT UNIQUE);")
-box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = 'now'; END;")
-box.sql.execute("PRAGMA sql_default_engine('vinyl');")
-box.sql.execute("CREATE TABLE n (s0 INT PRIMARY KEY, s1 TEXT UNIQUE, s2 REAL);")
-box.sql.execute("INSERT INTO m VALUES (0, '0');")
-box.sql.execute("INSERT INTO n VALUES (0, '',null);")
-box.sql.execute("UPDATE m SET s1 = 'The Rain In Spain';")
+box.execute("PRAGMA sql_default_engine ('memtx');")
+box.execute("CREATE TABLE m (s0 INT PRIMARY KEY, s1 TEXT UNIQUE);")
+box.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = 'now'; END;")
+box.execute("PRAGMA sql_default_engine('vinyl');")
+box.execute("CREATE TABLE n (s0 INT PRIMARY KEY, s1 TEXT UNIQUE, s2 REAL);")
+box.execute("INSERT INTO m VALUES (0, '0');")
+box.execute("INSERT INTO n VALUES (0, '',null);")
+box.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;")
+box.execute("ANALYZE n;")
+box.execute("DROP TABLE m;")
+box.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;")
+box.execute("PRAGMA sql_default_engine ('memtx');")
+box.execute("CREATE TABLE test (id INT PRIMARY KEY)")
+box.execute("PRAGMA sql_default_engine='vinyl'")
+box.execute("CREATE TABLE test2 (id INT PRIMARY KEY)")
+box.execute("INSERT INTO test2 VALUES (2)")
+box.execute("START TRANSACTION")
+box.execute("INSERT INTO test VALUES (1)")
+box.execute("SELECT * FROM test2")
+box.execute("ROLLBACK;")
+box.execute("DROP TABLE test;")
+box.execute("DROP TABLE test2;")
 
 --
 -- gh-3536: Some triggers cause error messages and/or half-finished updates
 --
-box.sql.execute("CREATE TABLE t (s1 INT, s2 INT, s3 INT, s4 INT PRIMARY KEY);")
-box.sql.execute("CREATE VIEW v AS SELECT s1, s2 FROM t;")
-box.sql.execute("CREATE TRIGGER tv INSTEAD OF UPDATE ON v BEGIN UPDATE t SET s3 = new.s1 WHERE s1 = old.s1; END;")
-box.sql.execute("INSERT INTO t VALUES (1,1,1,1);")
-box.sql.execute("UPDATE v SET s2 = s1 + 1;")
-box.sql.execute("UPDATE v SET s1 = s1 + 5;")
-box.sql.execute("SELECT * FROM t;")
-box.sql.execute("DROP VIEW v;")
-box.sql.execute("DROP TABLE t;")
+box.execute("CREATE TABLE t (s1 INT, s2 INT, s3 INT, s4 INT PRIMARY KEY);")
+box.execute("CREATE VIEW v AS SELECT s1, s2 FROM t;")
+box.execute("CREATE TRIGGER tv INSTEAD OF UPDATE ON v BEGIN UPDATE t SET s3 = new.s1 WHERE s1 = old.s1; END;")
+box.execute("INSERT INTO t VALUES (1,1,1,1);")
+box.execute("UPDATE v SET s2 = s1 + 1;")
+box.execute("UPDATE v SET s1 = s1 + 5;")
+box.execute("SELECT * FROM t;")
+box.execute("DROP VIEW v;")
+box.execute("DROP TABLE t;")
 
 --
 -- gh-3653: Dissallow bindings for DDL
 --
-box.sql.execute("CREATE TABLE t1(a INT PRIMARY KEY, b INT);")
+box.execute("CREATE TABLE t1(a INT PRIMARY KEY, b INT);")
 space_id = box.space.T1.id
-box.sql.execute("CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.a = ? BEGIN SELECT 1; END;")
+box.execute("CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.a = ? BEGIN SELECT 1; END;")
 tuple = {"TR1", space_id, {sql = [[CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.a = ? BEGIN SELECT 1; END;]]}}
 box.space._trigger:insert(tuple)
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
diff --git a/test/sql/types.result b/test/sql/types.result
index dd9011b..a0a1ba9 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -6,33 +6,34 @@ test_run = env.new()
 ...
 -- gh-3018: typeless columns are prohibited.
 --
-box.sql.execute("CREATE TABLE t1 (id PRIMARY KEY);")
+box.execute("CREATE TABLE t1 (id PRIMARY KEY);")
 ---
 - error: Keyword 'PRIMARY' is reserved. Please use double quotes if 'PRIMARY' is an
     identifier.
 ...
-box.sql.execute("CREATE TABLE t1 (a, id INT PRIMARY KEY);")
+box.execute("CREATE TABLE t1 (a, id INT PRIMARY KEY);")
 ---
 - error: Syntax error near ','
 ...
-box.sql.execute("CREATE TABLE t1 (id PRIMARY KEY, a INT);")
+box.execute("CREATE TABLE t1 (id PRIMARY KEY, a INT);")
 ---
 - error: Keyword 'PRIMARY' is reserved. Please use double quotes if 'PRIMARY' is an
     identifier.
 ...
-box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a);")
+box.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a);")
 ---
 - error: Syntax error near ')'
 ...
-box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b UNIQUE);")
+box.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b UNIQUE);")
 ---
 - error: Keyword 'UNIQUE' is reserved. Please use double quotes if 'UNIQUE' is an
     identifier.
 ...
 -- gh-3104: real type is stored in space format.
 --
-box.sql.execute("CREATE TABLE t1 (id TEXT PRIMARY KEY, a REAL, b INT, c TEXT, d SCALAR);")
+box.execute("CREATE TABLE t1 (id TEXT PRIMARY KEY, a REAL, b INT, c TEXT, d SCALAR);")
 ---
+- rowcount: 1
 ...
 box.space.T1:format()
 ---
@@ -42,8 +43,9 @@ box.space.T1:format()
   {'type': 'string', 'nullable_action': 'none', 'name': 'C', 'is_nullable': true},
   {'type': 'scalar', 'nullable_action': 'none', 'name': 'D', 'is_nullable': true}]
 ...
-box.sql.execute("CREATE VIEW v1 AS SELECT b + a, b - a FROM t1;")
+box.execute("CREATE VIEW v1 AS SELECT b + a, b - a FROM t1;")
 ---
+- rowcount: 1
 ...
 box.space.V1:format()
 ---
@@ -52,17 +54,21 @@ box.space.V1:format()
 ...
 -- gh-2494: index's part also features correct declared type.
 --
-box.sql.execute("CREATE INDEX i1 ON t1 (a);")
+box.execute("CREATE INDEX i1 ON t1 (a);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE INDEX i2 ON t1 (b);")
+box.execute("CREATE INDEX i2 ON t1 (b);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE INDEX i3 ON t1 (c);")
+box.execute("CREATE INDEX i3 ON t1 (c);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE INDEX i4 ON t1 (id, c, b, a, d);")
+box.execute("CREATE INDEX i4 ON t1 (id, c, b, a, d);")
 ---
+- rowcount: 1
 ...
 box.space.T1.index.I1.parts
 ---
@@ -100,11 +106,13 @@ box.space.T1.index.I4.parts
     is_nullable: true
     fieldno: 5
 ...
-box.sql.execute("DROP VIEW v1;")
+box.execute("DROP VIEW v1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP TABLE t1;")
 ---
+- rowcount: 1
 ...
 -- gh-3906: data of type BOOL is displayed as should
 -- during SQL SELECT.
@@ -126,9 +134,15 @@ sp:insert({2, false})
 ---
 - [2, false]
 ...
-box.sql.execute("SELECT * FROM test")
+box.execute("SELECT * FROM test")
 ---
-- - [1, 1]
+- metadata:
+  - name: ID
+    type: UNKNOWN
+  - name: A
+    type: BOOLEAN
+  rows:
+  - [1, 1]
   - [2, 0]
 ...
 sp:drop()
@@ -136,83 +150,99 @@ sp:drop()
 ...
 -- gh-3544: concatenation operator accepts only TEXT and BLOB.
 --
-box.sql.execute("SELECT 'abc' || 1;")
+box.execute("SELECT 'abc' || 1;")
 ---
 - error: 'Inconsistent types: expected TEXT or BLOB got INTEGER'
 ...
-box.sql.execute("SELECT 'abc' || 1.123;")
+box.execute("SELECT 'abc' || 1.123;")
 ---
 - error: 'Inconsistent types: expected TEXT or BLOB got REAL'
 ...
-box.sql.execute("SELECT 1 || 'abc';")
+box.execute("SELECT 1 || 'abc';")
 ---
 - error: 'Inconsistent types: expected TEXT or BLOB got INTEGER'
 ...
-box.sql.execute("SELECT 1.123 || 'abc';")
+box.execute("SELECT 1.123 || 'abc';")
 ---
 - error: 'Inconsistent types: expected TEXT or BLOB got REAL'
 ...
-box.sql.execute("SELECt 'a' || 'b' || 1;")
+box.execute("SELECt 'a' || 'b' || 1;")
 ---
 - error: 'Inconsistent types: expected TEXT or BLOB got INTEGER'
 ...
 -- What is more, they must be of the same type.
 --
-box.sql.execute("SELECT 'abc' || randomblob(5);")
+box.execute("SELECT 'abc' || randomblob(5);")
 ---
 - error: 'Inconsistent types: expected TEXT got BLOB'
 ...
-box.sql.execute("SELECT randomblob(5) || 'x';")
+box.execute("SELECT randomblob(5) || 'x';")
 ---
 - error: 'Inconsistent types: expected BLOB got TEXT'
 ...
 -- Result of BLOBs concatenation must be BLOB.
 --
-box.sql.execute("VALUES (TYPEOF(randomblob(5) || zeroblob(5)));")
+box.execute("VALUES (TYPEOF(randomblob(5) || zeroblob(5)));")
 ---
-- - ['blob']
+- metadata:
+  - name: column1
+    type: TEXT
+  rows:
+  - ['blob']
 ...
 -- gh-3954: LIKE accepts only arguments of type TEXT and NULLs.
 --
-box.sql.execute("CREATE TABLE t1 (s SCALAR PRIMARY KEY);")
+box.execute("CREATE TABLE t1 (s SCALAR PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES (randomblob(5));")
+box.execute("INSERT INTO t1 VALUES (randomblob(5));")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t1 WHERE s LIKE 'blob';")
+box.execute("SELECT * FROM t1 WHERE s LIKE 'blob';")
 ---
 - error: 'Inconsistent types: expected TEXT got BLOB'
 ...
-box.sql.execute("SELECT * FROM t1 WHERE 'blob' LIKE s;")
+box.execute("SELECT * FROM t1 WHERE 'blob' LIKE s;")
 ---
 - error: 'Inconsistent types: expected TEXT got BLOB'
 ...
-box.sql.execute("SELECT * FROM t1 WHERE 'blob' LIKE x'0000';")
+box.execute("SELECT * FROM t1 WHERE 'blob' LIKE x'0000';")
 ---
 - error: 'Inconsistent types: expected TEXT got BLOB'
 ...
-box.sql.execute("SELECT s LIKE NULL FROM t1;")
+box.execute("SELECT s LIKE NULL FROM t1;")
 ---
-- - [null]
+- metadata:
+  - name: s LIKE NULL
+    type: INTEGER
+  rows:
+  - [null]
 ...
-box.sql.execute("DELETE FROM t1;")
+box.execute("DELETE FROM t1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES (1);")
+box.execute("INSERT INTO t1 VALUES (1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("SELECT * FROM t1 WHERE s LIKE 'int';")
+box.execute("SELECT * FROM t1 WHERE s LIKE 'int';")
 ---
 - error: 'Inconsistent types: expected TEXT got INTEGER'
 ...
-box.sql.execute("SELECT * FROM t1 WHERE 'int' LIKE 4;")
+box.execute("SELECT * FROM t1 WHERE 'int' LIKE 4;")
 ---
 - error: 'Inconsistent types: expected TEXT got INTEGER'
 ...
-box.sql.execute("SELECT NULL LIKE s FROM t1;")
+box.execute("SELECT NULL LIKE s FROM t1;")
 ---
-- - [null]
+- metadata:
+  - name: NULL LIKE s
+    type: INTEGER
+  rows:
+  - [null]
 ...
 box.space.T1:drop()
 ---
diff --git a/test/sql/types.test.lua b/test/sql/types.test.lua
index bb8bf7d..dab5872 100644
--- a/test/sql/types.test.lua
+++ b/test/sql/types.test.lua
@@ -3,32 +3,32 @@ test_run = env.new()
 
 -- gh-3018: typeless columns are prohibited.
 --
-box.sql.execute("CREATE TABLE t1 (id PRIMARY KEY);")
-box.sql.execute("CREATE TABLE t1 (a, id INT PRIMARY KEY);")
-box.sql.execute("CREATE TABLE t1 (id PRIMARY KEY, a INT);")
-box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a);")
-box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b UNIQUE);")
+box.execute("CREATE TABLE t1 (id PRIMARY KEY);")
+box.execute("CREATE TABLE t1 (a, id INT PRIMARY KEY);")
+box.execute("CREATE TABLE t1 (id PRIMARY KEY, a INT);")
+box.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a);")
+box.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b UNIQUE);")
 
 -- gh-3104: real type is stored in space format.
 --
-box.sql.execute("CREATE TABLE t1 (id TEXT PRIMARY KEY, a REAL, b INT, c TEXT, d SCALAR);")
+box.execute("CREATE TABLE t1 (id TEXT PRIMARY KEY, a REAL, b INT, c TEXT, d SCALAR);")
 box.space.T1:format()
-box.sql.execute("CREATE VIEW v1 AS SELECT b + a, b - a FROM t1;")
+box.execute("CREATE VIEW v1 AS SELECT b + a, b - a FROM t1;")
 box.space.V1:format()
 
 -- gh-2494: index's part also features correct declared type.
 --
-box.sql.execute("CREATE INDEX i1 ON t1 (a);")
-box.sql.execute("CREATE INDEX i2 ON t1 (b);")
-box.sql.execute("CREATE INDEX i3 ON t1 (c);")
-box.sql.execute("CREATE INDEX i4 ON t1 (id, c, b, a, d);")
+box.execute("CREATE INDEX i1 ON t1 (a);")
+box.execute("CREATE INDEX i2 ON t1 (b);")
+box.execute("CREATE INDEX i3 ON t1 (c);")
+box.execute("CREATE INDEX i4 ON t1 (id, c, b, a, d);")
 box.space.T1.index.I1.parts
 box.space.T1.index.I2.parts
 box.space.T1.index.I3.parts
 box.space.T1.index.I4.parts
 
-box.sql.execute("DROP VIEW v1;")
-box.sql.execute("DROP TABLE t1;")
+box.execute("DROP VIEW v1;")
+box.execute("DROP TABLE t1;")
 
 -- gh-3906: data of type BOOL is displayed as should
 -- during SQL SELECT.
@@ -38,35 +38,35 @@ sp = box.schema.space.create("TEST", { format = format } )
 i = sp:create_index('primary', {parts = {1, 'unsigned' }})
 sp:insert({1, true})
 sp:insert({2, false})
-box.sql.execute("SELECT * FROM test")
+box.execute("SELECT * FROM test")
 sp:drop()
 
 -- gh-3544: concatenation operator accepts only TEXT and BLOB.
 --
-box.sql.execute("SELECT 'abc' || 1;")
-box.sql.execute("SELECT 'abc' || 1.123;")
-box.sql.execute("SELECT 1 || 'abc';")
-box.sql.execute("SELECT 1.123 || 'abc';")
-box.sql.execute("SELECt 'a' || 'b' || 1;")
+box.execute("SELECT 'abc' || 1;")
+box.execute("SELECT 'abc' || 1.123;")
+box.execute("SELECT 1 || 'abc';")
+box.execute("SELECT 1.123 || 'abc';")
+box.execute("SELECt 'a' || 'b' || 1;")
 -- What is more, they must be of the same type.
 --
-box.sql.execute("SELECT 'abc' || randomblob(5);")
-box.sql.execute("SELECT randomblob(5) || 'x';")
+box.execute("SELECT 'abc' || randomblob(5);")
+box.execute("SELECT randomblob(5) || 'x';")
 -- Result of BLOBs concatenation must be BLOB.
 --
-box.sql.execute("VALUES (TYPEOF(randomblob(5) || zeroblob(5)));")
+box.execute("VALUES (TYPEOF(randomblob(5) || zeroblob(5)));")
 
 -- gh-3954: LIKE accepts only arguments of type TEXT and NULLs.
 --
-box.sql.execute("CREATE TABLE t1 (s SCALAR PRIMARY KEY);")
-box.sql.execute("INSERT INTO t1 VALUES (randomblob(5));")
-box.sql.execute("SELECT * FROM t1 WHERE s LIKE 'blob';")
-box.sql.execute("SELECT * FROM t1 WHERE 'blob' LIKE s;")
-box.sql.execute("SELECT * FROM t1 WHERE 'blob' LIKE x'0000';")
-box.sql.execute("SELECT s LIKE NULL FROM t1;")
-box.sql.execute("DELETE FROM t1;")
-box.sql.execute("INSERT INTO t1 VALUES (1);")
-box.sql.execute("SELECT * FROM t1 WHERE s LIKE 'int';")
-box.sql.execute("SELECT * FROM t1 WHERE 'int' LIKE 4;")
-box.sql.execute("SELECT NULL LIKE s FROM t1;")
+box.execute("CREATE TABLE t1 (s SCALAR PRIMARY KEY);")
+box.execute("INSERT INTO t1 VALUES (randomblob(5));")
+box.execute("SELECT * FROM t1 WHERE s LIKE 'blob';")
+box.execute("SELECT * FROM t1 WHERE 'blob' LIKE s;")
+box.execute("SELECT * FROM t1 WHERE 'blob' LIKE x'0000';")
+box.execute("SELECT s LIKE NULL FROM t1;")
+box.execute("DELETE FROM t1;")
+box.execute("INSERT INTO t1 VALUES (1);")
+box.execute("SELECT * FROM t1 WHERE s LIKE 'int';")
+box.execute("SELECT * FROM t1 WHERE 'int' LIKE 4;")
+box.execute("SELECT NULL LIKE s FROM t1;")
 box.space.T1:drop()
diff --git a/test/sql/update-with-nested-select.result b/test/sql/update-with-nested-select.result
index e75fe5d..0a93243 100644
--- a/test/sql/update-with-nested-select.result
+++ b/test/sql/update-with-nested-select.result
@@ -4,36 +4,46 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- box.cfg()
 -- create space
-box.sql.execute("CREATE TABLE t1(a integer primary key, b INT UNIQUE, e INT);");
+box.execute("CREATE TABLE t1(a integer primary key, b INT UNIQUE, e INT);");
 ---
+- rowcount: 1
 ...
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 -- Seed entries
-box.sql.execute("INSERT INTO t1 VALUES(1,4,6);");
+box.execute("INSERT INTO t1 VALUES(1,4,6);");
 ---
+- rowcount: 1
 ...
-box.sql.execute("INSERT INTO t1 VALUES(2,5,7);");
+box.execute("INSERT INTO t1 VALUES(2,5,7);");
 ---
+- rowcount: 1
 ...
 -- Both entries must be updated
-box.sql.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);");
+box.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);");
 ---
+- rowcount: 2
 ...
 -- Check
-box.sql.execute("SELECT e FROM t1");
+box.execute("SELECT e FROM t1");
 ---
-- - [7]
+- metadata:
+  - name: E
+    type: INTEGER
+  rows:
+  - [7]
   - [8]
 ...
 -- Cleanup
-box.sql.execute("DROP TABLE t1;");
+box.execute("DROP TABLE t1;");
 ---
+- rowcount: 1
 ...
 -- Debug
 -- require("console").start()
diff --git a/test/sql/update-with-nested-select.test.lua b/test/sql/update-with-nested-select.test.lua
index 8e508b1..88424fc 100644
--- a/test/sql/update-with-nested-select.test.lua
+++ b/test/sql/update-with-nested-select.test.lua
@@ -1,27 +1,27 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- box.cfg()
 
 -- create space
-box.sql.execute("CREATE TABLE t1(a integer primary key, b INT UNIQUE, e INT);");
+box.execute("CREATE TABLE t1(a integer primary key, b INT UNIQUE, e INT);");
 
 -- Debug
--- box.sql.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
+-- box.execute("PRAGMA vdbe_debug=ON ; INSERT INTO zoobar VALUES (111, 222, 'c3', 444)")
 
 -- Seed entries
-box.sql.execute("INSERT INTO t1 VALUES(1,4,6);");
-box.sql.execute("INSERT INTO t1 VALUES(2,5,7);");
+box.execute("INSERT INTO t1 VALUES(1,4,6);");
+box.execute("INSERT INTO t1 VALUES(2,5,7);");
 
 -- Both entries must be updated
-box.sql.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);");
+box.execute("UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);");
 
 -- Check
-box.sql.execute("SELECT e FROM t1");
+box.execute("SELECT e FROM t1");
 
 -- Cleanup
-box.sql.execute("DROP TABLE t1;");
+box.execute("DROP TABLE t1;");
 
 -- Debug
 -- require("console").start()
diff --git a/test/sql/upgrade.result b/test/sql/upgrade.result
index 02ab9b4..9c999f1 100644
--- a/test/sql/upgrade.result
+++ b/test/sql/upgrade.result
@@ -4,8 +4,9 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 work_dir = 'sql/upgrade/1.10/'
 ---
@@ -66,17 +67,21 @@ box.space._index:get({box.space._space.index['name']:get('T1').id, 0})
 - [512, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]
 ...
 -- test system tables functionality
-box.sql.execute("CREATE TABLE t(x INTEGER PRIMARY KEY);")
+box.execute("CREATE TABLE t(x INTEGER PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE t_out(x INTEGER PRIMARY KEY);")
+box.execute("CREATE TABLE t_out(x INTEGER PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER t1t AFTER INSERT ON t BEGIN INSERT INTO t_out VALUES(1); END;")
+box.execute("CREATE TRIGGER t1t AFTER INSERT ON t BEGIN INSERT INTO t_out VALUES(1); END;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TRIGGER t2t AFTER INSERT ON t BEGIN INSERT INTO t_out VALUES(2); END;")
+box.execute("CREATE TRIGGER t2t AFTER INSERT ON t BEGIN INSERT INTO t_out VALUES(2); END;")
 ---
+- rowcount: 1
 ...
 box.space._space.index['name']:get('T')
 ---
@@ -120,8 +125,9 @@ assert(t1t.space_id == box.space.T.id)
 ---
 - true
 ...
-box.sql.execute("INSERT INTO T VALUES(1);")
+box.execute("INSERT INTO T VALUES(1);")
 ---
+- rowcount: 1
 ...
 box.space.T:select()
 ---
@@ -132,19 +138,29 @@ box.space.T_OUT:select()
 - - [1]
   - [2]
 ...
-box.sql.execute("SELECT * FROM T")
+box.execute("SELECT * FROM T")
 ---
-- - [1]
+- metadata:
+  - name: X
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("SELECT * FROM T")
+box.execute("SELECT * FROM T")
 ---
-- - [1]
+- metadata:
+  - name: X
+    type: INTEGER
+  rows:
+  - [1]
 ...
-box.sql.execute("DROP TABLE T;")
+box.execute("DROP TABLE T;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE T_OUT;")
+box.execute("DROP TABLE T_OUT;")
 ---
+- rowcount: 1
 ...
 test_run:switch('default')
 ---
diff --git a/test/sql/upgrade.test.lua b/test/sql/upgrade.test.lua
index cd4dd3c..036c1a6 100644
--- a/test/sql/upgrade.test.lua
+++ b/test/sql/upgrade.test.lua
@@ -1,6 +1,6 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 work_dir = 'sql/upgrade/1.10/'
 test_run:cmd('create server upgrade with script="sql/upgrade/upgrade.lua", workdir="' .. work_dir .. '"')
@@ -24,10 +24,10 @@ box.space._space.index['name']:get('T1')
 box.space._index:get({box.space._space.index['name']:get('T1').id, 0})
 
 -- test system tables functionality
-box.sql.execute("CREATE TABLE t(x INTEGER PRIMARY KEY);")
-box.sql.execute("CREATE TABLE t_out(x INTEGER PRIMARY KEY);")
-box.sql.execute("CREATE TRIGGER t1t AFTER INSERT ON t BEGIN INSERT INTO t_out VALUES(1); END;")
-box.sql.execute("CREATE TRIGGER t2t AFTER INSERT ON t BEGIN INSERT INTO t_out VALUES(2); END;")
+box.execute("CREATE TABLE t(x INTEGER PRIMARY KEY);")
+box.execute("CREATE TABLE t_out(x INTEGER PRIMARY KEY);")
+box.execute("CREATE TRIGGER t1t AFTER INSERT ON t BEGIN INSERT INTO t_out VALUES(1); END;")
+box.execute("CREATE TRIGGER t2t AFTER INSERT ON t BEGIN INSERT INTO t_out VALUES(2); END;")
 box.space._space.index['name']:get('T')
 box.space._space.index['name']:get('T_OUT')
 t1t = box.space._trigger:get('T1T')
@@ -39,15 +39,15 @@ t2t.opts
 assert(t1t.space_id == t2t.space_id)
 assert(t1t.space_id == box.space.T.id)
 
-box.sql.execute("INSERT INTO T VALUES(1);")
+box.execute("INSERT INTO T VALUES(1);")
 box.space.T:select()
 box.space.T_OUT:select()
-box.sql.execute("SELECT * FROM T")
-box.sql.execute("SELECT * FROM T")
+box.execute("SELECT * FROM T")
+box.execute("SELECT * FROM T")
 
 
-box.sql.execute("DROP TABLE T;")
-box.sql.execute("DROP TABLE T_OUT;")
+box.execute("DROP TABLE T;")
+box.execute("DROP TABLE T_OUT;")
 
 
 test_run:switch('default')
diff --git a/test/sql/view.result b/test/sql/view.result
index e99a9bd..b7efb84 100644
--- a/test/sql/view.result
+++ b/test/sql/view.result
@@ -4,20 +4,23 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 -- Verify that constraints on 'view' option are working.
 -- box.cfg()
 -- Create space and view.
-box.sql.execute("CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a, b));");
+box.execute("CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a, b));");
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW v1 AS SELECT a+b FROM t1;");
+box.execute("CREATE VIEW v1 AS SELECT a+b FROM t1;");
 ---
+- rowcount: 1
 ...
 -- View can't have any indexes.
-box.sql.execute("CREATE INDEX i1 on v1(a);");
+box.execute("CREATE INDEX i1 on v1(a);");
 ---
 - error: views can not be indexed
 ...
@@ -73,7 +76,7 @@ box.schema.create_space('view', {view = true})
 - error: Illegal parameters, unexpected option 'view'
 ...
 -- Space referenced by a view can't be renamed.
-box.sql.execute("ALTER TABLE t1 RENAME TO new_name;")
+box.execute("ALTER TABLE t1 RENAME TO new_name;")
 ---
 - error: 'Can''t modify space ''T1'': can not rename space which is referenced by
     view'
@@ -114,30 +117,36 @@ sp = box.space._space:replace(raw_sp);
 - error: 'Failed to execute SQL statement: SELECT 1;'
 ...
 -- Can't drop space via Lua if at least one view refers to it.
-box.sql.execute('CREATE TABLE t2(id INT PRIMARY KEY);');
+box.execute('CREATE TABLE t2(id INT PRIMARY KEY);');
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE VIEW v2 AS SELECT * FROM t2;');
+box.execute('CREATE VIEW v2 AS SELECT * FROM t2;');
 ---
+- rowcount: 1
 ...
 box.space.T2:drop();
 ---
 - error: 'Can''t drop space ''T2'': other views depend on this space'
 ...
-box.sql.execute('DROP VIEW v2;');
+box.execute('DROP VIEW v2;');
 ---
+- rowcount: 1
 ...
-box.sql.execute('DROP TABLE t2;');
+box.execute('DROP TABLE t2;');
 ---
+- rowcount: 1
 ...
 -- Check that alter transfers reference counter.
-box.sql.execute("CREATE TABLE t2(id INTEGER PRIMARY KEY);");
+box.execute("CREATE TABLE t2(id INTEGER PRIMARY KEY);");
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW v2 AS SELECT * FROM t2;");
+box.execute("CREATE VIEW v2 AS SELECT * FROM t2;");
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t2;");
+box.execute("DROP TABLE t2;");
 ---
 - error: 'Can''t drop space ''T2'': other views depend on this space'
 ...
@@ -147,99 +156,122 @@ sp = box.space._space:get{box.space.T2.id};
 sp = box.space._space:replace(sp);
 ---
 ...
-box.sql.execute("DROP TABLE t2;");
+box.execute("DROP TABLE t2;");
 ---
 - error: 'Can''t drop space ''T2'': other views depend on this space'
 ...
-box.sql.execute("DROP VIEW v2;");
+box.execute("DROP VIEW v2;");
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t2;");
+box.execute("DROP TABLE t2;");
 ---
+- rowcount: 1
 ...
 -- gh-3849: failed to create VIEW in form of AS VALUES (const);
 --
-box.sql.execute("CREATE VIEW cv AS VALUES(1);")
+box.execute("CREATE VIEW cv AS VALUES(1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW cv1 AS VALUES('k', 1);")
+box.execute("CREATE VIEW cv1 AS VALUES('k', 1);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW cv2 AS VALUES((VALUES((SELECT 1))));")
+box.execute("CREATE VIEW cv2 AS VALUES((VALUES((SELECT 1))));")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW cv3 AS VALUES(1+2, 1+2);")
+box.execute("CREATE VIEW cv3 AS VALUES(1+2, 1+2);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP VIEW cv;")
+box.execute("DROP VIEW cv;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP VIEW cv1;")
+box.execute("DROP VIEW cv1;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP VIEW cv2;")
+box.execute("DROP VIEW cv2;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP VIEW cv3;")
+box.execute("DROP VIEW cv3;")
 ---
+- rowcount: 1
 ...
 -- gh-3815: AS VALUES syntax didn't incerement VIEW reference
 -- counter. Moreover, tables within sub-select were not accounted
 -- as well.
 --
-box.sql.execute("CREATE TABLE b (s1 INT PRIMARY KEY);")
+box.execute("CREATE TABLE b (s1 INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW bv (wombat) AS VALUES ((SELECT 'k' FROM b));")
+box.execute("CREATE VIEW bv (wombat) AS VALUES ((SELECT 'k' FROM b));")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE b;")
+box.execute("DROP TABLE b;")
 ---
 - error: 'Can''t drop space ''B'': other views depend on this space'
 ...
-box.sql.execute("DROP VIEW bv;")
+box.execute("DROP VIEW bv;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE b;")
+box.execute("DROP TABLE b;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE b (s1 INT PRIMARY KEY);")
+box.execute("CREATE TABLE b (s1 INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE c (s1 INT PRIMARY KEY);")
+box.execute("CREATE TABLE c (s1 INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW bcv AS SELECT * FROM b WHERE s1 IN (SELECT * FROM c);")
+box.execute("CREATE VIEW bcv AS SELECT * FROM b WHERE s1 IN (SELECT * FROM c);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE c;")
+box.execute("DROP TABLE c;")
 ---
 - error: 'Can''t drop space ''C'': other views depend on this space'
 ...
-box.sql.execute("DROP VIEW bcv;")
+box.execute("DROP VIEW bcv;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE c;")
+box.execute("DROP TABLE c;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE TABLE c (s1 INT PRIMARY KEY);")
+box.execute("CREATE TABLE c (s1 INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW bcv(x, y) AS VALUES((SELECT 'k' FROM b), (VALUES((SELECT 1 FROM b WHERE s1 IN (VALUES((SELECT 1 + c.s1 FROM c)))))))")
+box.execute("CREATE VIEW bcv(x, y) AS VALUES((SELECT 'k' FROM b), (VALUES((SELECT 1 FROM b WHERE s1 IN (VALUES((SELECT 1 + c.s1 FROM c)))))))")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE c;")
+box.execute("DROP TABLE c;")
 ---
 - error: 'Can''t drop space ''C'': other views depend on this space'
 ...
 box.space.BCV:drop()
 ---
 ...
-box.sql.execute("DROP TABLE c;")
+box.execute("DROP TABLE c;")
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE b;")
+box.execute("DROP TABLE b;")
 ---
+- rowcount: 1
 ...
 -- gh-3814: make sure that recovery of view processed without
 -- unexpected errors.
@@ -248,20 +280,25 @@ box.snapshot()
 ---
 - ok
 ...
-box.sql.execute("CREATE TABLE t2 (id INT PRIMARY KEY);")
+box.execute("CREATE TABLE t2 (id INT PRIMARY KEY);")
 ---
+- rowcount: 1
 ...
-box.sql.execute("CREATE VIEW v2 AS SELECT * FROM t2;")
+box.execute("CREATE VIEW v2 AS SELECT * FROM t2;")
 ---
+- rowcount: 1
 ...
 test_run:cmd('restart server default')
-box.sql.execute("DROP TABLE t2;")
+box.execute("DROP TABLE t2;")
 ---
 - error: 'Can''t drop space ''T2'': other views depend on this space'
 ...
-box.sql.execute("SELECT * FROM v2;")
+box.execute("SELECT * FROM v2;")
 ---
-- []
+- metadata:
+  - name: ID
+    type: INTEGER
+  rows: []
 ...
 box.space.V2:drop()
 ---
@@ -270,9 +307,11 @@ box.space.T2:drop()
 ---
 ...
 -- Cleanup
-box.sql.execute("DROP VIEW v1;");
+box.execute("DROP VIEW v1;");
 ---
+- rowcount: 1
 ...
-box.sql.execute("DROP TABLE t1;");
+box.execute("DROP TABLE t1;");
 ---
+- rowcount: 1
 ...
diff --git a/test/sql/view.test.lua b/test/sql/view.test.lua
index 592d788..0008056 100644
--- a/test/sql/view.test.lua
+++ b/test/sql/view.test.lua
@@ -1,17 +1,17 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 
 -- Verify that constraints on 'view' option are working.
 
 -- box.cfg()
 
 -- Create space and view.
-box.sql.execute("CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a, b));");
-box.sql.execute("CREATE VIEW v1 AS SELECT a+b FROM t1;");
+box.execute("CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a, b));");
+box.execute("CREATE VIEW v1 AS SELECT a+b FROM t1;");
 
 -- View can't have any indexes.
-box.sql.execute("CREATE INDEX i1 on v1(a);");
+box.execute("CREATE INDEX i1 on v1(a);");
 v1 = box.space.V1;
 v1:create_index('primary', {parts = {1, 'string'}})
 v1:create_index('secondary', {parts = {1, 'string'}})
@@ -35,7 +35,7 @@ box.space._space:replace(v1);
 box.schema.create_space('view', {view = true})
 
 -- Space referenced by a view can't be renamed.
-box.sql.execute("ALTER TABLE t1 RENAME TO new_name;")
+box.execute("ALTER TABLE t1 RENAME TO new_name;")
 
 -- View can be created via straight insertion into _space.
 sp = box.schema.create_space('test');
@@ -53,70 +53,70 @@ raw_sp[6].sql = 'SELECT 1;';
 sp = box.space._space:replace(raw_sp);
 
 -- Can't drop space via Lua if at least one view refers to it.
-box.sql.execute('CREATE TABLE t2(id INT PRIMARY KEY);');
-box.sql.execute('CREATE VIEW v2 AS SELECT * FROM t2;');
+box.execute('CREATE TABLE t2(id INT PRIMARY KEY);');
+box.execute('CREATE VIEW v2 AS SELECT * FROM t2;');
 box.space.T2:drop();
-box.sql.execute('DROP VIEW v2;');
-box.sql.execute('DROP TABLE t2;');
+box.execute('DROP VIEW v2;');
+box.execute('DROP TABLE t2;');
 
 -- Check that alter transfers reference counter.
-box.sql.execute("CREATE TABLE t2(id INTEGER PRIMARY KEY);");
-box.sql.execute("CREATE VIEW v2 AS SELECT * FROM t2;");
-box.sql.execute("DROP TABLE t2;");
+box.execute("CREATE TABLE t2(id INTEGER PRIMARY KEY);");
+box.execute("CREATE VIEW v2 AS SELECT * FROM t2;");
+box.execute("DROP TABLE t2;");
 sp = box.space._space:get{box.space.T2.id};
 sp = box.space._space:replace(sp);
-box.sql.execute("DROP TABLE t2;");
-box.sql.execute("DROP VIEW v2;");
-box.sql.execute("DROP TABLE t2;");
+box.execute("DROP TABLE t2;");
+box.execute("DROP VIEW v2;");
+box.execute("DROP TABLE t2;");
 
 -- gh-3849: failed to create VIEW in form of AS VALUES (const);
 --
-box.sql.execute("CREATE VIEW cv AS VALUES(1);")
-box.sql.execute("CREATE VIEW cv1 AS VALUES('k', 1);")
-box.sql.execute("CREATE VIEW cv2 AS VALUES((VALUES((SELECT 1))));")
-box.sql.execute("CREATE VIEW cv3 AS VALUES(1+2, 1+2);")
-box.sql.execute("DROP VIEW cv;")
-box.sql.execute("DROP VIEW cv1;")
-box.sql.execute("DROP VIEW cv2;")
-box.sql.execute("DROP VIEW cv3;")
+box.execute("CREATE VIEW cv AS VALUES(1);")
+box.execute("CREATE VIEW cv1 AS VALUES('k', 1);")
+box.execute("CREATE VIEW cv2 AS VALUES((VALUES((SELECT 1))));")
+box.execute("CREATE VIEW cv3 AS VALUES(1+2, 1+2);")
+box.execute("DROP VIEW cv;")
+box.execute("DROP VIEW cv1;")
+box.execute("DROP VIEW cv2;")
+box.execute("DROP VIEW cv3;")
 
 -- gh-3815: AS VALUES syntax didn't incerement VIEW reference
 -- counter. Moreover, tables within sub-select were not accounted
 -- as well.
 --
-box.sql.execute("CREATE TABLE b (s1 INT PRIMARY KEY);")
-box.sql.execute("CREATE VIEW bv (wombat) AS VALUES ((SELECT 'k' FROM b));")
-box.sql.execute("DROP TABLE b;")
-box.sql.execute("DROP VIEW bv;")
-box.sql.execute("DROP TABLE b;")
-
-box.sql.execute("CREATE TABLE b (s1 INT PRIMARY KEY);")
-box.sql.execute("CREATE TABLE c (s1 INT PRIMARY KEY);")
-box.sql.execute("CREATE VIEW bcv AS SELECT * FROM b WHERE s1 IN (SELECT * FROM c);")
-box.sql.execute("DROP TABLE c;")
-box.sql.execute("DROP VIEW bcv;")
-box.sql.execute("DROP TABLE c;")
-
-box.sql.execute("CREATE TABLE c (s1 INT PRIMARY KEY);")
-box.sql.execute("CREATE VIEW bcv(x, y) AS VALUES((SELECT 'k' FROM b), (VALUES((SELECT 1 FROM b WHERE s1 IN (VALUES((SELECT 1 + c.s1 FROM c)))))))")
-box.sql.execute("DROP TABLE c;")
+box.execute("CREATE TABLE b (s1 INT PRIMARY KEY);")
+box.execute("CREATE VIEW bv (wombat) AS VALUES ((SELECT 'k' FROM b));")
+box.execute("DROP TABLE b;")
+box.execute("DROP VIEW bv;")
+box.execute("DROP TABLE b;")
+
+box.execute("CREATE TABLE b (s1 INT PRIMARY KEY);")
+box.execute("CREATE TABLE c (s1 INT PRIMARY KEY);")
+box.execute("CREATE VIEW bcv AS SELECT * FROM b WHERE s1 IN (SELECT * FROM c);")
+box.execute("DROP TABLE c;")
+box.execute("DROP VIEW bcv;")
+box.execute("DROP TABLE c;")
+
+box.execute("CREATE TABLE c (s1 INT PRIMARY KEY);")
+box.execute("CREATE VIEW bcv(x, y) AS VALUES((SELECT 'k' FROM b), (VALUES((SELECT 1 FROM b WHERE s1 IN (VALUES((SELECT 1 + c.s1 FROM c)))))))")
+box.execute("DROP TABLE c;")
 box.space.BCV:drop()
-box.sql.execute("DROP TABLE c;")
-box.sql.execute("DROP TABLE b;")
+box.execute("DROP TABLE c;")
+box.execute("DROP TABLE b;")
 
 -- gh-3814: make sure that recovery of view processed without
 -- unexpected errors.
 --
 box.snapshot()
-box.sql.execute("CREATE TABLE t2 (id INT PRIMARY KEY);")
-box.sql.execute("CREATE VIEW v2 AS SELECT * FROM t2;")
+box.execute("CREATE TABLE t2 (id INT PRIMARY KEY);")
+box.execute("CREATE VIEW v2 AS SELECT * FROM t2;")
 test_run:cmd('restart server default')
 
-box.sql.execute("DROP TABLE t2;")
-box.sql.execute("SELECT * FROM v2;")
+box.execute("DROP TABLE t2;")
+box.execute("SELECT * FROM v2;")
 box.space.V2:drop()
 box.space.T2:drop()
 
 -- Cleanup
-box.sql.execute("DROP VIEW v1;");
-box.sql.execute("DROP TABLE t1;");
+box.execute("DROP VIEW v1;");
+box.execute("DROP TABLE t1;");
diff --git a/test/sql/view_delayed_wal.result b/test/sql/view_delayed_wal.result
index 2e1047a..ff0c70f 100644
--- a/test/sql/view_delayed_wal.result
+++ b/test/sql/view_delayed_wal.result
@@ -4,8 +4,9 @@ test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 ---
+- rowcount: 0
 ...
 fiber = require('fiber')
 ---
@@ -15,10 +16,11 @@ fiber = require('fiber')
 -- it is impossible to create view on dropped (but not written
 -- into WAL) space.
 --
-box.sql.execute('CREATE TABLE t1(id INT PRIMARY KEY)')
+box.execute('CREATE TABLE t1(id INT PRIMARY KEY)')
 ---
+- rowcount: 1
 ...
-function create_view() box.sql.execute('CREATE VIEW v1 AS SELECT * FROM t1') end
+function create_view() box.execute('CREATE VIEW v1 AS SELECT * FROM t1') end
 ---
 ...
 function drop_index_t1() box.space._index:delete{box.space.T1.id, 0} end
@@ -60,11 +62,13 @@ box.space.V1
 -- dropping view, since view reference counter of space to be
 -- dropped is checked before firing on_commit trigger.
 --
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY)')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY)')
 ---
+- rowcount: 1
 ...
-box.sql.execute('CREATE VIEW view2 AS SELECT * FROM t2')
+box.execute('CREATE VIEW view2 AS SELECT * FROM t2')
 ---
+- rowcount: 1
 ...
 function drop_view() box.space._space:delete{box.space.VIEW2.id} end
 ---
diff --git a/test/sql/view_delayed_wal.test.lua b/test/sql/view_delayed_wal.test.lua
index 62ab7d7..8e73b03 100644
--- a/test/sql/view_delayed_wal.test.lua
+++ b/test/sql/view_delayed_wal.test.lua
@@ -1,6 +1,6 @@
 test_run = require('test_run').new()
 engine = test_run:get_cfg('engine')
-box.sql.execute('pragma sql_default_engine=\''..engine..'\'')
+box.execute('pragma sql_default_engine=\''..engine..'\'')
 fiber = require('fiber')
 
 -- View reference counters are incremented before firing
@@ -8,8 +8,8 @@ fiber = require('fiber')
 -- it is impossible to create view on dropped (but not written
 -- into WAL) space.
 --
-box.sql.execute('CREATE TABLE t1(id INT PRIMARY KEY)')
-function create_view() box.sql.execute('CREATE VIEW v1 AS SELECT * FROM t1') end
+box.execute('CREATE TABLE t1(id INT PRIMARY KEY)')
+function create_view() box.execute('CREATE VIEW v1 AS SELECT * FROM t1') end
 function drop_index_t1() box.space._index:delete{box.space.T1.id, 0} end
 function drop_space_t1() box.space._space:delete{box.space.T1.id} end
 box.error.injection.set("ERRINJ_WAL_DELAY", true)
@@ -26,8 +26,8 @@ box.space.V1
 -- dropping view, since view reference counter of space to be
 -- dropped is checked before firing on_commit trigger.
 --
-box.sql.execute('CREATE TABLE t2 (id INT PRIMARY KEY)')
-box.sql.execute('CREATE VIEW view2 AS SELECT * FROM t2')
+box.execute('CREATE TABLE t2 (id INT PRIMARY KEY)')
+box.execute('CREATE VIEW view2 AS SELECT * FROM t2')
 
 function drop_view() box.space._space:delete{box.space.VIEW2.id} end
 function drop_index_t2() box.space._index:delete{box.space.T2.id, 0} end
diff --git a/test/sql/vinyl-opts.result b/test/sql/vinyl-opts.result
index 4e6c4bc..19769f8 100644
--- a/test/sql/vinyl-opts.result
+++ b/test/sql/vinyl-opts.result
@@ -13,11 +13,13 @@ test_run:cmd("switch test")
 ---
 - true
 ...
-box.sql.execute('pragma sql_default_engine= \'vinyl\'')
+box.execute('pragma sql_default_engine= \'vinyl\'')
 ---
+- rowcount: 0
 ...
-box.sql.execute('CREATE TABLE v1 (id INT PRIMARY KEY, b INT);')
+box.execute('CREATE TABLE v1 (id INT PRIMARY KEY, b INT);')
 ---
+- rowcount: 1
 ...
 box.space.V1.index[0].options
 ---
@@ -27,8 +29,9 @@ box.space.V1.index[0].options
   bloom_fpr: 0.1
   range_size: 536870912
 ...
-box.sql.execute('CREATE INDEX i1 ON v1(b);')
+box.execute('CREATE INDEX i1 ON v1(b);')
 ---
+- rowcount: 1
 ...
 box.space.V1.index[1].options
 ---
diff --git a/test/sql/vinyl-opts.test.lua b/test/sql/vinyl-opts.test.lua
index 843693b..4460724 100644
--- a/test/sql/vinyl-opts.test.lua
+++ b/test/sql/vinyl-opts.test.lua
@@ -3,11 +3,11 @@ test_run:cmd("create server test with script='sql/vinyl-opts-cfg.lua'")
 test_run:cmd("start server test")
 test_run:cmd("switch test")
 
-box.sql.execute('pragma sql_default_engine= \'vinyl\'')
-box.sql.execute('CREATE TABLE v1 (id INT PRIMARY KEY, b INT);')
+box.execute('pragma sql_default_engine= \'vinyl\'')
+box.execute('CREATE TABLE v1 (id INT PRIMARY KEY, b INT);')
 box.space.V1.index[0].options
 
-box.sql.execute('CREATE INDEX i1 ON v1(b);')
+box.execute('CREATE INDEX i1 ON v1(b);')
 box.space.V1.index[1].options
 
 box.space.V1:drop()
-- 
2.7.4





More information about the Tarantool-patches mailing list