summaryrefslogtreecommitdiffstats
path: root/ext/misc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 05:16:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 05:16:48 +0000
commit3640b21e686fef7e3f25dc775112c7d4be43f197 (patch)
treee7fec2ad45891adeada1227d655062cbd201dd5a /ext/misc
parentReleasing progress-linux version 3.45.3-1~progress7.99u1. (diff)
downloadsqlite3-3640b21e686fef7e3f25dc775112c7d4be43f197.tar.xz
sqlite3-3640b21e686fef7e3f25dc775112c7d4be43f197.zip
Merging upstream version 3.46.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ext/misc')
-rw-r--r--ext/misc/cksumvfs.c6
-rw-r--r--ext/misc/fileio.c24
-rw-r--r--ext/misc/series.c120
-rw-r--r--ext/misc/sqlar.c7
-rw-r--r--ext/misc/vtablog.c194
5 files changed, 265 insertions, 86 deletions
diff --git a/ext/misc/cksumvfs.c b/ext/misc/cksumvfs.c
index e7c2c9d..2d7f658 100644
--- a/ext/misc/cksumvfs.c
+++ b/ext/misc/cksumvfs.c
@@ -446,9 +446,9 @@ static int cksmRead(
** (2) checksum verification is enabled
** (3) we are not in the middle of checkpoint
*/
- if( iAmt>=512 /* (1) */
- && p->verifyCksm /* (2) */
- && !p->inCkpt /* (3) */
+ if( iAmt>=512 && (iAmt & (iAmt-1))==0 /* (1) */
+ && p->verifyCksm /* (2) */
+ && !p->inCkpt /* (3) */
){
u8 cksum[8];
cksmCompute((u8*)zBuf, iAmt-8, cksum);
diff --git a/ext/misc/fileio.c b/ext/misc/fileio.c
index 70546ad..ca8090e 100644
--- a/ext/misc/fileio.c
+++ b/ext/misc/fileio.c
@@ -372,7 +372,9 @@ static int writeFile(
#if !defined(_WIN32) && !defined(WIN32)
if( S_ISLNK(mode) ){
const char *zTo = (const char*)sqlite3_value_text(pData);
- if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
+ if( zTo==0 ) return 1;
+ unlink(zFile);
+ if( symlink(zTo, zFile)<0 ) return 1;
}else
#endif
{
@@ -458,13 +460,19 @@ static int writeFile(
return 1;
}
#else
- /* Legacy unix */
- struct timeval times[2];
- times[0].tv_usec = times[1].tv_usec = 0;
- times[0].tv_sec = time(0);
- times[1].tv_sec = mtime;
- if( utimes(zFile, times) ){
- return 1;
+ /* Legacy unix.
+ **
+ ** Do not use utimes() on a symbolic link - it sees through the link and
+ ** modifies the timestamps on the target. Or fails if the target does
+ ** not exist. */
+ if( 0==S_ISLNK(mode) ){
+ struct timeval times[2];
+ times[0].tv_usec = times[1].tv_usec = 0;
+ times[0].tv_sec = time(0);
+ times[1].tv_sec = mtime;
+ if( utimes(zFile, times) ){
+ return 1;
+ }
}
#endif
}
diff --git a/ext/misc/series.c b/ext/misc/series.c
index abd6af7..0dfed18 100644
--- a/ext/misc/series.c
+++ b/ext/misc/series.c
@@ -103,16 +103,20 @@ SQLITE_EXTENSION_INIT1
** index is ix. The 0th member is given by smBase. The sequence members
** progress per ix increment by smStep.
*/
-static sqlite3_int64 genSeqMember(sqlite3_int64 smBase,
- sqlite3_int64 smStep,
- sqlite3_uint64 ix){
- if( ix>=(sqlite3_uint64)LLONG_MAX ){
+static sqlite3_int64 genSeqMember(
+ sqlite3_int64 smBase,
+ sqlite3_int64 smStep,
+ sqlite3_uint64 ix
+){
+ static const sqlite3_uint64 mxI64 =
+ ((sqlite3_uint64)0x7fffffff)<<32 | 0xffffffff;
+ if( ix>=mxI64 ){
/* Get ix into signed i64 range. */
- ix -= (sqlite3_uint64)LLONG_MAX;
+ ix -= mxI64;
/* With 2's complement ALU, this next can be 1 step, but is split into
* 2 for UBSAN's satisfaction (and hypothetical 1's complement ALUs.) */
- smBase += (LLONG_MAX/2) * smStep;
- smBase += (LLONG_MAX - LLONG_MAX/2) * smStep;
+ smBase += (mxI64/2) * smStep;
+ smBase += (mxI64 - mxI64/2) * smStep;
}
/* Under UBSAN (or on 1's complement machines), must do this last term
* in steps to avoid the dreaded (and harmless) signed multiply overlow. */
@@ -372,13 +376,13 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
** parameter. (idxStr is not used in this implementation.) idxNum
** is a bitmask showing which constraints are available:
**
-** 1: start=VALUE
-** 2: stop=VALUE
-** 4: step=VALUE
-**
-** Also, if bit 8 is set, that means that the series should be output
-** in descending order rather than in ascending order. If bit 16 is
-** set, then output must appear in ascending order.
+** 0x01: start=VALUE
+** 0x02: stop=VALUE
+** 0x04: step=VALUE
+** 0x08: descending order
+** 0x10: ascending order
+** 0x20: LIMIT VALUE
+** 0x40: OFFSET VALUE
**
** This routine should initialize the cursor and position it so that it
** is pointing at the first row, or pointing off the end of the table
@@ -392,26 +396,44 @@ static int seriesFilter(
series_cursor *pCur = (series_cursor *)pVtabCursor;
int i = 0;
(void)idxStrUnused;
- if( idxNum & 1 ){
+ if( idxNum & 0x01 ){
pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
}else{
pCur->ss.iBase = 0;
}
- if( idxNum & 2 ){
+ if( idxNum & 0x02 ){
pCur->ss.iTerm = sqlite3_value_int64(argv[i++]);
}else{
pCur->ss.iTerm = 0xffffffff;
}
- if( idxNum & 4 ){
+ if( idxNum & 0x04 ){
pCur->ss.iStep = sqlite3_value_int64(argv[i++]);
if( pCur->ss.iStep==0 ){
pCur->ss.iStep = 1;
}else if( pCur->ss.iStep<0 ){
- if( (idxNum & 16)==0 ) idxNum |= 8;
+ if( (idxNum & 0x10)==0 ) idxNum |= 0x08;
}
}else{
pCur->ss.iStep = 1;
}
+ if( idxNum & 0x20 ){
+ sqlite3_int64 iLimit = sqlite3_value_int64(argv[i++]);
+ sqlite3_int64 iTerm;
+ if( idxNum & 0x40 ){
+ sqlite3_int64 iOffset = sqlite3_value_int64(argv[i++]);
+ if( iOffset>0 ){
+ pCur->ss.iBase += pCur->ss.iStep*iOffset;
+ }
+ }
+ if( iLimit>=0 ){
+ iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
+ if( pCur->ss.iStep<0 ){
+ if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
+ }else{
+ if( iTerm<pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
+ }
+ }
+ }
for(i=0; i<argc; i++){
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
/* If any of the constraints have a NULL value, then return no rows.
@@ -422,7 +444,7 @@ static int seriesFilter(
break;
}
}
- if( idxNum & 8 ){
+ if( idxNum & 0x08 ){
pCur->ss.isReversing = pCur->ss.iStep > 0;
}else{
pCur->ss.isReversing = pCur->ss.iStep < 0;
@@ -442,10 +464,13 @@ static int seriesFilter(
**
** The query plan is represented by bits in idxNum:
**
-** (1) start = $value -- constraint exists
-** (2) stop = $value -- constraint exists
-** (4) step = $value -- constraint exists
-** (8) output in descending order
+** 0x01 start = $value -- constraint exists
+** 0x02 stop = $value -- constraint exists
+** 0x04 step = $value -- constraint exists
+** 0x08 output is in descending order
+** 0x10 output is in ascending order
+** 0x20 LIMIT $value -- constraint exists
+** 0x40 OFFSET $value -- constraint exists
*/
static int seriesBestIndex(
sqlite3_vtab *pVTab,
@@ -453,10 +478,12 @@ static int seriesBestIndex(
){
int i, j; /* Loop over constraints */
int idxNum = 0; /* The query plan bitmask */
+#ifndef ZERO_ARGUMENT_GENERATE_SERIES
int bStartSeen = 0; /* EQ constraint seen on the START column */
+#endif
int unusableMask = 0; /* Mask of unusable constraints */
int nArg = 0; /* Number of arguments that seriesFilter() expects */
- int aIdx[3]; /* Constraints on start, stop, and step */
+ int aIdx[5]; /* Constraints on start, stop, step, LIMIT, OFFSET */
const struct sqlite3_index_constraint *pConstraint;
/* This implementation assumes that the start, stop, and step columns
@@ -464,28 +491,54 @@ static int seriesBestIndex(
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
- aIdx[0] = aIdx[1] = aIdx[2] = -1;
+ aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = -1;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
int iCol; /* 0 for start, 1 for stop, 2 for step */
int iMask; /* bitmask for those column */
+ int op = pConstraint->op;
+ if( op>=SQLITE_INDEX_CONSTRAINT_LIMIT
+ && op<=SQLITE_INDEX_CONSTRAINT_OFFSET
+ ){
+ if( pConstraint->usable==0 ){
+ /* do nothing */
+ }else if( op==SQLITE_INDEX_CONSTRAINT_LIMIT ){
+ aIdx[3] = i;
+ idxNum |= 0x20;
+ }else{
+ assert( op==SQLITE_INDEX_CONSTRAINT_OFFSET );
+ aIdx[4] = i;
+ idxNum |= 0x40;
+ }
+ continue;
+ }
if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
assert( iCol>=0 && iCol<=2 );
iMask = 1 << iCol;
- if( iCol==0 ) bStartSeen = 1;
+#ifndef ZERO_ARGUMENT_GENERATE_SERIES
+ if( iCol==0 && op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ bStartSeen = 1;
+ }
+#endif
if( pConstraint->usable==0 ){
unusableMask |= iMask;
continue;
- }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ }else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){
idxNum |= iMask;
aIdx[iCol] = i;
}
}
- for(i=0; i<3; i++){
+ if( aIdx[3]==0 ){
+ /* Ignore OFFSET if LIMIT is omitted */
+ idxNum &= ~0x60;
+ aIdx[4] = 0;
+ }
+ for(i=0; i<5; i++){
if( (j = aIdx[i])>=0 ){
pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
+ pIdxInfo->aConstraintUsage[j].omit =
+ !SQLITE_SERIES_CONSTRAINT_VERIFY || i>=3;
}
}
/* The current generate_column() implementation requires at least one
@@ -506,19 +559,22 @@ static int seriesBestIndex(
** this plan is unusable */
return SQLITE_CONSTRAINT;
}
- if( (idxNum & 3)==3 ){
+ if( (idxNum & 0x03)==0x03 ){
/* Both start= and stop= boundaries are available. This is the
** the preferred case */
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
pIdxInfo->estimatedRows = 1000;
if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
if( pIdxInfo->aOrderBy[0].desc ){
- idxNum |= 8;
+ idxNum |= 0x08;
}else{
- idxNum |= 16;
+ idxNum |= 0x10;
}
pIdxInfo->orderByConsumed = 1;
}
+ }else if( (idxNum & 0x21)==0x21 ){
+ /* We have start= and LIMIT */
+ pIdxInfo->estimatedRows = 2500;
}else{
/* If either boundary is missing, we have to generate a huge span
** of numbers. Make this case very expensive so that the query
diff --git a/ext/misc/sqlar.c b/ext/misc/sqlar.c
index be079a5..9f726f0 100644
--- a/ext/misc/sqlar.c
+++ b/ext/misc/sqlar.c
@@ -81,7 +81,7 @@ static void sqlarUncompressFunc(
sqlite3_value **argv
){
uLong nData;
- uLongf sz;
+ sqlite3_int64 sz;
assert( argc==2 );
sz = sqlite3_value_int(argv[1]);
@@ -89,14 +89,15 @@ static void sqlarUncompressFunc(
if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
sqlite3_result_value(context, argv[0]);
}else{
+ uLongf szf = sz;
const Bytef *pData= sqlite3_value_blob(argv[0]);
Bytef *pOut = sqlite3_malloc(sz);
if( pOut==0 ){
sqlite3_result_error_nomem(context);
- }else if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
+ }else if( Z_OK!=uncompress(pOut, &szf, pData, nData) ){
sqlite3_result_error(context, "error in uncompress()", -1);
}else{
- sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
+ sqlite3_result_blob(context, pOut, szf, SQLITE_TRANSIENT);
}
sqlite3_free(pOut);
}
diff --git a/ext/misc/vtablog.c b/ext/misc/vtablog.c
index e414e7a..2cc29c2 100644
--- a/ext/misc/vtablog.c
+++ b/ext/misc/vtablog.c
@@ -38,8 +38,9 @@ SQLITE_EXTENSION_INIT1
typedef struct vtablog_vtab vtablog_vtab;
struct vtablog_vtab {
sqlite3_vtab base; /* Base class - must be first */
+ char *zDb; /* Schema name. argv[1] of xConnect/xCreate */
+ char *zName; /* Table name. argv[2] of xConnect/xCreate */
int nRow; /* Number of rows in the table */
- int iInst; /* Instance number for this vtablog table */
int nCursor; /* Number of cursors created */
};
@@ -167,15 +168,14 @@ static int vtablogConnectCreate(
char **pzErr,
int isCreate
){
- static int nInst = 0;
vtablog_vtab *pNew;
int i;
int rc;
- int iInst = ++nInst;
char *zSchema = 0;
char *zNRow = 0;
- printf("vtablog%s(tab=%d):\n", isCreate ? "Create" : "Connect", iInst);
+ printf("%s.%s.%s():\n", argv[1], argv[2],
+ isCreate ? "xCreate" : "xConnect");
printf(" argc=%d\n", argc);
for(i=0; i<argc; i++){
printf(" argv[%d] = ", i);
@@ -189,17 +189,18 @@ static int vtablogConnectCreate(
for(i=3; i<argc; i++){
const char *z = argv[i];
if( vtablog_string_parameter(pzErr, "schema", z, &zSchema) ){
- return SQLITE_ERROR;
+ rc = SQLITE_ERROR;
+ goto vtablog_end_connect;
}
if( vtablog_string_parameter(pzErr, "rows", z, &zNRow) ){
- return SQLITE_ERROR;
+ rc = SQLITE_ERROR;
+ goto vtablog_end_connect;
}
}
-
if( zSchema==0 ){
- *pzErr = sqlite3_mprintf("no schema defined");
- return SQLITE_ERROR;
+ zSchema = sqlite3_mprintf("%s","CREATE TABLE x(a,b);");
}
+ printf(" schema = '%s'\n", zSchema);
rc = sqlite3_declare_vtab(db, zSchema);
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc( sizeof(*pNew) );
@@ -208,8 +209,14 @@ static int vtablogConnectCreate(
memset(pNew, 0, sizeof(*pNew));
pNew->nRow = 10;
if( zNRow ) pNew->nRow = atoi(zNRow);
- pNew->iInst = iInst;
+ printf(" nrow = %d\n", pNew->nRow);
+ pNew->zDb = sqlite3_mprintf("%s", argv[1]);
+ pNew->zName = sqlite3_mprintf("%s", argv[2]);
}
+
+vtablog_end_connect:
+ sqlite3_free(zSchema);
+ sqlite3_free(zNRow);
return rc;
}
static int vtablogCreate(
@@ -237,7 +244,9 @@ static int vtablogConnect(
*/
static int vtablogDisconnect(sqlite3_vtab *pVtab){
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
- printf("vtablogDisconnect(%d)\n", pTab->iInst);
+ printf("%s.%s.xDisconnect()\n", pTab->zDb, pTab->zName);
+ sqlite3_free(pTab->zDb);
+ sqlite3_free(pTab->zName);
sqlite3_free(pVtab);
return SQLITE_OK;
}
@@ -247,7 +256,9 @@ static int vtablogDisconnect(sqlite3_vtab *pVtab){
*/
static int vtablogDestroy(sqlite3_vtab *pVtab){
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
- printf("vtablogDestroy(%d)\n", pTab->iInst);
+ printf("%s.%s.xDestroy()\n", pTab->zDb, pTab->zName);
+ sqlite3_free(pTab->zDb);
+ sqlite3_free(pTab->zName);
sqlite3_free(pVtab);
return SQLITE_OK;
}
@@ -258,7 +269,8 @@ static int vtablogDestroy(sqlite3_vtab *pVtab){
static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
vtablog_vtab *pTab = (vtablog_vtab*)p;
vtablog_cursor *pCur;
- printf("vtablogOpen(tab=%d, cursor=%d)\n", pTab->iInst, ++pTab->nCursor);
+ printf("%s.%s.xOpen(cursor=%d)\n", pTab->zDb, pTab->zName,
+ ++pTab->nCursor);
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
@@ -273,7 +285,7 @@ static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
static int vtablogClose(sqlite3_vtab_cursor *cur){
vtablog_cursor *pCur = (vtablog_cursor*)cur;
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
- printf("vtablogClose(tab=%d, cursor=%d)\n", pTab->iInst, pCur->iCursor);
+ printf("%s.%s.xClose(cursor=%d)\n", pTab->zDb, pTab->zName, pCur->iCursor);
sqlite3_free(cur);
return SQLITE_OK;
}
@@ -285,8 +297,9 @@ static int vtablogClose(sqlite3_vtab_cursor *cur){
static int vtablogNext(sqlite3_vtab_cursor *cur){
vtablog_cursor *pCur = (vtablog_cursor*)cur;
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
- printf("vtablogNext(tab=%d, cursor=%d) rowid %d -> %d\n",
- pTab->iInst, pCur->iCursor, (int)pCur->iRowid, (int)pCur->iRowid+1);
+ printf("%s.%s.xNext(cursor=%d) rowid %d -> %d\n",
+ pTab->zDb, pTab->zName, pCur->iCursor,
+ (int)pCur->iRowid, (int)pCur->iRowid+1);
pCur->iRowid++;
return SQLITE_OK;
}
@@ -310,8 +323,8 @@ static int vtablogColumn(
}else{
sqlite3_snprintf(sizeof(zVal),zVal,"{%d}%d", i, pCur->iRowid);
}
- printf("vtablogColumn(tab=%d, cursor=%d, i=%d): [%s]\n",
- pTab->iInst, pCur->iCursor, i, zVal);
+ printf("%s.%s.xColumn(cursor=%d, i=%d): [%s]\n",
+ pTab->zDb, pTab->zName, pCur->iCursor, i, zVal);
sqlite3_result_text(ctx, zVal, -1, SQLITE_TRANSIENT);
return SQLITE_OK;
}
@@ -323,8 +336,8 @@ static int vtablogColumn(
static int vtablogRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
vtablog_cursor *pCur = (vtablog_cursor*)cur;
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
- printf("vtablogRowid(tab=%d, cursor=%d): %d\n",
- pTab->iInst, pCur->iCursor, (int)pCur->iRowid);
+ printf("%s.%s.xRowid(cursor=%d): %d\n",
+ pTab->zDb, pTab->zName, pCur->iCursor, (int)pCur->iRowid);
*pRowid = pCur->iRowid;
return SQLITE_OK;
}
@@ -337,8 +350,8 @@ static int vtablogEof(sqlite3_vtab_cursor *cur){
vtablog_cursor *pCur = (vtablog_cursor*)cur;
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
int rc = pCur->iRowid >= pTab->nRow;
- printf("vtablogEof(tab=%d, cursor=%d): %d\n",
- pTab->iInst, pCur->iCursor, rc);
+ printf("%s.%s.xEof(cursor=%d): %d\n",
+ pTab->zDb, pTab->zName, pCur->iCursor, rc);
return rc;
}
@@ -417,7 +430,7 @@ static int vtablogFilter(
){
vtablog_cursor *pCur = (vtablog_cursor *)cur;
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
- printf("vtablogFilter(tab=%d, cursor=%d):\n", pTab->iInst, pCur->iCursor);
+ printf("%s.%s.xFilter(cursor=%d):\n", pTab->zDb, pTab->zName, pCur->iCursor);
pCur->iRowid = 0;
return SQLITE_OK;
}
@@ -430,12 +443,37 @@ static int vtablogFilter(
*/
static int vtablogBestIndex(
sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
+ sqlite3_index_info *p
){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
- printf("vtablogBestIndex(tab=%d):\n", pTab->iInst);
- pIdxInfo->estimatedCost = (double)500;
- pIdxInfo->estimatedRows = 500;
+ int i;
+ printf("%s.%s.xBestIndex():\n", pTab->zDb, pTab->zName);
+ printf(" colUsed: 0x%016llx\n", p->colUsed);
+ printf(" nConstraint: %d\n", p->nConstraint);
+ for(i=0; i<p->nConstraint; i++){
+ printf(
+ " constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
+ i,
+ p->aConstraint[i].iColumn,
+ p->aConstraint[i].iTermOffset,
+ p->aConstraint[i].op,
+ p->aConstraint[i].usable,
+ sqlite3_vtab_collation(p,i));
+ }
+ printf(" nOrderBy: %d\n", p->nOrderBy);
+ for(i=0; i<p->nOrderBy; i++){
+ printf(" orderby[%d]: col=%d desc=%d\n",
+ i,
+ p->aOrderBy[i].iColumn,
+ p->aOrderBy[i].desc);
+ }
+ p->estimatedCost = (double)500;
+ p->estimatedRows = 500;
+ printf(" idxNum=%d\n", p->idxNum);
+ printf(" idxStr=NULL\n");
+ printf(" orderByConsumed=%d\n", p->orderByConsumed);
+ printf(" estimatedCost=%g\n", p->estimatedCost);
+ printf(" estimatedRows=%lld\n", p->estimatedRows);
return SQLITE_OK;
}
@@ -454,7 +492,7 @@ static int vtablogUpdate(
){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
int i;
- printf("vtablogUpdate(tab=%d):\n", pTab->iInst);
+ printf("%s.%s.xUpdate():\n", pTab->zDb, pTab->zName);
printf(" argc=%d\n", argc);
for(i=0; i<argc; i++){
printf(" argv[%d]=", i);
@@ -464,12 +502,88 @@ static int vtablogUpdate(
return SQLITE_OK;
}
+static int vtablogBegin(sqlite3_vtab *tab){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("%s.%s.xBegin()\n", pTab->zDb, pTab->zName);
+ return SQLITE_OK;
+}
+static int vtablogSync(sqlite3_vtab *tab){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("%s.%s.xSync()\n", pTab->zDb, pTab->zName);
+ return SQLITE_OK;
+}
+static int vtablogCommit(sqlite3_vtab *tab){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("%s.%s.xCommit()\n", pTab->zDb, pTab->zName);
+ return SQLITE_OK;
+}
+static int vtablogRollback(sqlite3_vtab *tab){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("%s.%s.xRollback()\n", pTab->zDb, pTab->zName);
+ return SQLITE_OK;
+}
+static int vtablogSavepoint(sqlite3_vtab *tab, int N){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("%s.%s.xSavepoint(%d)\n", pTab->zDb, pTab->zName, N);
+ return SQLITE_OK;
+}
+static int vtablogRelease(sqlite3_vtab *tab, int N){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("%s.%s.xRelease(%d)\n", pTab->zDb, pTab->zName, N);
+ return SQLITE_OK;
+}
+static int vtablogRollbackTo(sqlite3_vtab *tab, int N){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("%s.%s.xRollbackTo(%d)\n", pTab->zDb, pTab->zName, N);
+ return SQLITE_OK;
+}
+
+static int vtablogFindMethod(
+ sqlite3_vtab *tab,
+ int nArg,
+ const char *zName,
+ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
+ void **ppArg
+){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("%s.%s.xFindMethod(nArg=%d, zName=%s)\n",
+ pTab->zDb, pTab->zName, nArg, zName);
+ return SQLITE_OK;
+}
+static int vtablogRename(sqlite3_vtab *tab, const char *zNew){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("%s.%s.xRename('%s')\n", pTab->zDb, pTab->zName, zNew);
+ sqlite3_free(pTab->zName);
+ pTab->zName = sqlite3_mprintf("%s", zNew);
+ return SQLITE_OK;
+}
+
+/* Any table name that contains the text "shadow" is seen as a
+** shadow table. Nothing else is.
+*/
+static int vtablogShadowName(const char *zName){
+ printf("vtablog.xShadowName('%s')\n", zName);
+ return sqlite3_strglob("*shadow*", zName)==0;
+}
+
+static int vtablogIntegrity(
+ sqlite3_vtab *tab,
+ const char *zSchema,
+ const char *zTabName,
+ int mFlags,
+ char **pzErr
+){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("%s.%s.xIntegrity(mFlags=0x%x)\n", pTab->zDb, pTab->zName, mFlags);
+ return 0;
+}
+
/*
** This following structure defines all the methods for the
** vtablog virtual table.
*/
static sqlite3_module vtablogModule = {
- 0, /* iVersion */
+ 4, /* iVersion */
vtablogCreate, /* xCreate */
vtablogConnect, /* xConnect */
vtablogBestIndex, /* xBestIndex */
@@ -483,17 +597,17 @@ static sqlite3_module vtablogModule = {
vtablogColumn, /* xColumn - read data */
vtablogRowid, /* xRowid - read data */
vtablogUpdate, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0, /* xRollbackTo */
- 0, /* xShadowName */
- 0 /* xIntegrity */
+ vtablogBegin, /* xBegin */
+ vtablogSync, /* xSync */
+ vtablogCommit, /* xCommit */
+ vtablogRollback, /* xRollback */
+ vtablogFindMethod, /* xFindMethod */
+ vtablogRename, /* xRename */
+ vtablogSavepoint, /* xSavepoint */
+ vtablogRelease, /* xRelease */
+ vtablogRollbackTo, /* xRollbackTo */
+ vtablogShadowName, /* xShadowName */
+ vtablogIntegrity /* xIntegrity */
};
#ifdef _WIN32