diff options
Diffstat (limited to 'ext/misc')
-rw-r--r-- | ext/misc/fileio.c | 2 | ||||
-rw-r--r-- | ext/misc/vtablog.c | 55 | ||||
-rw-r--r-- | ext/misc/zipfile.c | 22 | ||||
-rw-r--r-- | ext/misc/zorder.c | 60 |
4 files changed, 119 insertions, 20 deletions
diff --git a/ext/misc/fileio.c b/ext/misc/fileio.c index 01d9c220f..22d61df61 100644 --- a/ext/misc/fileio.c +++ b/ext/misc/fileio.c @@ -899,9 +899,9 @@ static int fsdirFilter( ){ const char *zDir = 0; fsdir_cursor *pCur = (fsdir_cursor*)cur; + int i; (void)idxStr; fsdirResetCursor(pCur); - int i; if( idxNum==0 ){ fsdirSetErrmsg(pCur, "table function fsdir requires an argument"); diff --git a/ext/misc/vtablog.c b/ext/misc/vtablog.c index e8f084e1b..44acc32e6 100644 --- a/ext/misc/vtablog.c +++ b/ext/misc/vtablog.c @@ -14,6 +14,13 @@ ** on stdout when its key interfaces are called. This is intended for ** interactive analysis and debugging of virtual table interfaces. ** +** To build this extension as a separately loaded shared library or +** DLL, use compiler command-lines similar to the following: +** +** (linux) gcc -fPIC -shared vtablog.c -o vtablog.so +** (mac) clang -fPIC -dynamiclib vtablog.c -o vtablog.dylib +** (windows) cl vtablog.c -link -dll -out:vtablog.dll +** ** Usage example: ** ** .load ./vtablog @@ -436,6 +443,39 @@ static int vtablogFilter( } /* +** Return an sqlite3_index_info operator name in static space. +** The name is possibly overwritten on subsequent calls. +*/ +static char *vtablogOpName(unsigned char op){ + static char zUnknown[30]; + char *zOut; + switch( op ){ + case SQLITE_INDEX_CONSTRAINT_EQ: zOut = "EQ"; break; + case SQLITE_INDEX_CONSTRAINT_GT: zOut = "GT"; break; + case SQLITE_INDEX_CONSTRAINT_LE: zOut = "LE"; break; + case SQLITE_INDEX_CONSTRAINT_LT: zOut = "LT"; break; + case SQLITE_INDEX_CONSTRAINT_GE: zOut = "GE"; break; + case SQLITE_INDEX_CONSTRAINT_MATCH: zOut = "MATCH"; break; + case SQLITE_INDEX_CONSTRAINT_LIKE: zOut = "LIKE"; break; + case SQLITE_INDEX_CONSTRAINT_GLOB: zOut = "GLOB"; break; + case SQLITE_INDEX_CONSTRAINT_REGEXP: zOut = "REGEXP"; break; + case SQLITE_INDEX_CONSTRAINT_NE: zOut = "NE"; break; + case SQLITE_INDEX_CONSTRAINT_ISNOT: zOut = "ISNOT"; break; + case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: zOut = "ISNOTNULL"; break; + case SQLITE_INDEX_CONSTRAINT_ISNULL: zOut = "ISNULL"; break; + case SQLITE_INDEX_CONSTRAINT_IS: zOut = "IS"; break; + case SQLITE_INDEX_CONSTRAINT_LIMIT: zOut = "LIMIT"; break; + case SQLITE_INDEX_CONSTRAINT_OFFSET: zOut = "OFFSET"; break; + case SQLITE_INDEX_CONSTRAINT_FUNCTION: zOut = "FUNCTION"; break; + default: + sqlite3_snprintf(sizeof(zUnknown),zUnknown,"%d",op); + zOut = zUnknown; + break; + } + return zOut; +} + +/* ** SQLite will invoke this method one or more times while planning a query ** that uses the vtablog virtual table. This routine needs to create ** a query plan for each invocation and compute an estimated cost for that @@ -451,14 +491,23 @@ static int vtablogBestIndex( printf(" colUsed: 0x%016llx\n", p->colUsed); printf(" nConstraint: %d\n", p->nConstraint); for(i=0; i<p->nConstraint; i++){ + sqlite3_value *pVal = 0; + int rc = sqlite3_vtab_rhs_value(p, i, &pVal); printf( - " constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n", + " constraint[%d]: col=%d termid=%d op=%s usabled=%d coll=%s rhs=", i, p->aConstraint[i].iColumn, p->aConstraint[i].iTermOffset, - p->aConstraint[i].op, + vtablogOpName(p->aConstraint[i].op), p->aConstraint[i].usable, - sqlite3_vtab_collation(p,i)); + sqlite3_vtab_collation(p,i) + ); + if( rc==SQLITE_OK ){ + vtablogQuote(pVal); + printf("\n"); + }else{ + printf("N/A\n"); + } } printf(" nOrderBy: %d\n", p->nOrderBy); for(i=0; i<p->nOrderBy; i++){ diff --git a/ext/misc/zipfile.c b/ext/misc/zipfile.c index 2377457df..9e78e7230 100644 --- a/ext/misc/zipfile.c +++ b/ext/misc/zipfile.c @@ -116,6 +116,7 @@ static const char ZIPFILE_SCHEMA[] = #define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */ #define ZIPFILE_BUFFER_SIZE (64*1024) +#define ZIPFILE_MX_NAME (250) /* Windows limitation on filename size */ /* @@ -672,6 +673,7 @@ static int zipfileReadLFH( pLFH->szUncompressed = zipfileRead32(aRead); pLFH->nFile = zipfileRead16(aRead); pLFH->nExtra = zipfileRead16(aRead); + if( pLFH->nFile>ZIPFILE_MX_NAME ) rc = SQLITE_ERROR; } return rc; } @@ -885,8 +887,12 @@ static int zipfileGetEntry( pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; pNew->iDataOff += lfh.nFile + lfh.nExtra; if( aBlob && pNew->cds.szCompressed ){ - pNew->aData = &pNew->aExtra[nExtra]; - memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed); + if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){ + rc = SQLITE_CORRUPT; + }else{ + pNew->aData = &pNew->aExtra[nExtra]; + memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed); + } } }else{ *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", @@ -1673,6 +1679,11 @@ static int zipfileUpdate( zPath = (const char*)sqlite3_value_text(apVal[2]); if( zPath==0 ) zPath = ""; nPath = (int)strlen(zPath); + if( nPath>ZIPFILE_MX_NAME ){ + zipfileTableErr(pTab, "filename too long; max: %d bytes", + ZIPFILE_MX_NAME); + rc = SQLITE_CONSTRAINT; + } mTime = zipfileGetTime(apVal[4]); } @@ -2034,6 +2045,13 @@ static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){ rc = SQLITE_ERROR; goto zipfile_step_out; } + if( nName>ZIPFILE_MX_NAME ){ + zErr = sqlite3_mprintf( + "filename argument to zipfile() too big; max: %d bytes", + ZIPFILE_MX_NAME); + rc = SQLITE_ERROR; + goto zipfile_step_out; + } /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use ** deflate compression) or NULL (choose automatically). */ diff --git a/ext/misc/zorder.c b/ext/misc/zorder.c index c385d3c3c..c4c5fcdc7 100644 --- a/ext/misc/zorder.c +++ b/ext/misc/zorder.c @@ -16,6 +16,17 @@ ** ** unzorder(Z,N,I) Extract the I-th dimension from N-dimensional ** Morton code Z. +** +** Compiling: +** +** (linux) gcc -fPIC -shared zorder.c -o zorder.so +** (mac) clang -fPIC -dynamiclib zorder.c -o zorder.dylib +** (windows) cl zorder.c -link -dll -out:zorder.dll +** +** Usage example: +** +** .load ./zorder +** SELECT zorder(1,2,3,4); */ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 @@ -25,43 +36,53 @@ SQLITE_EXTENSION_INIT1 /* ** Functions: zorder(X0,X1,....) ** -** Convert integers X0, X1, ... into morton code. +** Convert integers X0, X1, ... into morton code. There must be at least +** two arguments. There may be no more than 24 arguments. ** -** The output is a signed 64-bit integer. If any argument is too large, -** an error is thrown. +** The output is a signed 64-bit integer. If any argument is too large +** to be successfully encoded into a morton code, an error is raised. */ static void zorderFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ - sqlite3_int64 z, x[63]; + sqlite3_int64 z, x[24]; int i, j; z = 0; + if( argc<2 || argc>24 ){ + sqlite3_result_error(context, + "zorder() needs between 2 and 24 arguments4", -1); + return; + } for(i=0; i<argc; i++){ x[i] = sqlite3_value_int64(argv[i]); } - if( argc>0 ){ - for(i=0; i<63; i++){ - j = i%argc; - z |= (x[j]&1)<<i; - x[j] >>= 1; - } + for(i=0; i<63; i++){ + j = i%argc; + z |= (x[j]&1)<<i; + x[j] >>= 1; } sqlite3_result_int64(context, z); for(i=0; i<argc; i++){ if( x[i] ){ - sqlite3_result_error(context, "parameter too large", -1); + char *z = sqlite3_mprintf( + "the %r argument to zorder() (%lld) is too large " + "for a 64-bit %d-dimensional Morton code", + i+1, sqlite3_value_int64(argv[i]), argc); + sqlite3_result_error(context, z, -1); + sqlite3_free(z); + break; } } } /* -** Functions: unzorder(Z,N,I) +** Function: unzorder(Z,N,K) ** -** Assuming that Z is an N-dimensional Morton code, extract the I-th -** dimension. +** Assuming that Z is an N-dimensional Morton code, extract the K-th +** dimension. K is between 0 and N-1. N must be between 2 and 24. */ static void unzorderFunc( sqlite3_context *context, @@ -72,7 +93,18 @@ static void unzorderFunc( int j, k; z = sqlite3_value_int64(argv[0]); n = sqlite3_value_int64(argv[1]); + if( n<2 || n>24 ){ + sqlite3_result_error(context, + "N argument to unzorder(Z,N,K) should be between 2 and 24", + -1); + return; + } i = sqlite3_value_int64(argv[2]); + if( i<0 || i>=n ){ + sqlite3_result_error(context, + "K argument to unzorder(Z,N,K) should be between 0 and N-1", -1); + return; + } x = 0; for(k=0, j=i; j<63; j+=n, k++){ x |= ((z>>j)&1)<<k; |