/ Check-in [cdbfa664]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Adjustments to the collating-sequence refactoring to facilitate full-coverage testing and to fix some minor issues found by TH3.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | ticket-71e333e7
Files: files | file ages | folders
SHA1: cdbfa664839a409589ec7cebfc9111235d2f3b38
User & Date: drh 2012-12-08 21:36:26
Context
2012-12-08
21:51
Refactor collating-sequence handling as a fix for ticket [71e333e7d2e642]. The Expr.pColl field is removed from the Expr object. The COLLATE operator now becomes a separate instance of Expr in the expression tree. The code generator looks up the correct collating function as needed, rather than referring to Expr.pColl. check-in: 8542e618 user: drh tags: trunk
21:36
Adjustments to the collating-sequence refactoring to facilitate full-coverage testing and to fix some minor issues found by TH3. Closed-Leaf check-in: cdbfa664 user: drh tags: ticket-71e333e7
14:16
Make sure WHERE clause constraints A=B and B=A work the same even with COLLATE clauses. check-in: b3f53668 user: drh tags: ticket-71e333e7
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

    73     73         pNew->flags |= EP_Collate;
    74     74         pExpr = pNew;
    75     75       }
    76     76     }
    77     77     return pExpr;
    78     78   }
    79     79   Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
    80         -  if( zC ){
    81         -    Token s;
    82         -    s.z = zC;
    83         -    s.n = sqlite3Strlen30(s.z);
    84         -    pExpr = sqlite3ExprAddCollateToken(pParse, pExpr, &s);
    85         -  }
    86         -  return pExpr;
           80  +  Token s;
           81  +  assert( zC!=0 );
           82  +  s.z = zC;
           83  +  s.n = sqlite3Strlen30(s.z);
           84  +  return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
    87     85   }
    88     86   
    89     87   /*
    90     88   ** Skip over any TK_COLLATE and/or TK_AS operators at the root of
    91     89   ** an expression.
    92     90   */
    93     91   Expr *sqlite3ExprSkipCollate(Expr *pExpr){
................................................................................
   106    104   ** COLLATE operators take first precedence.  Left operands take
   107    105   ** precedence over right operands.
   108    106   */
   109    107   CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
   110    108     sqlite3 *db = pParse->db;
   111    109     CollSeq *pColl = 0;
   112    110     Expr *p = pExpr;
   113         -  while( p && pColl==0 ){
          111  +  while( p ){
   114    112       int op = p->op;
   115    113       if( op==TK_CAST || op==TK_UPLUS ){
   116    114         p = p->pLeft;
   117    115         continue;
   118    116       }
   119         -    if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
          117  +    assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
          118  +    if( op==TK_COLLATE ){
   120    119         if( db->init.busy ){
   121    120           /* Do not report errors when parsing while the schema */
   122    121           pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0);
   123    122         }else{
   124    123           pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
   125    124         }
   126    125         break;
................................................................................
   135    134         if( j>=0 ){
   136    135           const char *zColl = p->pTab->aCol[j].zColl;
   137    136           pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
   138    137         }
   139    138         break;
   140    139       }
   141    140       if( p->flags & EP_Collate ){
   142         -      if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
          141  +      if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
   143    142           p = p->pLeft;
   144    143         }else{
   145    144           p = p->pRight;
   146    145         }
   147    146       }else{
   148    147         break;
   149    148       }
................................................................................
  3359   3358   static int evalConstExpr(Walker *pWalker, Expr *pExpr){
  3360   3359     Parse *pParse = pWalker->pParse;
  3361   3360     switch( pExpr->op ){
  3362   3361       case TK_IN:
  3363   3362       case TK_REGISTER: {
  3364   3363         return WRC_Prune;
  3365   3364       }
         3365  +    case TK_COLLATE: {
         3366  +      return WRC_Continue;
         3367  +    }
  3366   3368       case TK_FUNCTION:
  3367   3369       case TK_AGG_FUNCTION:
  3368   3370       case TK_CONST_FUNC: {
  3369   3371         /* The arguments to a function have a fixed destination.
  3370   3372         ** Mark them this way to avoid generated unneeded OP_SCopy
  3371   3373         ** instructions. 
  3372   3374         */
................................................................................
  3380   3382           }
  3381   3383         }
  3382   3384         break;
  3383   3385       }
  3384   3386     }
  3385   3387     if( isAppropriateForFactoring(pExpr) ){
  3386   3388       int r1 = ++pParse->nMem;
  3387         -    int r2;
  3388         -    r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
  3389         -    if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1);
         3389  +    int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
         3390  +    /* If r2!=r1, it means that register r1 is never used.  That is harmless
         3391  +    ** but suboptimal, so we want to know about the situation to fix it.
         3392  +    ** Hence the following assert: */
         3393  +    assert( r2==r1 );
  3390   3394       pExpr->op2 = pExpr->op;
  3391   3395       pExpr->op = TK_REGISTER;
  3392   3396       pExpr->iTable = r2;
  3393   3397       return WRC_Prune;
  3394   3398     }
  3395   3399     return WRC_Continue;
  3396   3400   }
................................................................................
  3822   3826       }
  3823   3827     }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
  3824   3828       if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
  3825   3829       if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
  3826   3830         return pA->op==TK_COLLATE ? 1 : 2;
  3827   3831       }
  3828   3832     }
  3829         -  if( (pA->flags&EP_Collate)!=(pB->flags&EP_Collate) ) return 1;
  3830   3833     return 0;
  3831   3834   }
  3832   3835   
  3833   3836   /*
  3834   3837   ** Compare two ExprList objects.  Return 0 if they are identical and 
  3835   3838   ** non-zero if they differ in any way.
  3836   3839   **

Changes to src/vdbeaux.c.

   862    862         int i, j;
   863    863         KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
   864    864         assert( pKeyInfo->aSortOrder!=0 );
   865    865         sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
   866    866         i = sqlite3Strlen30(zTemp);
   867    867         for(j=0; j<pKeyInfo->nField; j++){
   868    868           CollSeq *pColl = pKeyInfo->aColl[j];
   869         -        if( pColl ){
   870         -          int n = sqlite3Strlen30(pColl->zName);
   871         -          if( i+n>nTemp-6 ){
   872         -            memcpy(&zTemp[i],",...",4);
   873         -            break;
   874         -          }
   875         -          zTemp[i++] = ',';
   876         -          if( pKeyInfo->aSortOrder[j] ){
   877         -            zTemp[i++] = '-';
   878         -          }
   879         -          memcpy(&zTemp[i], pColl->zName,n+1);
   880         -          i += n;
   881         -        }else if( i+4<nTemp-6 ){
   882         -          memcpy(&zTemp[i],",nil",4);
   883         -          i += 4;
          869  +        const char *zColl = pColl ? pColl->zName : "nil";
          870  +        int n = sqlite3Strlen30(zColl);
          871  +        if( i+n>nTemp-6 ){
          872  +          memcpy(&zTemp[i],",...",4);
          873  +          break;
   884    874           }
          875  +        zTemp[i++] = ',';
          876  +        if( pKeyInfo->aSortOrder[j] ){
          877  +          zTemp[i++] = '-';
          878  +        }
          879  +        memcpy(&zTemp[i], zColl, n+1);
          880  +        i += n;
   885    881         }
   886    882         zTemp[i++] = ')';
   887    883         zTemp[i] = 0;
   888    884         assert( i<nTemp );
   889    885         break;
   890    886       }
   891    887       case P4_COLLSEQ: {

Changes to src/where.c.

   666    666             assert(pX->pLeft);
   667    667             pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
   668    668             if( pColl==0 ) pColl = pParse->db->pDfltColl;
   669    669     
   670    670             for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
   671    671               if( NEVER(j>=pIdx->nColumn) ) return 0;
   672    672             }
   673         -          if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
          673  +          if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
   674    674           }
   675    675           return pTerm;
   676    676         }
   677    677       }
   678    678     }
   679    679     return 0;
   680    680   }