Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: imeevma@tarantool.org
Cc: tarantool-patches@dev.tarantool.org
Subject: Re: [Tarantool-patches] [PATCH v1 3/7] sql: rework OP_Seek* opcodes
Date: Thu, 5 Aug 2021 00:25:49 +0200	[thread overview]
Message-ID: <31aa2f05-09e9-ce24-5a46-894d3d23b8f7@tarantool.org> (raw)
In-Reply-To: <8722fbfce0455e13c01672793f6a5075dc0fc458.1627504973.git.imeevma@gmail.com>

Thanks for the patch!

See 3 comments below.

> diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
> index 47a940c56..5d1d7592e 100644
> --- a/src/box/sql/mem.h
> +++ b/src/box/sql/mem.h
> @@ -1028,3 +1028,20 @@ mpstream_encode_vdbe_mem(struct mpstream *stream, struct Mem *var);
>  char *
>  sql_vdbe_mem_encode_tuple(struct Mem *fields, uint32_t field_count,
>  			  uint32_t *tuple_size, struct region *region);
> +
> +static inline bool
> +is_mem_num_min(const struct Mem *mem)
> +{
> +	return (mem->field_type == FIELD_TYPE_INTEGER &&
> +		mem->type == MEM_TYPE_INT && mem->u.i == INT64_MIN) ||
> +	       (mem->field_type == FIELD_TYPE_UNSIGNED &&
> +		mem->type == MEM_TYPE_UINT && mem->u.u == 0);
> +}
> +
> +static inline bool
> +is_mem_num_max(const struct Mem *mem)

1. Could you please name them to mem_is_num_min() and mem_is_num_max()?
Also what if they are DOUBLE? Should't these functions be called then
mem_is_int_min() and mem_is_int_max()?

> +{
> +	return (mem->field_type == FIELD_TYPE_INTEGER ||
> +		mem->field_type == FIELD_TYPE_UNSIGNED) &&
> +	       mem->type == MEM_TYPE_UINT && mem->u.u == 0;
> +}
> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index 62f58def9..a69402720 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> @@ -2577,6 +2526,62 @@ case OP_Close: {
>   *
>   * See also: Found, NotFound, SeekGt, SeekGe, SeekLe
>   */
> +case OP_SeekLT: {       /* jump, in3 */
> +	struct VdbeCursor *cur = p->apCsr[pOp->p1];
> +#ifdef SQL_DEBUG
> +	cur->seekOp = pOp->opcode;
> +#endif
> +	cur->nullRow = 0;
> +	cur->uc.pCursor->iter_type = ITER_LT;
> +
> +	uint32_t len = pOp->p4.i;
> +	assert(pOp->p4type == P4_INT32);
> +	assert(len <= cur->key_def->part_count);
> +	struct Mem *mems = &aMem[pOp->p3];
> +	bool is_le = false;
> +	bool is_zero = false;
> +	for (uint32_t i = 0; i < len; ++i) {
> +		enum field_type type = cur->key_def->parts[i].type;
> +		struct Mem *mem = &mems[i];
> +		if (mem_is_field_compatible(mem, type))
> +			continue;
> +		if (!sql_type_is_numeric(type) || !mem_is_num(mem)) {
> +			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> +				 mem_str(mem), field_type_strs[type]);
> +			goto abort_due_to_error;
> +		}
> +		int cmp = mem_cast_implicit_number(mem, type);
> +		is_le = is_le || cmp > 0;
> +		/*
> +		 * If number before cast were less than min possible for given
> +		 * field type, than there is no point to use iterator since we
> +		 * won't find anything.
> +		 */
> +		is_zero = is_zero || (is_mem_num_min(mem) && cmp < 0);

2. Do you really need this optimization? Seems like a very rare case. The
same in the other places.

Also it looks like a lot of code duplication. But I see why, and again I
don't see a way to reuse all this code easily.

> +	}
> +	if (is_zero) {
> +		assert(pOp->p2 > 0);
> +		VdbeBranchTaken(1, 2);
> +		goto jump_to_p2;
> +	}

<...>

> +case OP_SeekLE: {       /* jump, in3 */

<...>

> +	cur->nullRow = 0;
> +	bool is_eq = (cur->uc.pCursor->hints & OPFLAG_SEEKEQ) != 0;
> +	cur->uc.pCursor->iter_type = is_eq ? ITER_REQ : ITER_LE;
> +	assert(!is_eq || pOp[1].opcode == OP_IdxLT);
> +
> +	uint32_t len = pOp->p4.i;
> +	assert(pOp->p4type == P4_INT32);
> +	assert(len <= cur->key_def->part_count);
> +	struct Mem *mems = &aMem[pOp->p3];
> +	bool is_lt = false;
> +	bool is_zero = false;
> +	for (uint32_t i = 0; i < len; ++i) {
> +		enum field_type type = cur->key_def->parts[i].type;
> +		struct Mem *mem = &mems[i];
> +		if (mem_is_field_compatible(mem, type))
> +			continue;
> +		if (!sql_type_is_numeric(type) || !mem_is_num(mem)) {
> +			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
> +				 mem_str(mem), field_type_strs[type]);
> +			goto abort_due_to_error;
>  		}
> -		iKey = i;
> -
> -		/* If the P3 value could not be converted into an integer without
> -		 * loss of information, then special processing is required...
> +		int cmp = mem_cast_implicit_number(mem, type);
> +		is_lt = is_lt || cmp < 0;

3. You needed to find values <= mem. The mem during cast was
turned into mem2 < mem, correct? Then you need to find values
<= mem2. Otherwise you skip mem2 itself. Or am I mistaken
somewhere? Similar questions to all the other usages of
mem_cast_implicit_number for seeking.

  reply	other threads:[~2021-08-04 22:25 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-28 20:51 [Tarantool-patches] [PATCH v1 0/7] Rework implicit cast Mergen Imeev via Tarantool-patches
2021-07-28 20:51 ` [Tarantool-patches] [PATCH v1 1/7] sql: rework implicit cast fo assignment Mergen Imeev via Tarantool-patches
2021-07-30 21:55   ` Vladislav Shpilevoy via Tarantool-patches
2021-08-04 22:21     ` Vladislav Shpilevoy via Tarantool-patches
2021-08-05 23:27     ` Mergen Imeev via Tarantool-patches
2021-08-06  0:13       ` Vladislav Shpilevoy via Tarantool-patches
2021-07-28 20:51 ` [Tarantool-patches] [PATCH v1 2/7] sql: remove implicit cast from comparison opcodes Mergen Imeev via Tarantool-patches
2021-08-04 22:24   ` Vladislav Shpilevoy via Tarantool-patches
2021-08-05 23:33     ` Mergen Imeev via Tarantool-patches
2021-08-06  0:13       ` Vladislav Shpilevoy via Tarantool-patches
2021-07-28 20:51 ` [Tarantool-patches] [PATCH v1 3/7] sql: rework OP_Seek* opcodes Mergen Imeev via Tarantool-patches
2021-08-04 22:25   ` Vladislav Shpilevoy via Tarantool-patches [this message]
2021-08-05 23:40     ` Mergen Imeev via Tarantool-patches
2021-07-28 20:51 ` [Tarantool-patches] [PATCH v1 4/7] sql: remove unnecessary calls of OP_ApplyType Mergen Imeev via Tarantool-patches
2021-08-04 22:26   ` Vladislav Shpilevoy via Tarantool-patches
2021-08-05 23:41     ` Mergen Imeev via Tarantool-patches
2021-07-28 20:51 ` [Tarantool-patches] [PATCH v1 5/7] sql: remove implicit cast from OP_MakeRecord Mergen Imeev via Tarantool-patches
2021-08-04 22:27   ` Vladislav Shpilevoy via Tarantool-patches
2021-08-05 23:43     ` Mergen Imeev via Tarantool-patches
2021-08-06  0:13       ` Vladislav Shpilevoy via Tarantool-patches
2021-07-28 20:51 ` [Tarantool-patches] [PATCH v1 6/7] sql: remove implicit cast from OP_MustBeInt Mergen Imeev via Tarantool-patches
2021-08-05 23:47   ` Mergen Imeev via Tarantool-patches
2021-07-28 20:51 ` [Tarantool-patches] [PATCH v1 7/7] sql: remove unused MEM cast functions Mergen Imeev via Tarantool-patches
2021-08-04 22:27   ` Vladislav Shpilevoy via Tarantool-patches
2021-08-05 23:45     ` Mergen Imeev via Tarantool-patches

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=31aa2f05-09e9-ce24-5a46-894d3d23b8f7@tarantool.org \
    --to=tarantool-patches@dev.tarantool.org \
    --cc=imeevma@tarantool.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH v1 3/7] sql: rework OP_Seek* opcodes' \
    /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