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 639356E459; Sun, 21 Nov 2021 18:53:57 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 639356E459 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1637510037; bh=yUzE0g62ILRSDYAywprsay7RDxXB5IFepdSPgZgkAjY=; h=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=eC1IUWo2OPDXuuziDClktC1PNCB4RJBlop00XaS1b2RPI1KkiD+SHwMukg/Uia+vw OnKnWQOH4ao3ygLqTiLBEG+dc0rCtcAbfspazpFJXZHxXBskg8i+qoSq40Gc1j7qZ+ g45zP+CGTDCSudRo25xghzu2smNMQ7B+vTSX+M/s= Received: from smtpng1.i.mail.ru (smtpng1.i.mail.ru [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 024BD6E459 for ; Sun, 21 Nov 2021 18:53:55 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 024BD6E459 Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1mopAB-00040F-8k; Sun, 21 Nov 2021 18:53:55 +0300 Message-ID: <684c473b-33ff-11e9-b6b2-0362cc24190f@tarantool.org> Date: Sun, 21 Nov 2021 16:53:54 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.3.2 Content-Language: en-US To: Konstantin Osipov , imeevma@tarantool.org, tarantool-patches@dev.tarantool.org References: <20211119172502.GA136743@starling> In-Reply-To: <20211119172502.GA136743@starling> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-7564579A: EEAE043A70213CC8 X-77F55803: 4F1203BC0FB41BD927BBD05C2915ABC3F0C6F04B338195A335972B5D0493B166182A05F5380850404C228DA9ACA6FE2777669F3EC14FC9AC6F0E7DE9F6FD17358561DB517986FB51671DD72C57976BE1 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE78E88BD1CA827EF00C2099A533E45F2D0395957E7521B51C2CFCAF695D4D8E9FCEA1F7E6F0F101C6778DA827A17800CE77FAFB841CE9024F9EA1F7E6F0F101C6723150C8DA25C47586E58E00D9D99D84E1BDDB23E98D2D38BBCA57AF85F7723F2D4A7976D62C1461CBCF8146C1632C830CC7F00164DA146DAFE8445B8C89999728AA50765F7900637D0FEED2715E18529389733CBF5DBD5E9C8A9BA7A39EFB766F5D81C698A659EA7CC7F00164DA146DA9985D098DBDEAEC82FFDA4F57982C5F4F6B57BC7E6449061A352F6E88A58FB86F5D81C698A659EA7E827F84554CEF5019E625A9149C048EE9ECD01F8117BC8BEE2021AF6380DFAD18AA50765F790063735872C767BF85DA227C277FBC8AE2E8BDC0F6C5B2EEF3D0C75ECD9A6C639B01B4E70A05D1297E1BBCB5012B2E24CD356 X-C1DE0DAB: 0D63561A33F958A5C9A77F23F7360F2BBDA7595E8BA510C021E48385E32B47C0D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA7506FE1F977233B9BB410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34C2E47CA9A56060907E4C0189EF8CD7A025EDEFA6A2358B280BEB1CF0CF3BEE37E166B893899DC4411D7E09C32AA3244CB1A54E01FD2F85FD0BBA400DBC61EC96259227199D06760AFACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojp2KOOpFlmzeqozTFGgEKLQ== X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5D0D3501797B7EEE9ED22CD2571C022F3A3841015FED1DE5223CC9A89AB576DD93FB559BB5D741EB963CF37A108A312F5C27E8A8C3839CE0E267EA787935ED9F1B X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH v1 1/1] sql: introduce operator [] 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: Vladislav Shpilevoy via Tarantool-patches Reply-To: Vladislav Shpilevoy Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Thanks for the patch! See 8 comments below. >> @TarantoolBot document >> Title: Operator [] in SQL >> >> Operator [] allows to get elements of MAP, ARRAY and ANY values. >> >> Rules for operator []: >> 1) operator applied to the value to the left of `[` ("left-value"); >> 2) if left-value is not MAP, ARRAY or ANY, an error is thrown; >> 3) if there is no values between `[` and `]`, left-value is returned as >> the result; 1. Why isn't it an error? Did I understand correctly that you mean [] with nothing inside? >> 4) if there is one value between `[` and `]` ("right-value"), the result >> is: >> a) if left-value is ANY and its primitive type is not MAP or ARRAY, >> the result is NULL; 2. Why not error? This looks a bit controversial with how hard the rules for explicit and implict casts are. >> b) if the type or primitive type of left-value is ARRAY, and >> right-value is INTEGER and its value is greater than 0 and not >> greater than the number of elements in ARRAY, the result will be a >> value with right-value as the index, otherwise the result will be >> NULL; 3. What if the right-value is not an integer? >> c) if the type or primitive type of left-value is MAP and it contains >> right-value as one of its keys, the result is the value with >> right-value as the key in left-value, otherwise the result is NULL; >> 5) if there is more than one value between `[` and `]` than >> left-value[a, b, c, ...] == left-value[a][b][c]... except it will >> return NULL, if any of the `[]` operators return NULL. >> >> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c >> index 789d8906c..abf47b8ef 100644 >> --- a/src/box/sql/expr.c >> +++ b/src/box/sql/expr.c >> @@ -3461,6 +3461,30 @@ expr_code_map(struct Parse *parser, struct Expr *expr, int reg) >> sqlVdbeAddOp3(vdbe, OP_Map, count, reg, values_reg); >> } >> >> +static void >> +expr_code_getitem(struct Parse *parser, struct Expr *expr, int reg) 4. The same as for the array/map patches - should be sql_expr_emit_... or expr_emit - depending on what prefix will you choose to use everywhere. >> +{ >> + struct Vdbe *vdbe = parser->pVdbe; >> + struct ExprList *list = expr->x.pList; >> + assert(list != NULL); >> diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c >> index cfb88bffe..195dfde2b 100644 >> --- a/src/box/sql/mem.c >> +++ b/src/box/sql/mem.c >> @@ -3107,6 +3107,65 @@ mem_encode_map(const struct Mem *mems, uint32_t count, uint32_t *size, >> return map; >> } >> >> +static int >> +mp_getitem(const char **data, const struct Mem *key) >> +{ >> + if ((mp_typeof(**data) != MP_ARRAY && mp_typeof(**data) != MP_MAP)) { 5. Double (()). Need only one. >> + *data = NULL; >> + return 0; >> + } >> + const char *end = *data; >> + if (mp_typeof(**data) == MP_ARRAY) { >> + uint32_t size = mp_decode_array(data); >> + if (!mem_is_uint(key) || key->u.u == 0 || key->u.u > size) { >> + *data = NULL; >> + return 0; >> + } >> + for (uint32_t i = 0; i < key->u.u - 1; ++i) >> + mp_next(data); >> + return 0; >> + } >> + struct Mem mem; >> + mem_create(&mem); >> + uint32_t size = mp_decode_map(data); >> + for (uint32_t i = 0; i < size; ++i) { >> + uint32_t len; >> + if (mem_from_mp_ephemeral(&mem, *data, &len) != 0) >> + return -1; 6. Lets add mem_is_trivial() assertion. Since you do not destroy the mem. >> + *data += len; >> + assert(!mem_is_map(&mem) && !mem_is_array(&mem)); >> + if (mem_cmp_scalar(&mem, key, NULL) == 0) >> + return 0; >> + mp_next(data); >> + } >> diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y >> index db7fef71a..30922b7f6 100644 >> --- a/src/box/sql/parse.y >> +++ b/src/box/sql/parse.y >> @@ -1126,6 +1127,22 @@ expr(A) ::= CAST(X) LP expr(E) AS typedef(T) RP(Y). { >> sqlExprAttachSubtrees(pParse->db, A.pExpr, E.pExpr, 0); >> } >> >> +expr(A) ::= expr(X) LB exprlist(Y) RB(E). { >> + struct Expr *expr = sql_expr_new_dequoted(pParse->db, TK_GETITEM, NULL); 7. sql_expr_new_anon(). >> + if (expr == NULL) { >> + sql_expr_list_delete(pParse->db, Y); >> + pParse->is_aborted = true; >> + return; >> + } >> + Y = sql_expr_list_append(pParse->db, Y, X.pExpr); >> + expr->x.pList = Y; >> + expr->type = FIELD_TYPE_ANY; >> + sqlExprSetHeightAndFlags(pParse, expr); >> + A.pExpr = expr; >> + A.zStart = X.zStart; >> + A.zEnd = &E.z[E.n]; >> +} 8. I got an assertion fail. box.cfg{listen = 3313} s = box.schema.create_space('TEST', {format = {{'ID'}, {'VALUE'}}}) _ = s:create_index('pk') s:replace{1, {[{key = 100}] = 200}} box.execute('SELECT value[1] FROM test') Assertion failed: (!mem_is_map(&mem) && !mem_is_array(&mem)), function mp_getitem, file /Users/gerold/Work/Repositories/tarantool/src/box/sql/mem.c, line 3136.