-C Implemenation\sof\sexperimental\sAPI\ssqlite3_schema_copy(),\sfor\scopying\sa\sdatabase\sschema\sbetween\sconnections.\sMore\stesting\sto\scome.
-D 2025-01-06T20:39:57.366
+C Fix\smany\sproblems\sin\sthe\ssqlite3_schema_copy()\sfunction.
+D 2025-01-07T21:04:51.236
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2
F src/alter.c c48e7cbb7f87b28e9e954bfed3327d8e1b8e2a020fbb5bbeca78f6534d6c3c31
-F src/analyze.c 19a2b6ed803a3c0add5f48adbac4735a064d329aa91790b94c968fef0bf7c438
+F src/analyze.c baba2f987e2564cfcfc31cc52b90da282644e35f93a94dcef30c07536bdf82c2
F src/attach.c 08235ab62ed5ccc93c22bf36e640d19effcd632319615851bccf724ec9341333
F src/auth.c 4c1ea890e0069ad73bead5d17a5b12c34cfa4f1a24175c8147ea439b64be271c
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 501daeef838fa82a9fb53540d72f29e3d9172c8867f1e19f94f681e2e20b966e
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
-F src/btree.c 2664c81f217a42afadc7c010bb4a175057d5e53b99e9512234eb74817f2ad59c
+F src/btree.c f840a13b2f7fe8d94925012946f0cc46251e4943852b9f00f2e11e808f716736
F src/btree.h bdeeb35614caa33526b603138f04c8d07a3f90a1300b5ade76848b755edf2027
F src/btreeInt.h caa893e74d2261fb0ff1681fce998533c0552858e882bd04fc6805075f5f6e75
-F src/build.c 19d6ba76fb72f81fed5323298284d56f0c32c7a59c38532e56c9811cdd9a89a5
-F src/callback.c 43c8ca52b1ecbdec43522f121126fd4e3ee10bc9ca01cdd3ae207cfa419780b6
+F src/build.c c8b1ce2275630b936f9e4f15694394fe29f542929e137771a03276dd285e628d
+F src/callback.c a8f3276f3f506e94b75b7102b8d4a76417cf9fa6ec1596faf0a6f7b8b4823e0e
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 193f6f9a75204274b7e7f45ac6d6517c12c70b55a5dfb39312dfc3a52e2a8138
F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
F src/func.c ce9dc15867388c76894fa67b3500f5726579b766b00ba617a2ad46c16ca76c1e
-F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
+F src/global.c c8f0ed504e7d4eec373e57d2ddc513c0cb03887de7c05ccb1865160e1ec6d601
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/json.c 68a98c020c22127f2d65f08855f7fc7460ff352a6ce0b543d8931dde83319c22
F src/legacy.c 5fff8efbb4f20396136beb913fff323686cff8f6f5d7d728189f68e98f7310bb
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
-F src/main.c 2aa8cea363b16f4093fc317f8bab38922c8e7b8d2c78b99cb64b6ab782a7c8e8
+F src/main.c bfeeca76e234be2f81c13f0ee9b08f399dbd7f06ee077158d2968cbfcc5d8894
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
F src/pcache1.c 437282ad81350c98a8592425b19e1b4e132196f7a81aef49b2ca39c50937b827
F src/pragma.c 464813bf39538eaa2c2cfe349de97888cc4d82645c0574d9c522190d46898149
F src/pragma.h 6ebbdee90ed56a892d2c728e27fd9c1ce48c8a28841888d0c6c147946b38cb25
-F src/prepare.c 3476a2d3353d3a881822f888fcd04bfdf5bf62a2a0566ffca83dc42190fdae19
+F src/prepare.c 4a8b68907511de0e8cd9a7ead5ee27d2fcee219683bf2c1d36bb9ae198700926
F src/printf.c 9480e90343dfde2406eeb25ff072774a77453d0f57fcd6495102f915dcc26a82
F src/random.c 9bd018738ec450bf35d28050b4b33fa9a6eebf3aaefb1a1cff42dc14a7725673
F src/resolve.c 2c127880c0634962837f16f2f48a295e514357af959330cc038de73015d5b5e8
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c d07d1872161db7c922194c5279d67686e8355c6d304ed0e0646fbaa59b59f561
F src/shell.c.in 40de636c1d90fb8a9ca7f49dc8f50d930f1b60736e73aca5eb37c4c7d0e47f9d
-F src/sqlite.h.in f991accd827e7853d092366690772b2de831a8fcbe1cb127f3831e39a4302e7e
+F src/sqlite.h.in b9d8969b238d4560d0cf6458957e710a3ebbbe85c8c614bd000819b34958bc40
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
-F src/sqliteInt.h 9e7a2d0941b10f059c1c62f13cea460b55bcd6b68c3a3c2fe170ce79e25a0032
+F src/sqliteInt.h 53123981e9aba70c4c58649b9b8b0f72b63025a413e69b3ca196d18ae68bd47e
F src/sqliteLimit.h da2cffdffa7d71b035f9e59668fbaad74b5939300dbfa9915304e6d8f72b0761
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c c6888598f08dee3d9112a38ef42c8f5c89ca7f3190f4694744d0b84250f4bf8c
F src/tclsqlite.h c6af51f31a2b2172d674608763a4b98fdf5cd587e4025053e546fb8077757262
-F src/test1.c 10d600bdbd99b4fa078195ca7d4746880f61553196a341ac7f1c246c1e882f24
+F src/test1.c ccbac0fdb30e4f77c515761aa776742f98258234e9d5be2d6a21bc6e1bf7ecd1
F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3
F src/test3.c e7573aa0f78ee4e070a4bc8c3493941c1aa64d5c66d4825c74c0f055451f432b
F src/test4.c 13e57ae7ec7a959ee180970aef09deed141252fe9bb07c61054f0dfa4f1dfd5d
F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl b4b9cc1520542d34ee061f9f12df0944d6ad1c438feba9db4078f6214e0a8111
+F test/tester.tcl 3c036e092942b97274718b7265142a6c8c57d90cdc6b66280d7974a69d5d6c5d
F test/testrunner.tcl 982939f0f1835007298b92e52694c207d16ef79143993b35e5cbc9f0c585938b x
F test/testrunner_data.tcl dbc0bb1c5b912dfd1e32b25d544318e412edd6085bd5fc9e6619cb93a739b786
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P dc3a24a784c95398656e0d7885f7eb0ee626b86c896e759a6ac5c243fd6f0ab7
-R 319fabba106aeb0d0322166af764ce3c
-T *branch * schema-copy
-T *sym-schema-copy *
-T -sym-cf8f1552-commit-instr *
+P 65ede04d2176e7206ca6ac004df14f488c274a6b092f6a7dc897b049012898fb
+R 1e0aeb33d9fdf3db04ec8caf3017ac1d
U dan
-Z 463cbc692201d0ebdc4f4cfb189d8b05
+Z 38efdb858d3d69b6af28ade3c3b371f8
# Remove this line to create a well-formed Fossil manifest.
-65ede04d2176e7206ca6ac004df14f488c274a6b092f6a7dc897b049012898fb
+ac9ca885902a105a4afc3bf157688c30f100bdb1064380328fd7f7a7fa126ee8
memcpy(pTo->aAvgEq, pFrom->aAvgEq, pFrom->nSampleCol * sizeof(tRowcnt));
memcpy(pTo->aSample[0].anEq, pFrom->aSample[0].anEq,
pTo->nSampleCol * 3 * sizeof(tRowcnt) * pTo->nSample
- );
+ );
for(ii=0; ii<pTo->nSample; ii++){
- pTo->aSample[ii].p = pFrom->aSample[ii].p;
- pTo->aSample[ii].n = pFrom->aSample[ii].n;
+ int nByte = pFrom->aSample[ii].n;
+ void *p = sqlite3DbMallocZero(db, nByte+8);
+ if( p ){
+ memcpy(p, pFrom->aSample[ii].p, nByte);
+ }
+ pTo->aSample[ii].p = p;
+ pTo->aSample[ii].n = nByte;
}
}
return SQLITE_OK;
return pBt->pSchema;
}
+void sqlite3BtreeSchemaPut(Btree *p, void *pTo){
+ BtShared *pBt = p->pBt;
+ assert( sqlite3BtreeHoldsMutex(p) );
+ assert( pBt->xFreeSchema );
+ assert( pBt->pSchema );
+
+ pBt->xFreeSchema(pBt->pSchema);
+ sqlite3DbFree(0, pBt->pSchema);
+ pBt->pSchema = pTo;
+}
+
/*
** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
** btree as the argument handle holds an exclusive lock on the
sqlite3WithDelete(db, (With*)pWith);
}
+struct TwoTable {
+ Table *pNew;
+ Table *pOld;
+};
+
+static int schemaCopyExprCb(Walker *p, Expr *pExpr){
+ struct TwoTable *pT = (struct TwoTable*)p->u.pSchema;
+ if( pExpr->op==TK_COLUMN && pExpr->y.pTab==pT->pOld ){
+ pExpr->y.pTab = pT->pNew;
+ }
+ return WRC_Continue;
+}
+
+static void schemaCopyExprWalker(Walker *p, struct TwoTable *pT){
+ memset(p, 0, sizeof(*p));
+ p->xExprCallback = schemaCopyExprCb;
+ p->xSelectCallback = sqlite3SelectWalkNoop;
+ p->u.pSchema = (Schema*)pT;
+}
+
static Index *schemaCopyIndexList(sqlite3 *db, Table *pTab, Index *pIdx){
Schema *pSchema = pTab->pSchema;
Index *pRet = 0;
pNew = sqlite3AllocateIndexObject(db, p->nColumn, nName+nExtra, &zExtra);
if( pNew ){
+ struct TwoTable twotable;
+ Walker sExprWalker;
+
pNew->zName = zExtra;
memcpy(pNew->zName, p->zName, nName);
zExtra += nName;
}
pNew->azColl[ii] = zColl;
}
+
pNew->pPartIdxWhere = sqlite3ExprDup(db, p->pPartIdxWhere, 0);
+ twotable.pNew = pTab;
+ twotable.pOld = p->pTable;
+ schemaCopyExprWalker(&sExprWalker, &twotable);
+ sqlite3WalkExpr(&sExprWalker, pNew->pPartIdxWhere);
+
pNew->aColExpr = sqlite3ExprListDup(db, p->aColExpr, 0);
+ sqlite3WalkExprList(&sExprWalker, pNew->aColExpr);
+
pNew->tnum = p->tnum;
pNew->szIdxRow = p->szIdxRow;
- memcpy(&pNew->onError,&p->onError,sizeof(Index)-offsetof(Index, onError));
+ memcpy(&pNew->nKeyCol,&p->nKeyCol,sizeof(Index)-offsetof(Index, nKeyCol));
pNew->isResized = 0;
#ifdef SQLITE_ENABLE_STAT4
assert( pNew->aiRowEst==0 && p->aiRowEst==0 );
+ pNew->aAvgEq = 0;
+ pNew->aSample = 0;
+ pNew->nSample = 0;
+ pNew->nSampleAlloc = 0;
sqlite3AnalyzeCopyStat4(db, pNew, p);
#endif
pNew = (Table*)sqlite3DbMallocRawNN(db, sizeof(Table));
if( pNew ){
+ Walker sExprWalker;
+ struct TwoTable twotable;
memcpy(pNew, pTab, sizeof(Table));
pNew->zName = sqlite3DbStrDup(db, pNew->zName);
- pNew->aCol = sqlite3DbMallocRawNN(db, pNew->nCol*sizeof(Column));
+ assert( pNew->nCol>0 || pNew->eTabType!=TABTYP_NORM );
+ if( pNew->nCol>0 ){
+ pNew->aCol = sqlite3DbMallocRawNN(db, pNew->nCol*sizeof(Column));
+ }
pNew->nTabRef = 1;
if( pNew->aCol ){
int ii;
pNew->zColAff = 0;
pNew->pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
+ twotable.pNew = pNew;
+ twotable.pOld = pTab;
+ schemaCopyExprWalker(&sExprWalker, &twotable);
+ sqlite3WalkExprList(&sExprWalker, pNew->pCheck);
+
if( IsView(pNew) ){
Walker sWalker;
memset(&sWalker, 0, sizeof(sWalker));
}
}else{
pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pNew->u.tab.pDfltList, 0);
+ sqlite3WalkExprList(&sExprWalker, pNew->u.tab.pDfltList);
pNew->u.tab.pFKey = schemaCopyFKeyList(db, pNew, pNew->u.tab.pFKey);
}
db->mallocFailed = 1;
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
- if( strcmp(pNew->zName, "sqlite_sequence")==0 ){
+ if( pTab->pSchema->pSeqTab==pTab ){
pTo->pSeqTab = pNew;
}
#endif
}
}
+void sqlite3SchemaCopy(sqlite3 *db, Schema *pTo, Schema *pFrom){
+ HashElem *k = 0;
+
+ DisableLookaside;
+ pTo->schema_cookie = pFrom->schema_cookie;
+ pTo->iGeneration = pFrom->iGeneration;
+ pTo->file_format = pFrom->file_format;
+ pTo->enc = pFrom->enc;
+ pTo->cache_size = pFrom->cache_size;
+ pTo->schemaFlags = pFrom->schemaFlags;
+
+#ifdef SQLITE_ENABLE_STAT4
+ if( pFrom->pStat4Space ){
+ pTo->pStat4Space = sqlite3_malloc(pFrom->nStat4Space);
+ if( pTo->pStat4Space==0 ){
+ sqlite3OomFault(db);
+ }
+ pTo->nStat4Space = 0;
+ }
+#endif
+
+ for(k=sqliteHashFirst(&pFrom->tblHash); k; k=sqliteHashNext(k)){
+ Table *pTab = (Table*)sqliteHashData(k);
+ schemaCopyTable(db, pTo, pTab);
+ }
+
+ EnableLookaside;
+}
+
int sqlite3_schema_copy(
sqlite3 *db, const char *zTo,
sqlite3 *dbFrom, const char *zFrom
int iFrom = 0;
Schema *pTo = 0;
Schema *pFrom = 0;
- HashElem *k = 0;
int rc = SQLITE_OK;
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
- DisableLookaside;
if( zTo ) iTo = sqlite3FindDbName(db, zTo);
if( zFrom ) iFrom = sqlite3FindDbName(dbFrom, zFrom);
pFrom = dbFrom->aDb[iFrom].pSchema;
assert( pTo && pFrom );
- pTo->schema_cookie = pFrom->schema_cookie;
- pTo->iGeneration = pFrom->iGeneration;
- pTo->file_format = pFrom->file_format;
- pTo->enc = pFrom->enc;
- pTo->cache_size = pFrom->cache_size;
- pTo->schemaFlags = pFrom->schemaFlags;
-
-#ifdef SQLITE_ENABLE_STAT4
- if( pFrom->pStat4Space ){
- pTo->pStat4Space = sqlite3_malloc(pFrom->nStat4Space);
- if( pTo->pStat4Space==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto schema_copy_done;
- }
- pTo->nStat4Space = 0;
- }
-#endif
-
- for(k=sqliteHashFirst(&pFrom->tblHash); k; k=sqliteHashNext(k)){
- Table *pTab = (Table*)sqliteHashData(k);
- schemaCopyTable(db, pTo, pTab);
- }
+ sqlite3SchemaCopy(db, pTo, pFrom);
schema_copy_done:
- EnableLookaside;
sqlite3BtreeLeaveAll(db);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
}
return p;
}
+
+int sqlite3SchemaTestCopy(sqlite3 *db, int iDb){
+ Btree *pBt = db->aDb[iDb].pBt;
+ Schema *pFrom = db->aDb[iDb].pSchema;
+ Schema *pTo = sqlite3BtreeSchema(pBt, 0, 0);
+
+ assert( pTo && pFrom );
+ sqlite3SchemaCopy(db, pTo, pFrom);
+ db->aDb[iDb].pSchema = pTo;
+
+ return (db->mallocFailed ? SQLITE_NOMEM : SQLITE_OK);
+}
+
0x7ffffffe, /* iOnceResetThreshold */
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
0, /* iPrngSeed */
+ 0, /* bTestSchemaCopy */
#ifdef SQLITE_DEBUG
{0,0,0,0,0,0}, /* aTune */
#endif
break;
}
+ /* sqlite3_test_control(SQLITE_TESTCTRL_SCHEMACOPY, int X);
+ **
+ ** X==0 Disable test sqlite3_schema_copy()
+ ** X==1 Enable test sqlite3_schema_copy()
+ */
+ case SQLITE_TESTCTRL_SCHEMACOPY: {
+ int b = va_arg(ap, int);
+ if( b>=0 ) sqlite3Config.bTestSchemaCopy = b>0;
+ rc = sqlite3Config.bTestSchemaCopy!=0;
+ break;
+ }
+
#if !defined(SQLITE_OMIT_WSD)
/* sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, int X);
**
assert( db->nDb>0 );
/* Do the main schema first */
if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
+ Schema *pNew = 0;
+ if( sqlite3Config.bTestSchemaCopy ){
+ pNew = sqlite3DbMallocZero(db, sizeof(Schema));
+ if( !pNew ) return SQLITE_NOMEM;
+ pNew->cache_size = db->aDb[0].pSchema->cache_size;
+ db->aDb[0].pSchema = pNew;
+ }
rc = sqlite3InitOne(db, 0, pzErrMsg, 0);
+ if( sqlite3Config.bTestSchemaCopy ){
+ int rc2 = sqlite3SchemaTestCopy(db, 0);
+ if( rc==SQLITE_OK ) rc = rc2;
+ sqlite3SchemaClear(pNew);
+ sqlite3DbFree(db, pNew);
+ }
if( rc ) return rc;
}
/* All other schemas after the main schema. The "temp" schema must be last */
#define SQLITE_TESTCTRL_TUNE 32
#define SQLITE_TESTCTRL_LOGEST 33
#define SQLITE_TESTCTRL_USELONGDOUBLE 34
-#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_SCHEMACOPY 35
+#define SQLITE_TESTCTRL_LAST 35 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
int iOnceResetThreshold; /* When to reset OP_Once counters */
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */
+ int bTestSchemaCopy; /* True to test schema copies internally */
/* vvvv--- must be last ---vvv */
#ifdef SQLITE_DEBUG
sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */
#endif
TriggerStep *sqlite3SchemaCopyTriggerStepList(sqlite3 *, TriggerStep*);
+int sqlite3SchemaTestCopy(sqlite3 *db, int);
+void sqlite3SchemaCopy(sqlite3 *db, Schema*, Schema*);
+void sqlite3BtreeSchemaPut(Btree *pBt, void*);
/*
** The interface to the LEMON-generated parser
{ "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
{ "SQLITE_TESTCTRL_INTERNAL_FUNCTIONS", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS},
{ "SQLITE_TESTCTRL_FK_NO_ACTION", SQLITE_TESTCTRL_FK_NO_ACTION},
+ { "SQLITE_TESTCTRL_SCHEMACOPY", SQLITE_TESTCTRL_SCHEMACOPY},
{ 0, 0 }
};
int iVerb;
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zDbName, onOff, tnum);
break;
}
+
+ case SQLITE_TESTCTRL_SCHEMACOPY: {
+ int val = 0;
+ sqlite3 *db = 0;
+ if( objc!=3 ){
+ Tcl_WrongNumArgs(interp, 2, objv, "BOOLEAN");
+ return TCL_ERROR;
+ }
+ if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
+ sqlite3_test_control(SQLITE_TESTCTRL_SCHEMACOPY, val);
+ break;
+ }
}
Tcl_ResetResult(interp);
set tcl_precision 15
sqlite3_test_control_pending_byte 0x0010000
+#sqlite3_test_control SQLITE_TESTCTRL_SCHEMACOPY 1
# If the pager codec is available, create a wrapper for the [sqlite3]
# command that appends "-key {xyzzy}" to the command line. i.e. this: