Tarantool development patches archive
 help / color / mirror / Atom feed
From: imeevma@tarantool.org
To: v.shpilevoy@tarantool.org, tarantool-patches@freelists.org
Subject: [tarantool-patches] [PATCH v2 7/7] sql: check new box.sql.execute()
Date: Thu, 22 Nov 2018 22:11:04 +0300	[thread overview]
Message-ID: <f84401fe772a1824ac091f849839b9c6f86b8e54.1542910674.git.imeevma@gmail.com> (raw)
In-Reply-To: <cover.1542910674.git.imeevma@gmail.com>

This commit checks that new implementation of box.sql.execute() is
able to pass all tests. This is temporary commit and should be
dropped later.

Needed for #3505
---
 src/box/execute.c      |  11 ++---
 src/box/execute.h      |   3 +-
 src/box/iproto.cc      |   3 +-
 src/box/lua/schema.lua |  23 ++++++++++
 src/box/lua/sql.c      | 117 ++++---------------------------------------------
 5 files changed, 42 insertions(+), 115 deletions(-)

diff --git a/src/box/execute.c b/src/box/execute.c
index 44cc7ea..433e71e 100644
--- a/src/box/execute.c
+++ b/src/box/execute.c
@@ -697,7 +697,7 @@ sql_get_description(struct sqlite3_stmt *stmt, struct vstream *stream,
 
 static inline int
 sql_execute(sqlite3 *db, struct sqlite3_stmt *stmt, struct port *port,
-	    struct region *region)
+	    struct region *region, int error_id)
 {
 	int rc, column_count = sqlite3_column_count(stmt);
 	if (column_count > 0) {
@@ -714,7 +714,7 @@ sql_execute(sqlite3 *db, struct sqlite3_stmt *stmt, struct port *port,
 		assert(rc != SQLITE_ROW && rc != SQLITE_OK);
 	}
 	if (rc != SQLITE_DONE) {
-		diag_set(ClientError, ER_SQL_EXECUTE, sqlite3_errmsg(db));
+		diag_set(ClientError, error_id, sqlite3_errmsg(db));
 		return -1;
 	}
 	return 0;
@@ -722,7 +722,8 @@ sql_execute(sqlite3 *db, struct sqlite3_stmt *stmt, struct port *port,
 
 int
 sql_prepare_and_execute(const struct sql_request *request,
-			struct sql_response *response, struct region *region)
+			struct sql_response *response, struct region *region,
+			int error_id)
 {
 	const char *sql = request->sql_text;
 	uint32_t len = request->sql_text_len;
@@ -733,7 +734,7 @@ sql_prepare_and_execute(const struct sql_request *request,
 		return -1;
 	}
 	if (sqlite3_prepare_v2(db, sql, len, &stmt, NULL) != SQLITE_OK) {
-		diag_set(ClientError, ER_SQL_EXECUTE, sqlite3_errmsg(db));
+		diag_set(ClientError, error_id, sqlite3_errmsg(db));
 		return -1;
 	}
 	assert(stmt != NULL);
@@ -741,7 +742,7 @@ sql_prepare_and_execute(const struct sql_request *request,
 	response->prep_stmt = stmt;
 	response->sync = request->sync;
 	if (sql_bind(request, stmt) == 0 &&
-	    sql_execute(db, stmt, &response->port, region) == 0)
+	    sql_execute(db, stmt, &response->port, region, error_id) == 0)
 		return 0;
 	port_destroy(&response->port);
 	sqlite3_finalize(stmt);
diff --git a/src/box/execute.h b/src/box/execute.h
index 8ee0a89..46b2ce1 100644
--- a/src/box/execute.h
+++ b/src/box/execute.h
@@ -157,7 +157,8 @@ lua_sql_bind_list_decode(struct lua_State *L, struct sql_request *request,
  */
 int
 sql_prepare_and_execute(const struct sql_request *request,
-			struct sql_response *response, struct region *region);
+			struct sql_response *response, struct region *region,
+			int error_id);
 
 #if defined(__cplusplus)
 } /* extern "C" { */
diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index 380a6ee..9d03bdf 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -1596,7 +1596,8 @@ tx_process_sql(struct cmsg *m)
 		goto error;
 	assert(msg->header.type == IPROTO_EXECUTE);
 	tx_inject_delay();
-	if (sql_prepare_and_execute(&msg->sql, &response, &fiber()->gc) != 0)
+	if (sql_prepare_and_execute(&msg->sql, &response, &fiber()->gc,
+	    ER_SQL_EXECUTE) != 0)
 		goto error;
 	/*
 	 * Take an obuf only after execute(). Else the buffer can
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index 8a804f0..02ec2fd 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -2456,3 +2456,26 @@ box.feedback.save = function(file_name)
 end
 
 box.NULL = msgpack.NULL
+
+box.sql.execute = function(sql)
+    local result = box.sql.new_execute(sql)
+    if result == nil then return end
+    local ret = nil
+    if result.rows ~= nil then
+        ret = {}
+        for key, row in pairs(result.rows) do
+            if type(row) == 'cdata' then
+                table.insert(ret, row:totable())
+            end
+        end
+    end
+    if result.metadata ~= nil then
+        if ret == nil then ret = {} end
+        ret[0] = {}
+        for key, row in pairs(result.metadata) do
+            table.insert(ret[0], row['name'])
+        end
+        setmetatable(ret, {__serialize = 'sequence'})
+    end
+    if ret ~= nil then return ret end
+end
diff --git a/src/box/lua/sql.c b/src/box/lua/sql.c
index 05556f9..c56dd4a 100644
--- a/src/box/lua/sql.c
+++ b/src/box/lua/sql.c
@@ -117,109 +117,6 @@ lua_vstream_init(struct vstream *vstream, struct lua_State *L)
 	vstream->L = L;
 }
 
-static void
-lua_push_column_names(struct lua_State *L, struct sqlite3_stmt *stmt)
-{
-	int column_count = sqlite3_column_count(stmt);
-	lua_createtable(L, column_count, 0);
-	for (int i = 0; i < column_count; i++) {
-		const char *name = sqlite3_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 sqlite3_stmt *stmt)
-{
-	int column_count = sqlite3_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 = sqlite3_column_type(stmt, i);
-		switch (type) {
-		case SQLITE_INTEGER:
-			luaL_pushint64(L, sqlite3_column_int64(stmt, i));
-			break;
-		case SQLITE_FLOAT:
-			lua_pushnumber(L, sqlite3_column_double(stmt, i));
-			break;
-		case SQLITE_TEXT: {
-			const void *text = sqlite3_column_text(stmt, i);
-			lua_pushlstring(L, text,
-					sqlite3_column_bytes(stmt, i));
-			break;
-		}
-		case SQLITE_BLOB: {
-			const void *blob = sqlite3_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,
-					sqlite3_column_bytes(stmt, i));
-			}
-			break;
-		}
-		case SQLITE_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)
-{
-	sqlite3 *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 sqlite3_stmt *stmt;
-	if (sqlite3_prepare_v2(db, sql, length, &stmt, &sql) != SQLITE_OK)
-		goto sqlerror;
-	assert(stmt != NULL);
-
-	int rc;
-	int retval_count;
-	if (sqlite3_column_count(stmt) == 0) {
-		while ((rc = sqlite3_step(stmt)) == SQLITE_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 = sqlite3_step(stmt)) == SQLITE_ROW) {
-			lua_push_row(L, stmt);
-			lua_rawseti(L, -2, ++row_count);
-		}
-		retval_count = 1;
-	}
-        if (rc != SQLITE_OK && rc != SQLITE_DONE)
-		goto sqlerror;
-	sqlite3_finalize(stmt);
-	return retval_count;
-sqlerror:
-	lua_pushstring(L, sqlite3_errmsg(db));
-	sqlite3_finalize(stmt);
-	return lua_error(L);
-}
-
 static int
 lbox_execute(struct lua_State *L)
 {
@@ -237,10 +134,12 @@ lbox_execute(struct lua_State *L)
 	request.sql_text_len = length;
 	if (lua_gettop(L) == 2)
 		if (lua_sql_bind_list_decode(L, &request, 2, &fiber()->gc) != 0)
-			return luaT_error(L);
+			goto sqlerror;
+
 	struct sql_response response = {.is_flatten = true};
-	if (sql_prepare_and_execute(&request, &response, &fiber()->gc) != 0)
-		return luaT_error(L);
+	if (sql_prepare_and_execute(&request, &response, &fiber()->gc,
+				    ER_SYSTEM) != 0)
+		goto sqlerror;
 
 	int keys;
 	struct vstream vstream;
@@ -248,9 +147,12 @@ lbox_execute(struct lua_State *L)
 	lua_newtable(L);
 	if (sql_response_dump(&response, &keys, &vstream) != 0) {
 		lua_pop(L, 1);
-		return luaT_error(L);
+		goto sqlerror;
 	}
 	return 1;
+sqlerror:
+	lua_pushstring(L, sqlite3_errmsg(db));
+	return lua_error(L);
 }
 
 static int
@@ -266,7 +168,6 @@ void
 box_lua_sqlite_init(struct lua_State *L)
 {
 	static const struct luaL_Reg module_funcs [] = {
-		{"execute", lua_sql_execute},
 		{"new_execute", lbox_execute},
 		{"debug", lua_sql_debug},
 		{NULL, NULL}
-- 
2.7.4

      parent reply	other threads:[~2018-11-22 19:11 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-22 19:10 [tarantool-patches] [PATCH v2 0/7] Remove box.sql.execute imeevma
2018-11-22 19:10 ` [tarantool-patches] [PATCH v2 1/7] box: store sql text and length in sql_request imeevma
2018-11-22 19:10 ` [tarantool-patches] [PATCH v2 2/7] box: add method dump_lua to port imeevma
2018-11-22 21:49   ` [tarantool-patches] " Vladislav Shpilevoy
2018-11-27 19:25     ` Imeev Mergen
2018-11-22 19:10 ` [tarantool-patches] [PATCH v2 3/7] iproto: remove iproto functions from execute.c imeevma
2018-11-22 19:10 ` [tarantool-patches] [PATCH v2 4/7] iproto: replace obuf by mpstream in execute.c imeevma
2018-11-22 19:11 ` [tarantool-patches] [PATCH v2 5/7] sql: create interface vstream imeevma
2018-11-22 21:49   ` [tarantool-patches] " Vladislav Shpilevoy
2018-11-27 19:25     ` Imeev Mergen
2018-11-22 19:11 ` [tarantool-patches] [PATCH v2 6/7] lua: create vstream implementation for Lua imeevma
2018-11-22 21:49   ` [tarantool-patches] " Vladislav Shpilevoy
2018-11-27 19:25     ` Imeev Mergen
2018-11-22 19:11 ` imeevma [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f84401fe772a1824ac091f849839b9c6f86b8e54.1542910674.git.imeevma@gmail.com \
    --to=imeevma@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [tarantool-patches] [PATCH v2 7/7] sql: check new box.sql.execute()' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox