Tarantool development patches archive
 help / color / mirror / Atom feed
From: Kirill Shcherbatov <kshcherbatov@tarantool.org>
To: tarantool-patches@freelists.org,
	Nikita Pettik <korablev@tarantool.org>,
	Konstantin Osipov <kostja.osipov@gmail.com>
Subject: [tarantool-patches] Re: [PATCH v3 0/3] box: run checks on insertions in LUA spaces
Date: Wed, 15 May 2019 11:37:03 +0300	[thread overview]
Message-ID: <b02cb7dd-9967-4835-8b6f-29c61de8cafe@tarantool.org> (raw)
In-Reply-To: <35C5E394-EC1A-421B-8868-F4451CC96DE1@tarantool.org>

> Sorry,  meant: "Why can’t we simply do this…"
> 
> So this is suggestion how to fix redundant fields decoding.

Not exactly like this, but quite similar(see attachment below).

At first, the bytecode is compiled with vdbe_emit_ck_constraint
based on sqlExprIfTrue encoder. So, this code refers BY FIELDNO
to some fields in memory having the following layout:
[0 X 0 0 X X 0 0 0 0]
So we may bind only min_field_count fields, there the min_field_count
it the fieldno + 1 of the rightmost referenced field.

Actually we may use a bitmap of used fields and bind only them, but
managing such bitmap (that may not fit into uint64_t e.g. in general case)
is costly and there is no difference between binding NULL and field
while we must decode via mp_next all min_field_count tuple fields anyway. 

=================================================

diff --git a/src/box/ck_constraint.c b/src/box/ck_constraint.c
index 52f615227..a6352f005 100644
--- a/src/box/ck_constraint.c
+++ b/src/box/ck_constraint.c
@@ -48,12 +48,14 @@
  */
 static int
 ck_constraint_resolve_field_names(struct Expr *expr,
-				  struct space_def *space_def)
+				  struct space_def *space_def,
+				  uint32_t *min_field_count)
 {
 	struct Parse parser;
 	sql_parser_create(&parser, sql_get());
 	parser.parse_only = true;
-	sql_resolve_self_reference(&parser, space_def, NC_IsCheck, expr, NULL);
+	sql_resolve_self_reference(&parser, space_def, NC_IsCheck, expr, NULL,
+				   min_field_count);
 	int rc = parser.is_aborted ? -1 : 0;
 	sql_parser_destroy(&parser);
 	return rc;
@@ -150,7 +152,7 @@ ck_constraint_program_run(struct ck_constraint *ck_constraint,
 	 */
 	uint32_t tuple_field_count = mp_decode_array(&new_tuple);
 	uint32_t field_count =
-		MIN(tuple_field_count, space->def->field_count);
+		MIN(tuple_field_count, ck_constraint->min_field_count);
 	for (uint32_t i = 0; i < field_count; i++) {
 		struct sql_bind bind;
 		if (sql_bind_decode(&bind, i + 1, &new_tuple) != 0 ||
@@ -214,6 +216,7 @@ ck_constraint_new(struct ck_constraint_def *ck_constraint_def,
 	ck_constraint->def = NULL;
 	ck_constraint->stmt = NULL;
 	ck_constraint->space_id = space_def->id;
+	ck_constraint->min_field_count = 0;
 	rlist_create(&ck_constraint->link);
 	trigger_create(&ck_constraint->trigger,
 		       ck_constraint_on_replace_trigger, ck_constraint,
@@ -222,7 +225,9 @@ ck_constraint_new(struct ck_constraint_def *ck_constraint_def,
 		sql_expr_compile(sql_get(), ck_constraint_def->expr_str,
 				 strlen(ck_constraint_def->expr_str));
 	if (expr == NULL ||
-	    ck_constraint_resolve_field_names(expr, space_def) != 0) {
+	    ck_constraint_resolve_field_names(expr, space_def,
+					      &ck_constraint->
+						  min_field_count) != 0) {
 		diag_set(ClientError, ER_CREATE_CK_CONSTRAINT,
 			 ck_constraint_def->name,
 			 box_error_message(box_error_last()));
diff --git a/src/box/ck_constraint.h b/src/box/ck_constraint.h
index abbfd3a8f..89fdaf806 100644
--- a/src/box/ck_constraint.h
+++ b/src/box/ck_constraint.h
@@ -87,6 +87,8 @@ struct ck_constraint {
 	 * built for.
 	 */
 	uint32_t space_id;
+	/** The index of the rightmost referenced field. */
+	uint32_t min_field_count;
 	/**
 	 * Organize check constraint structs into linked list
 	 * with space::ck_constraint.
diff --git a/src/box/sql.h b/src/box/sql.h
index 4bb27da8e..7be1210cd 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -278,12 +278,15 @@ sql_expr_list_append(struct sql *db, struct ExprList *expr_list,
  * @param def The definition of space being referenced.
  * @param type NC_IsCheck or NC_IdxExpr.
  * @param expr Expression to resolve.  May be NULL.
- * @param expr_list Expression list to resolve.  May be NUL.
+ * @param expr_list Expression list to resolve.  May be NULL.
+ * @param min_field_count[out] Return the index of the rightmost
+ *                             referenced field.
  */
 void
 sql_resolve_self_reference(struct Parse *parser, struct space_def *def,
 			   int type, struct Expr *expr,
-			   struct ExprList *expr_list);
+			   struct ExprList *expr_list,
+			   uint32_t *min_field_count);
 
 /**
  * Initialize a new parser object.
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 3709f6b1d..b515f52a5 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -2195,7 +2195,7 @@ index_fill_def(struct Parse *parse, struct index *index,
 	for (int i = 0; i < expr_list->nExpr; i++) {
 		struct Expr *expr = expr_list->a[i].pExpr;
 		sql_resolve_self_reference(parse, space_def, NC_IdxExpr,
-					   expr, 0);
+					   expr, NULL, NULL);
 		if (parse->is_aborted)
 			goto cleanup;
 
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 504096e6d..76baaa142 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -556,8 +556,13 @@ resolveExprStep(Walker * pWalker, Expr * pExpr)
 	case TK_ID:{
 			if ((pNC->ncFlags & NC_AllowAgg) != 0)
 				pNC->ncFlags |= NC_HasUnaggregatedId;
-			return lookupName(pParse, 0, pExpr->u.zToken, pNC,
-					  pExpr);
+			int rc = lookupName(pParse, 0, pExpr->u.zToken, pNC,
+					    pExpr);
+			assert(pExpr->iColumn >= 0);
+			pNC->min_field_count =
+				MAX(pNC->min_field_count,
+				    (uint32_t)pExpr->iColumn + 1);
+			return rc;
 		}
 
 		/* A table name and column name:     ID.ID
@@ -1611,7 +1616,8 @@ sqlResolveSelectNames(Parse * pParse,	/* The parser context */
 void
 sql_resolve_self_reference(struct Parse *parser, struct space_def *def,
 			   int type, struct Expr *expr,
-			   struct ExprList *expr_list)
+			   struct ExprList *expr_list,
+			   uint32_t *min_field_count)
 {
 	/* Fake SrcList for parser->create_table_def */
 	SrcList sSrc;
@@ -1631,8 +1637,11 @@ sql_resolve_self_reference(struct Parse *parser, struct space_def *def,
 	sNC.pParse = parser;
 	sNC.pSrcList = &sSrc;
 	sNC.ncFlags = type;
+	sNC.min_field_count = 0;
 	if (sqlResolveExprNames(&sNC, expr) != 0)
 		return;
 	if (expr_list != NULL)
 		sqlResolveExprListNames(&sNC, expr_list);
+	if (min_field_count != NULL)
+		*min_field_count = sNC.min_field_count;
 }
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 64f5f3d59..b2a354043 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -2352,6 +2352,8 @@ struct NameContext {
 	int nRef;		/* Number of names resolved by this context */
 	int nErr;		/* Number of errors encountered while resolving names */
 	u16 ncFlags;		/* Zero or more NC_* flags defined below */
+	/** The rightmost tuple field referenced by AST. */
+	uint32_t min_field_count;
 };
 
 /*

  reply	other threads:[~2019-05-15  8:37 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-14 15:02 [tarantool-patches] " Kirill Shcherbatov
2019-05-14 15:02 ` [tarantool-patches] [PATCH v3 1/3] schema: add new system space for CHECK constraints Kirill Shcherbatov
2019-05-14 18:29   ` [tarantool-patches] " Konstantin Osipov
2019-05-14 15:02 ` [tarantool-patches] [PATCH v3 2/3] box: run check constraint tests on space alter Kirill Shcherbatov
2019-05-14 15:02 ` [tarantool-patches] [PATCH v3 3/3] box: user-friendly interface to manage ck constraints Kirill Shcherbatov
2019-05-14 20:09   ` [tarantool-patches] " Konstantin Osipov
2019-05-14 17:00 ` [tarantool-patches] Re: [PATCH v3 0/3] box: run checks on insertions in LUA spaces Konstantin Osipov
     [not found]   ` <FB4C0C9D-E56E-4FEF-A2C5-87AD8BF634F9@gmail.com>
2019-05-14 18:22     ` n.pettik
2019-05-14 18:41       ` Konstantin Osipov
2019-05-14 18:49         ` n.pettik
2019-05-15  8:37           ` Kirill Shcherbatov [this message]
2019-05-16 13:51 ` Kirill Shcherbatov
2019-05-19 16:02 ` Vladislav Shpilevoy

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=b02cb7dd-9967-4835-8b6f-29c61de8cafe@tarantool.org \
    --to=kshcherbatov@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=kostja.osipov@gmail.com \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH v3 0/3] box: run checks on insertions in LUA spaces' \
    /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