1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Work toward more flexible typing for keys and values.

FossilOrigin-Name: 5c79f53131a7ab3c83f49e35a5021a6cdb2518fc
This commit is contained in:
drh
2015-11-19 19:27:07 +00:00
parent a87cc18948
commit c83ef77bb9
3 changed files with 196 additions and 74 deletions

View File

@@ -83,12 +83,21 @@ static int lsm1Connect(
} }
/* Column numbers */ /* Column numbers */
#define LSM1_COLUMN_KEY 0 #define LSM1_COLUMN_KEY 0
#define LSM1_COLUMN_VALUE 1 #define LSM1_COLUMN_BLOBKEY 1
#define LSM1_COLUMN_COMMAND 2 #define LSM1_COLUMN_VALUE 2
#define LSM1_COLUMN_BLOBVALUE 3
#define LSM1_COLUMN_COMMAND 4
rc = sqlite3_declare_vtab(db, rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(key,value,command hidden)"); "CREATE TABLE x("
" key," /* The primary key. Any non-NULL */
" blobkey," /* Pure BLOB primary key */
" value," /* The value associated with key. Any non-NULL */
" blobvalue," /* Pure BLOB value */
" command hidden" /* Insert here for control operations */
");"
);
connect_failed: connect_failed:
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
if( pNew ){ if( pNew ){
@@ -173,6 +182,72 @@ static int lsm1Eof(sqlite3_vtab_cursor *cur){
return pCur->atEof; return pCur->atEof;
} }
/*
** Rowids are not supported by the underlying virtual table. So always
** return 0 for the rowid.
*/
static int lsm1Rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
*pRowid = 0;
return SQLITE_OK;
}
/*
** Type prefixes on LSM keys
*/
#define LSM1_TYPE_NEGATIVE 0
#define LSM1_TYPE_POSITIVE 1
#define LSM1_TYPE_TEXT 2
#define LSM1_TYPE_BLOB 3
/*
** Generate a key encoding for pValue such that all keys compare in
** lexicographical order. Return an SQLite error code or SQLITE_OK.
**
** The key encoding is *pnKey bytes in length written into *ppKey.
** Space to hold the key is taken from pSpace if sufficient, or else
** from sqlite3_malloc(). The caller is responsible for freeing malloced
** space.
*/
static int lsm1EncodeKey(
sqlite3_value *pValue, /* Value to be encoded */
unsigned char **ppKey, /* Write the encoding here */
int *pnKey, /* Write the size of the encoding here */
unsigned char *pSpace, /* Use this space if it is large enough */
int nSpace /* Size of pSpace[] */
){
int eType = sqlite3_value_type(pValue);
*ppKey = 0;
*pnKey = 0;
switch( eType ){
default: {
return SQLITE_ERROR; /* We cannot handle NULL keys */
}
case SQLITE_BLOB:
case SQLITE_TEXT: {
int nVal = sqlite3_value_bytes(pValue);
const void *pVal;
if( eType==SQLITE_BLOB ){
eType = LSM1_TYPE_BLOB;
pVal = sqlite3_value_blob(pValue);
}else{
eType = LSM1_TYPE_TEXT;
pVal = (const void*)sqlite3_value_text(pValue);
if( pVal==0 ) return SQLITE_NOMEM;
}
if( nVal+1>nSpace ){
pSpace = sqlite3_malloc( nVal+1 );
if( pSpace==0 ) return SQLITE_NOMEM;
}
pSpace[0] = eType;
memcpy(&pSpace[1], pVal, nVal);
*ppKey = pSpace;
*pnKey = nVal+1;
break;
}
}
return SQLITE_OK;
}
/* /*
** Return values of columns for the row at which the lsm1_cursor ** Return values of columns for the row at which the lsm1_cursor
** is currently pointing. ** is currently pointing.
@@ -184,10 +259,34 @@ static int lsm1Column(
){ ){
lsm1_cursor *pCur = (lsm1_cursor*)cur; lsm1_cursor *pCur = (lsm1_cursor*)cur;
switch( i ){ switch( i ){
case LSM1_COLUMN_KEY: { case LSM1_COLUMN_BLOBKEY: {
const void *pVal; const void *pVal;
int nVal; int nVal;
if( lsm_csr_key(pCur->pLsmCur, (const void**)&pVal, &nVal)==LSM_OK ){ if( lsm_csr_key(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
}
break;
}
case LSM1_COLUMN_KEY: {
const unsigned char *pVal;
int nVal;
if( lsm_csr_key(pCur->pLsmCur, (const void**)&pVal, &nVal)==LSM_OK
&& nVal>=1
){
if( pVal[0]==LSM1_TYPE_BLOB ){
sqlite3_result_blob(ctx, (const void*)&pVal[1],nVal-1,
SQLITE_TRANSIENT);
}else if( pVal[0]==LSM1_TYPE_TEXT ){
sqlite3_result_text(ctx, (const char*)&pVal[1],nVal-1,
SQLITE_TRANSIENT);
}
}
break;
}
case LSM1_COLUMN_BLOBVALUE: {
const void *pVal;
int nVal;
if( lsm_csr_value(pCur->pLsmCur, (const void**)&pVal, &nVal)==LSM_OK ){
sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT); sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
} }
break; break;
@@ -203,7 +302,7 @@ static int lsm1Column(
case SQLITE_INTEGER: { case SQLITE_INTEGER: {
sqlite3_uint64 x = 0; sqlite3_uint64 x = 0;
int j; int j;
for(j=1; j<=8; j++){ for(j=1; j<nVal; j++){
x = (x<<8) | aVal[j]; x = (x<<8) | aVal[j];
} }
if( aVal[0]==SQLITE_INTEGER ){ if( aVal[0]==SQLITE_INTEGER ){
@@ -232,15 +331,6 @@ static int lsm1Column(
return SQLITE_OK; return SQLITE_OK;
} }
/*
** Rowids are not supported by the underlying virtual table. So always
** return 0 for the rowid.
*/
static int lsm1Rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
*pRowid = 0;
return SQLITE_OK;
}
/* Move to the first row to return. /* Move to the first row to return.
*/ */
static int lsm1Filter( static int lsm1Filter(
@@ -275,9 +365,27 @@ static int lsm1Filter(
** Only comparisons against the key are allowed. The idxNum defines ** Only comparisons against the key are allowed. The idxNum defines
** which comparisons are available: ** which comparisons are available:
** **
** 0 Full table scan only ** 0 Full table scan only
** 1 key==? single argument for ? ** bit 1 key==?1 single argument for ?1
** ** bit 2 key>?1
** bit 3 key>=?1
** bit 4 key<?N (N==1 if bits 2,3 clear, or 2 if bits2,3 set)
** bit 5 key<=?N (N==1 if bits 2,3 clear, or 2 if bits2,3 set)
** bit 6 Use blobkey instead of key
**
** To put it another way:
**
** 0 Full table scan.
** 1 key==?1
** 2 key>?1
** 4 key>=?1
** 8 key<?1
** 10 key>?1 AND key<?2
** 12 key>=?1 AND key<?2
** 16 key<=?1
** 18 key>?1 AND key<=?2
** 20 key>=?1 AND key<=?2
** 33..52 Use blobkey in place of key...
*/ */
static int lsm1BestIndex( static int lsm1BestIndex(
sqlite3_vtab *tab, sqlite3_vtab *tab,
@@ -337,6 +445,11 @@ int lsm1Update(
int eType; int eType;
int rc; int rc;
sqlite3_value *pValue; sqlite3_value *pValue;
const unsigned char *pVal;
unsigned char *pData;
int nVal;
unsigned char pSpace[100];
if( argc==1 ){ if( argc==1 ){
pVTab->zErrMsg = sqlite3_mprintf("cannot DELETE"); pVTab->zErrMsg = sqlite3_mprintf("cannot DELETE");
return SQLITE_ERROR; return SQLITE_ERROR;
@@ -352,60 +465,69 @@ int lsm1Update(
if( sqlite3_value_type(argv[2+LSM1_COLUMN_COMMAND])!=SQLITE_NULL ){ if( sqlite3_value_type(argv[2+LSM1_COLUMN_COMMAND])!=SQLITE_NULL ){
return SQLITE_OK; return SQLITE_OK;
} }
if( sqlite3_value_type(argv[2+LSM1_COLUMN_KEY])!=SQLITE_BLOB ){ if( sqlite3_value_type(argv[2+LSM1_COLUMN_BLOBKEY])==SQLITE_BLOB ){
pVTab->zErrMsg = sqlite3_mprintf("BLOB keys only"); /* Use the blob key exactly as supplied */
return SQLITE_ERROR; pKey = sqlite3_value_blob(argv[2+LSM1_COLUMN_BLOBKEY]);
nKey = sqlite3_value_bytes(argv[2+LSM1_COLUMN_BLOBKEY]);
}else{
/* Use a key encoding that sorts in lexicographical order */
rc = lsm1EncodeKey(argv[2+LSM1_COLUMN_KEY],
(unsigned char**)&pKey,&nKey,
pSpace,sizeof(pSpace));
if( rc ) return rc;
} }
pKey = sqlite3_value_blob(argv[2+LSM1_COLUMN_KEY]); if( sqlite3_value_type(argv[2+LSM1_COLUMN_BLOBVALUE])==SQLITE_BLOB ){
nKey = sqlite3_value_bytes(argv[2+LSM1_COLUMN_KEY]); pVal = sqlite3_value_blob(argv[2+LSM1_COLUMN_BLOBVALUE]);
pValue = argv[2+LSM1_COLUMN_VALUE]; nVal = sqlite3_value_bytes(argv[2+LSM1_COLUMN_BLOBVALUE]);
eType = sqlite3_value_type(pValue); rc = lsm_insert(p->pDb, pKey, nKey, pVal, nVal);
switch( eType ){ }else{
case SQLITE_NULL: { pValue = argv[2+LSM1_COLUMN_VALUE];
rc = lsm_delete(p->pDb, pKey, nKey); eType = sqlite3_value_type(pValue);
break; switch( eType ){
} case SQLITE_NULL: {
case SQLITE_BLOB: rc = lsm_delete(p->pDb, pKey, nKey);
case SQLITE_TEXT: { break;
const unsigned char *pVal;
unsigned char *pData;
int nVal;
if( eType==SQLITE_TEXT ){
pVal = sqlite3_value_text(pValue);
}else{
pVal = (unsigned char*)sqlite3_value_blob(pValue);
} }
nVal = sqlite3_value_bytes(pValue); case SQLITE_BLOB:
pData = sqlite3_malloc( nVal+1 ); case SQLITE_TEXT: {
if( pData==0 ){ if( eType==SQLITE_TEXT ){
rc = SQLITE_NOMEM; pVal = sqlite3_value_text(pValue);
}else{ }else{
pData[0] = eType; pVal = (unsigned char*)sqlite3_value_blob(pValue);
memcpy(&pData[1], pVal, nVal); }
rc = lsm_insert(p->pDb, pKey, nKey, pData, nVal+1); nVal = sqlite3_value_bytes(pValue);
sqlite3_free(pData); pData = sqlite3_malloc( nVal+1 );
if( pData==0 ){
rc = SQLITE_NOMEM;
}else{
pData[0] = eType;
memcpy(&pData[1], pVal, nVal);
rc = lsm_insert(p->pDb, pKey, nKey, pData, nVal+1);
sqlite3_free(pData);
}
break;
} }
break; case SQLITE_INTEGER:
} case SQLITE_FLOAT: {
case SQLITE_INTEGER: sqlite3_uint64 x;
case SQLITE_FLOAT: { unsigned char aVal[9];
sqlite3_uint64 x; int i;
unsigned char aVal[9]; if( eType==SQLITE_INTEGER ){
int i; *(sqlite3_int64*)&x = sqlite3_value_int64(pValue);
if( eType==SQLITE_INTEGER ){ }else{
*(sqlite3_int64*)&x = sqlite3_value_int64(pValue); *(double*)&x = sqlite3_value_double(pValue);
}else{ }
*(double*)&x = sqlite3_value_double(pValue); for(i=8; x>0 && i>=1; i--){
aVal[i] = x & 0xff;
x >>= 8;
}
aVal[i] = eType;
rc = lsm_insert(p->pDb, pKey, nKey, &aVal[i], 9-i);
break;
} }
for(i=8; i>=1; i--){
aVal[i] = x & 0xff;
x >>= 8;
}
aVal[0] = eType;
rc = lsm_insert(p->pDb, pKey, nKey, aVal, 9);
break;
} }
} }
if( pKey!=(const void*)pSpace ) sqlite3_free((void*)pKey);
return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR; return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
} }

View File

@@ -1,5 +1,5 @@
C Basic\sfunctionality\sis\snow\sworking. C Work\stoward\smore\sflexible\styping\sfor\skeys\sand\svalues.
D 2015-11-17T02:23:09.421 D 2015-11-19T19:27:07.806
F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc e928e68168df69b353300ac87c10105206653a03 F Makefile.msc e928e68168df69b353300ac87c10105206653a03
@@ -205,7 +205,7 @@ F ext/lsm1/lsm_str.c 77ebdd5040ddf267a6f724d4c83132d2dce8a226
F ext/lsm1/lsm_tree.c 5d9fb2bc58a1a70c75126bd8d7198f7b627e165b F ext/lsm1/lsm_tree.c 5d9fb2bc58a1a70c75126bd8d7198f7b627e165b
F ext/lsm1/lsm_unix.c fcaf5b6738713f1229dc0e1a90393ecf24f787f2 F ext/lsm1/lsm_unix.c fcaf5b6738713f1229dc0e1a90393ecf24f787f2
F ext/lsm1/lsm_varint.c b19ae9bd26b5a1e8402fb8a564b25d9542338a41 F ext/lsm1/lsm_varint.c b19ae9bd26b5a1e8402fb8a564b25d9542338a41
F ext/lsm1/lsm_vtab.c 1ffcc9bfbf4fc46ba8c6b3734309781a35c7d1e9 F ext/lsm1/lsm_vtab.c 37be4d5928de455f752fdd8108ea1e6cd06ce6e0
F ext/misc/amatch.c a1a8f66c29d40bd71b075546ddeddb477b17a2bb F ext/misc/amatch.c a1a8f66c29d40bd71b075546ddeddb477b17a2bb
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704 F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83 F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
@@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P a32849d6bf66462d1f511714a00f24519d7b7079 P aa129c51ecf5c917cfac30be330886f8a10f49e1
R cc1cce61ea394db14460eb0001eb1ea8 R 0be85f8175b37708c20cac5856fe94dc
U drh U drh
Z 05fa355531114cffc58ad422946d5107 Z 35d0ab7ac6da941b099070286c057861

View File

@@ -1 +1 @@
aa129c51ecf5c917cfac30be330886f8a10f49e1 5c79f53131a7ab3c83f49e35a5021a6cdb2518fc