SQLite

Check-in [cdbfa66483]
Login

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
Timelines: family | ancestors | descendants | both | ticket-71e333e7
Files: files | file ages | folders
SHA1: cdbfa664839a409589ec7cebfc9111235d2f3b38
User & Date: drh 2012-12-08 21:36:26.700
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: 8542e6180d 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: cdbfa66483 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: b3f5366811 user: drh tags: ticket-71e333e7)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/expr.c.
73
74
75
76
77
78
79
80
81
82
83
84





85
86
87
88
89
90
91
92
93
73
74
75
76
77
78
79





80
81
82
83
84


85
86
87
88
89
90
91







-
-
-
-
-
+
+
+
+
+
-
-







      pNew->flags |= EP_Collate;
      pExpr = pNew;
    }
  }
  return pExpr;
}
Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
  if( zC ){
    Token s;
    s.z = zC;
    s.n = sqlite3Strlen30(s.z);
    pExpr = sqlite3ExprAddCollateToken(pParse, pExpr, &s);
  Token s;
  assert( zC!=0 );
  s.z = zC;
  s.n = sqlite3Strlen30(s.z);
  return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
  }
  return pExpr;
}

/*
** Skip over any TK_COLLATE and/or TK_AS operators at the root of
** an expression.
*/
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
106
107
108
109
110
111
112
113

114
115
116
117
118

119

120
121
122
123
124
125
126
104
105
106
107
108
109
110

111
112
113
114
115
116
117

118
119
120
121
122
123
124
125







-
+





+
-
+







** COLLATE operators take first precedence.  Left operands take
** precedence over right operands.
*/
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
  sqlite3 *db = pParse->db;
  CollSeq *pColl = 0;
  Expr *p = pExpr;
  while( p && pColl==0 ){
  while( p ){
    int op = p->op;
    if( op==TK_CAST || op==TK_UPLUS ){
      p = p->pLeft;
      continue;
    }
    assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
    if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
    if( op==TK_COLLATE ){
      if( db->init.busy ){
        /* Do not report errors when parsing while the schema */
        pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0);
      }else{
        pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
      }
      break;
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148







-
+







      if( j>=0 ){
        const char *zColl = p->pTab->aCol[j].zColl;
        pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
      }
      break;
    }
    if( p->flags & EP_Collate ){
      if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
      if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
        p = p->pLeft;
      }else{
        p = p->pRight;
      }
    }else{
      break;
    }
3359
3360
3361
3362
3363
3364
3365



3366
3367
3368
3369
3370
3371
3372
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374







+
+
+







static int evalConstExpr(Walker *pWalker, Expr *pExpr){
  Parse *pParse = pWalker->pParse;
  switch( pExpr->op ){
    case TK_IN:
    case TK_REGISTER: {
      return WRC_Prune;
    }
    case TK_COLLATE: {
      return WRC_Continue;
    }
    case TK_FUNCTION:
    case TK_AGG_FUNCTION:
    case TK_CONST_FUNC: {
      /* The arguments to a function have a fixed destination.
      ** Mark them this way to avoid generated unneeded OP_SCopy
      ** instructions. 
      */
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389





3390
3391
3392
3393
3394
3395
3396
3382
3383
3384
3385
3386
3387
3388



3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400







-
-
-
+
+
+
+
+







        }
      }
      break;
    }
  }
  if( isAppropriateForFactoring(pExpr) ){
    int r1 = ++pParse->nMem;
    int r2;
    r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
    if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1);
    int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
    /* If r2!=r1, it means that register r1 is never used.  That is harmless
    ** but suboptimal, so we want to know about the situation to fix it.
    ** Hence the following assert: */
    assert( r2==r1 );
    pExpr->op2 = pExpr->op;
    pExpr->op = TK_REGISTER;
    pExpr->iTable = r2;
    return WRC_Prune;
  }
  return WRC_Continue;
}
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3826
3827
3828
3829
3830
3831
3832

3833
3834
3835
3836
3837
3838
3839







-







    }
  }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
    if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
    if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
      return pA->op==TK_COLLATE ? 1 : 2;
    }
  }
  if( (pA->flags&EP_Collate)!=(pB->flags&EP_Collate) ) return 1;
  return 0;
}

/*
** Compare two ExprList objects.  Return 0 if they are identical and 
** non-zero if they differ in any way.
**
Changes to src/vdbeaux.c.
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880












881
882
883
884
885
886
887
888
889
890
891
862
863
864
865
866
867
868












869
870
871
872
873
874
875
876
877
878
879
880




881
882
883
884
885
886
887







-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-







      int i, j;
      KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
      assert( pKeyInfo->aSortOrder!=0 );
      sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
      i = sqlite3Strlen30(zTemp);
      for(j=0; j<pKeyInfo->nField; j++){
        CollSeq *pColl = pKeyInfo->aColl[j];
        if( pColl ){
          int n = sqlite3Strlen30(pColl->zName);
          if( i+n>nTemp-6 ){
            memcpy(&zTemp[i],",...",4);
            break;
          }
          zTemp[i++] = ',';
          if( pKeyInfo->aSortOrder[j] ){
            zTemp[i++] = '-';
          }
          memcpy(&zTemp[i], pColl->zName,n+1);
          i += n;
        const char *zColl = pColl ? pColl->zName : "nil";
        int n = sqlite3Strlen30(zColl);
        if( i+n>nTemp-6 ){
          memcpy(&zTemp[i],",...",4);
          break;
        }
        zTemp[i++] = ',';
        if( pKeyInfo->aSortOrder[j] ){
          zTemp[i++] = '-';
        }
        memcpy(&zTemp[i], zColl, n+1);
        i += n;
        }else if( i+4<nTemp-6 ){
          memcpy(&zTemp[i],",nil",4);
          i += 4;
        }
      }
      zTemp[i++] = ')';
      zTemp[i] = 0;
      assert( i<nTemp );
      break;
    }
    case P4_COLLSEQ: {
Changes to src/where.c.
666
667
668
669
670
671
672
673

674
675
676
677
678
679
680
666
667
668
669
670
671
672

673
674
675
676
677
678
679
680







-
+







          assert(pX->pLeft);
          pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
          if( pColl==0 ) pColl = pParse->db->pDfltColl;
  
          for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
            if( NEVER(j>=pIdx->nColumn) ) return 0;
          }
          if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
          if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
        }
        return pTerm;
      }
    }
  }
  return 0;
}