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 C545C276DA for ; Thu, 14 Feb 2019 18:26:27 -0500 (EST) 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 y-ceZWkZIAz5 for ; Thu, 14 Feb 2019 18:26:27 -0500 (EST) Received: from smtp37.i.mail.ru (smtp37.i.mail.ru [94.100.177.97]) (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 CE7FC259C0 for ; Thu, 14 Feb 2019 18:26:26 -0500 (EST) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 12.2 \(3445.102.3\)) Subject: [tarantool-patches] Re: [PATCH 1/2] sql: refactor sql_expr_coll and sql_binary_compare_coll_seq functions From: "n.pettik" In-Reply-To: <07f58a45-5cf2-e848-78f1-c8a67028733c@tarantool.org> Date: Fri, 15 Feb 2019 02:26:21 +0300 Content-Transfer-Encoding: quoted-printable Message-Id: <7E6C9742-DC6B-47FC-B594-B897E3EEA1F8@tarantool.org> References: <276917ac3b405134ae0f075127888912395d511e.1547644179.git.korablev@tarantool.org> <07f58a45-5cf2-e848-78f1-c8a67028733c@tarantool.org> 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: tarantool-patches@freelists.org Cc: Vladislav Shpilevoy > On 16/01/2019 16:13, Nikita Pettik wrote: >> Lets make sql_expr_coll() return error code for two reasons. Firstly, >> we are going to use this function to detect operands of concatenation >> with incompatible collations. Secondly, pointer to struct coll in = most >> cases is redundant since collation id (which in turn returned via = output >> parameter) is enough to proceed the same operations. >> For the same reason lets make sql_binary_compare_coll_seq() return >> collation id instead of struct coll* and remove corresponding output >> parameter. >=20 > First of all, I agree with Kostja - it does not help in anything that > you removed coll * from output parameters/return value. It just slows > down some places like codeCompare, sqlite3ExprCodeIN, = sqlite3ExprCodeTarget > etc. - you just do coll_by_id() twice. > Moreover, maybe making some > places more accurate and compact, it pads out other ones and involves > additional headers like in whereexpr.c. Please, return as it was. Ok, then I will move struct coll * to output params for sql_expr_coll(). As for sql_binary_compare_coll_seq(), struct coll is needed only once - in codeCompare(); other 5 usages of this function leads to throwing away struct coll. In this case I believe it is really reasonable to operate = only with id. Anyway, id moved to output params, now it returns error code. >> Needed for #3947 >> --- >> src/box/sql/expr.c | 82 = ++++++++++++++++++++++++------------------------- >> src/box/sql/select.c | 27 ++++++++++------ >> src/box/sql/sqliteInt.h | 14 ++++----- >> src/box/sql/where.c | 56 ++++++++++++++++----------------- >> src/box/sql/whereexpr.c | 23 ++++++++------ >> 5 files changed, 105 insertions(+), 97 deletions(-) >> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c >> index b67b22c23..f8819f779 100644 >> --- a/src/box/sql/expr.c >> +++ b/src/box/sql/expr.c >> @@ -205,7 +204,7 @@ sql_expr_coll(Parse *parse, Expr *p, bool = *is_explicit_coll, uint32_t *coll_id) >> } >> if (op =3D=3D TK_COLLATE || >> (op =3D=3D TK_REGISTER && p->op2 =3D=3D TK_COLLATE)) = { >> - coll =3D sql_get_coll_seq(parse, p->u.zToken, = coll_id); >> + (void) sql_get_coll_seq(parse, p->u.zToken, = coll_id); >=20 > 1. It is not necessary to prefix (void) each function result of which > you ignore. By the way, I do not understand why do you ignore it. Here > and in all other places. Yep, it is not necessary, but this way is more descriptive. Refactored whole function, so it is not longer ignored. >> @@ -377,27 +376,28 @@ illegal_collation_mix: >> return -1; >> } >> -struct coll * >> -sql_binary_compare_coll_seq(Parse *parser, Expr *left, Expr *right, >> - uint32_t *coll_id) >> +uint32_t >> +sql_binary_compare_coll_seq(Parse *parser, Expr *left, Expr *right) >> { >> assert(left !=3D NULL); >> bool is_lhs_forced; >> bool is_rhs_forced; >> uint32_t lhs_coll_id; >> uint32_t rhs_coll_id; >> - struct coll *lhs_coll =3D sql_expr_coll(parser, left, = &is_lhs_forced, >> - &lhs_coll_id); >> - struct coll *rhs_coll =3D sql_expr_coll(parser, right, = &is_rhs_forced, >> - &rhs_coll_id); >> + if (sql_expr_coll(parser, left, &is_lhs_forced, &lhs_coll_id) !=3D= 0) >> + goto err; >> + if (sql_expr_coll(parser, right, &is_rhs_forced, &rhs_coll_id) = !=3D 0) >> + goto err; >> + uint32_t coll_id; >> if (collations_check_compatibility(lhs_coll_id, is_lhs_forced, >> rhs_coll_id, is_rhs_forced, >> - coll_id) !=3D 0) { >> - parser->rc =3D SQL_TARANTOOL_ERROR; >> - parser->nErr++; >> - return NULL; >> - } >> - return *coll_id =3D=3D rhs_coll_id ? rhs_coll : lhs_coll;; >> + &coll_id) !=3D 0) >> + goto err; >> + return coll_id; >> +err: >> + parser->rc =3D SQL_TARANTOOL_ERROR; >> + parser->nErr++; >> + return COLL_NONE; >=20 > 2. Please, do not return some obscure error codes - we use only 0/-1 > and NULL/not NULL almost everywhere except some archaic or misreviewed > code. If you want to return an error, it is better to move coll_id to > out parameters. Ok, that=E2=80=99s what I did. See diff below. >> diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h >> index 7501fadc8..50d297815 100644 >> --- a/src/box/sql/sqliteInt.h >> +++ b/src/box/sql/sqliteInt.h >> @@ -4337,10 +4337,10 @@ const char *sqlite3ErrStr(int); >> * clause is used. >> * @param[out] coll_id Collation identifier. >> * >> - * @retval Pointer to collation. >> + * @retval Return code: < 0 in case of error, 0 on success. >=20 > 3. Please, use separate @retval for each value. As you wish. It is not matter of discussion, but this rule seems to be inconsistent: somewhere we use one retval clause for all possible return values; in other places - several ones. >> */ >> -struct coll * >> -sql_expr_coll(Parse * pParse, Expr * pExpr, bool *is_explicit_coll, >> +int >> +sql_expr_coll(Parse *parse, Expr *p, bool *is_explicit_coll, >> uint32_t *coll_id); >> Expr *sqlite3ExprAddCollateToken(Parse * pParse, Expr *, const = Token *, int); >> @@ -4684,13 +4684,11 @@ collations_check_compatibility(uint32_t = lhs_id, bool is_lhs_forced, >> * @param parser Parser. >> * @param left Left expression. >> * @param right Right expression. Can be NULL. >> - * @param[out] coll_id Collation identifier. >> * >> - * @retval Collation object. >> + * @retval Id of collation object. >=20 > 4. You didn't mentioned that it can be COLL_NONE, that means an error. Skipped this comment due to refactoring of this function. diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index a367a07d4..5617e0f62 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -193,10 +193,13 @@ sqlExprSkipCollate(Expr * pExpr) } =20 int -sql_expr_coll(Parse *parse, Expr *p, bool *is_explicit_coll, uint32_t = *coll_id) +sql_expr_coll(Parse *parse, Expr *p, bool *is_explicit_coll, uint32_t = *coll_id, + struct coll **coll) { + assert(coll !=3D NULL); *is_explicit_coll =3D false; *coll_id =3D COLL_NONE; + *coll =3D NULL; while (p !=3D NULL) { int op =3D p->op; if (op =3D=3D TK_CAST || op =3D=3D TK_UPLUS) { @@ -205,7 +208,9 @@ sql_expr_coll(Parse *parse, Expr *p, bool = *is_explicit_coll, uint32_t *coll_id) } if (op =3D=3D TK_COLLATE || (op =3D=3D TK_REGISTER && p->op2 =3D=3D TK_COLLATE)) = { - (void) sql_get_coll_seq(parse, p->u.zToken, = coll_id); + *coll =3D sql_get_coll_seq(parse, p->u.zToken, = coll_id); + if (coll =3D=3D NULL) + return -1; *is_explicit_coll =3D true; break; } @@ -217,8 +222,8 @@ sql_expr_coll(Parse *parse, Expr *p, bool = *is_explicit_coll, uint32_t *coll_id) */ int j =3D p->iColumn; if (j >=3D 0) { - (void) = sql_column_collation(p->space_def, j, - coll_id); + *coll =3D = sql_column_collation(p->space_def, j, + coll_id); } break; } @@ -335,28 +340,30 @@ illegal_collation_mix: return -1; } =20 -uint32_t -sql_binary_compare_coll_seq(Parse *parser, Expr *left, Expr *right) +int +sql_binary_compare_coll_seq(Parse *parser, Expr *left, Expr *right, + uint32_t *id) { assert(left !=3D NULL); + assert(id !=3D NULL); bool is_lhs_forced; bool is_rhs_forced; uint32_t lhs_coll_id; uint32_t rhs_coll_id; - if (sql_expr_coll(parser, left, &is_lhs_forced, &lhs_coll_id) !=3D= 0) - goto err; - if (sql_expr_coll(parser, right, &is_rhs_forced, &rhs_coll_id) = !=3D 0) - goto err; - uint32_t coll_id; + struct coll *unused; + if (sql_expr_coll(parser, left, &is_lhs_forced, &lhs_coll_id, + &unused) !=3D 0) + return -1; + if (sql_expr_coll(parser, right, &is_rhs_forced, &rhs_coll_id, + &unused) !=3D 0) + return -1; if (collations_check_compatibility(lhs_coll_id, is_lhs_forced, - rhs_coll_id, is_rhs_forced, - &coll_id) !=3D 0) - goto err; - return coll_id; -err: - parser->rc =3D SQL_TARANTOOL_ERROR; - parser->nErr++; - return COLL_NONE; + rhs_coll_id, is_rhs_forced, = id) !=3D 0) { + parser->rc =3D SQL_TARANTOOL_ERROR; + parser->nErr++; + return -1; + } + return 0; } =20 /* @@ -372,7 +379,9 @@ codeCompare(Parse * pParse, /* The parsing (and code = generating) context */ int jumpIfNull /* If true, jump if either operand is = NULL */ ) { - uint32_t id =3D sql_binary_compare_coll_seq(pParse, pLeft, = pRight); + uint32_t id; + if (sql_binary_compare_coll_seq(pParse, pLeft, pRight, &id) !=3D = 0) + return -1; struct coll *coll =3D coll_by_id(id)->coll; int p5 =3D binaryCompareP5(pLeft, pRight, jumpIfNull); int addr =3D sqlVdbeAddOp4(pParse->pVdbe, opcode, in2, dest, = in1, @@ -2428,8 +2437,9 @@ sqlFindInIndex(Parse * pParse, /* Parsing = context */ for (i =3D 0; i < nExpr; i++) { Expr *pLhs =3D = sqlVectorFieldSubexpr(pX->pLeft, i); Expr *pRhs =3D = pEList->a[i].pExpr; - uint32_t id =3D - = sql_binary_compare_coll_seq(pParse, pLhs, pRhs); + uint32_t id; + if = (sql_binary_compare_coll_seq(pParse, pLhs, pRhs, &id) !=3D 0) + break; int j; =20 for (j =3D 0; j < nExpr; j++) { @@ -2749,9 +2759,9 @@ sqlCodeSubselect(Parse * pParse, /* Parsing = context */ Expr *p =3D = sqlVectorFieldSubexpr (pLeft, i); - = key_info->parts[i].coll_id =3D - = sql_binary_compare_coll_seq(pParse, p, - = pEList->a[i].pExpr); + if = (sql_binary_compare_coll_seq(pParse, p, pEList->a[i].pExpr, + = &key_info->parts[i].coll_id) !=3D 0) + return 0; } } } else if (ALWAYS(pExpr->x.pList !=3D 0)) { @@ -2770,9 +2780,11 @@ sqlCodeSubselect(Parse * pParse, /* Parsing = context */ enum field_type lhs_type =3D sql_expr_type(pLeft); bool unused; - (void) sql_expr_coll(pParse, = pExpr->pLeft, - &unused, - = &key_info->parts[0].coll_id); + struct coll *unused_coll; + if (sql_expr_coll(pParse, pExpr->pLeft, = &unused, + = &key_info->parts[0].coll_id, + &unused_coll) !=3D 0) + return 0; =20 /* Loop through each expression in = . */ r1 =3D sqlGetTempReg(pParse); @@ -3035,9 +3047,10 @@ sqlExprCodeIN(Parse * pParse, /* Parsing and = code generating context */ bool unused; uint32_t id; ExprList *pList =3D pExpr->x.pList; - if (sql_expr_coll(pParse, pExpr->pLeft, &unused, &id) !=3D= 0) + struct coll *coll; + if (sql_expr_coll(pParse, pExpr->pLeft, &unused, &id, + &coll) !=3D 0) goto sqlExprCodeIN_finished; - struct coll *coll =3D coll_by_id(id)->coll; int labelOk =3D sqlVdbeMakeLabel(v); int r2, regToFree; int regCkNull =3D 0; @@ -3169,9 +3182,9 @@ sqlExprCodeIN(Parse * pParse, /* Parsing and = code generating context */ uint32_t id; int r3 =3D sqlGetTempReg(pParse); Expr *p =3D sqlVectorFieldSubexpr(pLeft, i); - if (sql_expr_coll(pParse, p, &unused, &id) !=3D 0) + struct coll *pColl; + if (sql_expr_coll(pParse, p, &unused, &id, &pColl) !=3D = 0) goto sqlExprCodeIN_finished; - struct coll *pColl =3D coll_by_id(id)->coll; /* Tarantool: Replace i -> aiMap [i], since original = order of columns * is preserved. */ @@ -4001,9 +4014,9 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, = int target) uint32_t id; if (sql_expr_coll(pParse, = pFarg->a[i].pExpr, - &unused, &id) = !=3D 0) - break; - coll =3D coll_by_id(id)->coll;; + &unused, &id, + &coll) !=3D 0) + return 0; } } if (pFarg) { diff --git a/src/box/sql/select.c b/src/box/sql/select.c index aed40455b..926f5d011 100644 --- a/src/box/sql/select.c +++ b/src/box/sql/select.c @@ -1042,11 +1042,12 @@ selectInnerLoop(Parse * pParse, /* The = parser context */ for (i =3D 0; i < nResultCol; i++) { bool is_found; uint32_t id; + struct coll *coll; if (sql_expr_coll(pParse, = pEList->a[i].pExpr, - &is_found, = &id) !=3D 0) + &is_found, = &id, + &coll) !=3D 0) break; - struct coll *coll =3D = coll_by_id(id)->coll; if (i < nResultCol - 1) { sqlVdbeAddOp3(v, OP_Ne, = regResult + i, @@ -1428,7 +1429,9 @@ sql_expr_list_to_key_info(struct Parse *parse, = struct ExprList *list, int start) struct key_part_def *part =3D &key_info->parts[i - = start]; bool unused; uint32_t id; - if (sql_expr_coll(parse, item->pExpr, &unused, &id) !=3D = 0) { + struct coll *unused_coll; + if (sql_expr_coll(parse, item->pExpr, &unused, &id, + &unused_coll) !=3D 0) { sqlDbFree(parse->db, key_info); return NULL; } @@ -1970,10 +1973,10 @@ sqlSelectAddColumnTypeAndCollation(Parse * = pParse, /* Parsing contexts */ pTab->def->fields[i].type =3D sql_expr_type(p); bool is_found; uint32_t coll_id; - + struct coll *unused; if (pTab->def->fields[i].coll_id =3D=3D COLL_NONE && - sql_expr_coll(pParse, p, &is_found, &coll_id) =3D=3D = 0 && - coll_id !=3D COLL_NONE) + sql_expr_coll(pParse, p, &is_found, &coll_id, + &unused) =3D=3D 0 && coll_id !=3D = COLL_NONE) pTab->def->fields[i].coll_id =3D coll_id; } } @@ -2221,9 +2224,10 @@ multi_select_coll_seq_r(struct Parse *parser, = struct Select *p, int n, * resolution and we would not have got this far. */ assert(n >=3D 0 && n < p->pEList->nExpr); + struct coll *unused; if (sql_expr_coll(parser, p->pEList->a[n].pExpr, = &is_current_forced, - ¤t_coll_id) !=3D 0) - return COLL_NONE; + ¤t_coll_id, &unused) !=3D 0) + return 0; uint32_t res_coll_id; if (collations_check_compatibility(prior_coll_id, = is_prior_forced, current_coll_id, = is_current_forced, @@ -2279,7 +2283,10 @@ sql_multiselect_orderby_to_key_info(struct Parse = *parse, struct Select *s, uint32_t id; bool unused; if ((term->flags & EP_Collate) !=3D 0) { - (void) sql_expr_coll(parse, term, &unused, &id); + struct coll *unused_coll; + if (sql_expr_coll(parse, term, &unused, &id, + &unused_coll) !=3D 0) + return 0; } else { id =3D multi_select_coll_seq(parse, s, item->u.x.iOrderByCol = - 1); @@ -5357,9 +5364,8 @@ updateAccumulator(Parse * pParse, AggInfo * = pAggInfo) for (j =3D 0, pItem =3D pList->a; coll =3D=3D = NULL && j < nArg; j++, pItem++) { if (sql_expr_coll(pParse, pItem->pExpr, - &unused, &id) !=3D 0) + &unused, &id, &coll) = !=3D 0) return; - coll =3D coll_by_id(id)->coll; } if (regHit =3D=3D 0 && pAggInfo->nAccumulator) regHit =3D ++pParse->nMem; diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index 87cdbbcc1..70f971f8c 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -4344,12 +4344,14 @@ const char *sqlErrStr(int); * @param[out] is_explicit_coll Flag set if explicit COLLATE * clause is used. * @param[out] coll_id Collation identifier. + * @param[out] coll Collation object. * - * @retval Return code: < 0 in case of error, 0 on success. + * @retval 0 on success. + * @retval -1 in case of error. */ int -sql_expr_coll(Parse *parse, Expr *p, bool *is_explicit_coll, - uint32_t *coll_id); +sql_expr_coll(Parse *parse, Expr *p, bool *is_explicit_coll, uint32_t = *coll_id, + struct coll **coll); =20 Expr *sqlExprAddCollateToken(Parse * pParse, Expr *, const Token *, = int); Expr *sqlExprAddCollateString(Parse *, Expr *, const char *); @@ -4681,11 +4683,14 @@ collations_check_compatibility(uint32_t lhs_id, = bool is_lhs_forced, * @param parser Parser. * @param left Left expression. * @param right Right expression. Can be NULL. + * @param[out] id Id of resulting collation. * - * @retval Id of collation object. + * @retval 0 on success. + * @retval -1 in case of error (e.g. no collation found). */ -uint32_t -sql_binary_compare_coll_seq(Parse *parser, Expr *left, Expr *right); +int +sql_binary_compare_coll_seq(Parse *parser, Expr *left, Expr *right, + uint32_t *id); int sqlTempInMemory(const sql *); #ifndef SQL_OMIT_CTE With *sqlWithAdd(Parse *, With *, Token *, ExprList *, Select *); diff --git a/src/box/sql/where.c b/src/box/sql/where.c index f27de5dd7..631a5feba 100644 --- a/src/box/sql/where.c +++ b/src/box/sql/where.c @@ -306,10 +306,12 @@ whereScanNext(WhereScan * pScan) Parse = *pParse =3D = pWC->pWInfo->pParse; = assert(pX->pLeft); - uint32_t = id =3D - = sql_binary_compare_coll_seq( - = pParse, pX->pLeft, - = pX->pRight); + uint32_t = id; + if = (sql_binary_compare_coll_seq( + = pParse, pX->pLeft, + = pX->pRight, &id) !=3D 0) + = break; struct = coll *coll =3D = id !=3D COLL_NONE ? = coll_by_id(id)->coll : @@ -559,8 +561,9 @@ findIndexCol(Parse * pParse, /* Parse context = */ p->iColumn =3D=3D (int) part_to_match->fieldno) { bool is_found; uint32_t id; + struct coll *unused; if (sql_expr_coll(pParse, pList->a[i].pExpr, - &is_found, &id) !=3D 0) + &is_found, &id, &unused) !=3D = 0) return -1; if (id =3D=3D part_to_match->coll_id) return i; @@ -2280,7 +2283,9 @@ whereRangeVectorLen(Parse * pParse, /* = Parsing context */ space->def->fields[pLhs->iColumn].type : = FIELD_TYPE_INTEGER; if (type !=3D idx_type) break; - uint32_t id =3D sql_binary_compare_coll_seq(pParse, = pLhs, pRhs); + uint32_t id; + if (sql_binary_compare_coll_seq(pParse, pLhs, pRhs, &id) = !=3D 0) + break; if (id =3D=3D COLL_NONE) break; if (idx_def->key_def->parts[i + nEq].coll_id !=3D id) @@ -3264,13 +3269,14 @@ wherePathSatisfiesOrderBy(WhereInfo * pWInfo, = /* The WHERE clause */ bool unused; uint32_t lhs_id; uint32_t rhs_id; + struct coll *unused_coll; if (sql_expr_coll(pWInfo->pParse, pOrderBy->a[i].pExpr, = &unused, - &lhs_id) !=3D 0) + &lhs_id, &unused_coll) = !=3D 0) return 0; if (sql_expr_coll(pWInfo->pParse, pTerm->pExpr, &unused, - &rhs_id) !=3D 0) + &rhs_id, &unused_coll) = !=3D 0) return 0; if (lhs_id !=3D rhs_id) continue; @@ -3395,9 +3401,11 @@ wherePathSatisfiesOrderBy(WhereInfo * pWInfo, = /* The WHERE clause */ if (iColumn >=3D 0) { bool is_found; uint32_t id; - = sql_expr_coll(pWInfo->pParse, - = pOrderBy->a[i].pExpr, - &is_found, = &id); + struct coll *unused; + if = (sql_expr_coll(pWInfo->pParse, + = pOrderBy->a[i].pExpr, + = &is_found, &id, &unused) !=3D 0) + return 0; if = (idx_def->key_def->parts[j].coll_id !=3D id) continue; } diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c index 758c92896..703980f02 100644 --- a/src/box/sql/whereexpr.c +++ b/src/box/sql/whereexpr.c @@ -168,8 +168,10 @@ exprCommute(Parse * pParse, Expr * pExpr) } else { bool is_found; uint32_t id; - (void) sql_expr_coll(pParse, pExpr->pLeft, = &is_found, - &id); + struct coll *unused; + if (sql_expr_coll(pParse, pExpr->pLeft, = &is_found, &id, + &unused) !=3D 0) + return; if (id !=3D COLL_NONE) { /* * Neither X nor Y have COLLATE @@ -849,16 +851,21 @@ termIsEquivalence(Parse * pParse, Expr * pExpr) if (lhs_type !=3D rhs_type && (!sql_type_is_numeric(lhs_type) || !sql_type_is_numeric(rhs_type))) return 0; - uint32_t id =3D sql_binary_compare_coll_seq(pParse, = pExpr->pLeft, - pExpr->pRight); + uint32_t id; + if (sql_binary_compare_coll_seq(pParse, pExpr->pLeft, = pExpr->pRight, + &id) !=3D 0) + return 0; if (id =3D=3D COLL_NONE) return 1; bool unused1; uint32_t lhs_id; uint32_t rhs_id; - if (sql_expr_coll(pParse, pExpr->pLeft, &unused1, &lhs_id) !=3D = 0) + struct coll *unused; + if (sql_expr_coll(pParse, pExpr->pLeft, &unused1, &lhs_id, + &unused) !=3D 0) return 0; - if (sql_expr_coll(pParse, pExpr->pRight, &unused1, &rhs_id) !=3D = 0) + if (sql_expr_coll(pParse, pExpr->pRight, &unused1, &rhs_id, + &unused) !=3D 0) return 0; return lhs_id !=3D COLL_NONE && lhs_id =3D=3D rhs_id; }