From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id D27162AA85 for ; Thu, 21 Mar 2019 15:30:08 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qJhY6GjNbRrx for ; Thu, 21 Mar 2019 15:30:08 -0400 (EDT) Received: from smtpng3.m.smailru.net (smtpng3.m.smailru.net [94.100.177.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 7826F2AA8F for ; Thu, 21 Mar 2019 15:30:08 -0400 (EDT) From: imeevma@tarantool.org Subject: [tarantool-patches] [PATCH v1 2/3] sql: define flags for OP_MakeRecord Date: Thu, 21 Mar 2019 22:30:06 +0300 Message-Id: <5e4fa2917100f0be0058bdb8149ebd6c225f0f19.1553195994.git.imeevma@gmail.com> In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-Help: List-Unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-Subscribe: List-Owner: List-post: List-Archive: To: korablev@tarantool.org Cc: tarantool-patches@freelists.org 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@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->p3p1 || 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