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

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

Overview
Comment:Add support for (variable length) integer keys in LSM1.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | lsm-vtab
Files: files | file ages | folders
SHA1: 32f3daec0a8084b258b2513c8025bc4d95a5d757
User & Date: drh 2016-02-23 01:37:24
Context
2016-02-23
01:41
Merge trunk enhancements. check-in: fac4f4ec user: drh tags: lsm-vtab
01:37
Add support for (variable length) integer keys in LSM1. check-in: 32f3daec user: drh tags: lsm-vtab
2016-02-22
13:01
Merge up to trunk. check-in: f9e5fb88 user: drh tags: lsm-vtab
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/lsm1/lsm_vtab.c.

   194    194   /*
   195    195   ** Type prefixes on LSM keys
   196    196   */
   197    197   #define LSM1_TYPE_NEGATIVE   0
   198    198   #define LSM1_TYPE_POSITIVE   1
   199    199   #define LSM1_TYPE_TEXT       2
   200    200   #define LSM1_TYPE_BLOB       3
          201  +
          202  +/*
          203  +** Write a 32-bit unsigned integer as 4 big-endian bytes.
          204  +*/
          205  +static void varintWrite32(unsigned char *z, unsigned int y){
          206  +  z[0] = (unsigned char)(y>>24);
          207  +  z[1] = (unsigned char)(y>>16);
          208  +  z[2] = (unsigned char)(y>>8);
          209  +  z[3] = (unsigned char)(y);
          210  +}
          211  +
          212  +/*
          213  +** Write a varint into z[].  The buffer z[] must be at least 9 characters
          214  +** long to accommodate the largest possible varint.  Return the number of
          215  +** bytes of z[] used.
          216  +*/
          217  +static int lsm1PutVarint64(unsigned char *z, sqlite3_uint64 x){
          218  +  unsigned int w, y;
          219  +  if( x<=240 ){
          220  +    z[0] = (unsigned char)x;
          221  +    return 1;
          222  +  }
          223  +  if( x<=2287 ){
          224  +    y = (unsigned int)(x - 240);
          225  +    z[0] = (unsigned char)(y/256 + 241);
          226  +    z[1] = (unsigned char)(y%256);
          227  +    return 2;
          228  +  }
          229  +  if( x<=67823 ){
          230  +    y = (unsigned int)(x - 2288);
          231  +    z[0] = 249;
          232  +    z[1] = (unsigned char)(y/256);
          233  +    z[2] = (unsigned char)(y%256);
          234  +    return 3;
          235  +  }
          236  +  y = (unsigned int)x;
          237  +  w = (unsigned int)(x>>32);
          238  +  if( w==0 ){
          239  +    if( y<=16777215 ){
          240  +      z[0] = 250;
          241  +      z[1] = (unsigned char)(y>>16);
          242  +      z[2] = (unsigned char)(y>>8);
          243  +      z[3] = (unsigned char)(y);
          244  +      return 4;
          245  +    }
          246  +    z[0] = 251;
          247  +    varintWrite32(z+1, y);
          248  +    return 5;
          249  +  }
          250  +  if( w<=255 ){
          251  +    z[0] = 252;
          252  +    z[1] = (unsigned char)w;
          253  +    varintWrite32(z+2, y);
          254  +    return 6;
          255  +  }
          256  +  if( w<=65535 ){
          257  +    z[0] = 253;
          258  +    z[1] = (unsigned char)(w>>8);
          259  +    z[2] = (unsigned char)w;
          260  +    varintWrite32(z+3, y);
          261  +    return 7;
          262  +  }
          263  +  if( w<=16777215 ){
          264  +    z[0] = 254;
          265  +    z[1] = (unsigned char)(w>>16);
          266  +    z[2] = (unsigned char)(w>>8);
          267  +    z[3] = (unsigned char)w;
          268  +    varintWrite32(z+4, y);
          269  +    return 8;
          270  +  }
          271  +  z[0] = 255;
          272  +  varintWrite32(z+1, w);
          273  +  varintWrite32(z+5, y);
          274  +  return 9;
          275  +}
          276  +
          277  +/*
          278  +** Decode the varint in the first n bytes z[].  Write the integer value
          279  +** into *pResult and return the number of bytes in the varint.
          280  +**
          281  +** If the decode fails because there are not enough bytes in z[] then
          282  +** return 0;
          283  +*/
          284  +static int lsm1GetVarint64(
          285  +  const unsigned char *z,
          286  +  int n,
          287  +  sqlite3_uint64 *pResult
          288  +){
          289  +  unsigned int x;
          290  +  if( n<1 ) return 0;
          291  +  if( z[0]<=240 ){
          292  +    *pResult = z[0];
          293  +    return 1;
          294  +  }
          295  +  if( z[0]<=248 ){
          296  +    if( n<2 ) return 0;
          297  +    *pResult = (z[0]-241)*256 + z[1] + 240;
          298  +    return 2;
          299  +  }
          300  +  if( n<z[0]-246 ) return 0;
          301  +  if( z[0]==249 ){
          302  +    *pResult = 2288 + 256*z[1] + z[2];
          303  +    return 3;
          304  +  }
          305  +  if( z[0]==250 ){
          306  +    *pResult = (z[1]<<16) + (z[2]<<8) + z[3];
          307  +    return 4;
          308  +  }
          309  +  x = (z[1]<<24) + (z[2]<<16) + (z[3]<<8) + z[4];
          310  +  if( z[0]==251 ){
          311  +    *pResult = x;
          312  +    return 5;
          313  +  }
          314  +  if( z[0]==252 ){
          315  +    *pResult = (((sqlite3_uint64)x)<<8) + z[5];
          316  +    return 6;
          317  +  }
          318  +  if( z[0]==253 ){
          319  +    *pResult = (((sqlite3_uint64)x)<<16) + (z[5]<<8) + z[6];
          320  +    return 7;
          321  +  }
          322  +  if( z[0]==254 ){
          323  +    *pResult = (((sqlite3_uint64)x)<<24) + (z[5]<<16) + (z[6]<<8) + z[7];
          324  +    return 8;
          325  +  }
          326  +  *pResult = (((sqlite3_uint64)x)<<32) +
          327  +               (0xffffffff & ((z[5]<<24) + (z[6]<<16) + (z[7]<<8) + z[8]));
          328  +  return 9;
          329  +}
   201    330   
   202    331   /*
   203    332   ** Generate a key encoding for pValue such that all keys compare in
   204    333   ** lexicographical order.  Return an SQLite error code or SQLITE_OK.
   205    334   **
   206    335   ** The key encoding is *pnKey bytes in length written into *ppKey.
   207    336   ** Space to hold the key is taken from pSpace if sufficient, or else
................................................................................
   214    343     int *pnKey,                /* Write the size of the encoding here */
   215    344     unsigned char *pSpace,     /* Use this space if it is large enough */
   216    345     int nSpace                 /* Size of pSpace[] */
   217    346   ){
   218    347     int eType = sqlite3_value_type(pValue);
   219    348     *ppKey = 0;
   220    349     *pnKey = 0;
          350  +  assert( nSpace>=32 );
   221    351     switch( eType ){
   222    352       default: {
   223    353         return SQLITE_ERROR;  /* We cannot handle NULL keys */
   224    354       }
   225    355       case SQLITE_BLOB:
   226    356       case SQLITE_TEXT: {
   227    357         int nVal = sqlite3_value_bytes(pValue);
................................................................................
   240    370         }
   241    371         pSpace[0] = eType;
   242    372         memcpy(&pSpace[1], pVal, nVal);
   243    373         *ppKey = pSpace;
   244    374         *pnKey = nVal+1;
   245    375         break;
   246    376       }
          377  +    case SQLITE_INTEGER: {
          378  +      sqlite3_int64 iVal = sqlite3_value_int64(pValue);
          379  +      sqlite3_uint64 uVal;
          380  +      if( iVal<0 ){
          381  +        if( iVal==0xffffffffffffffffLL ) return SQLITE_ERROR;
          382  +        uVal = -iVal;
          383  +        eType = LSM1_TYPE_NEGATIVE;
          384  +      }else{
          385  +        uVal = iVal;
          386  +        eType = LSM1_TYPE_POSITIVE;
          387  +      }
          388  +      pSpace[0] = eType;
          389  +      *ppKey = pSpace;
          390  +      *pnKey = 1 + lsm1PutVarint64(&pSpace[1], uVal);
          391  +    }
   247    392     }
   248    393     return SQLITE_OK;
   249    394   }
   250    395   
   251    396   /*
   252    397   ** Return values of columns for the row at which the lsm1_cursor
   253    398   ** is currently pointing.
................................................................................
   275    420         ){
   276    421           if( pVal[0]==LSM1_TYPE_BLOB ){
   277    422             sqlite3_result_blob(ctx, (const void*)&pVal[1],nVal-1,
   278    423                                 SQLITE_TRANSIENT);
   279    424           }else if( pVal[0]==LSM1_TYPE_TEXT ){
   280    425             sqlite3_result_text(ctx, (const char*)&pVal[1],nVal-1,
   281    426                                 SQLITE_TRANSIENT);
   282         -        }
          427  +        }else if( nVal>=2 && nVal<=9 &&
          428  +           (pVal[0]==LSM1_TYPE_POSITIVE || pVal[0]==LSM1_TYPE_NEGATIVE)
          429  +        ){
          430  +          sqlite3_uint64 uVal = 0;
          431  +          lsm1GetVarint64(pVal+1, nVal-1, &uVal);
          432  +          if( pVal[0]==LSM1_TYPE_NEGATIVE ){
          433  +            sqlite3_result_int64(ctx, -(sqlite3_int64)uVal);
          434  +          }else{
          435  +            sqlite3_result_int64(ctx, (sqlite3_int64)uVal); 
          436  +          }
          437  +        }         
   283    438         }
   284    439         break;
   285    440       }
   286    441       case LSM1_COLUMN_BLOBVALUE: {
   287    442         const void *pVal;
   288    443         int nVal;
   289    444         if( lsm_csr_value(pCur->pLsmCur, (const void**)&pVal, &nVal)==LSM_OK ){