[tarantool-patches] [PATCH v1 2/3] sql: define flags for OP_MakeRecord

imeevma at tarantool.org imeevma at tarantool.org
Thu Mar 21 22:30:06 MSK 2019


This patch defines three flags for OPcode OP_MakeRecord.

The first flag is OPFLAG_IS_EPHEMERAL allows to do some
optimization as created record will be inserted into ephemeral
space. This flag was created before this patch, but only here it
gotten its own name.

The second flag is OPFLAG_P2_IS_REG allows to use register P2 not
only as count of fields of created record, but also as number of
register that contains count of fields. This feature needed to
create records with number of fields determined during execution
of VDBE.

The third flag is OPFLAG_MAKE_ARRAY allows to change subtype of
created record to SQL_SUBTYPE_MSGPACK. Record, with this subtype
is considered as ARRAY and can be used as part of new record.

Needed for #2843
---
 src/box/sql/delete.c |  2 +-
 src/box/sql/insert.c |  2 +-
 src/box/sql/select.c |  6 +++---
 src/box/sql/sqlInt.h |  7 +++++++
 src/box/sql/update.c |  2 +-
 src/box/sql/vdbe.c   | 34 +++++++++++++++++++++++++---------
 6 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index f4d0334..d52e904 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -336,7 +336,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
 			/* Set flag to save memory allocating one
 			 * by malloc.
 			 */
-			sqlVdbeChangeP5(v, 1);
+			sqlVdbeChangeP5(v, OPFLAG_IS_EPHEMERAL);
 			sqlVdbeAddOp2(v, OP_IdxInsert, reg_key, reg_eph);
 		}
 
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 6f7f020..1484596 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -478,7 +478,7 @@ sqlInsert(Parse * pParse,	/* Parser context */
 			sqlVdbeAddOp3(v, OP_MakeRecord, regCopy,
 					  nColumn + 1, regRec);
 			/* Set flag to save memory allocating one by malloc. */
-			sqlVdbeChangeP5(v, 1);
+			sqlVdbeChangeP5(v, OPFLAG_IS_EPHEMERAL);
 			sqlVdbeAddOp2(v, OP_IdxInsert, regRec, reg_eph);
 
 			sqlVdbeGoto(v, addrL);
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 5195656..8a55e37 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1152,7 +1152,7 @@ selectInnerLoop(Parse * pParse,		/* The parser context */
 			sqlVdbeAddOp3(v, OP_MakeRecord, regResult,
 					  nResultCol, r1 + nPrefixReg);
 			/* Set flag to save memory allocating one by malloc. */
-			sqlVdbeChangeP5(v, 1);
+			sqlVdbeChangeP5(v, OPFLAG_IS_EPHEMERAL);
 #ifndef SQL_OMIT_CTE
 			if (eDest == SRT_DistFifo) {
 				/* If the destination is DistFifo, then cursor (iParm+1) is open
@@ -1189,7 +1189,7 @@ selectInnerLoop(Parse * pParse,		/* The parser context */
 				sqlVdbeAddOp3(v, OP_Copy, regResult, regCopy, nResultCol - 1);
 				sqlVdbeAddOp3(v, OP_MakeRecord, regCopy, nResultCol + 1, regRec);
 				/* Set flag to save memory allocating one by malloc. */
-				sqlVdbeChangeP5(v, 1);
+				sqlVdbeChangeP5(v, OPFLAG_IS_EPHEMERAL);
 				sqlVdbeAddOp2(v, OP_IdxInsert, regRec, pDest->reg_eph);
 				sqlReleaseTempReg(pParse, regRec);
 				sqlReleaseTempRange(pParse, regCopy, nResultCol + 1);
@@ -3086,7 +3086,7 @@ generateOutputSubroutine(struct Parse *parse, struct Select *p,
 			sqlVdbeAddOp3(v, OP_MakeRecord, regCopy,
 					  in->nSdst + 1, regRec);
 			/* Set flag to save memory allocating one by malloc. */
-			sqlVdbeChangeP5(v, 1);
+			sqlVdbeChangeP5(v, OPFLAG_IS_EPHEMERAL);
 			sqlVdbeAddOp2(v, OP_IdxInsert, regRec, dest->reg_eph);
 			sqlReleaseTempRange(parse, regCopy, in->nSdst + 1);
 			sqlReleaseTempReg(parse, regRec);
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 8967ea3..aed6cfb 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -2787,6 +2787,13 @@ struct Parse {
 #define OPFLAG_SAVEPOSITION  0x02	/* OP_Delete: keep cursor position */
 #define OPFLAG_AUXDELETE     0x04	/* OP_Delete: index in a DELETE op */
 
+/* OP_MakeRecord: inserton into ephemeral space. */
+#define OPFLAG_IS_EPHEMERAL  0x01
+/* OP_MakeRecord: p2 is number of register contains true value. */
+#define OPFLAG_P2_IS_REG     0x02
+/* OP_MakeRecord: result should be array instead of scalar. */
+#define OPFLAG_MAKE_ARRAY    0x04
+
 #define OPFLAG_SAME_FRAME    0x01	/* OP_FCopy: use same frame for source
 					 * register
 					 */
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index 05ceeb4..7add2ba 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -285,7 +285,7 @@ sqlUpdate(Parse * pParse,		/* The parser context */
 		 * Set flag to save memory allocating one by
 		 * malloc.
 		 */
-		sqlVdbeChangeP5(v, 1);
+		sqlVdbeChangeP5(v, OPFLAG_IS_EPHEMERAL);
 		sqlVdbeAddOp2(v, OP_IdxInsert, regKey, reg_eph);
 	}
 	/* End the database scan loop.
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index ed7bf88..e057efd 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2868,18 +2868,26 @@ case OP_ApplyType: {
 /* Opcode: MakeRecord P1 P2 P3 P4 P5
  * Synopsis: r[P3]=mkrec(r[P1 at P2])
  *
- * Convert P2 registers beginning with P1 into the [record format]
+ * If flag OPFLAG_P2_IS_REG is set then reg_count is the number
+ * that contains in r[P2], else reg_count = P2.
+ *
+ * Convert reg_count registers beginning with P1 into the [record format]
  * use as a data record in a database table or as a key
  * in an index.  The OP_Column opcode can decode the record later.
  *
- * P4 may be a string that is P2 characters long.  The nth character of the
- * string indicates the column type that should be used for the nth
+ * If flag OPFLAG_MAKE_ARRAY is set than subtype of craeted record
+ * should be set as SQL_SUBTYPE_MSGPACK.
+ *
+ * P4 may be a string that is reg_count characters long.  The nth
+ * character of the string indicates the column type that should
+ * be used for the nth
  * field of the index key.
  *
  * If P4 is NULL then all index fields have type SCALAR.
  *
- * If P5 is not NULL then record under construction is intended to be inserted
- * into ephemeral space. Thus, sort of memory optimization can be performed.
+ * If flag OPFLAG_IS_EPHEMERAL is set then record under
+ * construction is intended to be inserted into ephemeral space.
+ * Thus, sort of memory optimization can be performed.
  */
 case OP_MakeRecord: {
 	Mem *pRec;             /* The new record */
@@ -2887,6 +2895,9 @@ case OP_MakeRecord: {
 	Mem MAYBE_UNUSED *pLast;  /* Last field of the record */
 	int nField;            /* Number of fields in the record */
 	u8 bIsEphemeral;
+	int reg_count = pOp->p2;
+	if ((pOp->p5 & OPFLAG_P2_IS_REG) != 0)
+		reg_count = aMem[reg_count].u.i;
 
 	/* Assuming the record contains N fields, the record format looks
 	 * like this:
@@ -2905,14 +2916,15 @@ case OP_MakeRecord: {
 	 */
 	nField = pOp->p1;
 	enum field_type *types = pOp->p4.types;
-	bIsEphemeral = pOp->p5;
-	assert(nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem+1 - p->nCursor)+1);
+	bIsEphemeral = pOp->p5 & OPFLAG_IS_EPHEMERAL;
+	assert((nField > 0) && (reg_count > 0) &&
+	       (reg_count + nField <= (p->nMem + 1 - p->nCursor) + 1));
 	pData0 = &aMem[nField];
-	nField = pOp->p2;
+	nField = reg_count;
 	pLast = &pData0[nField-1];
 
 	/* Identify the output register */
-	assert(pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2);
+	assert(pOp->p3 < pOp->p1 || pOp->p3 >= pOp->p1 + reg_count);
 	pOut = &aMem[pOp->p3];
 	memAboutToChange(p, pOut);
 
@@ -2964,6 +2976,10 @@ case OP_MakeRecord: {
 		pOut->n = tuple_size;
 		pOut->z = tuple;
 	}
+	if ((pOp->p5 & OPFLAG_MAKE_ARRAY) != 0) {
+		pOut->flags |= MEM_Subtype;
+		pOut->subtype = SQL_SUBTYPE_MSGPACK;
+	}
 	if (rc)
 		goto no_mem;
 	assert(sqlVdbeCheckMemInvariants(pOut));
-- 
2.7.4





More information about the Tarantool-patches mailing list