From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: tarantool-patches@freelists.org, imeevma@tarantool.org Subject: [tarantool-patches] Re: [PATCH v6 2/5] iproto: create port_sql Date: Sat, 29 Dec 2018 16:19:33 +0300 [thread overview] Message-ID: <bae3df1a-6c71-3037-31c6-3b83706a034c@tarantool.org> (raw) In-Reply-To: <8390b09d95aa5bcaa6ef89924d9a334dff746f19.1546017932.git.imeevma@gmail.com> Thanks for the patch! See 11 comments below. On 28/12/2018 21:11, imeevma@tarantool.org wrote: > Hi! Thank you for review! My answers, diff between versions and > new version below. > > On 12/25/18 5:57 PM, Vladislav Shpilevoy wrote: >> Hi! Thanks for the patch! See 4 comments below. > >> 1. Please, write a comment about how could you use port_tuple_vtab on >> port_sql. Here I expected to see words about calling methods of a base >> structure, like BaseClass::method in C++. > Added. Not sure that it is enough. Than add more explanations? Hardly it is possible to 'overexplain' something, but it is as easy as nothing to 'underexplain'. > >> 2. Please, rename this method to port_sql_create and call here port_tuple_create() >> explicitly. It is just a constructor. port_tuple_add, used in sql_execute(), will >> work anyway. Since port_sql is derived from port_tuple, it can be used wherever the >> base. > Done. > >> 3. I think, we should not expose port_sql to the header. It is used in execute.c >> only. Same about port_tuple_to_port_sql. > Done. > >> 4. Do not forget about comments. It still describes 'response' parameter. > Fixed. > > > Diff between versions: > > commit 414bf16c094fbb7b9e0ecb6b4b56f069f109ef86 > Author: Mergen Imeev <imeevma@gmail.com> > Date: Wed Dec 26 22:00:35 2018 +0300 > > Temporary: review fixes > > diff --git a/src/box/execute.c b/src/box/execute.c > index b07de28..c6fcb50 100644 > --- a/src/box/execute.c > +++ b/src/box/execute.c > @@ -83,6 +83,36 @@ struct sql_bind { > }; > > /** > + * Port implementation used for dump tuples, stored in port_tuple, > + * to obuf or Lua. 1. Not only tuples, but the whole response, including headers, meta, info. > + * > + * All port_tuple methods can be used with port_sql, since > + * port_sql is a structure inherited from port_tuple. Calling > + * port_tuple methods we are going via port_tuple_vtab. 2. Not sure if the sentence is correct. 'Calling we are going' looks flawed. Maybe better 'Port_tuple methods are called via explicit access to port_tuple_vtab just like C++ does with BaseClass::method, when it is called in a child method'. ? Or something like this. > + */ > +struct port_sql { > + /* port_tuple to inherit from. */ > + struct port_tuple port_tuple; > + /* Prepared SQL statement. */ > + struct sqlite3_stmt *stmt; > +}; > +static_assert(sizeof(struct port_sql) <= sizeof(struct port), > + "sizeof(struct port_sql) must be <= sizeof(struct port)"); > + > +static int > +port_sql_dump_msgpack(struct port *port, struct obuf *out); 3. Please, add empty line between function declarations. Also, we usually write a comment above a first function declaration appearance, so the whole comment about port_sql_dump_msgpack() should be put here. > +static void > +port_sql_destroy(struct port *base); 4. Correct me if I am wrong, but as I see, port_sql_destroy can be implemented right here, without pre-announcement. Also, please, move port_sql_create here to gather all methods in one place. > + > +const struct port_vtab port_sql_vtab = { 5. 'static'. It is not used anywhere outside execute.c now. > + .dump_msgpack = port_sql_dump_msgpack, > + .dump_msgpack_16 = NULL, > + .dump_lua = NULL, > + .dump_plain = NULL, > + .destroy = port_sql_destroy, 6. Not sure why, but in new code we do not explicitly write attribute names. Instead, we use /* .method_name = */ func, not .method_name = func, To be honest I like your way and how it was done in old code, but Vladimir once forced me to use /* ... = */, so lets follow. > +}; > + > +/** > * Return a string name of a parameter marker. > * @param Bind to get name. > * @retval Zero terminated name. > @@ -356,6 +386,11 @@ sql_row_to_port(struct sqlite3_stmt *stmt, int column_count, > if (tuple == NULL) > goto error; > region_truncate(region, svp); > + /* > + * The port_tuple_add function can be used with port_sql, > + * since it does not call any port_tuple methods and works > + * only with fields. 7. It does not matter even if it would call port_tuple_methods. As we stated in port_sql comment, we derived from port_tuple and can use it in-place of base. I do not think this particular place should be commented at all. > + */ > return port_tuple_add(port, tuple); > > error: > commit 8390b09d95aa5bcaa6ef89924d9a334dff746f19 > Author: Mergen Imeev <imeevma@gmail.com> > Date: Fri Dec 21 14:52:03 2018 +0300 > > iproto: create port_sql > > This patch creates port_sql implementation for the port. This will > allow us to dump sql responses to obuf or to Lua. Also this patch > defines methods dump_msgpack() and destroy() of port_sql. > > Part of #3505 > > diff --git a/src/box/execute.c b/src/box/execute.c > index 38b6cbc..c6fcb50 100644 > --- a/src/box/execute.c > +++ b/src/box/execute.c > @@ -575,26 +606,19 @@ err: > rc = -1; > goto finish; > } > - size = mp_sizeof_uint(IPROTO_DATA) + > - mp_sizeof_array(port_tuple->size); > + size = mp_sizeof_uint(IPROTO_DATA); > pos = (char *) obuf_alloc(out, size); > if (pos == NULL) { > diag_set(OutOfMemory, size, "obuf_alloc", "pos"); > goto err; > } > pos = mp_encode_uint(pos, IPROTO_DATA); > - pos = mp_encode_array(pos, port_tuple->size); > - /* > - * Just like SELECT, SQL uses output format compatible > - * with Tarantool 1.6 > - */ > - if (port_dump_msgpack_16(&response->port, out) < 0) { > - /* Failed port dump destroyes the port. */ > + /* Calling BaseStruct::methods via its vtab. */ 8. Lets do not repeat this comment on each port_tuple_vtab usage. It it direct repetition of what is said in port_sql comment. > + if (port_tuple_vtab.dump_msgpack(port, out) < 0) > goto err; > - } > } else { > int keys = 1; > - assert(port_tuple->size == 0); > + assert(((struct port_tuple *)port)->size == 0); > struct stailq *autoinc_id_list = > vdbe_autoinc_id_list((struct Vdbe *)stmt); > uint32_t map_size = stailq_empty(autoinc_id_list) ? 1 : 2; > @@ -643,7 +667,63 @@ err: > + > +static inline int > +sql_execute(sqlite3 *db, struct sqlite3_stmt *stmt, struct port *port, > + struct region *region) 9. The function is not so trivial to omit a comment. Please, write it. In particular what a one should do with region after sql_execute() is finished. Should it be cleared? > +{ > + int rc, column_count = sqlite3_column_count(stmt); > + if (column_count > 0) { > + /* Either ROW or DONE or ERROR. */ > + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { > + if (sql_row_to_port(stmt, column_count, region, > + port) != 0) > + return -1; > + } > + assert(rc == SQLITE_DONE || rc != SQLITE_OK); > + } else { > + /* No rows. Either DONE or ERROR. */ > + rc = sqlite3_step(stmt); > + assert(rc != SQLITE_ROW && rc != SQLITE_OK); > + } > + if (rc != SQLITE_DONE) { > + diag_set(ClientError, ER_SQL_EXECUTE, sqlite3_errmsg(db)); > + return -1; > + } > + return 0; > +} > + > +int > +sql_prepare_and_execute(const char *sql, int len, const struct sql_bind *bind, > + uint32_t bind_count, struct port *port, > + struct region *region) > +{ > + struct sqlite3_stmt *stmt; > + sqlite3 *db = sql_get(); > + if (db == NULL) { > + diag_set(ClientError, ER_LOADING); > + return -1; 10. Not sure if it is possible. Is it? > + } > + if (sqlite3_prepare_v2(db, sql, len, &stmt, NULL) != SQLITE_OK) { > + diag_set(ClientError, ER_SQL_EXECUTE, sqlite3_errmsg(db)); > + return -1; > + } > + assert(stmt != NULL); > + port_sql_create(port, stmt); > + if (sql_bind(stmt, bind, bind_count) == 0 && > + sql_execute(db, stmt, port, region) == 0) > + return 0; > + port_destroy(port); > + return -1; > +} > diff --git a/src/box/iproto.cc b/src/box/iproto.cc > index a08c8c5..9dc0462 100644 > --- a/src/box/iproto.cc > +++ b/src/box/iproto.cc > @@ -1645,7 +1645,7 @@ tx_process_sql(struct cmsg *m) > /* Prepare memory for the iproto header. */ > if (iproto_prepare_header(out, &header_svp, IPROTO_HEADER_LEN) != 0) > goto error; > - if (sql_response_dump(&response, out) != 0) { > + if (port_dump_msgpack(&port, out) != 0) { > obuf_rollback_to_svp(out, &header_svp); > goto error; 11. Port leaks if an error occurred in iproto_prepare_header. > } Sorry, most of comments are minor and I could fix them myself, but I was asked to do not rewrite patches if they are not urgent.
next prev parent reply other threads:[~2018-12-29 13:19 UTC|newest] Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-12-28 18:11 [tarantool-patches] [PATCH v6 0/5] sql: remove box.sql.execute imeevma 2018-12-28 18:11 ` [tarantool-patches] [PATCH v6 1/5] iproto: move map creation to sql_response_dump() imeevma 2018-12-28 18:11 ` [tarantool-patches] [PATCH v6 2/5] iproto: create port_sql imeevma 2018-12-29 13:19 ` Vladislav Shpilevoy [this message] 2018-12-28 18:11 ` [tarantool-patches] [PATCH v6 3/5] lua: create method dump_lua for port_sql imeevma 2018-12-29 13:19 ` [tarantool-patches] " Vladislav Shpilevoy 2018-12-28 18:11 ` [tarantool-patches] [PATCH v6 4/5] lua: parameter binding for new execute() imeevma 2018-12-29 13:19 ` [tarantool-patches] " Vladislav Shpilevoy 2018-12-28 18:11 ` [tarantool-patches] [PATCH v6 5/5] sql: check new box.sql.execute() imeevma
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=bae3df1a-6c71-3037-31c6-3b83706a034c@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=imeevma@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='[tarantool-patches] Re: [PATCH v6 2/5] iproto: create port_sql' \ /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