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
prev 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