/ Check-in [68b23c3d]
Login

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

Overview
Comment:Add code to check the validity of CollSeq objects during runtime. This code was not able to detect anomalies such as came up as a result of ticket [e4a18565a36884b00edf66541f38c693827968ab] so it is put into a branch for historical reference, with the intent of leaving it out of trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | collseq-checking
Files: files | file ages | folders
SHA1:68b23c3d41ce9303f42251d0c199181312e148f9
User & Date: drh 2014-12-05 14:36:15
Context
2014-12-05
14:36
Add code to check the validity of CollSeq objects during runtime. This code was not able to detect anomalies such as came up as a result of ticket [e4a18565a36884b00edf66541f38c693827968ab] so it is put into a branch for historical reference, with the intent of leaving it out of trunk. Closed-Leaf check-in: 68b23c3d user: drh tags: collseq-checking
14:34
Improved comment on the sharedB.test test script. Closed-Leaf check-in: 71f589e3 user: drh tags: fix-stale-keyinfo-cache
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/callback.c.

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
182
183
184
185
186
187
188

























189
190
191
192
193
194
195
...
211
212
213
214
215
216
217

218


219
220
221
222
223
224
225
    */
    callCollNeeded(db, enc, zName);
    p = sqlite3FindCollSeq(db, enc, zName, 0);
  }
  if( p && !p->xCmp && synthCollSeq(db, p) ){
    p = 0;
  }
  assert( !p || p->xCmp );
  if( p==0 ){
    sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
  }
  return p;
}

/*
................................................................................
        pColl = 0;
      }
    }
  }
  return pColl;
}


























/*
** Parameter zName points to a UTF-8 encoded string nName bytes long.
** Return the CollSeq* pointer for the collation sequence named zName
** for the encoding 'enc' from the database 'db'.
**
** If the entry specified is not found and 'create' is true, then create a
** new entry.  Otherwise return NULL.
................................................................................
  if( zName ){
    pColl = findCollSeqEntry(db, zName, create);
  }else{
    pColl = db->pDfltColl;
  }
  assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
  assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );

  if( pColl ) pColl += enc-1;


  return pColl;
}

/* During the search for the best function definition, this procedure
** is called to test how well the function passed as the first argument
** matches the request for a function with nArg arguments in a system
** that uses encoding enc. The value returned indicates how well the







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
|
>
>







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    */
    callCollNeeded(db, enc, zName);
    p = sqlite3FindCollSeq(db, enc, zName, 0);
  }
  if( p && !p->xCmp && synthCollSeq(db, p) ){
    p = 0;
  }
  assert( p==0 || (sqlite3ValidCollSeq(p) && p->xCmp!=0) );
  if( p==0 ){
    sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
  }
  return p;
}

/*
................................................................................
        pColl = 0;
      }
    }
  }
  return pColl;
}

#ifdef SQLITE_DEBUG
/*
** The following routine does sanity checking on a CollSeq object and
** returns 1 if everything looks ok and 0 if the CollSeq object appears
** to be corrupt.  This routine is used only inside of assert() statements.
*/
int sqlite3ValidCollSeq(const CollSeq *p){
  /* The CollSeq must be one of a triple and the zName field must
  ** point to the first byte after that triple 
  */
  int n = (int)(p->zName - (char*)p)/sizeof(CollSeq);
  if( n<=0 || n>3 ) return 0;

  /* Check for valid enc values */
  if( p->enc==SQLITE_UTF8 ) return 1;
  if( p->enc==SQLITE_UTF16LE ) return 1;
  if( p->enc==SQLITE_UTF16BE ) return 1;
  if( p->enc==(SQLITE_UTF16LE|SQLITE_UTF16_ALIGNED) ) return 1;
  if( p->enc==(SQLITE_UTF16BE|SQLITE_UTF16_ALIGNED) ) return 1;

  /* Otherwise, malformed */
  return 0;
}
#endif /* SQLITE_DEBUG */

/*
** Parameter zName points to a UTF-8 encoded string nName bytes long.
** Return the CollSeq* pointer for the collation sequence named zName
** for the encoding 'enc' from the database 'db'.
**
** If the entry specified is not found and 'create' is true, then create a
** new entry.  Otherwise return NULL.
................................................................................
  if( zName ){
    pColl = findCollSeqEntry(db, zName, create);
  }else{
    pColl = db->pDfltColl;
  }
  assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
  assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
  if( pColl ){
    pColl += enc-1;
    assert( sqlite3ValidCollSeq(pColl) );
  }
  return pColl;
}

/* During the search for the best function definition, this procedure
** is called to test how well the function passed as the first argument
** matches the request for a function with nArg arguments in a system
** that uses encoding enc. The value returned indicates how well the

Changes to src/sqliteInt.h.

3449
3450
3451
3452
3453
3454
3455



3456
3457
3458
3459
3460
3461
3462

#if defined(SQLITE_TEST) 
const char *sqlite3ErrName(int);
#endif

const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);



CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*);
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*);
int sqlite3CheckCollSeq(Parse *, CollSeq *);







>
>
>







3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465

#if defined(SQLITE_TEST) 
const char *sqlite3ErrName(int);
#endif

const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
#if defined(SQLITE_DEBUG)
int sqlite3ValidCollSeq(const CollSeq*);
#endif
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*);
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*);
int sqlite3CheckCollSeq(Parse *, CollSeq *);

Changes to src/vdbeaux.c.

1050
1051
1052
1053
1054
1055
1056

1057
1058
1059
1060
1061
1062
1063
....
3354
3355
3356
3357
3358
3359
3360

3361
3362
3363
3364
3365
3366
3367
....
3469
3470
3471
3472
3473
3474
3475

3476
3477
3478
3479
3480
3481
3482
      assert( pKeyInfo->aSortOrder!=0 );
      sqlite3_snprintf(nTemp, zTemp, "k(%d", pKeyInfo->nField);
      i = sqlite3Strlen30(zTemp);
      for(j=0; j<pKeyInfo->nField; j++){
        CollSeq *pColl = pKeyInfo->aColl[j];
        const char *zColl = pColl ? pColl->zName : "nil";
        int n = sqlite3Strlen30(zColl);

        if( n==6 && memcmp(zColl,"BINARY",6)==0 ){
          zColl = "B";
          n = 1;
        }
        if( i+n>nTemp-6 ){
          memcpy(&zTemp[i],",...",4);
          break;
................................................................................
*/
static int vdbeCompareMemString(
  const Mem *pMem1,
  const Mem *pMem2,
  const CollSeq *pColl,
  u8 *prcErr                      /* If an OOM occurs, set to SQLITE_NOMEM */
){

  if( pMem1->enc==pColl->enc ){
    /* The strings are already in the correct encoding.  Call the
     ** comparison function directly */
    return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
  }else{
    int rc;
    const void *v1, *v2;
................................................................................
    /* The collation sequence must be defined at this point, even if
    ** the user deletes the collation sequence after the vdbe program is
    ** compiled (this was not always the case).
    */
    assert( !pColl || pColl->xCmp );

    if( pColl ){

      return vdbeCompareMemString(pMem1, pMem2, pColl, 0);
    }
    /* If a NULL pointer was passed as the collate function, fall through
    ** to the blob case and use memcmp().  */
  }
 
  /* Both values must be blobs.  Compare using memcmp().  */







>







 







>







 







>







1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
....
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
....
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
      assert( pKeyInfo->aSortOrder!=0 );
      sqlite3_snprintf(nTemp, zTemp, "k(%d", pKeyInfo->nField);
      i = sqlite3Strlen30(zTemp);
      for(j=0; j<pKeyInfo->nField; j++){
        CollSeq *pColl = pKeyInfo->aColl[j];
        const char *zColl = pColl ? pColl->zName : "nil";
        int n = sqlite3Strlen30(zColl);
        assert( pColl==0 || sqlite3ValidCollSeq(pColl) );
        if( n==6 && memcmp(zColl,"BINARY",6)==0 ){
          zColl = "B";
          n = 1;
        }
        if( i+n>nTemp-6 ){
          memcpy(&zTemp[i],",...",4);
          break;
................................................................................
*/
static int vdbeCompareMemString(
  const Mem *pMem1,
  const Mem *pMem2,
  const CollSeq *pColl,
  u8 *prcErr                      /* If an OOM occurs, set to SQLITE_NOMEM */
){
  assert( sqlite3ValidCollSeq(pColl) );
  if( pMem1->enc==pColl->enc ){
    /* The strings are already in the correct encoding.  Call the
     ** comparison function directly */
    return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
  }else{
    int rc;
    const void *v1, *v2;
................................................................................
    /* The collation sequence must be defined at this point, even if
    ** the user deletes the collation sequence after the vdbe program is
    ** compiled (this was not always the case).
    */
    assert( !pColl || pColl->xCmp );

    if( pColl ){
      assert( sqlite3ValidCollSeq(pColl) );
      return vdbeCompareMemString(pMem1, pMem2, pColl, 0);
    }
    /* If a NULL pointer was passed as the collate function, fall through
    ** to the blob case and use memcmp().  */
  }
 
  /* Both values must be blobs.  Compare using memcmp().  */