From: "n.pettik" <korablev@tarantool.org> To: tarantool-patches@freelists.org Cc: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> Subject: [tarantool-patches] Re: [PATCH 5/8] sql: replace field type with affinity for VDBE runtime Date: Fri, 1 Feb 2019 19:39:00 +0300 [thread overview] Message-ID: <2ED4082B-7899-4880-8FF2-25E1A3E6D90B@tarantool.org> (raw) In-Reply-To: <115cb635-13f4-1946-22b3-36b828d9d679@tarantool.org> >>>> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c >>>> index 0a80ca622..ca39faf51 100644 >>>> --- a/src/box/sql/expr.c >>>> +++ b/src/box/sql/expr.c >>>> @@ -3172,7 +3177,10 @@ sqlite3ExprCodeIN(Parse * pParse, /* Parsing and code generating context */ >>>> * of the RHS using the LHS as a probe. If found, the result is >>>> * true. >>>> */ >>>> - sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); >>>> + enum field_type *types = sql_affinity_str_to_field_type_str(zAff); >>>> + types[nVector] = field_type_MAX; >>>> + sqlite3VdbeAddOp4(v, OP_ApplyType, rLhs, nVector, 0, (char *)types, >>>> + P4_DYNAMIC); >>> >>> 2. Why do you need types[nVector] = field_type_MAX? As I see, before your patch >>> there was no additional zero termination. >> To cut off array of types. Before my patch, first nVector bytes >> were copied inside vdbeChangeP4Full() and automatically >> terminated with NULL (sqlite3DbStrNDup). > > Still do not understand. As I see, zAff was taken from exprINAffinity(). > This function allocates a string of affinities of length > sqlite3ExprVectorSize(pExpr->pLeft). But nVector was initialized with > exactly the same value. So strlen(zAff) should be equal to nVector, and > your function sql_affinity_str_to_field_type_str() should return already > correct array. I tried to test it and faced into a very strange situation. > > Firstly, it appeared that already at the beginning of the > function, after this code: > > zAff = exprINAffinity(pParse, pExpr); > nVector = sqlite3ExprVectorSize(pExpr->pLeft); > > They are not already equal. This assertion fails: > > strlen(zAff) == nVector. > > I tried to print their values in debug, and found, that > zAff is stored in a buffer of length 2, but both bytes are > zeros. Why? It is a first strange situation. In a nutshell: owing to the fact that AFFINITY_UNDEFINED equals to 0. Long story: Consider simple example: SELECT NULL IN (2, 3, 4, NULL) When we reach sqlite3ExprCodeIN(), pExpr represents AST with the root in IN operator: (lldb) print (int)pExpr->op (int) $4 = 12 #define TK_IN 12 LHS of the root is NULL (terminal symbol): (lldb) print *pExpr->pLeft (Expr) $6 = { op = 'K' = (affinity = AFFINITY_UNDEFINED, on_conflict_action = ON_CONFLICT_ACTION_NONE) flags = 8388612 u = (zToken = "NULL", iValue = 59018336) So nVector is 1. Moreover, NULL's affinity is UNDEFINED. That is due to assigment to all expression by default UNDEFINED affinity (as you may remember, I fixed it in the next patch by setting it to SCALAR): 811 /* Construct a new Expr object from a single identifier. Use the 812 ** new Expr to populate pOut. Set the span of pOut to be the identifier 813 ** that created the expression. 814 */ 815 static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ 816 Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); 817 if( p ){ 818 memset(p, 0, sizeof(Expr)); 819 switch (op) { 820 case TK_STRING: 821 p->affinity = AFFINITY_TEXT; 822 break; 823 case TK_BLOB: 824 p->affinity = AFFINITY_BLOB; Since NULL token is out of TK_STRING, TK_BLOB etc enumeration, its affinity is 0, i.e. UNDERFINED. Therefore, we see that nVector is 1, so zAff is of lenght 2 (because of additional null-termination), and finally, sql_affinity_str_to_field_type_str() returns shorter array, then is should be. Fortunately, it doesn’t affect further patches, since there we get rid of affinity, and SCALAR in enum is not 0. > Secondly, your function sql_affinity_str_to_field_type_str() > in such a case returns a buffer of one byte - [field_type_MAX], > because it uses strlen(affinity_str) + 1, which == 1 here. > > Further, you do types[nVector] = field_type_MAX, so you are > out of array bounds, because nVector == 1, not 0. The only > reason why it does not fail is that malloc returns more > memory than necessary. > > Please, check out if I am right, and fix the bug if so. > > The assertion fails in sql-tap/randexpr1.test.lua. As a workaround (this problem is automatically resolved in next patch) I suggest to pass to sql_affinity_str_to.. len of affinity array: diff --git a/src/box/sql/build.c b/src/box/sql/build.c index 514d0ca9d..3adc6e262 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -521,17 +521,16 @@ sql_field_type_to_affinity(enum field_type field_type) } enum field_type * -sql_affinity_str_to_field_type_str(const char *affinity_str) +sql_affinity_str_to_field_type_str(const char *affinity_str, uint32_t len) { if (affinity_str == NULL) return NULL; - size_t len = strlen(affinity_str) + 1; - size_t sz = len * sizeof(enum field_type); + size_t sz = (len + 1) * sizeof(enum field_type); enum field_type *types = (enum field_type *) sqlite3DbMallocRaw(sql_get(), sz); - for (uint32_t i = 0; i < len - 1; ++i) + for (uint32_t i = 0; i < len; ++i) types[i] = sql_affinity_to_field_type(affinity_str[i]); - types[len - 1] = field_type_MAX; + types[len] = field_type_MAX; return types; } diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index d263c1bb5..b02089bc2 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -3177,8 +3177,8 @@ sqlite3ExprCodeIN(Parse * pParse, /* Parsing and code generating context */ * of the RHS using the LHS as a probe. If found, the result is * true. */ - enum field_type *types = sql_affinity_str_to_field_type_str(zAff); - types[nVector] = field_type_MAX; + enum field_type *types = sql_affinity_str_to_field_type_str(zAff, + nVector); sqlite3VdbeAddOp4(v, OP_ApplyType, rLhs, nVector, 0, (char *)types, P4_DYNAMIC); if (destIfFalse == destIfNull) { diff --git a/src/box/sql/select.c b/src/box/sql/select.c index 4b6983842..ef4514374 100644 --- a/src/box/sql/select.c +++ b/src/box/sql/select.c @@ -1204,7 +1204,8 @@ selectInnerLoop(Parse * pParse, /* The parser context */ (unsigned int)nResultCol); enum field_type *types = sql_affinity_str_to_field_type_str( - pDest->zAffSdst); + pDest->zAffSdst, + strlen(pDest->zAffSdst)); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, r1, (char *)types, P4_DYNAMIC); @@ -1631,7 +1632,8 @@ generateSortTail(Parse * pParse, /* Parsing context */ sqlite3Strlen30(pDest->zAffSdst)); enum field_type *types = - sql_affinity_str_to_field_type_str(pDest->zAffSdst); + sql_affinity_str_to_field_type_str(pDest->zAffSdst, + strlen(pDest->zAffSdst)); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regTupleid, (char *)types, P4_DYNAMIC); @@ -3070,7 +3072,8 @@ generateOutputSubroutine(struct Parse *parse, struct Select *p, testcase(in->nSdst > 1); r1 = sqlite3GetTempReg(parse); enum field_type *types = - sql_affinity_str_to_field_type_str(dest->zAffSdst); + sql_affinity_str_to_field_type_str(dest->zAffSdst, + strlen(dest->zAffSdst)); sqlite3VdbeAddOp4(v, OP_MakeRecord, in->iSdst, in->nSdst, r1, (char *)types, P4_DYNAMIC); diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h index 729e5257c..79999509c 100644 --- a/src/box/sql/sqliteInt.h +++ b/src/box/sql/sqliteInt.h @@ -3454,7 +3454,7 @@ enum affinity_type sql_field_type_to_affinity(enum field_type field_type); enum field_type * -sql_affinity_str_to_field_type_str(const char *affinity_str); +sql_affinity_str_to_field_type_str(const char *affinity_str, uint32_t len); /** * Compile view, i.e. create struct Select from diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c index efbc91cf8..e3e7c5222 100644 --- a/src/box/sql/wherecode.c +++ b/src/box/sql/wherecode.c @@ -398,8 +398,7 @@ codeApplyAffinity(Parse * pParse, int base, int n, char *zAff) if (n > 0) { enum field_type *types = - sql_affinity_str_to_field_type_str(zAff); - types[n] = field_type_MAX; + sql_affinity_str_to_field_type_str(zAff, n); sqlite3VdbeAddOp4(v, OP_ApplyType, base, n, 0, (char *)types, P4_DYNAMIC); > Also, see 2 comments below. > >> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c >> index 58e35e0d9..d263c1bb5 100644 >> --- a/src/box/sql/expr.c >> +++ b/src/box/sql/expr.c >> @@ -2854,8 +2854,17 @@ sqlite3CodeSubselect(Parse * pParse, /* Parsing context */ >> jmpIfDynamic = -1; >> } >> r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); >> + enum field_type type = >> + sql_affinity_to_field_type(affinity); >> + size_t sz = 2 * sizeof(enum field_type); >> + enum field_type *types = >> + sqlite3DbMallocRaw(pParse->db, >> + sz); >> + types[0] = type; >> + types[1] = field_type_MAX; > > 1. Please, either check for malloc result, or just use the > same method as in other places - declare it on the stack and pass > sizeof(this_array) instead of P4_DYNAMIC. Sorry, I accidentally added it to diff - it was proposal to refactoring (unsuccessful). Returned to its previous state. diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index d263c1bb5..5676d0720 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -2856,15 +2856,11 @@ sqlite3CodeSubselect(Parse * pParse, /* Parsing context */ r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); enum field_type type = sql_affinity_to_field_type(affinity); - size_t sz = 2 * sizeof(enum field_type); - enum field_type *types = - sqlite3DbMallocRaw(pParse->db, - sz); - types[0] = type; - types[1] = field_type_MAX; + enum field_type types[2] = + { type, field_type_MAX }; sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, (char *)types, - P4_DYNAMIC); + sizeof(types)); >> sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, >> - 1, r2, &affinity, 1); >> + 1, r2, (char *)types, >> + P4_DYNAMIC); >> sqlite3ExprCacheAffinityChange(pParse, >> r3, 1); >> sqlite3VdbeAddOp2(v, OP_IdxInsert, r2, >> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c >> index 24d992284..80d2fd0aa 100644 >> --- a/src/box/sql/vdbe.c >> +++ b/src/box/sql/vdbe.c >> @@ -2881,7 +2873,7 @@ case OP_MakeRecord: { >> * of the record to data0. >> */ >> nField = pOp->p1; >> - zAffinity = pOp->p4.z; >> + enum field_type *types = (enum field_type *)pOp->p4.z; > > 2. Maybe, it is worth adding enum field_type *types into VdbeOp.p4union > and do not cast. Like we did with many other pointers. Thanks for suggestion, but I guess it is not necessary now. Lets consider this refactoring a bit later.
next prev parent reply other threads:[~2019-02-01 16:39 UTC|newest] Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-12-28 9:34 [tarantool-patches] [PATCH 0/8] Eliminate affinity from source code Nikita Pettik 2018-12-28 9:34 ` [tarantool-patches] [PATCH 1/8] sql: remove SQLITE_ENABLE_UPDATE_DELETE_LIMIT define Nikita Pettik 2018-12-29 17:42 ` [tarantool-patches] " Vladislav Shpilevoy 2019-01-16 14:25 ` n.pettik 2018-12-28 9:34 ` [tarantool-patches] [PATCH 2/8] sql: use field type instead of affinity for type_def Nikita Pettik 2018-12-29 17:42 ` [tarantool-patches] " Vladislav Shpilevoy 2019-01-16 14:26 ` n.pettik 2018-12-28 9:34 ` [tarantool-patches] [PATCH 3/8] sql: remove numeric affinity Nikita Pettik 2018-12-29 9:01 ` [tarantool-patches] " Konstantin Osipov 2018-12-29 17:42 ` Vladislav Shpilevoy 2019-01-09 8:26 ` Konstantin Osipov 2019-01-16 14:26 ` n.pettik 2019-01-22 15:41 ` Vladislav Shpilevoy 2019-01-28 16:39 ` n.pettik 2019-01-30 13:04 ` Vladislav Shpilevoy 2019-02-01 16:39 ` n.pettik 2019-01-09 8:20 ` Konstantin Osipov 2018-12-28 9:34 ` [tarantool-patches] [PATCH 4/8] sql: replace affinity with field type for func Nikita Pettik 2018-12-28 9:34 ` [tarantool-patches] [PATCH 5/8] sql: replace field type with affinity for VDBE runtime Nikita Pettik 2018-12-29 17:42 ` [tarantool-patches] " Vladislav Shpilevoy 2019-01-16 14:26 ` n.pettik 2019-01-22 15:41 ` Vladislav Shpilevoy 2019-01-28 16:39 ` n.pettik 2019-01-30 13:04 ` Vladislav Shpilevoy 2019-02-01 16:39 ` n.pettik [this message] 2019-02-05 15:08 ` Vladislav Shpilevoy 2019-02-05 17:46 ` n.pettik 2018-12-28 9:34 ` [tarantool-patches] [PATCH 6/8] sql: replace affinity with field type in struct Expr Nikita Pettik 2018-12-29 17:42 ` [tarantool-patches] " Vladislav Shpilevoy 2019-01-16 14:26 ` n.pettik 2019-01-22 15:41 ` Vladislav Shpilevoy 2019-01-28 16:39 ` n.pettik 2019-01-30 13:04 ` Vladislav Shpilevoy 2019-02-01 16:39 ` n.pettik 2019-02-05 15:08 ` Vladislav Shpilevoy 2019-02-05 17:46 ` n.pettik 2018-12-28 9:34 ` [tarantool-patches] [PATCH 7/8] sql: clean-up affinity from SQL source code Nikita Pettik 2018-12-29 17:42 ` [tarantool-patches] " Vladislav Shpilevoy 2019-01-16 14:26 ` n.pettik 2019-01-22 15:41 ` Vladislav Shpilevoy 2019-01-28 16:40 ` n.pettik 2019-01-30 13:04 ` Vladislav Shpilevoy 2019-02-01 16:39 ` n.pettik 2019-02-05 15:08 ` Vladislav Shpilevoy 2019-02-05 17:46 ` n.pettik 2018-12-28 9:34 ` [tarantool-patches] [PATCH 8/8] Remove affinity from field definition Nikita Pettik 2019-02-05 19:41 ` [tarantool-patches] Re: [PATCH 0/8] Eliminate affinity from source code Vladislav Shpilevoy 2019-02-08 13:37 ` Kirill Yukhin
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=2ED4082B-7899-4880-8FF2-25E1A3E6D90B@tarantool.org \ --to=korablev@tarantool.org \ --cc=tarantool-patches@freelists.org \ --cc=v.shpilevoy@tarantool.org \ --subject='[tarantool-patches] Re: [PATCH 5/8] sql: replace field type with affinity for VDBE runtime' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox