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 762796EC40; Thu, 19 Aug 2021 11:35:17 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 762796EC40 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1629362117; bh=mR0NxHGF3jW4Gjw+OEC7SUQA4j8H8ZgPwut+BRcdaNE=; h=Date:To:Cc:References:In-Reply-To:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=ev+3V7ePQbYbCG/5xPUB9W+sDRtGCyS75ofTKtJU/+qPirterjW3w3CRPb5Zr/TlA /Mbm6J44BlJ48uJQaKo+aX33GBZqpAKom2HpFSi6t3OYTy1jAVSPR8M5/bIkC7ulRx EkIEpG81FRZB9i/CDRYCGWfXfqkSSKpF2+VudMb4= Received: from smtpng2.i.mail.ru (smtpng2.i.mail.ru [94.100.179.3]) (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 9E0C76EC40 for ; Thu, 19 Aug 2021 11:35:16 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 9E0C76EC40 Received: by smtpng2.m.smailru.net with esmtpa (envelope-from ) id 1mGdW7-0006pX-PI; Thu, 19 Aug 2021 11:35:16 +0300 Date: Thu, 19 Aug 2021 11:35:14 +0300 To: imeevma@tarantool.org Cc: tarantool-patches@dev.tarantool.org Message-ID: <20210819083514.i4hlig526gy6domj@esperanza> References: <6f4f310f2d43267c4264844cd966641ce70e804b.1629297142.git.imeevma@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <6f4f310f2d43267c4264844cd966641ce70e804b.1629297142.git.imeevma@gmail.com> X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD92087353F0EC44DD910164DC12A5633065676A9727AC27C74182A05F5380850400423057AAB5766EC7DF4BA372D8D942E855F244D2B2CBA2E6EC242FFC44CD075 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7A140E7B1D51EB231EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637AA32F0A5ADCF96E68638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D8FAF3E1F39A434D22AE4483C8443D0E3D117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8BAA867293B0326636D2E47CDBA5A96583BA9C0B312567BB231DD303D21008E29813377AFFFEAFD269A417C69337E82CC2E827F84554CEF50127C277FBC8AE2E8BA83251EDC214901ED5E8D9A59859A8B6A45692FFBBD75A6A089D37D7C0E48F6C5571747095F342E88FB05168BE4CE3AF X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A213B5FB47DCBC3458834459D11680B505284C2DD9C545D77D58D3E2F66B69DAF0 X-C1DE0DAB: 0D63561A33F958A5E14C8850307EB1C6FD1A441DFC65EC58AF19A450ACE985D9D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA758B25CD4253D1D611410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34A9873270276D433464330455606186662AC9CCD8EA4EBB8EF89A738E005355886023DD873B9450D01D7E09C32AA3244C22446B9ED6D8889186848CE1A94EF0C481560E2432555DBBFACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojGSxK+6r6oBHWJ4Cv9ote7w== X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5DD49AE8A5FD15ED3357E2D280EBEA23FD274CEFED1673C562683ABF942079399BFB559BB5D741EB966A65DFF43FF7BE03240331F90058701C67EA787935ED9F1B X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH v2 2/5] sql: introduce SQL built-in functions to parser 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: Vladimir Davydov via Tarantool-patches Reply-To: Vladimir Davydov Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" On Wed, Aug 18, 2021 at 05:34:59PM +0300, imeevma@tarantool.org wrote: > diff --git a/extra/mkkeywordhash.c b/extra/mkkeywordhash.c > index 0d998506c..369d9e1dd 100644 > --- a/extra/mkkeywordhash.c > +++ b/extra/mkkeywordhash.c > @@ -184,7 +184,6 @@ static Keyword aKeywordTable[] = { > { "BLOB", "TK_STANDARD", true }, > { "BINARY", "TK_ID", true }, > { "CALL", "TK_STANDARD", true }, > - { "CHAR", "TK_CHAR", true }, > { "CHARACTER", "TK_ID", true }, > { "CONDITION", "TK_STANDARD", true }, > { "CONNECT", "TK_STANDARD", true }, > @@ -251,6 +250,42 @@ static Keyword aKeywordTable[] = { > { "LEADING", "TK_LEADING", true }, > { "TRAILING", "TK_TRAILING", true }, > { "BOTH", "TK_BOTH", true }, > + { "ABS", "TK_ABS", true }, > + { "AVG", "TK_AVG", true }, > + { "CHAR", "TK_CHAR", true }, > + { "CHAR_LENGTH", "TK_CHAR_LEN", true }, > + { "CHARACTER_LENGTH", "TK_CHAR_LEN", true }, > + { "COALESCE", "TK_COALESCE", true }, > + { "COUNT", "TK_COUNT", true }, > + { "GREATEST", "TK_GREATEST", true }, > + { "GROUP_CONCAT", "TK_GROUP_CONCAT",true }, > + { "HEX", "TK_HEX", true }, > + { "IFNULL", "TK_IFNULL", true }, > + { "LEAST", "TK_LEAST", true }, > + { "LENGTH", "TK_LENGTH", true }, > + { "LIKELIHOOD", "TK_LIKELIHOOD", true }, > + { "LIKELY", "TK_LIKELY", true }, > + { "LOWER", "TK_LOWER", true }, > + { "MAX", "TK_MAX", true }, > + { "MIN", "TK_MIN", true }, > + { "NULLIF", "TK_NULLIF", true }, > + { "POSITION", "TK_POSITION", true }, > + { "PRINTF", "TK_PRINTF", true }, > + { "QUOTE", "TK_QUOTE", true }, > + { "RANDOM", "TK_RANDOM", true }, > + { "RANDOMBLOB", "TK_RANDOMBLOB", true }, > + { "ROUND", "TK_ROUND", true }, > + { "ROW_COUNT", "TK_ROW_COUNT", true }, > + { "SOUNDEX", "TK_SOUNDEX", true }, > + { "SUBSTR", "TK_SUBSTR", true }, > + { "SUM", "TK_SUM", true }, > + { "TOTAL", "TK_TOTAL", true }, > + { "TYPEOF", "TK_TYPEOF", true }, > + { "UNICODE", "TK_UNICODE", true }, > + { "UNLIKELY", "TK_UNLIKELY", true }, > + { "UPPER", "TK_UPPER", true }, > + { "VERSION", "TK_VERSION", true }, > + { "ZEROBLOB", "TK_ZEROBLOB", true }, Should be sorted? > }; > > /* Number of keywords */ > diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y > index bd041e862..cb2e627db 100644 > --- a/src/box/sql/parse.y > +++ b/src/box/sql/parse.y > @@ -1172,27 +1172,506 @@ trim_specification(A) ::= LEADING. { A = TRIM_LEADING; } > trim_specification(A) ::= TRAILING. { A = TRIM_TRAILING; } > trim_specification(A) ::= BOTH. { A = TRIM_BOTH; } > > -expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP(E). { > - if( Y && Y->nExpr>pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG] ){ > - const char *err = > - tt_sprintf("Number of arguments to function %.*s", X.n, X.z); > - diag_set(ClientError, ER_SQL_PARSER_LIMIT, err, Y->nExpr, > - pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]); > +expr(A) ::= ABS(X) LP distinct(D) exprlist(Y) RP(E). { > + if (Y == NULL || Y->nExpr != 1) { > + int n = Y == NULL ? 0 : Y->nExpr; > + diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "ABS", "1", n); > pParse->is_aborted = true; > + return; > } > A.pExpr = sqlExprFunction(pParse, Y, &X); > - spanSet(&A,&X,&E); > - if( D==SF_Distinct && A.pExpr ){ > + spanSet(&A, &X, &E); > + if(D == SF_Distinct && A.pExpr) > A.pExpr->flags |= EP_Distinct; > +} > + > +expr(A) ::= AVG(X) LP distinct(D) exprlist(Y) RP(E). { > + if (Y == NULL || Y->nExpr != 1) { > + int n = Y == NULL ? 0 : Y->nExpr; > + diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "AVG", "1", n); > + pParse->is_aborted = true; > + return; > } > + A.pExpr = sqlExprFunction(pParse, Y, &X); > + spanSet(&A, &X, &E); > + if(D == SF_Distinct && A.pExpr) > + A.pExpr->flags |= EP_Distinct; > } > > -/* > - * type_func(A) ::= DATE(A) . > - * type_func(A) ::= DATETIME(A) . > - */ > -type_func(A) ::= CHAR(A) . > -expr(A) ::= type_func(X) LP distinct(D) exprlist(Y) RP(E). { > +expr(A) ::= CHAR(X) LP distinct(D) exprlist(Y) RP(E). { > + if (Y != NULL && Y->nExpr > pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]) { > + const char *str = tt_sprintf("from %d to %d", 0, > + pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]); > + diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "CHAR", str, Y->nExpr); > + pParse->is_aborted = true; > + return; > + } > + A.pExpr = sqlExprFunction(pParse, Y, &X); > + spanSet(&A, &X, &E); > + if(D == SF_Distinct && A.pExpr) > + A.pExpr->flags |= EP_Distinct; > +} > + > +expr(A) ::= CHAR_LEN(X) LP distinct(D) exprlist(Y) RP(E). { > + if (Y == NULL || Y->nExpr != 1) { > + int n = Y == NULL ? 0 : Y->nExpr; > + const char *name = X.n == strlen("CHAR_LENGTH") ? "CHAR_LENGTH" : > + "CHARACTER_LENGTH"; > + diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, name, "1", n); > + pParse->is_aborted = true; > + return; > + } > + A.pExpr = sqlExprFunction(pParse, Y, &X); > + spanSet(&A, &X, &E); > + if(D == SF_Distinct && A.pExpr) > + A.pExpr->flags |= EP_Distinct; > +} > + > +expr(A) ::= COALESCE(X) LP distinct(D) exprlist(Y) RP(E). { > + if (Y == NULL || Y->nExpr < 2 || > + Y->nExpr > pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]) { > + int n = Y == NULL ? 0 : Y->nExpr; > + const char *str = tt_sprintf("from %d to %d", 2, > + pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]); > + diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "COALESCE", str, n); > + pParse->is_aborted = true; > + return; > + } > + A.pExpr = sqlExprFunction(pParse, Y, &X); > + spanSet(&A, &X, &E); > + if(D == SF_Distinct && A.pExpr) > + A.pExpr->flags |= EP_Distinct; > +} Can you the code to a helper function to avoid copy-paste? > diff --git a/test/box/tx_man.result b/test/box/tx_man.result > index 786d7fc30..b99fbc2ca 100644 > --- a/test/box/tx_man.result > +++ b/test/box/tx_man.result > @@ -2129,11 +2129,11 @@ tx1:rollback() > > -- gh-6095: SQL query may crash in MVCC mode if it involves ephemeral spaces. > -- > -box.execute([[ CREATE TABLE test (id INT NOT NULL PRIMARY KEY, count INT NOT NULL)]]) > +box.execute([[ CREATE TABLE test (id INT NOT NULL PRIMARY KEY, "COUNT" INT NOT NULL)]]) > | --- > | - row_count: 1 > | ... > -box.execute([[ UPDATE test SET count = count + 1 WHERE id = 0 ]]) > +box.execute([[ UPDATE test SET "COUNT" = "COUNT" + 1 WHERE id = 0 ]]) This looks bad. MySQL and PostgreSQL allow that. > | --- > | - row_count: 0 > | ... > diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua > index e7b35c9d9..7dd85025a 100755 > --- a/test/sql-tap/func.test.lua > +++ b/test/sql-tap/func.test.lua > @@ -68,7 +68,7 @@ test:do_catchsql_test( > SELECT length(*) FROM tbl1 ORDER BY t1 > ]], { > -- > - 1, "Wrong number of arguments is passed to LENGTH(): expected 1, got 0" > + 1, "Syntax error at line 1 near '*'" This is probably okay. > -- > }) > > @@ -2483,7 +2483,7 @@ test:do_catchsql_test( > SELECT coalesce() > ]], { > -- > - 1, "Wrong number of arguments is passed to COALESCE(): expected at least two, got 0" > + 1, "Wrong number of arguments is passed to COALESCE(): expected from 2 to 127, got 0" And this too.