Tarantool development patches archive
 help / color / mirror / Atom feed
From: "n.pettik" <korablev@tarantool.org>
To: tarantool-patches@freelists.org
Cc: Kirill Shcherbatov <kshcherbatov@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH v2 8/8] box: get rid of box.internal.sql_function_create
Date: Tue, 13 Aug 2019 23:43:11 +0300	[thread overview]
Message-ID: <AE5CD1D0-5AB5-42FE-A299-A66BDFC303D9@tarantool.org> (raw)
In-Reply-To: <8c42515c61f85e03dcd5abe35055b9301379de0a.1565275470.git.kshcherbatov@tarantool.org>


> diff --git a/src/box/func_def.h b/src/box/func_def.h
> index d99d89190..988d080f0 100644
> --- a/src/box/func_def.h
> +++ b/src/box/func_def.h
> @@ -110,7 +110,7 @@ struct func_def {
> 	 */
> 	bool is_sandboxed;
> 	/** The count of function's input arguments. */
> -	int param_count;
> +	uint32_t param_count;
> 	/** The type of the value returned by function. */
> 	enum field_type returns;
> 	/** Function aggregate option. */
> diff --git a/src/box/port.h b/src/box/port.h
> index a7f5d81bd..26f85b145 100644
> --- a/src/box/port.h
> +++ b/src/box/port.h
> @@ -113,6 +113,23 @@ static_assert(sizeof(struct port_lua) <= sizeof(struct port),
> void
> port_lua_create(struct port *port, struct lua_State *L);
> 
> +struct sql_value;
> +struct sql_context;

Nit: forward declaration of sql_context is redundant.

> +
> +/** Port implementation used with vdbe memory variables. */
> +struct port_vdbemem {
> +    const struct port_vtab *vtab;
> +    struct sql_value *mem;
> +    uint32_t size;

Nit: I’d better call it mem_count (or at least add brief explanation comment).

> diff --git a/src/lib/core/port.h b/src/lib/core/port.h
> index 09a026df5..17096d0d0 100644
> --- a/src/lib/core/port.h
> +++ b/src/lib/core/port.h
> @@ -98,6 +98,19 @@ struct port_vtab {
> 	 * is responsible for cleaning up.
> 	 **/
> 	const char *(*get_msgpack)(struct port *port, uint32_t *size);
> +	/**
> +	 * Get the content of a port as a sequence of vdbe memory
> +	 * variables. The SQL VDBE uses this representation for
> +	 * process data. This API is usefull to pass VDBE
> +	 * variables to sql builtin functions.
> +	 * The lifecycle of the returned value is
> +	 * implementation-specific: it may either be returned
> +	 * directly from the port, in which case the data will
> +	 * stay alive as long as the port is alive, or it may be
> +	 * allocated on the fiber()->gc, in which case the caller
> +	 * is responsible for cleaning up.
> +	 */

Consider comment fixes:

diff --git a/src/lib/core/port.h b/src/lib/core/port.h
index 17096d0d0..c6ca115a1 100644
--- a/src/lib/core/port.h
+++ b/src/lib/core/port.h
@@ -99,16 +99,12 @@ struct port_vtab {
         **/
        const char *(*get_msgpack)(struct port *port, uint32_t *size);
        /**
-        * Get the content of a port as a sequence of vdbe memory
-        * variables. The SQL VDBE uses this representation for
-        * process data. This API is usefull to pass VDBE
-        * variables to sql builtin functions.
-        * The lifecycle of the returned value is
-        * implementation-specific: it may either be returned
-        * directly from the port, in which case the data will
-        * stay alive as long as the port is alive, or it may be
-        * allocated on the fiber()->gc, in which case the caller
-        * is responsible for cleaning up.
+        * Get the content of a port as a sequence of VDBE memory
+        * cells. This API is used to pass VDBE variables to
+        * user-defined Lua functions (see OP_Function in sql/vdbe.c).
+        * The lifecycle of the returned value is the same as for
+        * @get_msgpack method, i.e. it depends on particular
+        * implementation.
         */
        struct sql_value *(*get_vdbemem)(struct port *port, uint32_t *size);
        /** Destroy a port and release associated resources. */

> +	struct sql_value *(*get_vdbemem)(struct port *port, uint32_t *size);
> 	/** Destroy a port and release associated resources. */
> 	void (*destroy)(struct port *port);
> };
> 
> 
> diff --git a/src/box/sql/func.c b/src/box/sql/func.c
> index f07c52b95..ea94d6151 100644
> --- a/src/box/sql/func.c
> +++ b/src/box/sql/func.c
> @@ -45,6 +45,10 @@
> #include <unicode/uchar.h>
> #include <unicode/ucol.h>
> #include "box/coll_id_cache.h"
> +#include "box/port.h"
> +#include "box/tuple.h"
> +#include "lua/utils.h"
> +#include "mpstream.h"
> 
> /*
>  * Return the collating function associated with a function.
> @@ -70,6 +74,279 @@ sqlSkipAccumulatorLoad(sql_context * context)
> 	context->skipFlag = 1;
> }
> 
> +/**
> + * Allocate a sequence of initialized vdbe memory registers
> + * on region.
> + */
> +static struct Mem *
> +vdbemem_alloc_on_region(uint32_t count)

Nit: we already have sql_vdbe_mem_alloc_region()
which allocates memory for string using region.
Could you rename it (the original one I mean) to avoid
any confusions?

> +{
> +	struct region *region = &fiber()->gc;
> +	struct Mem *ret = region_alloc(region, count * sizeof(*ret));
> +	if (ret == NULL) {
> +		diag_set(OutOfMemory, count * sizeof(*ret),
> +			 "region_alloc", "ret");
> +		return NULL;
> +	}
> +	memset(ret, 0, count * sizeof(*ret));
> +	for (uint32_t i = 0; i < count; i++) {
> +		sqlVdbeMemInit(&ret[i], sql_get(), MEM_Null);
> +		assert(memIsValid(&ret[i]));
> +	}
> +	return ret;
> +}
> +
> +static const char *
> +port_vdbemem_get_msgpack(struct port *base, uint32_t *size)

In fact, this function is unused and is not tested at all.

> +{
> +	struct port_vdbemem *port = (struct port_vdbemem *) base;
> +	struct region *region = &fiber()->gc;
> +	size_t region_svp = region_used(region);
> +	bool is_error = false;
> +	struct mpstream stream;
> +	mpstream_init(&stream, region, region_reserve_cb, region_alloc_cb,
> +		      set_encode_error, &is_error);
> +	mpstream_encode_array(&stream, port->size);
> +	for (uint32_t i = 0; i < port->size && !is_error; i++) {
> +		sql_value *param =
> +			(sql_value *)((struct Mem *)port->mem + i);
> +		switch (sql_value_type(param)) {
> +		case MP_INT: {
> +			sql_int64 val = sql_value_int64(param);
> +			if (val < 0) {
> +				mpstream_encode_int(&stream, val);
> +				break;
> +			}
> +			FALLTHROUGH;
> +		}
> +		case MP_UINT: {
> +			sql_int64 val = sql_value_int64(param);
> +			mpstream_encode_uint(&stream, val);
> +			break;
> +		}
> +		case MP_DOUBLE: {
> +			mpstream_encode_double(&stream,
> +					       sql_value_double(param));
> +			break;
> +		}
> +		case MP_STR: {
> +			mpstream_encode_str(&stream,
> +					(const char *) sql_value_text(param));

Nit: a bit broken indentation. You can use auxiliary tmp var.

> +			break;
> +		}
> +		case MP_BIN: {
> +			mpstream_encode_binl(&stream, sql_value_bytes(param));
> +			mpstream_memcpy(&stream, sql_value_blob(param),
> +					sql_value_bytes(param));
> +			break;

> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index a66becc89..23b6995d7 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> 
> @@ -1767,6 +1768,50 @@ case OP_BuiltinFunction: {
> 	break;
> }
> 
> +/* Opcode: Function P1 P2 P3 P4 P5
> + * Synopsis: r[P3]=func(r[P2@P5])
> + *
> + * Invoke a user function (P4 is a pointer to a function object
> + * that defines the function) with P5 arguments taken from
> + * register P2 and successors. The result of the function is
> + * stored in register P3.
> + * Register P3 must not be one of the function inputs.

Nit: you don’t check this fact.

> + *
> + * P1 is a 32-bit bitmask indicating whether or not each argument
> + * to the function was determined to be constant at compile time.
> + * If the first argument was constant then bit 0 of P1 is set.

This comment is not related to the code: P1 is not involved at all.

> + */
> +case OP_Function: {
> +	struct func *func = pOp->p4.func;
> +	int argc = pOp->p5;
> +	struct Mem *argv = &aMem[pOp->p2];
> +	struct port args, ret;
> +
> +	struct region *region = &fiber()->gc;
> +	size_t region_svp = region_used(region);
> +	port_vdbemem_create(&args, (struct sql_value *)argv, argc);
> +	if (func_call(func, &args, &ret) != 0)
> +		goto abort_due_to_error;
> +
> +	pOut = vdbe_prepare_null_out(p, pOp->p3);
> +	uint32_t size;
> +	struct Mem *mem = (struct Mem *)port_get_vdbemem(&ret, &size);
> +	if (mem != NULL && size > 0)
> +		*pOut = mem[0];
> +	port_destroy(&ret);
> +	region_truncate(region, region_svp);
> +	if (mem == NULL)
> +		goto abort_due_to_error;
> +
> +	/* Copy the result of the function into register P3 */
> +	if (pOut->flags & (MEM_Str|MEM_Blob))

Nit:

diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 23b6995d7..69cbab45c 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1803,8 +1803,11 @@ case OP_Function: {
        if (mem == NULL)
                goto abort_due_to_error;
 
-       /* Copy the result of the function into register P3 */
-       if (pOut->flags & (MEM_Str|MEM_Blob))
+       /*
+        * Copy the result of the function invocation into
+        * register P3.
+        */
+       if ((pOut->flags & (MEM_Str | MEM_Blob)) != 0)
                if (sqlVdbeMemTooBig(pOut)) goto too_big;
 
        REGISTER_TRACE(p, pOp->p3, pOut);

> +		if (sqlVdbeMemTooBig(pOut)) goto too_big;
> +
> +	REGISTER_TRACE(p, pOp->p3, pOut);
> +	UPDATE_MAX_BLOBSIZE(pOut);
> +	break;
> +}
> +
> /* Opcode: BitAnd P1 P2 P3 * *
>  * Synopsis: r[P3]=r[P1]&r[P2]
>  *
> 
> diff --git a/test/box/function1.result b/test/box/function1.result
> index 5b091f72b..48c9ad6cf 100644
> --- a/test/box/function1.result
> +++ b/test/box/function1.result
> @@ -366,6 +366,177 @@ test_run:cmd("setopt delimiter ''");
> +box.execute('SELECT "function1.divide"()')
> +---
> +- null
> +- invalid argument
> +...
> +box.execute('SELECT "function1.divide"(6)')
> +---
> +- null
> +- wrong number of arguments to function function1.divide()
> +...
> +box.execute('SELECT "function1.divide"(6, 3)')
> +---
> +- null
> +- wrong number of arguments to function function1.divide()

Oh, could you please fix this awful error message?
At least, it lacks a verb. Personally I would prefer smth like:
“invalid number of arguments is passed to %s: expected %d, got %d"

  reply	other threads:[~2019-08-13 20:43 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-08 14:50 [tarantool-patches] [PATCH v2 0/8] sql: uniform SQL and Lua functions subsystem Kirill Shcherbatov
2019-08-08 14:50 ` [tarantool-patches] [PATCH v2 1/8] sql: remove SQL_PreferBuiltin flag Kirill Shcherbatov
2019-08-09 16:07   ` [tarantool-patches] " n.pettik
2019-08-12 21:58   ` Konstantin Osipov
2019-08-08 14:50 ` [tarantool-patches] [PATCH v2 2/8] sql: GREATEST, LEAST instead of MIN/MAX overload Kirill Shcherbatov
2019-08-09 17:37   ` [tarantool-patches] " n.pettik
2019-08-13  8:26     ` Kirill Shcherbatov
2019-08-12 21:59   ` Konstantin Osipov
2019-08-08 14:50 ` [tarantool-patches] [PATCH v2 3/8] sql: wrap all trim functions in dispatcher Kirill Shcherbatov
2019-08-09 18:05   ` [tarantool-patches] " n.pettik
2019-08-13  8:28     ` Kirill Shcherbatov
2019-08-13 22:19       ` n.pettik
2019-08-12 22:00   ` Konstantin Osipov
2019-08-08 14:50 ` [tarantool-patches] [PATCH v2 4/8] sql: get rid of SQL_FUNC_COUNT flag Kirill Shcherbatov
2019-08-12 22:01   ` [tarantool-patches] " Konstantin Osipov
2019-08-13 20:35   ` n.pettik
2019-08-14  7:25     ` Kirill Shcherbatov
2019-08-08 14:50 ` [tarantool-patches] [PATCH v2 5/8] sql: introduce a signature_mask for functions Kirill Shcherbatov
2019-08-12 22:04   ` [tarantool-patches] " Konstantin Osipov
2019-08-13  8:32     ` Kirill Shcherbatov
2019-08-13  8:44       ` Konstantin Osipov
2019-08-13 20:38   ` n.pettik
2019-08-14  7:21     ` Kirill Shcherbatov
2019-08-08 14:50 ` [tarantool-patches] [PATCH v2 6/8] sql: rename OP_Function to OP_BuiltinFunction Kirill Shcherbatov
2019-08-12 22:04   ` [tarantool-patches] " Konstantin Osipov
2019-08-13 20:36   ` n.pettik
2019-08-08 14:50 ` [tarantool-patches] [PATCH v2 7/8] sql: get rid of FuncDef function hash Kirill Shcherbatov
2019-08-12 22:11   ` [tarantool-patches] " Konstantin Osipov
2019-08-13  7:29     ` Kirill Shcherbatov
2019-08-13  8:42       ` Konstantin Osipov
2019-08-13  9:45         ` Kirill Shcherbatov
2019-08-13 20:40   ` n.pettik
2019-08-16 12:57     ` Kirill Shcherbatov
2019-08-20 16:06       ` n.pettik
2019-08-08 14:50 ` [tarantool-patches] [PATCH v2 8/8] box: get rid of box.internal.sql_function_create Kirill Shcherbatov
2019-08-13 20:43   ` n.pettik [this message]
2019-08-16 12:57     ` [tarantool-patches] " Kirill Shcherbatov
2019-08-20 19:36       ` n.pettik

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=AE5CD1D0-5AB5-42FE-A299-A66BDFC303D9@tarantool.org \
    --to=korablev@tarantool.org \
    --cc=kshcherbatov@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH v2 8/8] box: get rid of box.internal.sql_function_create' \
    /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