/ Check-in [b9493c5f]
Login

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

Overview
Comment:Use the faster LIKE function from sqlite v2. Add special user functions to test builds to test the auxdata APIs. (CVS 1610)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b9493c5facea4d24a6cbc4f6fa2f75dc2399a11d
User & Date: danielk1977 2004-06-17 05:36:44
Context
2004-06-17
06:13
Handle conflicting ON CONFLICT clauses in table definitions. (CVS 1611) check-in: 12e77e75 user: danielk1977 tags: trunk
05:36
Use the faster LIKE function from sqlite v2. Add special user functions to test builds to test the auxdata APIs. (CVS 1610) check-in: b9493c5f user: danielk1977 tags: trunk
00:01
Remove the second definition of SQLITE_N_BTREE_META from test3.c. (CVS 1609) check-in: b1e66ae4 user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/func.c.

    12     12   ** This file contains the C functions that implement various SQL
    13     13   ** functions of SQLite.  
    14     14   **
    15     15   ** There is only one exported symbol in this file - the function
    16     16   ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
    17     17   ** All other code has file scope.
    18     18   **
    19         -** $Id: func.c,v 1.70 2004/06/16 10:39:24 danielk1977 Exp $
           19  +** $Id: func.c,v 1.71 2004/06/17 05:36:44 danielk1977 Exp $
    20     20   */
    21     21   #include <ctype.h>
    22     22   #include <math.h>
    23     23   #include <stdlib.h>
    24     24   #include <assert.h>
    25     25   #include "sqliteInt.h"
    26     26   #include "vdbeInt.h"
................................................................................
   313    313   typedef struct LikePattern LikePattern;
   314    314   
   315    315   void deleteLike(void *pLike){
   316    316     sqliteFree(pLike);
   317    317   }
   318    318   
   319    319   
          320  +#if 0
   320    321   /* #define TRACE_LIKE */
   321         -
   322    322   #if defined(TRACE_LIKE) && !defined(NDEBUG)
   323    323   char *dumpLike(LikePattern *pLike){
   324    324     int i;
   325    325     int k = 0;
   326    326     char *zBuf = (char *)sqliteMalloc(pLike->nState*40);
   327    327     
   328    328     k += sprintf(&zBuf[k], "%d states - ", pLike->nState);
................................................................................
   538    538     }while( c && pState>=aState );
   539    539   
   540    540     if( (pState-aState)==pLike->nState || (pState-aState)<-1 ){
   541    541       sqlite3_result_int(context, 1);
   542    542     }else{
   543    543       sqlite3_result_int(context, 0);
   544    544     }
          545  +}
          546  +#endif
          547  +
          548  +/*
          549  +** Implementation of the like() SQL function.  This function implements
          550  +** the build-in LIKE operator.  The first argument to the function is the
          551  +** pattern and the second argument is the string.  So, the SQL statements:
          552  +**
          553  +**       A LIKE B
          554  +**
          555  +** is implemented as like(B,A).
          556  +**
          557  +** If the pointer retrieved by via a call to sqlite3_user_data() is
          558  +** not NULL, then this function uses UTF-16. Otherwise UTF-8.
          559  +*/
          560  +static void likeFunc(
          561  +  sqlite3_context *context, 
          562  +  int argc, 
          563  +  sqlite3_value **argv
          564  +){
          565  +  const unsigned char *zA = sqlite3_value_text(argv[0]);
          566  +  const unsigned char *zB = sqlite3_value_text(argv[1]);
          567  +  if( zA && zB ){
          568  +    sqlite3_result_int(context, sqlite3utf8LikeCompare(zA, zB));
          569  +  }
   545    570   }
   546    571   
   547    572   /*
   548    573   ** Implementation of the glob() SQL function.  This function implements
   549    574   ** the build-in GLOB operator.  The first argument to the function is the
   550    575   ** string and the second argument is the pattern.  So, the SQL statements:
   551    576   **
................................................................................
   781    806   static void test_destructor_count(
   782    807     sqlite3_context *pCtx, 
   783    808     int nArg,
   784    809     sqlite3_value **argv
   785    810   ){
   786    811     sqlite3_result_int(pCtx, test_destructor_count_var);
   787    812   }
          813  +
          814  +static void free_test_auxdata(void *p) {sqliteFree(p);}
          815  +static void test_auxdata(
          816  +  sqlite3_context *pCtx, 
          817  +  int nArg,
          818  +  sqlite3_value **argv
          819  +){
          820  +  int i;
          821  +  char *zRet = sqliteMalloc(nArg*2);
          822  +  if( !zRet ) return;
          823  +  for(i=0; i<nArg; i++){
          824  +    char const *z = sqlite3_value_text(argv[i]);
          825  +    if( z ){
          826  +      char *zAux = sqlite3_get_auxdata(pCtx, i);
          827  +      if( zAux ){
          828  +        zRet[i*2] = '1';
          829  +        if( strcmp(zAux, z) ){
          830  +          sqlite3_result_error(pCtx, "Auxilary data corruption", -1);
          831  +          return;
          832  +        }
          833  +      }else{
          834  +        zRet[i*2] = '0';
          835  +        zAux = sqliteStrDup(z);
          836  +        sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
          837  +      }
          838  +      zRet[i*2+1] = ' ';
          839  +    }
          840  +  }
          841  +  sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
          842  +}
   788    843   #endif
   789    844   
   790    845   /*
   791    846   ** An instance of the following structure holds the context of a
   792    847   ** sum() or avg() aggregate computation.
   793    848   */
   794    849   typedef struct SumCtx SumCtx;
................................................................................
   961   1016       { "lower",                       1, 0, SQLITE_UTF8, 0, lowerFunc  },
   962   1017       { "coalesce",                   -1, 0, SQLITE_UTF8, 0, ifnullFunc },
   963   1018       { "coalesce",                    0, 0, SQLITE_UTF8, 0, 0          },
   964   1019       { "coalesce",                    1, 0, SQLITE_UTF8, 0, 0          },
   965   1020       { "ifnull",                      2, 0, SQLITE_UTF8, 1, ifnullFunc },
   966   1021       { "random",                     -1, 0, SQLITE_UTF8, 0, randomFunc },
   967   1022       { "like",                        2, 0, SQLITE_UTF8, 0, likeFunc   },
   968         -    { "like",                        2, 2, SQLITE_UTF16,0, likeFunc   },
         1023  +/* { "like",                        2, 2, SQLITE_UTF16,0, likeFunc   }, */
   969   1024       { "glob",                        2, 0, SQLITE_UTF8, 0, globFunc   },
   970   1025       { "nullif",                      2, 0, SQLITE_UTF8, 0, nullifFunc },
   971   1026       { "sqlite_version",              0, 0, SQLITE_UTF8, 0, versionFunc},
   972   1027       { "quote",                       1, 0, SQLITE_UTF8, 0, quoteFunc  },
   973   1028       { "last_insert_rowid",           0, 1, SQLITE_UTF8, 0, last_insert_rowid },
   974   1029       { "change_count",                0, 1, SQLITE_UTF8, 0, change_count      },
   975   1030       { "last_statement_change_count", 0, 1, SQLITE_UTF8, 0, 
................................................................................
   977   1032   #ifdef SQLITE_SOUNDEX
   978   1033       { "soundex",                     1, 0, SQLITE_UTF8, 0, soundexFunc},
   979   1034   #endif
   980   1035   #ifdef SQLITE_TEST
   981   1036       { "randstr",                     2, 0, SQLITE_UTF8, 0, randStr    },
   982   1037       { "test_destructor",             1, 0, SQLITE_UTF8, 0, test_destructor},
   983   1038       { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count},
         1039  +    { "test_auxdata",               -1, 0, SQLITE_UTF8, 0, test_auxdata},
   984   1040   #endif
   985   1041     };
   986   1042     static struct {
   987   1043       char *zName;
   988   1044       signed char nArg;
   989   1045       u8 argType;
   990   1046       u8 needCollSeq;

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.285 2004/06/12 09:25:21 danielk1977 Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.286 2004/06/17 05:36:44 danielk1977 Exp $
    15     15   */
    16     16   #include "config.h"
    17     17   #include "sqlite3.h"
    18     18   #include "hash.h"
    19     19   #include "parse.h"
    20     20   #include <stdio.h>
    21     21   #include <stdlib.h>
................................................................................
  1378   1378   unsigned char *sqlite3utf16to8(const void *pData, int N, int big_endian);
  1379   1379   void *sqlite3utf8to16be(const unsigned char *pIn, int N);
  1380   1380   void *sqlite3utf8to16le(const unsigned char *pIn, int N);
  1381   1381   void sqlite3utf16to16le(void *pData, int N);
  1382   1382   void sqlite3utf16to16be(void *pData, int N);
  1383   1383   int sqlite3utf16ByteLen(const void *pData, int nChar);
  1384   1384   int sqlite3utf8CharLen(const char *pData, int nByte);
         1385  +int sqlite3utf8LikeCompare(const unsigned char*, const unsigned char*);
  1385   1386   int sqlite3PutVarint(unsigned char *, u64);
  1386   1387   int sqlite3GetVarint(const unsigned char *, u64 *);
  1387   1388   int sqlite3GetVarint32(const unsigned char *, u32 *);
  1388   1389   int sqlite3VarintLen(u64 v);
  1389   1390   char sqlite3AffinityType(const char *, int);
  1390   1391   void sqlite3IndexAffinityStr(Vdbe *, Index *);
  1391   1392   void sqlite3TableAffinityStr(Vdbe *, Table *);
................................................................................
  1410   1411   int sqlite3CheckObjectName(Parse *, const char *);
  1411   1412   
  1412   1413   const void *sqlite3ValueText(sqlite3_value*, u8);
  1413   1414   int sqlite3ValueBytes(sqlite3_value*, u8);
  1414   1415   void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8);
  1415   1416   void sqlite3ValueFree(sqlite3_value*);
  1416   1417   sqlite3_value *sqlite3ValueNew();
  1417         -

Changes to src/utf.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains routines used to translate between UTF-8, 
    13     13   ** UTF-16, UTF-16BE, and UTF-16LE.
    14     14   **
    15         -** $Id: utf.c,v 1.19 2004/06/12 00:42:35 danielk1977 Exp $
           15  +** $Id: utf.c,v 1.20 2004/06/17 05:36:44 danielk1977 Exp $
    16     16   **
    17     17   ** Notes on UTF-8:
    18     18   **
    19     19   **   Byte-0    Byte-1    Byte-2    Byte-3    Value
    20     20   **  0xxxxxxx                                 00000000 00000000 0xxxxxxx
    21     21   **  110yyyyy  10xxxxxx                       00000000 00000yyy yyxxxxxx
    22     22   **  1110zzzz  10yyyyyy  10xxxxxx             00000000 zzzzyyyy yyxxxxxx
................................................................................
    81     81   ** case relationship between the 26 characters used in the English
    82     82   ** language only.
    83     83   **
    84     84   ** This means that characters with umlauts etc. will not be folded
    85     85   ** correctly (unless they are encoded as composite characters, which would
    86     86   ** doubtless cause much trouble).
    87     87   */
    88         -#define LOWERCASE(x) (x<91?(int)(UpperToLower[x]):x);
           88  +#define LOWERCASE(x) (x<91?(int)(UpperToLower[x]):x)
    89     89   static unsigned char UpperToLower[91] = {
    90     90         0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
    91     91        18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
    92     92        36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
    93     93        54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
    94     94       104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
    95     95       122,
................................................................................
   705    705     }else{
   706    706       *zOut = sqlite3utf16to8(zData, nData, enc1==SQLITE_UTF16BE);
   707    707       if( !(*zOut) ) return SQLITE_NOMEM;
   708    708       *nOut = strlen(*zOut);
   709    709     }
   710    710     return SQLITE_OK;
   711    711   }
          712  +
          713  +#define sqliteNextChar(X)  while( (0xc0&*++(X))==0x80 ){}
          714  +
          715  +/*
          716  +** Compare two UTF-8 strings for equality using the "LIKE" operator of
          717  +** SQL.  The '%' character matches any sequence of 0 or more
          718  +** characters and '_' matches any single character.  Case is
          719  +** not significant.
          720  +*/
          721  +int sqlite3utf8LikeCompare(
          722  +  const unsigned char *zPattern, 
          723  +  const unsigned char *zString
          724  +){
          725  +  register int c;
          726  +  int c2;
          727  +
          728  +  while( (c = LOWERCASE(*zPattern))!=0 ){
          729  +    switch( c ){
          730  +      case '%': {
          731  +        while( (c=zPattern[1]) == '%' || c == '_' ){
          732  +          if( c=='_' ){
          733  +            if( *zString==0 ) return 0;
          734  +            sqliteNextChar(zString);
          735  +          }
          736  +          zPattern++;
          737  +        }
          738  +        if( c==0 ) return 1;
          739  +        c = LOWERCASE(c);
          740  +        while( (c2=LOWERCASE(*zString))!=0 ){
          741  +          while( c2 != 0 && c2 != c ){ 
          742  +            zString++;
          743  +            c2 = LOWERCASE(*zString); 
          744  +          }
          745  +          if( c2==0 ) return 0;
          746  +          if( sqlite3utf8LikeCompare(&zPattern[1],zString) ) return 1;
          747  +          sqliteNextChar(zString);
          748  +        }
          749  +        return 0;
          750  +      }
          751  +      case '_': {
          752  +        if( *zString==0 ) return 0;
          753  +        sqliteNextChar(zString);
          754  +        zPattern++;
          755  +        break;
          756  +      }
          757  +      default: {
          758  +        if( c != LOWERCASE(*zString) ) return 0;
          759  +        zPattern++;
          760  +        zString++;
          761  +        break;
          762  +      }
          763  +    }
          764  +  }
          765  +  return *zString==0;
          766  +}

Changes to src/vdbemem.c.

   143    143   /*
   144    144   ** Make sure the given Mem is \u0000 terminated.
   145    145   */
   146    146   int sqlite3VdbeMemNulTerminate(Mem *pMem){
   147    147     if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & (MEM_Str|MEM_Blob))==0 ){
   148    148       return SQLITE_OK;   /* Nothing to do */
   149    149     }
   150         -  /* Only static or ephemeral strings can be unterminated */
   151         -  assert( (pMem->flags & (MEM_Static|MEM_Ephem))!=0 );
          150  +
          151  +  if( pMem->flags & (MEM_Static|MEM_Ephem) ){
   152    152     return sqlite3VdbeMemMakeWriteable(pMem);
          153  +  }else{
          154  +    if( pMem->flags & MEM_Dyn ){
          155  +      if( pMem->xDel ){
          156  +        char *z = sqliteMalloc(pMem->n+2);
          157  +        if( !z ) return SQLITE_NOMEM;
          158  +        memcpy(z, pMem->z, pMem->n);
          159  +        pMem->xDel(pMem->z);
          160  +        pMem->xDel = 0;
          161  +        pMem->z = z;
          162  +      }else{
          163  +        pMem->z = sqliteRealloc(pMem->z, pMem->n+2);
          164  +        if( !pMem->z ) return SQLITE_NOMEM;
          165  +      }
          166  +    }else{
          167  +      assert( pMem->flags & MEM_Short );
          168  +      if( pMem->n+2>NBFS ){
          169  +        char *z = sqliteMalloc(pMem->n+2);
          170  +        if( !z ) return SQLITE_NOMEM;
          171  +        memcpy(z, pMem->z, pMem->n);
          172  +        pMem->flags &= !(MEM_Short);
          173  +        pMem->flags |= MEM_Dyn;
          174  +        pMem->xDel = 0;
          175  +        pMem->z = z;
          176  +      }
          177  +    }
          178  +    pMem->z[pMem->n++] = 0;
          179  +    pMem->z[pMem->n++] = 0;
          180  +  }
          181  +  return SQLITE_OK;
   153    182   }
   154    183   
   155    184   /*
   156    185   ** Add MEM_Str to the set of representations for the given Mem.
   157    186   ** A NULL is converted into an empty string.  Numbers are converted
   158    187   ** using sqlite3_snprintf().  Converting a BLOB to a string is a
   159    188   ** no-op.

Changes to test/expr.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing expressions.
    13     13   #
    14         -# $Id: expr.test,v 1.33 2004/06/02 00:41:10 drh Exp $
           14  +# $Id: expr.test,v 1.34 2004/06/17 05:36:45 danielk1977 Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Create a table to work with.
    20     20   #
    21     21   execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}
................................................................................
   228    228   test_expr expr-4.20 {r1='0.0', r2='abc'} {r1>r2} 0
   229    229   
   230    230   test_expr expr-5.1 {t1='abc', t2='xyz'} {t1 LIKE t2} 0
   231    231   test_expr expr-5.2 {t1='abc', t2='ABC'} {t1 LIKE t2} 1
   232    232   test_expr expr-5.3 {t1='abc', t2='A_C'} {t1 LIKE t2} 1
   233    233   test_expr expr-5.4 {t1='abc', t2='abc_'} {t1 LIKE t2} 0
   234    234   test_expr expr-5.5 {t1='abc', t2='A%C'} {t1 LIKE t2} 1
          235  +test_expr expr-5.5a {t1='abdc', t2='a%c'} {t1 LIKE t2} 1
   235    236   test_expr expr-5.5b {t1='ac', t2='A%C'} {t1 LIKE t2} 1
   236    237   test_expr expr-5.6 {t1='abxyzzyc', t2='A%C'} {t1 LIKE t2} 1
   237    238   test_expr expr-5.7 {t1='abxyzzy', t2='A%C'} {t1 LIKE t2} 0
   238    239   test_expr expr-5.8 {t1='abxyzzycx', t2='A%C'} {t1 LIKE t2} 0
   239    240   test_expr expr-5.8b {t1='abxyzzycy', t2='A%CX'} {t1 LIKE t2} 0
   240    241   test_expr expr-5.9 {t1='abc', t2='A%_C'} {t1 LIKE t2} 1
   241    242   test_expr expr-5.9b {t1='ac', t2='A%_C'} {t1 LIKE t2} 0

Changes to test/func.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing built-in functions.
    13     13   #
    14         -# $Id: func.test,v 1.21 2004/06/12 09:25:30 danielk1977 Exp $
           14  +# $Id: func.test,v 1.22 2004/06/17 05:36:45 danielk1977 Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Create a table to work with.
    20     20   #
    21     21   do_test func-0.0 {
................................................................................
   333    333   do_test func-11.1 {
   334    334     execsql {
   335    335       SELECT sqlite_version(*);
   336    336     }
   337    337   } [sqlite -version]
   338    338   
   339    339   # Test that destructors passed to sqlite by calls to sqlite3_result_text()
   340         -# etc. are called.
          340  +# etc. are called. These tests use two special user-defined functions
          341  +# (implemented in func.c) only available in test builds. 
          342  +#
          343  +# Function test_destructor() takes one argument and returns a copy of the
          344  +# text form of that argument. A destructor is associated with the return
          345  +# value. Function test_destructor_count() returns the number of outstanding
          346  +# destructor calls for values returned by test_destructor().
          347  +#
   341    348   do_test func-12.1 {
   342    349     execsql {
   343    350       SELECT test_destructor('hello world'), test_destructor_count();
   344    351     }
   345    352   } {{hello world} 1}
   346    353   do_test func-12.2 {
   347    354     execsql {
................................................................................
   367    374     }
   368    375   } {hello world}
   369    376   do_test func-12.6 {
   370    377     execsql {
   371    378       SELECT test_destructor_count();
   372    379     }
   373    380   } {0}
          381  +do_test func-12.7 {
          382  +  execsql {
          383  +    DROP TABLE t4;
          384  +  }
          385  +} {}
          386  +
          387  +# Test that the auxdata API for scalar functions works. This test uses
          388  +# a special user-defined function only available in test builds,
          389  +# test_auxdata(). Function test_auxdata() takes any number of arguments.
          390  +do_test func-13.1 {
          391  +  execsql {
          392  +    SELECT test_auxdata('hello world');
          393  +  }
          394  +} {0}
          395  +do_test func-13.2 {
          396  +  execsql {
          397  +    CREATE TABLE t4(a, b);
          398  +    INSERT INTO t4 VALUES('abc', 'def');
          399  +    INSERT INTO t4 VALUES('ghi', 'jkl');
          400  +  }
          401  +} {}
          402  +do_test func-13.3 {
          403  +  execsql {
          404  +    SELECT test_auxdata('hello world') FROM t4;
          405  +  }
          406  +} {0 1}
          407  +do_test func-13.4 {
          408  +  execsql {
          409  +    SELECT test_auxdata('hello world', 123) FROM t4;
          410  +  }
          411  +} {{0 0} {1 1}}
          412  +do_test func-13.5 {
          413  +  execsql {
          414  +    SELECT test_auxdata('hello world', a) FROM t4;
          415  +  }
          416  +} {{0 0} {1 0}}
          417  +do_test func-13.6 {
          418  +  execsql {
          419  +    SELECT test_auxdata('hello'||'world', a) FROM t4;
          420  +  }
          421  +} {{0 0} {1 0}}
          422  +
          423  +# Test that auxilary data is preserved between calls for SQL variables.
          424  +do_test func-13.7 {
          425  +  db close
          426  +  set DB [sqlite db test.db]
          427  +  set sql "SELECT test_auxdata( ? , a ) FROM t4;"
          428  +  set STMT [sqlite3_prepare $DB $sql -1 TAIL]
          429  +  sqlite3_bind_text $STMT 1 hello -1
          430  +  set res [list]
          431  +  while { "SQLITE_ROW"==[sqlite3_step $STMT] } {
          432  +    lappend res [sqlite3_column_text $STMT 0]
          433  +  }
          434  +  lappend res [sqlite3_finalize $STMT]
          435  +} {{0 0} {1 0} SQLITE_OK}
   374    436   
   375    437   
   376    438   finish_test
   377    439   
   378    440   
   379    441