From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 2DCB42C122 for ; Tue, 3 Apr 2018 19:02:23 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id gIy3tr5oRkse for ; Tue, 3 Apr 2018 19:02:23 -0400 (EDT) Received: from smtp33.i.mail.ru (smtp33.i.mail.ru [94.100.177.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id B77152C10A for ; Tue, 3 Apr 2018 19:02:22 -0400 (EDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 10.3 \(3273\)) Subject: [tarantool-patches] Re: [PATCH 3/4] sql: simplify lua SQL executor From: "n.pettik" In-Reply-To: <6ae678aac75653b3486c8a194c504c231ea34f56.1522769319.git.v.shpilevoy@tarantool.org> Date: Wed, 4 Apr 2018 02:02:20 +0300 Content-Transfer-Encoding: quoted-printable Message-Id: <110D9983-C81A-4687-90A4-75354BBED30A@tarantool.org> References: <6ae678aac75653b3486c8a194c504c231ea34f56.1522769319.git.v.shpilevoy@tarantool.org> Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: Vladislav Shpilevoy Cc: tarantool-patches@freelists.org Ack. > On 3 Apr 2018, at 18:34, Vladislav Shpilevoy = wrote: >=20 > 1) Code is completely unreadable and complicated by strange > optimizations; > 2) It still supposes, that there can be multiple statements in a > single string; > 3) It pushes first letter of affinity together with column names > - why? It is not used anywhere. >=20 > Lets remove prepared statements list, affinity first letters > pushing. > --- > src/box/lua/sql.c | 239 = ++++++++---------------------------------------------- > 1 file changed, 35 insertions(+), 204 deletions(-) >=20 > diff --git a/src/box/lua/sql.c b/src/box/lua/sql.c > index 12b81383d..e693aeaad 100644 > --- a/src/box/lua/sql.c > +++ b/src/box/lua/sql.c > @@ -6,132 +6,12 @@ > #include "lua/utils.h" > #include "info.h" >=20 > -struct prep_stmt > -{ > - sqlite3_stmt *stmt; > -}; > - > -struct prep_stmt_list > -{ > - uint8_t *mem_end; /* denotes actual size of sql_ctx = struct */ > - uint32_t pool_size; /* mem at the end used for aux = allocations; > - pool grows from mem_end > - towards stmt[] array */ > - uint32_t last_select_stmt_index; /* UINT32_MAX if no = selects */ > - uint32_t column_count; /* in last select stmt */ > - uint32_t stmt_count; > - struct prep_stmt stmt[6]; /* overlayed with the mem pool; > - actual size could be larger or = smaller */ > - /* uint8_t mem_pool[] */ > -}; > - > -static inline int > -prep_stmt_list_needs_free(struct prep_stmt_list *l) > -{ > - return (uint8_t *)(l + 1) !=3D l->mem_end; > -} > - > -/* Release resources and free the list itself, unless it was = preallocated > - * (i.e. l points to an automatic variable) */ > -static void > -prep_stmt_list_free(struct prep_stmt_list *l) > -{ > - if (l =3D=3D NULL) > - return; > - for (size_t i =3D 0, n =3D l->stmt_count; i < n; i++) > - sqlite3_finalize(l->stmt[i].stmt); > - if (prep_stmt_list_needs_free(l)) > - free(l); > -} > - > -static struct prep_stmt_list * > -prep_stmt_list_init(struct prep_stmt_list *prealloc) > -{ > - prealloc->mem_end =3D (uint8_t *)(prealloc + 1); > - prealloc->pool_size =3D 0; > - prealloc->last_select_stmt_index =3D UINT32_MAX; > - prealloc->column_count =3D 0; > - prealloc->stmt_count =3D 0; > - return prealloc; > -} > - > -/* Allocate mem from the prep_stmt_list pool. > - * If not enough space is available, reallocates the list. > - * If reallocation is needed but l was preallocated, old mem is left > - * intact and a new memory chunk is allocated. */ > -static void * > -prep_stmt_list_palloc(struct prep_stmt_list **pl, > - size_t size, size_t alignment) > -{ > - assert((alignment & (alignment - 1)) =3D=3D 0); /* 2 ^ k */ > - assert(alignment <=3D __alignof__((*pl)->stmt[0])); > - > - struct prep_stmt_list *l =3D *pl; > - uint32_t pool_size =3D l->pool_size; > - uint32_t pool_size_max =3D (uint32_t)( > - l->mem_end - (uint8_t *)(l->stmt + l->stmt_count) > - ); > - > - assert(UINT32_MAX - pool_size >=3D size); > - pool_size +=3D size; > - > - assert(UINT32_MAX - pool_size >=3D alignment - 1); > - pool_size +=3D alignment - 1; > - pool_size &=3D ~(alignment - 1); > - > - if (pool_size > pool_size_max) { > - size_t prev_size =3D l->mem_end - (uint8_t *)l; > - size_t size =3D prev_size; > - while (size < prev_size + (pool_size - pool_size_max)) { > - assert(SIZE_MAX - size >=3D size); > - size +=3D size; > - } > - if (prep_stmt_list_needs_free(l)) { > - l =3D realloc(l, size); > - if (l =3D=3D NULL) > - return NULL; > - } else { > - l =3D malloc(size); > - if (l =3D=3D NULL) > - return NULL; > - memcpy(l, *pl, prev_size); > - } > - l->mem_end =3D (uint8_t *)l + size; > - /* move the pool data */ > - memmove((uint8_t *)l + prev_size - l->pool_size, > - l->mem_end - l->pool_size, > - l->pool_size); > - *pl =3D l; > - } > - > - l->pool_size =3D pool_size; > - return l->mem_end - pool_size; > -} > - > -/* push new stmt; reallocate memory if needed > - * returns a pointer to the new stmt or NULL if out of memory. > - * If reallocation is needed but l was preallocated, old mem is left > - * intact and a new memory chunk is allocated. */ > -static struct prep_stmt * > -prep_stmt_list_push(struct prep_stmt_list **pl) > -{ > - struct prep_stmt_list *l; > - /* make sure we don't collide with the pool */ > - if (prep_stmt_list_palloc(pl, sizeof(l->stmt[0]), 1 > - ) =3D=3D NULL) > - return NULL; > - l =3D *pl; > - l->pool_size -=3D sizeof(l->stmt[0]); > - return l->stmt + (l->stmt_count++); > -} > - > static void > -lua_push_column_names(struct lua_State *L, struct prep_stmt_list *l) > +lua_push_column_names(struct lua_State *L, struct sqlite3_stmt *stmt) > { > - sqlite3_stmt *stmt =3D l->stmt[l->last_select_stmt_index].stmt; > - int n =3D l->column_count; > - lua_createtable(L, n, 0); > - for (int i =3D 0; i < n; i++) { > + int column_count =3D sqlite3_column_count(stmt); > + lua_createtable(L, column_count, 0); > + for (int i =3D 0; i < column_count; i++) { > const char *name =3D sqlite3_column_name(stmt, i); > lua_pushstring(L, name =3D=3D NULL ? "" : name); > lua_rawseti(L, -2, i+1); > @@ -139,11 +19,9 @@ lua_push_column_names(struct lua_State *L, struct = prep_stmt_list *l) > } >=20 > static void > -lua_push_row(struct lua_State *L, struct prep_stmt_list *l) > +lua_push_row(struct lua_State *L, struct sqlite3_stmt *stmt) > { > - sqlite3_stmt *stmt =3D l->stmt[l->last_select_stmt_index].stmt; > - int column_count =3D l->column_count; > - char *typestr =3D (void *)(l->mem_end - column_count); > + int column_count =3D sqlite3_column_count(stmt); >=20 > lua_createtable(L, column_count, 0); > lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_array_metatable_ref); > @@ -153,124 +31,77 @@ lua_push_row(struct lua_State *L, struct = prep_stmt_list *l) > int type =3D sqlite3_column_type(stmt, i); > switch (type) { > case SQLITE_INTEGER: > - typestr[i] =3D 'i'; > - luaL_pushint64(L, sqlite3_column_int64(stmt, i)); > + luaL_pushint64(L, sqlite3_column_int64(stmt, = i)); > break; > case SQLITE_FLOAT: > - typestr[i] =3D 'f'; > lua_pushnumber(L, sqlite3_column_double(stmt, = i)); > break; > case SQLITE_TEXT: { > const void *text =3D sqlite3_column_text(stmt, = i); > - typestr[i] =3D 's'; > lua_pushlstring(L, text, > sqlite3_column_bytes(stmt, i)); > break; > } > case SQLITE_BLOB: { > const void *blob =3D sqlite3_column_blob(stmt, = i); > - typestr[i] =3D 'b'; > lua_pushlstring(L, blob, > sqlite3_column_bytes(stmt, i)); > break; > } > case SQLITE_NULL: > - typestr[i] =3D '-'; > lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_nil_ref); > break; > default: > - typestr[i] =3D '?'; > assert(0); > } > lua_rawseti(L, -2, i+1); > } > - > - lua_pushlstring(L, typestr, column_count); > - lua_rawseti(L, -2, 0); > } >=20 > static int > lua_sql_execute(struct lua_State *L) > { > - int rc; > sqlite3 *db =3D sql_get(); > - struct prep_stmt_list *l =3D NULL, stock_l; > - size_t length; > - const char *sql, *sql_end; > - > if (db =3D=3D NULL) > return luaL_error(L, "not ready"); >=20 > - sql =3D lua_tolstring(L, 1, &length); > + size_t length; > + const char *sql =3D lua_tolstring(L, 1, &length); > if (sql =3D=3D NULL) > return luaL_error(L, "usage: = box.sql.execute(sqlstring)"); >=20 > - assert(length <=3D INT_MAX); > - sql_end =3D sql + length; > + struct sqlite3_stmt *stmt; > + if (sqlite3_prepare_v2(db, sql, length, &stmt, &sql) !=3D = SQLITE_OK) > + goto sqlerror; > + assert(stmt !=3D NULL); >=20 > - l =3D prep_stmt_list_init(&stock_l); > - do { > - > - struct prep_stmt *ps =3D prep_stmt_list_push(&l); > - if (ps =3D=3D NULL) > - goto outofmem; > - rc =3D sqlite3_prepare_v2(db, sql, (int)(sql_end - sql), > - &ps->stmt, &sql); > - if (rc !=3D SQLITE_OK) > - goto sqlerror; > - > - if (ps->stmt =3D=3D NULL) { > - /* only whitespace */ > - assert(sql =3D=3D sql_end); > - l->stmt_count --; > - break; > - } > - > - int column_count =3D sqlite3_column_count(ps->stmt); > - if (column_count =3D=3D 0) { > - while ((rc =3D sqlite3_step(ps->stmt)) =3D=3D = SQLITE_ROW) { ; } > - } else { > - char *typestr; > - l->column_count =3D column_count; > - l->last_select_stmt_index =3D l->stmt_count - 1; > - > - assert(l->pool_size =3D=3D 0); > - /* This might possibly call realloc() and ruin = *ps. */ > - typestr =3D prep_stmt_list_palloc(&l, = column_count, 1); > - if (typestr =3D=3D NULL) > - goto outofmem; > - /* Refill *ps. */ > - ps =3D l->stmt + l->stmt_count - 1; > - > - lua_settop(L, 1); /* discard any results */ > - > - /* create result table */ > - lua_createtable(L, 7, 0); > - lua_pushvalue(L, lua_upvalueindex(1)); > - lua_setmetatable(L, -2); > - lua_push_column_names(L, l); > - lua_rawseti(L, -2, 0); > - > - int row_count =3D 0; > - while ((rc =3D sqlite3_step(ps->stmt)) =3D=3D = SQLITE_ROW) { > - lua_push_row(L, l); > - row_count++; > - lua_rawseti(L, -2, row_count); > - } > - l->pool_size =3D 0; > + int rc; > + int retval_count; > + if (sqlite3_column_count(stmt) =3D=3D 0) { > + while ((rc =3D sqlite3_step(stmt)) =3D=3D SQLITE_ROW); > + retval_count =3D 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 =3D 0; > + while ((rc =3D sqlite3_step(stmt)) =3D=3D SQLITE_ROW) { > + lua_push_row(L, stmt); > + lua_rawseti(L, -2, ++row_count); > } > + retval_count =3D 1; > + } > if (rc !=3D SQLITE_OK && rc !=3D SQLITE_DONE) > - goto sqlerror; > - } while (sql !=3D sql_end); > - prep_stmt_list_free(l); > - return lua_gettop(L) - 1; > + goto sqlerror; > + sqlite3_finalize(stmt); > + return retval_count; > sqlerror: > lua_pushstring(L, sqlite3_errmsg(db)); > - prep_stmt_list_free(l);=09 > + sqlite3_finalize(stmt); > return lua_error(L); > -outofmem: > - prep_stmt_list_free(l); > - return luaL_error(L, "out of memory"); > } >=20 > static int > --=20 > 2.14.3 (Apple Git-98) >=20 >=20