From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 481986EC63; Fri, 9 Apr 2021 23:06:01 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 481986EC63 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1617998761; bh=Qu1VyP1ate0awlLeJBX4mvdaC+zvyA8ZUNrU/iJvOAA=; h=To:Cc:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=zRmBR1a5WvCVKAKeZNuM77ib1YNPsGV14DbNTJ2OgSkRsKE1EYzxalGzGoH/dpYzI 7/GnMezoKvoGbS90l1NzchcCoycvoCfMRGusV3fREZ82erR9PjyTqAp3aC7Os894ix mUf1gJEqTgh9GbTy5WlrsuknHqDWCBxlJryXPy58= Received: from smtpng1.m.smailru.net (smtpng1.m.smailru.net [94.100.181.251]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 986186EC61 for ; Fri, 9 Apr 2021 23:05:30 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 986186EC61 Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1lUxNh-0005e5-SN; Fri, 09 Apr 2021 23:05:30 +0300 To: v.shpilevoy@tarantool.org, tsafin@tarantool.org Cc: tarantool-patches@dev.tarantool.org Date: Fri, 9 Apr 2021 23:05:29 +0300 Message-Id: <26b61648509b08b4cde3307015d398372cdd20f3.1617984948.git.imeevma@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: EEAE043A70213CC8 X-77F55803: 4F1203BC0FB41BD92FFCB8E6708E7480257C85EA0BB7A95D0F00AE41BB9A5343182A05F538085040ECC70F8A7C02C5D706842C15A4C8354F957229D26FEF662A6AC6BF71844596CE X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE70D278D70F8433719EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F790063725FA9CD6081C82518638F802B75D45FF914D58D5BE9E6BC1A93B80C6DEB9DEE97C6FB206A91F05B2EC28BCD5E1A2851CD0518D1539014B1DCCD65611471A2689D2E47CDBA5A96583C09775C1D3CA48CFE97D2AE7161E217F117882F4460429724CE54428C33FAD30A8DF7F3B2552694AC26CFBAC0749D213D2E47CDBA5A9658378DA827A17800CE749E2213E709ACCBA9FA2833FD35BB23DF004C906525384302BEBFE083D3B9BA73A03B725D353964B0B7D0EA88DDEDAC722CA9DD8327EE4930A3850AC1BE2E735E4A630A5B664A4FFC4224003CC83647689D4C264860C145E X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A2AD77751E876CB595E8F7B195E1C978310CCB944C547E9CAF491AA492AB43C9A7 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975CD0035DD76F8A8A4F44A747E3D9C9287522EFE55D929B1ADD9C2B6934AE262D3EE7EAB7254005DCED114C52B35DBB74F4E7EAB7254005DCEDCCE3E035A672CDEE1E0A4E2319210D9B64D260DF9561598F01A9E91200F654B0D18C7F408F36097E8E8E86DC7131B365E7726E8460B7C23C X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D346840168BCAD8054E9A88FF1652678FE1678BBC3D067C30B4DADD7D7B43A6AD76F75AED45D68429031D7E09C32AA3244C79FE32F398C7251C9428C015FC01E69C69B6CAE0477E908DFACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojyO2lHpuZu4SYoJhMUgVQEg== X-Mailru-Sender: 689FA8AB762F73936BC43F508A0638229D8998E25A1A1EDA97C38F7A3468E8D983D72C36FC87018B9F80AB2734326CD2FB559BB5D741EB96352A0ABBE4FDA4210A04DAD6CC59E33667EA787935ED9F1B X-Mras: Ok Subject: [Tarantool-patches] [PATCH v5 32/52] sql: introduce mem_set_*() for map and array X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Mergen Imeev via Tarantool-patches Reply-To: imeevma@tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Thank you for the review! My answers and new patch below. On 30.03.2021 02:05, Vladislav Shpilevoy wrote: > Thanks for the patch! > >> diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c >> index 7885caaf5..583de00a2 100644 >> --- a/src/box/sql/mem.c >> +++ b/src/box/sql/mem.c >> @@ -508,6 +508,86 @@ mem_append_to_binary(struct Mem *mem, const char *value, uint32_t size) >> return 0; >> } >> >> +void >> +mem_set_ephemeral_map(struct Mem *mem, char *value, uint32_t size) >> +{ >> + assert(mp_typeof(*value) == MP_MAP); >> + mem_set_const_bin(mem, value, size, MEM_Ephem); >> + mem->flags |= MEM_Subtype; >> + mem->subtype = SQL_SUBTYPE_MSGPACK; >> + mem->field_type = FIELD_TYPE_MAP; >> +} >> + >> +void >> +mem_set_static_map(struct Mem *mem, char *value, uint32_t size) >> +{ >> + assert(mp_typeof(*value) == MP_MAP); >> + mem_set_const_bin(mem, value, size, MEM_Static); >> + mem->flags |= MEM_Subtype; >> + mem->subtype = SQL_SUBTYPE_MSGPACK; >> + mem->field_type = FIELD_TYPE_MAP; >> +} >> + >> +void >> +mem_set_dynamic_map(struct Mem *mem, char *value, uint32_t size) > > I think I lost the clue of what is the difference between dynamic > and allocated. Maybe worth adding a comment? Or find a better name? > Added a comment. Didn't thought about new names for now. > For instance, if one of them is supposed to copy the map, and the > other one to steal its ownership, then you could call them > mem_set_map_copy() and mem_set_map_move(), where move is the same as > C++ move - steal the resource. The same for the others dynamic/allocated > terminology in the function names. > In some sense dynamic and allocated allocation types steals the ownership of allocated memory, however there is difference in way they free it. I described it in comments to the functions. > I think I also lost the understanding of static vs ephem by now. Static - available always, ephemeral - may become unavailable at some point. Thought it is true that the border between these two allocation type not as clear as should be. New patch: commit 26b61648509b08b4cde3307015d398372cdd20f3 Author: Mergen Imeev Date: Tue Mar 16 13:50:54 2021 +0300 sql: introduce mem_set_*() for map and array This patch introduces set of mem_set_*() functions for MAP and ARRAY. These functions clears MEM and sets it to given binary value. Binary value must be MAP or ARRAY. Degree of clearing and type of allocation of the binary value is determined by the function used. Part of #5818 diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c index 508b1dee3..61849cde7 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -520,6 +520,75 @@ mem_set_zerobin(struct Mem *mem, int n) mem->field_type = FIELD_TYPE_VARBINARY; } +static inline void +set_msgpack_value(struct Mem *mem, char *value, uint32_t size, int alloc_type, + enum field_type type) +{ + if (alloc_type == MEM_Ephem || alloc_type == MEM_Static) + set_bin_const(mem, value, size, alloc_type); + else + set_bin_dynamic(mem, value, size, alloc_type); + mem->flags |= MEM_Subtype; + mem->subtype = SQL_SUBTYPE_MSGPACK; + mem->field_type = type; +} + +void +mem_set_map_ephemeral(struct Mem *mem, char *value, uint32_t size) +{ + assert(mp_typeof(*value) == MP_MAP); + set_msgpack_value(mem, value, size, MEM_Ephem, FIELD_TYPE_MAP); +} + +void +mem_set_map_static(struct Mem *mem, char *value, uint32_t size) +{ + assert(mp_typeof(*value) == MP_MAP); + set_msgpack_value(mem, value, size, MEM_Static, FIELD_TYPE_MAP); +} + +void +mem_set_map_dynamic(struct Mem *mem, char *value, uint32_t size) +{ + assert(mp_typeof(*value) == MP_MAP); + set_msgpack_value(mem, value, size, MEM_Dyn, FIELD_TYPE_MAP); +} + +void +mem_set_map_allocated(struct Mem *mem, char *value, uint32_t size) +{ + assert(mp_typeof(*value) == MP_MAP); + set_msgpack_value(mem, value, size, 0, FIELD_TYPE_MAP); +} + +void +mem_set_array_ephemeral(struct Mem *mem, char *value, uint32_t size) +{ + assert(mp_typeof(*value) == MP_ARRAY); + set_msgpack_value(mem, value, size, MEM_Ephem, FIELD_TYPE_ARRAY); +} + +void +mem_set_array_static(struct Mem *mem, char *value, uint32_t size) +{ + assert(mp_typeof(*value) == MP_ARRAY); + set_msgpack_value(mem, value, size, MEM_Static, FIELD_TYPE_ARRAY); +} + +void +mem_set_array_dynamic(struct Mem *mem, char *value, uint32_t size) +{ + assert(mp_typeof(*value) == MP_ARRAY); + set_msgpack_value(mem, value, size, MEM_Dyn, FIELD_TYPE_ARRAY); +} + +void +mem_set_array_allocated(struct Mem *mem, char *value, uint32_t size) +{ + assert(mp_typeof(*value) == MP_ARRAY); + set_msgpack_value(mem, value, size, 0, FIELD_TYPE_ARRAY); +} + int mem_copy(struct Mem *to, const struct Mem *from) { @@ -2173,102 +2242,6 @@ mem_set_ptr(struct Mem *mem, void *ptr) mem->u.p = ptr; } -/* - * Change the value of a Mem to be a string or a BLOB. - * - * The memory management strategy depends on the value of the xDel - * parameter. If the value passed is SQL_TRANSIENT, then the - * string is copied into a (possibly existing) buffer managed by the - * Mem structure. Otherwise, any existing buffer is freed and the - * pointer copied. - * - * If the string is too large (if it exceeds the SQL_LIMIT_LENGTH - * size limit) then no memory allocation occurs. If the string can be - * stored without allocating memory, then it is. If a memory allocation - * is required to store the string, then value of pMem is unchanged. In - * either case, error is returned. - */ -int -sqlVdbeMemSetStr(Mem * pMem, /* Memory cell to set to string value */ - const char *z, /* String pointer */ - int n, /* Bytes in string, or negative */ - u8 not_blob, /* Encoding of z. 0 for BLOBs */ - void (*xDel) (void *) /* Destructor function */ - ) -{ - int nByte = n; /* New value for pMem->n */ - int iLimit; /* Maximum allowed string or blob size */ - u16 flags = 0; /* New value for pMem->flags */ - - /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ - if (!z) { - mem_clear(pMem); - return 0; - } - - if (pMem->db) { - iLimit = pMem->db->aLimit[SQL_LIMIT_LENGTH]; - } else { - iLimit = SQL_MAX_LENGTH; - } - flags = (not_blob == 0 ? MEM_Blob : MEM_Str); - if (nByte < 0) { - assert(not_blob != 0); - nByte = sqlStrlen30(z); - if (nByte > iLimit) - nByte = iLimit + 1; - flags |= MEM_Term; - } - - /* The following block sets the new values of Mem.z and Mem.xDel. It - * also sets a flag in local variable "flags" to indicate the memory - * management (one of MEM_Dyn or MEM_Static). - */ - if (xDel == SQL_TRANSIENT) { - int nAlloc = nByte; - if (flags & MEM_Term) { - nAlloc += 1; //SQL_UTF8 - } - if (nByte > iLimit) { - diag_set(ClientError, ER_SQL_EXECUTE, "string or binary"\ - "string is too big"); - return -1; - } - testcase(nAlloc == 0); - testcase(nAlloc == 31); - testcase(nAlloc == 32); - if (sqlVdbeMemClearAndResize(pMem, MAX(nAlloc, 32))) { - return -1; - } - memcpy(pMem->z, z, nAlloc); - } else if (xDel == SQL_DYNAMIC) { - mem_destroy(pMem); - pMem->zMalloc = pMem->z = (char *)z; - pMem->szMalloc = sqlDbMallocSize(pMem->db, pMem->zMalloc); - } else { - mem_destroy(pMem); - pMem->z = (char *)z; - pMem->xDel = xDel; - flags |= ((xDel == SQL_STATIC) ? MEM_Static : MEM_Dyn); - } - - pMem->n = nByte; - pMem->flags = flags; - assert((pMem->flags & (MEM_Str | MEM_Blob)) != 0); - if ((pMem->flags & MEM_Str) != 0) - pMem->field_type = FIELD_TYPE_STRING; - else - pMem->field_type = FIELD_TYPE_VARBINARY; - - if (nByte > iLimit) { - diag_set(ClientError, ER_SQL_EXECUTE, "string or binary string"\ - "is too big"); - return -1; - } - - return 0; -} - /* * Free an sql_value object */ diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h index 0aeb23496..b3a602f6e 100644 --- a/src/box/sql/mem.h +++ b/src/box/sql/mem.h @@ -287,6 +287,71 @@ mem_set_zerobin(struct Mem *mem, int n); int mem_copy_bin(struct Mem *mem, const char *value, uint32_t size); +/** + * Clear MEM and set it to MAP. The binary value belongs to another object. The + * binary value must be msgpack of MAP type. + */ +void +mem_set_map_ephemeral(struct Mem *mem, char *value, uint32_t size); + +/** + * Clear MEM and set it to MAP. The binary value is static. The binary value + * must be msgpack of MAP type. + */ +void +mem_set_map_static(struct Mem *mem, char *value, uint32_t size); + +/** + * Clear MEM and set it to MAP. The binary value was allocated by another object + * and passed to MEM. The binary value must be msgpack of MAP type. MEMs with + * this allocation type must free given memory whenever the MEM changes. + */ +void +mem_set_map_dynamic(struct Mem *mem, char *value, uint32_t size); + +/** + * Clear MEM and set it to MAP. The binary value was allocated by another object + * and passed to MEM. The binary value must be msgpack of MAP type. MEMs with + * this allocation type only deallocate the string on destruction. Also, the + * memory may be reallocated if MEM is set to a different value of this + * allocation type. + */ +void +mem_set_map_allocated(struct Mem *mem, char *value, uint32_t size); + +/** + * Clear MEM and set it to ARRAY. The binary value belongs to another object. + * The binary value must be msgpack of ARRAY type. + */ +void +mem_set_array_ephemeral(struct Mem *mem, char *value, uint32_t size); + +/** + * Clear MEM and set it to ARRAY. The binary value is static. The binary value + * must be msgpack of ARRAY type. + */ +void +mem_set_array_static(struct Mem *mem, char *value, uint32_t size); + +/** + * Clear MEM and set it to ARRAY. The binary value was allocated by another + * object and passed to MEM. The binary value must be msgpack of ARRAY type. + * MEMs with this allocation type must free given memory whenever the MEM + * changes. + */ +void +mem_set_array_dynamic(struct Mem *mem, char *value, uint32_t size); + +/** + * Clear MEM and set it to ARRAY. The binary value was allocated by another + * object and passed to MEM. The binary value must be msgpack of ARRAY type. + * MEMs with this allocation type only deallocate the string on destruction. + * Also, the memory may be reallocated if MEM is set to a different value of + * this allocation type. + */ +void +mem_set_array_allocated(struct Mem *mem, char *value, uint32_t size); + /** * Copy content of MEM from one MEM to another. In case source MEM contains * string or binary and allocation type is not STATIC, this value is copied to @@ -564,8 +629,6 @@ int sqlVdbeMemClearAndResize(struct Mem * pMem, int n); void mem_set_ptr(struct Mem *mem, void *ptr); -int -sqlVdbeMemSetStr(struct Mem *, const char *, int, u8, void (*)(void *)); void sqlValueFree(struct Mem *); struct Mem *sqlValueNew(struct sql *); diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 19a0b041c..9434a4d06 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -894,9 +894,11 @@ case OP_Blob: { /* out2 */ */ mem_set_bin_static(pOut, pOp->p4.z, pOp->p1); } else { - sqlVdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); - pOut->flags |= MEM_Subtype; - pOut->subtype = pOp->p3; + assert(pOp->p3 == SQL_SUBTYPE_MSGPACK); + if (mp_typeof(*pOp->p4.z) == MP_MAP) + mem_set_map_static(pOut, pOp->p4.z, pOp->p1); + else + mem_set_array_static(pOut, pOp->p4.z, pOp->p1); } UPDATE_MAX_BLOBSIZE(pOut); break;