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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
manifest
12
manifest
@@ -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
|
||||||
|
@@ -1 +1 @@
|
|||||||
aa129c51ecf5c917cfac30be330886f8a10f49e1
|
5c79f53131a7ab3c83f49e35a5021a6cdb2518fc
|
Reference in New Issue
Block a user