/ Check-in [313df946]
Login

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

Overview
Comment:Work toward redesigning the interface to the LSM1 virtual table.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 313df946668b943b0a9a9a91fd7bafa7212d05765c7714fa6c0de46aa9062a74
User & Date: drh 2017-08-09 18:40:35
Context
2017-08-09
19:27
Various bug fixes for the new LSM1 virtual table design. check-in: 94434a25 user: drh tags: trunk
18:40
Work toward redesigning the interface to the LSM1 virtual table. check-in: 313df946 user: drh tags: trunk
2017-08-08
21:40
The identifier "vsnprintf" appears to be a reserved word in recent versions of XCode, so avoid using it as a structure field. check-in: 795eede3 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/lsm1/lsm_vtab.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   **
    13     13   ** This file implements a simple virtual table wrapper around the LSM
    14     14   ** storage engine from SQLite4.
           15  +**
           16  +** USAGE
           17  +**
           18  +**   CREATE VIRTUAL TABLE demo USING lsm1(filename,key,keytype,value1,...);
           19  +**
           20  +** The keytype must be one of: UINT, TEXT, BLOB.  All keys must be of that
           21  +** one type.  "UINT" means unsigned integer.  The values may be any
           22  +** SQLite datatype.
           23  +**
           24  +** INTERNALS
           25  +**
           26  +** The key encoding for BLOB and TEXT is just a copy of the blob or text.
           27  +** UTF-8 is used for text.  The key encoding for UINT is the variable-length
           28  +** integer format at https://sqlite.org/src4/doc/trunk/www/varint.wiki.
           29  +**
           30  +** The values are encoded as a single blob (since that is what lsm stores as
           31  +** its content).  There is a "type integer" followed by "content" for each
           32  +** value, alternating back and forth.  The content might be empty.
           33  +**
           34  +**    TYPE1  CONTENT1  TYPE2  CONTENT2  TYPE3  CONTENT3 ....
           35  +**
           36  +** Each "type integer" is encoded as a variable-length integer in the
           37  +** format of the link above.  Let the type integer be T.  The actual
           38  +** datatype is an integer 0-5 equal to T%6.  Values 1 through 5 correspond
           39  +** to SQLITE_INTEGER through SQLITE_NULL.  The size of the content in bytes
           40  +** is T/6.  Type value 0 means that the value is an integer whose actual
           41  +** values is T/6 and there is no content.  The type-value-0 integer format
           42  +** only works for integers in the range of 0 through 40.
           43  +**
           44  +** There is no content for NULL or type-0 integers.  For BLOB and TEXT
           45  +** values, the content is the blob data or the UTF-8 text data.  For
           46  +** non-negative integers X, the content is a variable-length integer X*2.
           47  +** For negative integers Y, the content is varaible-length integer (1-Y)*2+1.
           48  +** For FLOAT values, the content is the variable length encoding of the
           49  +** integer with the same bit pattern as the IEEE754 floating point value.
    15     50   */
    16     51   #include "sqlite3ext.h"
    17     52   SQLITE_EXTENSION_INIT1
    18     53   #include "lsm.h"
    19     54   #include <assert.h>
    20     55   #include <string.h>
    21     56   
    22     57   /* Forward declaration of subclasses of virtual table objects */
    23     58   typedef struct lsm1_vtab lsm1_vtab;
    24     59   typedef struct lsm1_cursor lsm1_cursor;
           60  +typedef struct lsm1_vblob lsm1_vblob;
    25     61   
    26     62   /* Primitive types */
    27     63   typedef unsigned char u8;
           64  +typedef unsigned int u32;
           65  +typedef sqlite3_uint64 u64;
    28     66   
    29     67   /* An open connection to an LSM table */
    30     68   struct lsm1_vtab {
    31     69     sqlite3_vtab base;          /* Base class - must be first */
    32     70     lsm_db *pDb;                /* Open connection to the LSM table */
           71  +  u8 keyType;                 /* SQLITE_BLOB, _TEXT, or _INTEGER */
           72  +  u32 nVal;                   /* Number of value columns */
    33     73   };
    34     74   
    35     75   
    36     76   /* lsm1_cursor is a subclass of sqlite3_vtab_cursor which will
    37     77   ** serve as the underlying representation of a cursor that scans
    38     78   ** over rows of the result
    39     79   */
    40     80   struct lsm1_cursor {
    41     81     sqlite3_vtab_cursor base;  /* Base class - must be first */
    42     82     lsm_cursor *pLsmCur;       /* The LSM cursor */
    43     83     u8 isDesc;                 /* 0: scan forward.  1: scan reverse */
    44     84     u8 atEof;                  /* True if the scan is complete */
    45     85     u8 bUnique;                /* True if no more than one row of output */
           86  +  u8 *zData;                 /* Content of the current row */
           87  +  u32 nData;                 /* Number of bytes in the current row */
           88  +  u8 *aeType;                /* Types for all column values */
           89  +  u32 *aiOfst;               /* Offsets to the various fields */
           90  +  u32 *aiLen;                /* Length of each field */
           91  +  u8 *pKey2;                 /* Loop termination key, or NULL */
           92  +  u32 nKey2;                 /* Length of the loop termination key */
           93  +};
           94  +
           95  +/* An extensible buffer object.
           96  +**
           97  +** Content can be appended.  Space to hold new content is automatically
           98  +** allocated.
           99  +*/
          100  +struct lsm1_vblob {
          101  +  u8 *a;             /* Space to hold content, from sqlite3_malloc64() */
          102  +  u64 n;             /* Bytes of space used */
          103  +  u64 nAlloc;        /* Bytes of space allocated */
          104  +  u8 errNoMem;       /* True if a memory allocation error has been seen */
    46    105   };
          106  +
          107  +#if defined(__GNUC__)
          108  +#  define LSM1_NOINLINE  __attribute__((noinline))
          109  +#elif defined(_MSC_VER) && _MSC_VER>=1310
          110  +#  define LSM1_NOINLINE  __declspec(noinline)
          111  +#else
          112  +#  define LSM1_NOINLINE
          113  +#endif
          114  +
          115  +
          116  +/* Increase the available space in the vblob object so that it can hold
          117  +** at least N more bytes.  Return the number of errors.
          118  +*/
          119  +static int lsm1VblobEnlarge(lsm1_vblob *p, u32 N){
          120  +  if( p->n+N>p->nAlloc ){
          121  +    if( p->errNoMem ) return 1;
          122  +    p->nAlloc += N + (p->nAlloc ? p->nAlloc : N);
          123  +    p->a = sqlite3_realloc64(p->a, p->nAlloc);
          124  +    if( p->a==0 ){
          125  +      p->n = 0;
          126  +      p->nAlloc = 0;
          127  +      p->errNoMem = 1;
          128  +      return 1;
          129  +    }
          130  +    p->nAlloc = sqlite3_msize(p->a);
          131  +  }
          132  +  return 0;
          133  +}
          134  +
          135  +/* Append N bytes to a vblob after first enlarging it */
          136  +static LSM1_NOINLINE void lsm1VblobEnlargeAndAppend(
          137  +  lsm1_vblob *p,
          138  +  const u8 *pData,
          139  +  u32 N
          140  +){
          141  +  if( p->n+N>p->nAlloc && lsm1VblobEnlarge(p, N) ) return;
          142  +  memcpy(p->a+p->n, pData, N);
          143  +  p->n += N;
          144  +}
          145  +
          146  +/* Append N bytes to a vblob */
          147  +static void lsm1VblobAppend(lsm1_vblob *p, const u8 *pData, u32 N){
          148  +  sqlite3_int64 n = p->n;
          149  +  if( n+N>p->nAlloc ){
          150  +    lsm1VblobEnlargeAndAppend(p, pData, N);
          151  +  }else{
          152  +    p->n += N;
          153  +    memcpy(p->a+n, pData, N);
          154  +  }
          155  +}
          156  +
          157  +/* append text to a vblob */
          158  +static void lsm1VblobAppendText(lsm1_vblob *p, const char *z){
          159  +  lsm1VblobAppend(p, (u8*)z, (u32)strlen(z));
          160  +}
    47    161   
    48    162   /* Dequote the string */
    49    163   static void lsm1Dequote(char *z){
    50    164     int j;
    51    165     char cQuote = z[0];
    52    166     size_t i, n;
    53    167   
................................................................................
    72    186     int argc, const char *const*argv,
    73    187     sqlite3_vtab **ppVtab,
    74    188     char **pzErr
    75    189   ){
    76    190     lsm1_vtab *pNew;
    77    191     int rc;
    78    192     char *zFilename;
          193  +  u8 keyType = 0;
          194  +  int i;
          195  +  lsm1_vblob sql;
          196  +  static const char *azTypes[] = { "UINT",         "TEXT",     "BLOB" };
          197  +  static const u8 aeTypes[] =    { SQLITE_INTEGER, SQLITE_TEXT, SQLITE_BLOB };
          198  +  static const char *azArgName[] = {"filename", "key", "key type", "value1" };
    79    199   
    80         -  if( argc!=4 || argv[3]==0 || argv[3][0]==0 ){
    81         -    *pzErr = sqlite3_mprintf("filename argument missing");
          200  +  for(i=0; i<sizeof(azArgName)/sizeof(azArgName[0]); i++){
          201  +    if( argc<i+4 || argv[i+3]==0 || argv[i+3][0]==0 ){
          202  +      *pzErr = sqlite3_mprintf("%s (%r) argument missing",
          203  +                               azArgName[i], i+1);
          204  +      return SQLITE_ERROR;
          205  +    }
          206  +  }
          207  +  for(i=0; i<sizeof(azTypes)/sizeof(azTypes[0]); i++){
          208  +    if( sqlite3_stricmp(azTypes[i],argv[5])==0 ){
          209  +      keyType = aeTypes[i];
          210  +      break;
          211  +    }
          212  +  }
          213  +  if( keyType==0 ){
          214  +    *pzErr = sqlite3_mprintf("key type should be INT, TEXT, or BLOB");
    82    215       return SQLITE_ERROR;
    83    216     }
    84    217     *ppVtab = sqlite3_malloc( sizeof(*pNew) );
    85    218     pNew = (lsm1_vtab*)*ppVtab;
    86    219     if( pNew==0 ){
    87    220       return SQLITE_NOMEM;
    88    221     }
    89    222     memset(pNew, 0, sizeof(*pNew));
          223  +  pNew->keyType = keyType;
    90    224     rc = lsm_new(0, &pNew->pDb);
    91    225     if( rc ){
    92    226       *pzErr = sqlite3_mprintf("lsm_new failed with error code %d",  rc);
    93    227       rc = SQLITE_ERROR;
    94    228       goto connect_failed;
    95    229     }
    96    230     zFilename = sqlite3_mprintf("%s", argv[3]);
................................................................................
    99    233     sqlite3_free(zFilename);
   100    234     if( rc ){
   101    235       *pzErr = sqlite3_mprintf("lsm_open failed with %d", rc);
   102    236       rc = SQLITE_ERROR;
   103    237       goto connect_failed;
   104    238     }
   105    239   
   106         -/* Column numbers */
   107         -#define LSM1_COLUMN_KEY         0
   108         -#define LSM1_COLUMN_BLOBKEY     1
   109         -#define LSM1_COLUMN_VALUE       2
   110         -#define LSM1_COLUMN_BLOBVALUE   3
   111         -#define LSM1_COLUMN_COMMAND     4
          240  +  memset(&sql, 0, sizeof(sql));
          241  +  lsm1VblobAppendText(&sql, "CREATE TABLE x(");
          242  +  lsm1VblobAppendText(&sql, argv[4]);
          243  +  lsm1VblobAppendText(&sql, " ");
          244  +  lsm1VblobAppendText(&sql, argv[5]);
          245  +  for(i=6; i<argc; i++){
          246  +    lsm1VblobAppendText(&sql, ", ");
          247  +    lsm1VblobAppendText(&sql, argv[i]);
          248  +    pNew->nVal++;
          249  +  }
          250  +  lsm1VblobAppendText(&sql, 
          251  +      ", lsm1_command HIDDEN, lsm1_key HIDDEN, lsm1_value HIDDEN)");
          252  +  lsm1VblobAppend(&sql, (u8*)"", 1);
          253  +  if( sql.errNoMem ){
          254  +    rc = SQLITE_NOMEM;
          255  +    goto connect_failed;
          256  +  }
          257  +  rc = sqlite3_declare_vtab(db, (const char*)sql.a);
          258  +  sqlite3_free(sql.a);
   112    259   
   113         -  rc = sqlite3_declare_vtab(db,
   114         -     "CREATE TABLE x("
   115         -     "  key,"              /* The primary key.  Any non-NULL */
   116         -     "  blobkey,"          /* Pure BLOB primary key */
   117         -     "  value,"            /* The value associated with key.  Any non-NULL */
   118         -     "  blobvalue,"        /* Pure BLOB value */
   119         -     "  command hidden"    /* Insert here for control operations */
   120         -     ");"
   121         -  );
   122    260   connect_failed:
   123    261     if( rc!=SQLITE_OK ){
   124    262       if( pNew ){
   125    263         if( pNew->pDb ) lsm_close(pNew->pDb);
   126    264         sqlite3_free(pNew);
   127    265       }
   128    266       *ppVtab = 0;
................................................................................
   143    281   /*
   144    282   ** Constructor for a new lsm1_cursor object.
   145    283   */
   146    284   static int lsm1Open(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
   147    285     lsm1_vtab *p = (lsm1_vtab*)pVtab;
   148    286     lsm1_cursor *pCur;
   149    287     int rc;
   150         -  pCur = sqlite3_malloc( sizeof(*pCur) );
          288  +  pCur = sqlite3_malloc64( sizeof(*pCur)
          289  +                 + p->nVal*(sizeof(pCur->aiOfst)+sizeof(pCur->aiLen)+1) );
   151    290     if( pCur==0 ) return SQLITE_NOMEM;
   152    291     memset(pCur, 0, sizeof(*pCur));
          292  +  pCur->aiOfst = (u32*)&pCur[1];
          293  +  pCur->aiLen = &pCur->aiOfst[p->nVal];
          294  +  pCur->aeType = (u8*)&pCur->aiLen[p->nVal];
   153    295     *ppCursor = &pCur->base;
   154    296     rc = lsm_csr_open(p->pDb, &pCur->pLsmCur);
   155    297     if( rc==LSM_OK ){
   156    298       rc = SQLITE_OK;
   157    299     }else{
   158    300       sqlite3_free(pCur);
   159    301       *ppCursor = 0;
................................................................................
   163    305   }
   164    306   
   165    307   /*
   166    308   ** Destructor for a lsm1_cursor.
   167    309   */
   168    310   static int lsm1Close(sqlite3_vtab_cursor *cur){
   169    311     lsm1_cursor *pCur = (lsm1_cursor*)cur;
          312  +  sqlite3_free(pCur->pKey2);
   170    313     lsm_csr_close(pCur->pLsmCur);
   171    314     sqlite3_free(pCur);
   172    315     return SQLITE_OK;
   173    316   }
   174    317   
   175    318   
   176    319   /*
................................................................................
   186    329         rc = lsm_csr_prev(pCur->pLsmCur);
   187    330       }else{
   188    331         rc = lsm_csr_next(pCur->pLsmCur);
   189    332       }
   190    333       if( rc==LSM_OK && lsm_csr_valid(pCur->pLsmCur)==0 ){
   191    334         pCur->atEof = 1;
   192    335       }
          336  +    if( pCur->pKey2 && pCur->atEof==0 ){
          337  +      const u8 *pVal;
          338  +      u32 nVal;
          339  +      assert( pCur->isDesc==0 );
          340  +      rc = lsm_csr_key(pCur->pLsmCur, (const void**)&pVal, (int*)&nVal);
          341  +      if( rc==LSM_OK ){
          342  +        u32 len = pCur->nKey2;
          343  +        int c;
          344  +        if( len>nVal ) len = nVal;
          345  +        c = memcmp(pVal, pCur->pKey2, len);
          346  +        if( c==0 ) c = nVal - pCur->nKey2;
          347  +        if( c>0 ) pCur->atEof = 1;
          348  +      }
          349  +    }
          350  +    pCur->zData = 0;
   193    351     }
   194    352     return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
   195    353   }
   196    354   
   197    355   /*
   198    356   ** Return TRUE if the cursor has been moved off of the last
   199    357   ** row of output.
................................................................................
   290    448       return 8;
   291    449     }
   292    450     z[0] = 255;
   293    451     varintWrite32(z+1, w);
   294    452     varintWrite32(z+5, y);
   295    453     return 9;
   296    454   }
          455  +
          456  +/* Append non-negative integer x as a variable-length integer.
          457  +*/
          458  +static void lsm1VblobAppendVarint(lsm1_vblob *p, sqlite3_uint64 x){
          459  +  sqlite3_int64 n = p->n;
          460  +  if( n+9>p->nAlloc && lsm1VblobEnlarge(p, 9) ) return;
          461  +  p->n += lsm1PutVarint64(p->a+p->n, x);
          462  +}
   297    463   
   298    464   /*
   299    465   ** Decode the varint in the first n bytes z[].  Write the integer value
   300    466   ** into *pResult and return the number of bytes in the varint.
   301    467   **
   302    468   ** If the decode fails because there are not enough bytes in z[] then
   303    469   ** return 0;
................................................................................
   345    511       return 8;
   346    512     }
   347    513     *pResult = (((sqlite3_uint64)x)<<32) +
   348    514                  (0xffffffff & ((z[5]<<24) + (z[6]<<16) + (z[7]<<8) + z[8]));
   349    515     return 9;
   350    516   }
   351    517   
   352         -/*
   353         -** Generate a key encoding for pValue such that all keys compare in
   354         -** lexicographical order.  Return an SQLite error code or SQLITE_OK.
          518  +/* Encoded a signed integer as a varint.  Numbers close to zero uses fewer
          519  +** bytes than numbers far away from zero.  However, the result is not in
          520  +** lexicographical order.
   355    521   **
   356         -** The key encoding is *pnKey bytes in length written into *ppKey.
   357         -** Space to hold the key is taken from pSpace if sufficient, or else
   358         -** from sqlite3_malloc().  The caller is responsible for freeing malloced
   359         -** space.
          522  +** Encoding:  Non-negative integer X is encoding as an unsigned
          523  +** varint X*2.  Negative integer Y is encoding as an unsigned
          524  +** varint (1-Y)*2 + 1.
   360    525   */
   361         -static int lsm1EncodeKey(
   362         -  sqlite3_value *pValue,     /* Value to be encoded */
   363         -  unsigned char **ppKey,     /* Write the encoding here */
   364         -  int *pnKey,                /* Write the size of the encoding here */
   365         -  unsigned char *pSpace,     /* Use this space if it is large enough */
   366         -  int nSpace                 /* Size of pSpace[] */
          526  +static int lsm1PutSignedVarint64(u8 *z, sqlite3_int64 v){
          527  +  sqlite3_uint64 u;
          528  +  if( v>=0 ){
          529  +    u = (sqlite3_uint64)v;
          530  +    return lsm1PutVarint64(z, u*2);
          531  +  }else{
          532  +    u = (sqlite3_uint64)(1-v);
          533  +    return lsm1PutVarint64(z, u*2+1);
          534  +  }
          535  +}
          536  +
          537  +/* Decoded a signed varint. */
          538  +static int lsm1GetSignedVarint64(
          539  +  const unsigned char *z,
          540  +  int n,
          541  +  sqlite3_int64 *pResult
   367    542   ){
   368         -  int eType = sqlite3_value_type(pValue);
   369         -  *ppKey = 0;
   370         -  *pnKey = 0;
   371         -  assert( nSpace>=32 );
   372         -  switch( eType ){
   373         -    default: {
   374         -      return SQLITE_ERROR;  /* We cannot handle NULL keys */
   375         -    }
   376         -    case SQLITE_BLOB:
   377         -    case SQLITE_TEXT: {
   378         -      int nVal = sqlite3_value_bytes(pValue);
   379         -      const void *pVal;
   380         -      if( eType==SQLITE_BLOB ){
   381         -        eType = LSM1_TYPE_BLOB;
   382         -        pVal = sqlite3_value_blob(pValue);
   383         -      }else{
   384         -        eType = LSM1_TYPE_TEXT;
   385         -        pVal = (const void*)sqlite3_value_text(pValue);
   386         -        if( pVal==0 ) return SQLITE_NOMEM;
   387         -      }
   388         -      if( nVal+1>nSpace ){
   389         -        pSpace = sqlite3_malloc( nVal+1 );
   390         -        if( pSpace==0 ) return SQLITE_NOMEM;
   391         -      }
   392         -      pSpace[0] = (unsigned char)eType;
   393         -      memcpy(&pSpace[1], pVal, nVal);
   394         -      *ppKey = pSpace;
   395         -      *pnKey = nVal+1;
   396         -      break;
   397         -    }
   398         -    case SQLITE_INTEGER: {
   399         -      sqlite3_int64 iVal = sqlite3_value_int64(pValue);
   400         -      sqlite3_uint64 uVal;
   401         -      if( iVal<0 ){
   402         -        if( iVal==0xffffffffffffffffLL ) return SQLITE_ERROR;
   403         -        uVal = *(sqlite3_uint64*)&iVal;
   404         -        eType = LSM1_TYPE_NEGATIVE;
   405         -      }else{
   406         -        uVal = iVal;
   407         -        eType = LSM1_TYPE_POSITIVE;
   408         -      }
   409         -      pSpace[0] = (unsigned char)eType;
   410         -      *ppKey = pSpace;
   411         -      *pnKey = 1 + lsm1PutVarint64(&pSpace[1], uVal);
   412         -    }
   413         -  }
   414         -  return SQLITE_OK;
          543  +  sqlite3_uint64 u = 0;
          544  +  n = lsm1GetVarint64(z, n, &u);
          545  +  if( u&1 ){
          546  +    *pResult = -1 - (sqlite3_int64)(u>>1);
          547  +  }else{
          548  +    *pResult = (sqlite3_int64)(u>>1);
          549  +  }
          550  +  return n;
          551  +}
          552  +
          553  +
          554  +/*
          555  +** Read the value part of the key-value pair and decode it into columns.
          556  +*/
          557  +static int lsm1DecodeValues(lsm1_cursor *pCur){
          558  +  lsm1_vtab *pTab = (lsm1_vtab*)(pCur->base.pVtab);
          559  +  int i, n;
          560  +  int rc;
          561  +  u8 eType;
          562  +  sqlite3_uint64 v;
          563  +
          564  +  if( pCur->zData ) return 1;
          565  +  rc = lsm_csr_value(pCur->pLsmCur, (const void**)&pCur->zData,
          566  +                     (int*)&pCur->nData);
          567  +  if( rc ) return 0;
          568  +  for(i=n=0; i<pTab->nVal; i++){
          569  +    v = 0;
          570  +    n += lsm1GetVarint64(pCur->zData+n, pCur->nData-n, &v);
          571  +    pCur->aeType[i] = eType = (u8)(v%6);
          572  +    if( eType==0 ){
          573  +      pCur->aiOfst[i] = (u32)(v/6);
          574  +      pCur->aiLen[i] = 0;
          575  +    }else{ 
          576  +      pCur->aiOfst[i] = n;
          577  +      n += (pCur->aiLen[i] = (u32)(v/6));
          578  +    }
          579  +    if( n>pCur->nData ) break;
          580  +  }
          581  +  if( i<pTab->nVal ){
          582  +    pCur->zData = 0;
          583  +    return 0;
          584  +  }
          585  +  return 1;
   415    586   }
   416    587   
   417    588   /*
   418    589   ** Return values of columns for the row at which the lsm1_cursor
   419    590   ** is currently pointing.
   420    591   */
   421    592   static int lsm1Column(
   422    593     sqlite3_vtab_cursor *cur,   /* The cursor */
   423    594     sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
   424    595     int i                       /* Which column to return */
   425    596   ){
   426    597     lsm1_cursor *pCur = (lsm1_cursor*)cur;
   427         -  switch( i ){
   428         -    case LSM1_COLUMN_BLOBKEY: {
          598  +  lsm1_vtab *pTab = (lsm1_vtab*)(cur->pVtab);
          599  +  if( i==0 ){
          600  +    /* The key column */
          601  +    const void *pVal;
          602  +    int nVal;
          603  +    if( lsm_csr_key(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
          604  +      if( pTab->keyType==SQLITE_BLOB ){
          605  +        sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
          606  +      }else if( pTab->keyType==SQLITE_TEXT ){
          607  +        sqlite3_result_text(ctx,(const char*)pVal, nVal, SQLITE_TRANSIENT);
          608  +      }else{
          609  +        const unsigned char *z = (const unsigned char*)pVal;
          610  +        sqlite3_uint64 v1;
          611  +        lsm1GetVarint64(z, nVal, &v1);
          612  +        sqlite3_result_int64(ctx, (sqlite3_int64)v1);
          613  +      }
          614  +    }
          615  +  }else if( i>pTab->nVal ){
          616  +    if( i==pTab->nVal+2 ){  /* lsm1_key */
   429    617         const void *pVal;
   430    618         int nVal;
   431    619         if( lsm_csr_key(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
   432    620           sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
   433    621         }
   434         -      break;
   435         -    }
   436         -    case LSM1_COLUMN_KEY: {
   437         -      const unsigned char *pVal;
   438         -      int nVal;
   439         -      if( lsm_csr_key(pCur->pLsmCur, (const void**)&pVal, &nVal)==LSM_OK
   440         -       && nVal>=1
   441         -      ){
   442         -        if( pVal[0]==LSM1_TYPE_BLOB ){
   443         -          sqlite3_result_blob(ctx, (const void*)&pVal[1],nVal-1,
   444         -                              SQLITE_TRANSIENT);
   445         -        }else if( pVal[0]==LSM1_TYPE_TEXT ){
   446         -          sqlite3_result_text(ctx, (const char*)&pVal[1],nVal-1,
   447         -                              SQLITE_TRANSIENT);
   448         -        }else if( nVal>=2 && nVal<=10 &&
   449         -           (pVal[0]==LSM1_TYPE_POSITIVE || pVal[0]==LSM1_TYPE_NEGATIVE)
   450         -        ){
   451         -          sqlite3_int64 iVal;
   452         -          lsm1GetVarint64(pVal+1, nVal-1, (sqlite3_uint64*)&iVal);
   453         -          sqlite3_result_int64(ctx, iVal);
   454         -        }         
   455         -      }
   456         -      break;
   457         -    }
   458         -    case LSM1_COLUMN_BLOBVALUE: {
          622  +    }else if( i==pTab->nVal+3 ){  /* lsm1_value */
   459    623         const void *pVal;
   460    624         int nVal;
   461         -      if( lsm_csr_value(pCur->pLsmCur, (const void**)&pVal, &nVal)==LSM_OK ){
          625  +      if( lsm_csr_value(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
   462    626           sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
   463    627         }
   464         -      break;
   465    628       }
   466         -    case LSM1_COLUMN_VALUE: {
   467         -      const unsigned char *aVal;
   468         -      int nVal;
   469         -      if( lsm_csr_value(pCur->pLsmCur, (const void**)&aVal, &nVal)==LSM_OK
   470         -          && nVal>=1
   471         -      ){
   472         -        switch( aVal[0] ){
   473         -          case SQLITE_FLOAT:
   474         -          case SQLITE_INTEGER: {
   475         -            sqlite3_uint64 x = 0;
   476         -            int j;
   477         -            for(j=1; j<nVal; j++){
   478         -              x = (x<<8) | aVal[j];
   479         -            }
   480         -            if( aVal[0]==SQLITE_INTEGER ){
   481         -              sqlite3_result_int64(ctx, *(sqlite3_int64*)&x);
   482         -            }else{
   483         -              double r;
   484         -              assert( sizeof(r)==sizeof(x) );
   485         -              memcpy(&r, &x, sizeof(r));
   486         -              sqlite3_result_double(ctx, r);
   487         -            }
   488         -            break;
   489         -          }
   490         -          case SQLITE_TEXT: {
   491         -            sqlite3_result_text(ctx, (char*)&aVal[1], nVal-1, SQLITE_TRANSIENT);
   492         -            break;
   493         -          }
   494         -          case SQLITE_BLOB: {
   495         -            sqlite3_result_blob(ctx, &aVal[1], nVal-1, SQLITE_TRANSIENT);
   496         -            break;
   497         -          }
   498         -        }
   499         -      }
   500         -      break;
   501         -    }
   502         -    default: {
   503         -      break;
          629  +  }else if( lsm1DecodeValues(pCur) ){
          630  +    /* The i-th value column (where leftmost is 1) */
          631  +    const u8 *zData;
          632  +    u32 nData;
          633  +    i--;
          634  +    zData = pCur->zData + pCur->aiOfst[i];
          635  +    nData = pCur->aiLen[i];
          636  +    switch( pCur->aeType[i] ){
          637  +      case 0: {  /* in-line integer */
          638  +        sqlite3_result_int(ctx, pCur->aiOfst[i]);
          639  +        break;
          640  +      }
          641  +      case SQLITE_INTEGER: {
          642  +        sqlite3_int64 v;
          643  +        lsm1GetSignedVarint64(zData, nData, &v);
          644  +        sqlite3_result_int64(ctx, v);
          645  +        break;
          646  +      }
          647  +      case SQLITE_FLOAT: {
          648  +        sqlite3_uint64 v1 = 0;
          649  +        double v;
          650  +        lsm1GetVarint64(zData, nData, &v1);
          651  +        memcpy(&v, &v1, sizeof(v));
          652  +        sqlite3_result_double(ctx, v);
          653  +        break;
          654  +      }
          655  +      case SQLITE_TEXT: {
          656  +        sqlite3_result_text(ctx, (const char*)zData, nData, SQLITE_TRANSIENT);
          657  +      }
          658  +      case SQLITE_BLOB: {
          659  +        sqlite3_result_blob(ctx, zData, nData, SQLITE_TRANSIENT);
          660  +      }
          661  +      default: {
          662  +         /* A NULL.  Do nothing */
          663  +      }
   504    664       }
   505    665     }
   506    666     return SQLITE_OK;
   507    667   }
   508    668   
   509    669   /* Move to the first row to return.
   510    670   */
   511    671   static int lsm1Filter(
   512    672     sqlite3_vtab_cursor *pVtabCursor, 
   513    673     int idxNum, const char *idxStr,
   514    674     int argc, sqlite3_value **argv
   515    675   ){
   516    676     lsm1_cursor *pCur = (lsm1_cursor *)pVtabCursor;
          677  +  lsm1_vtab *pTab = (lsm1_vtab*)(pCur->base.pVtab);
   517    678     int rc = LSM_OK;
          679  +  int seekType = -1;
          680  +  const void *pVal = 0;
          681  +  int nVal;
          682  +  u8 keyType = pTab->keyType;
          683  +  u8 aKey1[16];
          684  +
   518    685     pCur->atEof = 1;
   519         -  if( idxNum==1 ){
   520         -    assert( argc==1 );
   521         -    pCur->isDesc = 0;
   522         -    pCur->bUnique = 1;
   523         -    if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
   524         -      const void *pVal = sqlite3_value_blob(argv[0]);
   525         -      int nVal = sqlite3_value_bytes(argv[0]);
   526         -      rc = lsm_csr_seek(pCur->pLsmCur, pVal, nVal, LSM_SEEK_EQ);
          686  +  sqlite3_free(pCur->pKey2);
          687  +  pCur->pKey2 = 0;
          688  +  if( idxNum<99 ){
          689  +    if( keyType==SQLITE_BLOB ){
          690  +      pVal = sqlite3_value_blob(argv[0]);
          691  +      nVal = sqlite3_value_bytes(argv[0]);
          692  +    }else if( keyType==SQLITE_TEXT ){
          693  +      pVal = sqlite3_value_text(argv[0]);
          694  +      nVal = sqlite3_value_bytes(argv[0]);
          695  +    }else{
          696  +      sqlite3_int64 v = sqlite3_value_int64(argv[0]);
          697  +      if( v<0 ) v = 0;
          698  +      nVal = lsm1PutVarint64(aKey1, v);
          699  +      pVal = aKey1;
          700  +    }
          701  +  }
          702  +  switch( idxNum ){
          703  +    case 0: {   /* key==argv[0] */
          704  +      assert( argc==1 );
          705  +      seekType = LSM_SEEK_EQ;
          706  +      pCur->isDesc = 0;
          707  +      pCur->bUnique = 1;
          708  +      break;
          709  +    }
          710  +    case 1: {  /* key>=argv[0] AND key<=argv[1] */
          711  +      u8 aKey[12];
          712  +      seekType = LSM_SEEK_GE;
          713  +      pCur->isDesc = 0;
          714  +      pCur->bUnique = 0;
          715  +      if( keyType==SQLITE_INTEGER ){
          716  +        sqlite3_int64 v = sqlite3_value_int64(argv[1]);
          717  +        if( v<0 ) v = 0;
          718  +        pCur->nKey2 = lsm1PutVarint64(aKey, (sqlite3_uint64)v);
          719  +        pCur->pKey2 = sqlite3_malloc( pCur->nKey2 );
          720  +        if( pCur->pKey2==0 ) return SQLITE_NOMEM;
          721  +        memcpy(pCur->pKey2, aKey, pCur->nKey2);
          722  +      }else{
          723  +        pCur->nKey2 = sqlite3_value_bytes(argv[1]);
          724  +        pCur->pKey2 = sqlite3_malloc( pCur->nKey2 );
          725  +        if( pCur->pKey2==0 ) return SQLITE_NOMEM;
          726  +        if( keyType==SQLITE_BLOB ){
          727  +          memcpy(pCur->pKey2, sqlite3_value_blob(argv[1]), pCur->nKey2);
          728  +        }else{
          729  +          memcpy(pCur->pKey2, sqlite3_value_text(argv[1]), pCur->nKey2);
          730  +        }
          731  +      }
          732  +      break;
          733  +    }
          734  +    case 2: {  /* key>=argv[0] */
          735  +      seekType = LSM_SEEK_GE;
          736  +      pCur->isDesc = 0;
          737  +      pCur->bUnique = 0;
          738  +      break;
          739  +    }
          740  +    case 3: {  /* key<=argv[0] */
          741  +      seekType = LSM_SEEK_LE;
          742  +      pCur->isDesc = 1;
          743  +      pCur->bUnique = 0;
          744  +      break;
          745  +    }
          746  +    default: { /* full table scan */
          747  +      pCur->isDesc = 0;
          748  +      pCur->bUnique = 0;
          749  +      break;
   527    750       }
          751  +  }
          752  +  if( pVal ){
          753  +    rc = lsm_csr_seek(pCur->pLsmCur, pVal, nVal, seekType);
   528    754     }else{
   529    755       rc = lsm_csr_first(pCur->pLsmCur);
   530         -    pCur->isDesc = 0;
   531         -    pCur->bUnique = 0;
   532    756     }
   533    757     if( rc==LSM_OK && lsm_csr_valid(pCur->pLsmCur)!=0 ){
   534    758       pCur->atEof = 0;
   535    759     }
   536    760     return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
   537    761   }
   538    762   
   539    763   /*
   540    764   ** Only comparisons against the key are allowed.  The idxNum defines
   541    765   ** which comparisons are available:
   542    766   **
   543         -**     0        Full table scan only
   544         -**   bit 1      key==?1  single argument for ?1
   545         -**   bit 2      key>?1
   546         -**   bit 3      key>=?1
   547         -**   bit 4      key<?N   (N==1 if bits 2,3 clear, or 2 if bits2,3 set)
   548         -**   bit 5      key<=?N  (N==1 if bits 2,3 clear, or 2 if bits2,3 set)
   549         -**   bit 6      Use blobkey instead of key
   550         -**
   551         -** To put it another way:
   552         -**
   553         -**     0        Full table scan.
   554         -**     1        key==?1
   555         -**     2        key>?1
   556         -**     4        key>=?1
   557         -**     8        key<?1
   558         -**     10       key>?1 AND key<?2
   559         -**     12       key>=?1 AND key<?2
   560         -**     16       key<=?1
   561         -**     18       key>?1 AND key<=?2
   562         -**     20       key>=?1 AND key<=?2
   563         -**     33..52   Use blobkey in place of key...
          767  +**     0        key==?1
          768  +**     1        key>=?1 AND key<=?2
          769  +**     2        key>?1 or key>=?1
          770  +**     3        key<?1 or key<=?1
          771  +**    99        Full table scan only
   564    772   */
   565    773   static int lsm1BestIndex(
   566    774     sqlite3_vtab *tab,
   567    775     sqlite3_index_info *pIdxInfo
   568    776   ){
   569    777     int i;                 /* Loop over constraints */
   570         -  int idxNum = 0;        /* The query plan bitmask */
          778  +  int idxNum = 99;       /* The query plan */
   571    779     int nArg = 0;          /* Number of arguments to xFilter */
   572         -  int eqIdx = -1;        /* Index of the key== constraint, or -1 if none */
          780  +  int argIdx = -1;       /* Index of the key== constraint, or -1 if none */
          781  +  int iIdx2 = -1;        /* The index of the second key */
          782  +  int omit1 = 0;
          783  +  int omit2 = 0;
   573    784   
   574    785     const struct sqlite3_index_constraint *pConstraint;
   575    786     pConstraint = pIdxInfo->aConstraint;
   576    787     for(i=0; i<pIdxInfo->nConstraint && idxNum<16; i++, pConstraint++){
   577    788       if( pConstraint->usable==0 ) continue;
   578         -    if( pConstraint->iColumn!=LSM1_COLUMN_KEY ) continue;
   579         -    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
          789  +    if( pConstraint->iColumn!=0 ) continue;
   580    790       switch( pConstraint->op ){
   581    791         case SQLITE_INDEX_CONSTRAINT_EQ: {
   582         -        eqIdx = i;
   583         -        idxNum = 1;
          792  +        if( idxNum>0 ){
          793  +          argIdx = i;
          794  +          iIdx2 = -1;
          795  +          idxNum = 0;
          796  +          omit1 = 1;
          797  +        }
          798  +        break;
          799  +      }
          800  +      case SQLITE_INDEX_CONSTRAINT_GE:
          801  +      case SQLITE_INDEX_CONSTRAINT_GT: {
          802  +        if( idxNum==99 ){
          803  +          argIdx = i;
          804  +          idxNum = 2;
          805  +          omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE;
          806  +        }else if( idxNum==3 ){
          807  +          iIdx2 = idxNum;
          808  +          omit2 = omit1;
          809  +          argIdx = i;
          810  +          idxNum = 1;
          811  +          omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE;
          812  +        }
          813  +        break;
          814  +      }
          815  +      case SQLITE_INDEX_CONSTRAINT_LE:
          816  +      case SQLITE_INDEX_CONSTRAINT_LT: {
          817  +        if( idxNum==99 ){
          818  +          argIdx = i;
          819  +          idxNum = 3;
          820  +          omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE;
          821  +        }else if( idxNum==2 ){
          822  +          iIdx2 = i;
          823  +          idxNum = 1;
          824  +          omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE;
          825  +        }
   584    826           break;
   585    827         }
   586    828       }
   587    829     }
   588         -  if( eqIdx>=0 ){
   589         -    pIdxInfo->aConstraintUsage[eqIdx].argvIndex = ++nArg;
   590         -    pIdxInfo->aConstraintUsage[eqIdx].omit = 1;
          830  +  if( argIdx>=0 ){
          831  +    pIdxInfo->aConstraintUsage[argIdx].argvIndex = ++nArg;
          832  +    pIdxInfo->aConstraintUsage[argIdx].omit = omit1;
          833  +  }
          834  +  if( iIdx2>=0 ){
          835  +    pIdxInfo->aConstraintUsage[iIdx2].argvIndex = ++nArg;
          836  +    pIdxInfo->aConstraintUsage[iIdx2].omit = omit2;
   591    837     }
   592         -  if( idxNum==1 ){
          838  +  if( idxNum==0 ){
   593    839       pIdxInfo->estimatedCost = (double)1;
   594    840       pIdxInfo->estimatedRows = 1;
   595    841       pIdxInfo->orderByConsumed = 1;
          842  +  }else if( idxNum==1 ){
          843  +    pIdxInfo->estimatedCost = (double)100;
          844  +    pIdxInfo->estimatedRows = 100;
          845  +  }else if( idxNum<99 ){
          846  +    pIdxInfo->estimatedCost = (double)5000;
          847  +    pIdxInfo->estimatedRows = 5000;
   596    848     }else{
   597    849       /* Full table scan */
   598    850       pIdxInfo->estimatedCost = (double)2147483647;
   599    851       pIdxInfo->estimatedRows = 2147483647;
   600    852     }
   601    853     pIdxInfo->idxNum = idxNum;
   602    854     return SQLITE_OK;
................................................................................
   611    863   int lsm1Update(
   612    864     sqlite3_vtab *pVTab,
   613    865     int argc,
   614    866     sqlite3_value **argv,
   615    867     sqlite_int64 *pRowid
   616    868   ){
   617    869     lsm1_vtab *p = (lsm1_vtab*)pVTab;
   618         -  const void *pKey;
   619         -  void *pFree = 0;
   620    870     int nKey;
   621         -  int eType;
          871  +  int i;
   622    872     int rc = LSM_OK;
   623         -  sqlite3_value *pValue;
   624         -  const unsigned char *pVal;
   625         -  unsigned char *pData;
   626         -  int nVal;
   627         -  unsigned char pSpace[100];
          873  +  unsigned char *pKey;
          874  +  unsigned char aKey[16];
          875  +  unsigned char pSpace[16];
          876  +  lsm1_vblob val;
   628    877   
   629    878     if( argc==1 ){
   630    879       pVTab->zErrMsg = sqlite3_mprintf("cannot DELETE");
   631    880       return SQLITE_ERROR;
   632    881     }
   633    882     if( sqlite3_value_type(argv[0])!=SQLITE_NULL ){
   634    883       pVTab->zErrMsg = sqlite3_mprintf("cannot UPDATE");
   635    884       return SQLITE_ERROR;
   636    885     }
   637    886   
   638         -  /* "INSERT INTO tab(command) VALUES('....')" is used to implement
          887  +  /* "INSERT INTO tab(lsm1_command) VALUES('....')" is used to implement
   639    888     ** special commands.
   640    889     */
   641         -  if( sqlite3_value_type(argv[2+LSM1_COLUMN_COMMAND])!=SQLITE_NULL ){
          890  +  if( sqlite3_value_type(argv[3+p->nVal])!=SQLITE_NULL ){
   642    891       return SQLITE_OK;
   643    892     }
   644         -  if( sqlite3_value_type(argv[2+LSM1_COLUMN_BLOBKEY])==SQLITE_BLOB ){
   645         -    /* Use the blob key exactly as supplied */
   646         -    pKey = sqlite3_value_blob(argv[2+LSM1_COLUMN_BLOBKEY]);
   647         -    nKey = sqlite3_value_bytes(argv[2+LSM1_COLUMN_BLOBKEY]);
          893  +  if( p->keyType==SQLITE_BLOB ){
          894  +    pKey = (u8*)sqlite3_value_blob(argv[2]);
          895  +    nKey = sqlite3_value_bytes(argv[2]);
          896  +  }else if( p->keyType==SQLITE_TEXT ){
          897  +    pKey = (u8*)sqlite3_value_text(argv[2]);
          898  +    nKey = sqlite3_value_bytes(argv[2]);
   648    899     }else{
   649         -    /* Use a key encoding that sorts in lexicographical order */
   650         -    rc = lsm1EncodeKey(argv[2+LSM1_COLUMN_KEY],
   651         -                       (unsigned char**)&pKey,&nKey,
   652         -                       pSpace,sizeof(pSpace));
   653         -    if( rc ) return rc;
   654         -    if( pKey!=(const void*)pSpace ) pFree = (void*)pKey;
          900  +    sqlite3_int64 v = sqlite3_value_int64(argv[2]);
          901  +    if( v>=0 ){
          902  +      nKey = lsm1PutVarint64(aKey, (sqlite3_uint64)v);
          903  +      pKey = aKey;
          904  +    }else{
          905  +      pVTab->zErrMsg = sqlite3_mprintf("key must be non-negative");
          906  +      return SQLITE_ERROR;
          907  +    }
   655    908     }
   656         -  if( sqlite3_value_type(argv[2+LSM1_COLUMN_BLOBVALUE])==SQLITE_BLOB ){
   657         -    pVal = sqlite3_value_blob(argv[2+LSM1_COLUMN_BLOBVALUE]);
   658         -    nVal = sqlite3_value_bytes(argv[2+LSM1_COLUMN_BLOBVALUE]);
   659         -    rc = lsm_insert(p->pDb, pKey, nKey, pVal, nVal);
   660         -  }else{
   661         -    pValue = argv[2+LSM1_COLUMN_VALUE];
   662         -    eType = sqlite3_value_type(pValue);
          909  +  memset(&val, 0, sizeof(val));
          910  +  for(i=0; i<p->nVal; i++){
          911  +    u8 eType = sqlite3_value_type(argv[3+i]);
   663    912       switch( eType ){
   664    913         case SQLITE_NULL: {
   665         -        rc = lsm_delete(p->pDb, pKey, nKey);
          914  +        lsm1VblobAppendVarint(&val, SQLITE_NULL);
   666    915           break;
   667    916         }
   668         -      case SQLITE_BLOB:
   669         -      case SQLITE_TEXT: {
   670         -        if( eType==SQLITE_TEXT ){
   671         -          pVal = sqlite3_value_text(pValue);
          917  +      case SQLITE_INTEGER: {
          918  +        sqlite3_int64 v = sqlite3_value_int64(argv[3+i]);
          919  +        if( v>=0 && v<=240/6 ){
          920  +          lsm1VblobAppendVarint(&val, v*6);
   672    921           }else{
   673         -          pVal = (unsigned char*)sqlite3_value_blob(pValue);
   674         -        }
   675         -        nVal = sqlite3_value_bytes(pValue);
   676         -        pData = sqlite3_malloc( nVal+1 );
   677         -        if( pData==0 ){
   678         -          rc = SQLITE_NOMEM;
   679         -        }else{
   680         -          pData[0] = (unsigned char)eType;
   681         -          memcpy(&pData[1], pVal, nVal);
   682         -          rc = lsm_insert(p->pDb, pKey, nKey, pData, nVal+1);
   683         -          sqlite3_free(pData);
          922  +          int n = lsm1PutSignedVarint64(pSpace, v);
          923  +          lsm1VblobAppendVarint(&val, SQLITE_INTEGER + n*6);
          924  +          lsm1VblobAppend(&val, pSpace, n);
   684    925           }
   685    926           break;
   686    927         }
   687         -      case SQLITE_INTEGER:
   688    928         case SQLITE_FLOAT: {
   689         -        sqlite3_uint64 x;
   690         -        unsigned char aVal[9];
   691         -        int i;
   692         -        if( eType==SQLITE_INTEGER ){
   693         -          *(sqlite3_int64*)&x = sqlite3_value_int64(pValue);
   694         -        }else{
   695         -          double r = sqlite3_value_double(pValue);
   696         -          assert( sizeof(r)==sizeof(x) );
   697         -          memcpy(&x, &r, sizeof(r));
   698         -        }
   699         -        for(i=8; x>0 && i>=1; i--){
   700         -          aVal[i] = x & 0xff;
   701         -          x >>= 8;
   702         -        }
   703         -        aVal[i] = (unsigned char)eType;
   704         -        rc = lsm_insert(p->pDb, pKey, nKey, &aVal[i], 9-i);
          929  +        double r = sqlite3_value_double(argv[3+i]);
          930  +        sqlite3_uint64 u;
          931  +        int n;
          932  +        memcpy(&u, &r, 8);
          933  +        n = lsm1PutSignedVarint64(pSpace, u);
          934  +        lsm1VblobAppendVarint(&val, SQLITE_FLOAT + n*6);
          935  +        lsm1VblobAppend(&val, pSpace, n);
          936  +        break;
          937  +      }
          938  +      case SQLITE_BLOB: {
          939  +        int n = sqlite3_value_bytes(argv[3+i]);
          940  +        lsm1VblobAppendVarint(&val, n*6 + SQLITE_BLOB);
          941  +        lsm1VblobAppend(&val, sqlite3_value_blob(argv[2+i]), n);
          942  +        break;
          943  +      }
          944  +      case SQLITE_TEXT: {
          945  +        int n = sqlite3_value_bytes(argv[3+i]);
          946  +        lsm1VblobAppendVarint(&val, n*6 + SQLITE_TEXT);
          947  +        lsm1VblobAppend(&val, sqlite3_value_text(argv[2+i]), n);
   705    948           break;
   706    949         }
   707    950       }
   708    951     }
   709         -  sqlite3_free(pFree);
          952  +  if( val.errNoMem ){
          953  +    return SQLITE_NOMEM;
          954  +  }
          955  +  rc = lsm_insert(p->pDb, pKey, nKey, val.a, val.n);
          956  +  sqlite3_free(val.a);
   710    957     return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
   711    958   }      
   712    959   
   713    960   /* Begin a transaction
   714    961   */
   715    962   static int lsm1Begin(sqlite3_vtab *pVtab){
   716    963     lsm1_vtab *p = (lsm1_vtab*)pVtab;

Changes to ext/lsm1/test/lsm1_simple.test.

    16     16   set testprefix lsm1_simple
    17     17   return_if_no_lsm1
    18     18   load_lsm1_vtab db
    19     19   
    20     20   forcedelete testlsm.db
    21     21   
    22     22   do_execsql_test 1.0 {
    23         -  CREATE VIRTUAL TABLE x1 USING lsm1(testlsm.db);
           23  +  CREATE VIRTUAL TABLE x1 USING lsm1(testlsm.db,a,UINT,b,c,d);
    24     24     PRAGMA table_info(x1);
    25     25   } {
    26         -  0 key       {} 0 {} 0 
    27         -  1 blobkey   {} 0 {} 0 
    28         -  2 value     {} 0 {} 0 
    29         -  3 blobvalue {} 0 {} 0
           26  +  0 a UINT 0 {} 0 
           27  +  1 b {} 0 {} 0 
           28  +  2 c {} 0 {} 0 
           29  +  3 d {} 0 {} 0
    30     30   }
    31     31   
    32     32   do_execsql_test 1.1 {
    33         -  INSERT INTO x1(blobkey, blobvalue) VALUES(x'abcd', x'1234');
    34         -  SELECT quote(blobkey), quote(blobvalue) FROM x1;
    35         -} {X'ABCD' X'1234'}
           33  +  INSERT INTO x1(a,b,c,d) VALUES(15, 11, 22, 33);
           34  +  SELECT * FROM x1;
           35  +} {15 11 22 33}
    36     36   
    37     37   do_catchsql_test 1.2 {
    38         -  UPDATE x1 SET blobvalue = x'7890' WHERE blobkey = x'abcd';
           38  +  UPDATE x1 SET d = d+1.0 WHERE a=15;
    39     39   } {1 {cannot UPDATE}}
    40     40   
    41     41   do_catchsql_test 1.3 {
    42         -  DELETE FROM x1 WHERE blobkey = x'abcd'
           42  +  DELETE FROM x1 WHERE a=15;
    43     43   } {1 {cannot DELETE}}
    44     44   
    45     45   do_test 1.4 {
    46     46     lsort [glob testlsm.db*]
    47     47   } {testlsm.db testlsm.db-log testlsm.db-shm}
    48     48   
    49     49   db close
    50     50   do_test 1.5 {
    51     51     lsort [glob testlsm.db*]
    52     52   } {testlsm.db}
    53     53   
    54     54   finish_test
    55         -
    56         -