If a zipfile virtual table is created with no argument - "CREATE VIRTUAL TABLE
zzz USING zipfile()" - accumulate data in memory. Support "SELECT zipfile_blob(z) FROM zzz LIMIT 1" to retrieve a zip archive image. FossilOrigin-Name: e63185edfe0c316aa60c1fa085d032425ecc7db54536dfa5a977772eaf3c240e
This commit is contained in:
parent
1822ebf9b1
commit
26333ee3ca
@ -103,6 +103,8 @@ static const char ZIPFILE_SCHEMA[] =
|
||||
#define ZIPFILE_SIGNATURE_EOCD 0x06054b50
|
||||
#define ZIPFILE_LFH_FIXED_SZ 30
|
||||
|
||||
#define ZIPFILE_EOCD_FIXED_SZ 22
|
||||
|
||||
/*
|
||||
** Set the error message contained in context ctx to the results of
|
||||
** vprintf(zFmt, ...).
|
||||
@ -645,7 +647,7 @@ static int zipfileGetEntry(
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( aBlob==0 ){
|
||||
aRead = (u8*)pTab->aBuffer;
|
||||
aRead = pTab->aBuffer;
|
||||
rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
|
||||
}else{
|
||||
aRead = (u8*)&aBlob[iOff];
|
||||
@ -1094,10 +1096,7 @@ static int zipfileFilter(
|
||||
if( pTab->zFile ){
|
||||
zFile = pTab->zFile;
|
||||
}else if( idxNum==0 ){
|
||||
/* Error. This is an eponymous virtual table and the user has not
|
||||
** supplied a file name. */
|
||||
zipfileSetErrmsg(pCsr, "table function zipfile() requires an argument");
|
||||
return SQLITE_ERROR;
|
||||
bInMemory = 1;
|
||||
}else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
|
||||
const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
|
||||
int nBlob = sqlite3_value_bytes(argv[0]);
|
||||
@ -1166,11 +1165,14 @@ static int zipfileBestIndex(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static ZipfileEntry *zipfileNewEntry(const char *zPath){
|
||||
static ZipfileEntry *zipfileNewEntry(const char *zPath, int nData){
|
||||
ZipfileEntry *pNew;
|
||||
pNew = sqlite3_malloc(sizeof(ZipfileEntry));
|
||||
pNew = sqlite3_malloc(sizeof(ZipfileEntry) + nData);
|
||||
if( pNew ){
|
||||
memset(pNew, 0, sizeof(ZipfileEntry));
|
||||
if( nData ){
|
||||
pNew->aData = (u8*)&pNew[1];
|
||||
}
|
||||
pNew->cds.zFile = sqlite3_mprintf("%s", zPath);
|
||||
if( pNew->cds.zFile==0 ){
|
||||
sqlite3_free(pNew);
|
||||
@ -1180,46 +1182,51 @@ static ZipfileEntry *zipfileNewEntry(const char *zPath){
|
||||
return pNew;
|
||||
}
|
||||
|
||||
static int zipfileAppendEntry(
|
||||
ZipfileTab *pTab,
|
||||
ZipfileCDS *pCds,
|
||||
const char *zPath, /* Path for new entry */
|
||||
int nPath, /* strlen(zPath) */
|
||||
const u8 *pData,
|
||||
int nData,
|
||||
u32 mTime
|
||||
){
|
||||
u8 *aBuf = pTab->aBuffer;
|
||||
int rc;
|
||||
static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){
|
||||
ZipfileCDS *pCds = &pEntry->cds;
|
||||
u8 *a = aBuf;
|
||||
|
||||
pCds->nExtra = 9;
|
||||
|
||||
zipfileWrite32(aBuf, ZIPFILE_SIGNATURE_LFH);
|
||||
zipfileWrite16(aBuf, pCds->iVersionExtract);
|
||||
zipfileWrite16(aBuf, pCds->flags);
|
||||
zipfileWrite16(aBuf, pCds->iCompression);
|
||||
zipfileWrite16(aBuf, pCds->mTime);
|
||||
zipfileWrite16(aBuf, pCds->mDate);
|
||||
zipfileWrite32(aBuf, pCds->crc32);
|
||||
zipfileWrite32(aBuf, pCds->szCompressed);
|
||||
zipfileWrite32(aBuf, pCds->szUncompressed);
|
||||
zipfileWrite16(aBuf, (u16)nPath);
|
||||
zipfileWrite16(aBuf, pCds->nExtra);
|
||||
assert( aBuf==&pTab->aBuffer[ZIPFILE_LFH_FIXED_SZ] );
|
||||
rc = zipfileAppendData(pTab, pTab->aBuffer, (int)(aBuf - pTab->aBuffer));
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = zipfileAppendData(pTab, (const u8*)zPath, nPath);
|
||||
}
|
||||
/* Write the LFH itself */
|
||||
zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH);
|
||||
zipfileWrite16(a, pCds->iVersionExtract);
|
||||
zipfileWrite16(a, pCds->flags);
|
||||
zipfileWrite16(a, pCds->iCompression);
|
||||
zipfileWrite16(a, pCds->mTime);
|
||||
zipfileWrite16(a, pCds->mDate);
|
||||
zipfileWrite32(a, pCds->crc32);
|
||||
zipfileWrite32(a, pCds->szCompressed);
|
||||
zipfileWrite32(a, pCds->szUncompressed);
|
||||
zipfileWrite16(a, (u16)pCds->nFile);
|
||||
zipfileWrite16(a, pCds->nExtra);
|
||||
assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] );
|
||||
|
||||
if( rc==SQLITE_OK && pCds->nExtra ){
|
||||
aBuf = pTab->aBuffer;
|
||||
zipfileWrite16(aBuf, ZIPFILE_EXTRA_TIMESTAMP);
|
||||
zipfileWrite16(aBuf, 5);
|
||||
*aBuf++ = 0x01;
|
||||
zipfileWrite32(aBuf, mTime);
|
||||
rc = zipfileAppendData(pTab, pTab->aBuffer, 9);
|
||||
}
|
||||
/* Add the file name */
|
||||
memcpy(a, pCds->zFile, (int)pCds->nFile);
|
||||
a += (int)pCds->nFile;
|
||||
|
||||
/* The "extra" data */
|
||||
zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
|
||||
zipfileWrite16(a, 5);
|
||||
*a++ = 0x01;
|
||||
zipfileWrite32(a, pEntry->mUnixTime);
|
||||
|
||||
return a-aBuf;
|
||||
}
|
||||
|
||||
static int zipfileAppendEntry(
|
||||
ZipfileTab *pTab,
|
||||
ZipfileEntry *pEntry,
|
||||
const u8 *pData,
|
||||
int nData
|
||||
){
|
||||
u8 *aBuf = pTab->aBuffer;
|
||||
int nBuf;
|
||||
int rc;
|
||||
|
||||
nBuf = zipfileSerializeLFH(pEntry, aBuf);
|
||||
rc = zipfileAppendData(pTab, aBuf, nBuf);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = zipfileAppendData(pTab, pData, nData);
|
||||
}
|
||||
@ -1303,8 +1310,7 @@ static int zipfileUpdate(
|
||||
int bIsDir = 0;
|
||||
u32 iCrc32 = 0;
|
||||
|
||||
assert( pTab->zFile );
|
||||
assert( pTab->pWriteFd );
|
||||
assert( (pTab->zFile==0)==(pTab->pWriteFd==0) );
|
||||
|
||||
/* If this is a DELETE or UPDATE, find the archive entry to delete. */
|
||||
if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
|
||||
@ -1407,7 +1413,7 @@ static int zipfileUpdate(
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Create the new CDS record. */
|
||||
pNew = zipfileNewEntry(zPath);
|
||||
pNew = zipfileNewEntry(zPath, pTab->zFile ? 0 : (nData+1));
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@ -1423,9 +1429,11 @@ static int zipfileUpdate(
|
||||
pNew->cds.iOffset = (u32)pTab->szCurrent;
|
||||
pNew->cds.nFile = nPath;
|
||||
pNew->mUnixTime = (u32)mTime;
|
||||
rc = zipfileAppendEntry(
|
||||
pTab, &pNew->cds, zPath, nPath, pData, nData, pNew->mUnixTime
|
||||
);
|
||||
if( pTab->zFile ){
|
||||
rc = zipfileAppendEntry(pTab, pNew, pData, nData);
|
||||
}else{
|
||||
memcpy(pNew->aData, pData, nData);
|
||||
}
|
||||
zipfileAddEntry(pTab, pOld, pNew);
|
||||
}
|
||||
}
|
||||
@ -1450,20 +1458,24 @@ static int zipfileUpdate(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
|
||||
u8 *a = aBuf;
|
||||
zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD);
|
||||
zipfileWrite16(a, p->iDisk);
|
||||
zipfileWrite16(a, p->iFirstDisk);
|
||||
zipfileWrite16(a, p->nEntry);
|
||||
zipfileWrite16(a, p->nEntryTotal);
|
||||
zipfileWrite32(a, p->nSize);
|
||||
zipfileWrite32(a, p->iOffset);
|
||||
zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/
|
||||
|
||||
return a-aBuf;
|
||||
}
|
||||
|
||||
static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
|
||||
u8 *aBuf = pTab->aBuffer;
|
||||
|
||||
zipfileWrite32(aBuf, ZIPFILE_SIGNATURE_EOCD);
|
||||
zipfileWrite16(aBuf, p->iDisk);
|
||||
zipfileWrite16(aBuf, p->iFirstDisk);
|
||||
zipfileWrite16(aBuf, p->nEntry);
|
||||
zipfileWrite16(aBuf, p->nEntryTotal);
|
||||
zipfileWrite32(aBuf, p->nSize);
|
||||
zipfileWrite32(aBuf, p->iOffset);
|
||||
zipfileWrite16(aBuf, 0); /* Size of trailing comment in bytes*/
|
||||
|
||||
assert( (aBuf-pTab->aBuffer)==22 );
|
||||
return zipfileAppendData(pTab, pTab->aBuffer, (int)(aBuf - pTab->aBuffer));
|
||||
int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer);
|
||||
assert( nBuf==ZIPFILE_EOCD_FIXED_SZ );
|
||||
return zipfileAppendData(pTab, pTab->aBuffer, nBuf);
|
||||
}
|
||||
|
||||
static int zipfileBegin(sqlite3_vtab *pVtab){
|
||||
@ -1471,34 +1483,26 @@ static int zipfileBegin(sqlite3_vtab *pVtab){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( pTab->pWriteFd==0 );
|
||||
if( pTab->zFile ){
|
||||
/* Open a write fd on the file. Also load the entire central directory
|
||||
** structure into memory. During the transaction any new file data is
|
||||
** appended to the archive file, but the central directory is accumulated
|
||||
** in main-memory until the transaction is committed. */
|
||||
pTab->pWriteFd = fopen(pTab->zFile, "ab+");
|
||||
if( pTab->pWriteFd==0 ){
|
||||
pTab->base.zErrMsg = sqlite3_mprintf(
|
||||
"zipfile: failed to open file %s for writing", pTab->zFile
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
fseek(pTab->pWriteFd, 0, SEEK_END);
|
||||
pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
|
||||
rc = zipfileLoadDirectory(pTab, 0, 0);
|
||||
}
|
||||
|
||||
/* This table is only writable if a default archive path was specified
|
||||
** as part of the CREATE VIRTUAL TABLE statement. */
|
||||
if( pTab->zFile==0 ){
|
||||
pTab->base.zErrMsg = sqlite3_mprintf(
|
||||
"zipfile: writing requires a default archive"
|
||||
);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* Open a write fd on the file. Also load the entire central directory
|
||||
** structure into memory. During the transaction any new file data is
|
||||
** appended to the archive file, but the central directory is accumulated
|
||||
** in main-memory until the transaction is committed. */
|
||||
pTab->pWriteFd = fopen(pTab->zFile, "ab+");
|
||||
if( pTab->pWriteFd==0 ){
|
||||
pTab->base.zErrMsg = sqlite3_mprintf(
|
||||
"zipfile: failed to open file %s for writing", pTab->zFile
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
fseek(pTab->pWriteFd, 0, SEEK_END);
|
||||
pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
|
||||
rc = zipfileLoadDirectory(pTab, 0, 0);
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
zipfileCleanupTransaction(pTab);
|
||||
if( rc!=SQLITE_OK ){
|
||||
zipfileCleanupTransaction(pTab);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -1643,6 +1647,73 @@ static void zipfileFunctionCds(
|
||||
}
|
||||
}
|
||||
|
||||
static void zipfileFree(void *p) { sqlite3_free(p); }
|
||||
|
||||
static void zipfileFunctionBlob(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
ZipfileCsr *pCsr;
|
||||
ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
|
||||
ZipfileEntry *p;
|
||||
int nBody = 0;
|
||||
int nCds = 0;
|
||||
int nEocd = ZIPFILE_EOCD_FIXED_SZ;
|
||||
ZipfileEOCD eocd;
|
||||
|
||||
u8 *aZip;
|
||||
int nZip;
|
||||
|
||||
u8 *aBody;
|
||||
u8 *aCds;
|
||||
|
||||
pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
|
||||
if( pCsr->pFile || pTab->zFile ){
|
||||
sqlite3_result_error(context, "illegal use of zipfile_blob()", -1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Figure out how large the final file will be */
|
||||
for(p=pTab->pFirstEntry; p; p=p->pNext){
|
||||
nBody += ZIPFILE_LFH_FIXED_SZ + p->cds.nFile + 9 + p->cds.szCompressed;
|
||||
nCds += ZIPFILE_CDS_FIXED_SZ + p->cds.nFile + 9;
|
||||
}
|
||||
|
||||
/* Allocate space to create the serialized file */
|
||||
nZip = nBody + nCds + nEocd;
|
||||
aZip = (u8*)sqlite3_malloc(nZip);
|
||||
if( aZip==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
aBody = aZip;
|
||||
aCds = &aZip[nBody];
|
||||
|
||||
/* Populate the body and CDS */
|
||||
memset(&eocd, 0, sizeof(eocd));
|
||||
for(p=pTab->pFirstEntry; p; p=p->pNext){
|
||||
p->cds.iOffset = (aBody - aZip);
|
||||
aBody += zipfileSerializeLFH(p, aBody);
|
||||
if( p->cds.szCompressed ){
|
||||
memcpy(aBody, p->aData, p->cds.szCompressed);
|
||||
aBody += p->cds.szCompressed;
|
||||
}
|
||||
aCds += zipfileSerializeCDS(p, aCds);
|
||||
eocd.nEntry++;
|
||||
}
|
||||
|
||||
/* Append the EOCD record */
|
||||
assert( aBody==&aZip[nBody] );
|
||||
assert( aCds==&aZip[nBody+nCds] );
|
||||
eocd.nEntryTotal = eocd.nEntry;
|
||||
eocd.nSize = nCds;
|
||||
eocd.iOffset = nBody;
|
||||
zipfileSerializeEOCD(&eocd, aCds);
|
||||
|
||||
sqlite3_result_blob(context, aZip, nZip, zipfileFree);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** xFindFunction method.
|
||||
@ -1660,6 +1731,11 @@ static int zipfileFindFunction(
|
||||
*ppArg = (void*)pVtab;
|
||||
return 1;
|
||||
}
|
||||
if( sqlite3_stricmp("zipfile_blob", zName)==0 ){
|
||||
*pxFunc = zipfileFunctionBlob;
|
||||
*ppArg = (void*)pVtab;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1693,9 +1769,8 @@ static int zipfileRegister(sqlite3 *db){
|
||||
};
|
||||
|
||||
int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_overload_function(db, "zipfile_cds", -1);
|
||||
}
|
||||
if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
|
||||
if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_blob", -1);
|
||||
return rc;
|
||||
}
|
||||
#else /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
||||
C Changes\sto\savoid\sa\sharmless\sUB\swarning\sfrom\sclang.
|
||||
D 2018-01-27T14:25:27.955
|
||||
C If\sa\szipfile\svirtual\stable\sis\screated\swith\sno\sargument\s-\s"CREATE\sVIRTUAL\sTABLE\nzzz\sUSING\szipfile()"\s-\saccumulate\sdata\sin\smemory.\sSupport\s"SELECT\nzipfile_blob(z)\sFROM\szzz\sLIMIT\s1"\sto\sretrieve\sa\szip\sarchive\simage.
|
||||
D 2018-01-27T16:29:59.042
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in 7a3f714b4fcf793108042b7b0a5c720b0b310ec84314d61ba7f3f49f27e550ea
|
||||
@ -304,7 +304,7 @@ F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
|
||||
F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9
|
||||
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
|
||||
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
|
||||
F ext/misc/zipfile.c 40195c1cfb43e0ebdf176d37346fea1cb18246e35fbfce477eadc2ff5f7490df
|
||||
F ext/misc/zipfile.c df57128d9ad2a1e60097d7971e787b582fb66ce0926577cb6f5978f7af210b8c
|
||||
F ext/rbu/rbu.c ea7d1b7eb44c123a2a619332e19fe5313500705c4a58aaa1887905c0d83ffc2e
|
||||
F ext/rbu/rbu1.test 43836fac8c7179a358eaf38a8a1ef3d6e6285842
|
||||
F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee
|
||||
@ -1603,7 +1603,7 @@ F test/wordcount.c cb589cec469a1d90add05b1f8cee75c7210338d87a5afd65260ed5c0f4bbf
|
||||
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
|
||||
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
|
||||
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
|
||||
F test/zipfile.test 0834b33e000991a80d94167e84af346162d212526d8efee0b9d4ba84589fe292
|
||||
F test/zipfile.test 1b213bdc31eddd4a41042875dbdb29b6ea12b7da7a372a8eb07f61d0d76d800f
|
||||
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
||||
F tool/GetTclKit.bat 8995df40c4209808b31f24de0b58f90930239a234f7591e3675d45bfbb990c5d
|
||||
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
|
||||
@ -1702,7 +1702,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 5259d4847f2b73f26b2385f9d8cff8fe0cabc54b4deab8477c87c8d1bb5535b1
|
||||
R dc25ffafa3daf6e245ccddfac4936cfd
|
||||
U drh
|
||||
Z 83f6cfb83d43c9463ef36c14a8c84938
|
||||
P 19f5c1400054df10688ab448e7e23afef97cab4a7c7a3e411f7527509b515dd8
|
||||
R 8b2b96d9b8d1e07c4df7e0d2971e5e57
|
||||
U dan
|
||||
Z e468bfc5bd8b08bb5b9404b26ad000bc
|
||||
|
@ -1 +1 @@
|
||||
19f5c1400054df10688ab448e7e23afef97cab4a7c7a3e411f7527509b515dd8
|
||||
e63185edfe0c316aa60c1fa085d032425ecc7db54536dfa5a977772eaf3c240e
|
@ -32,8 +32,23 @@ proc do_zipfile_blob_test {tn file} {
|
||||
set data [read $fd]
|
||||
close $fd
|
||||
|
||||
set res2 [db eval { SELECT name,mode,mtime,method,quote(data) FROM zipfile($data) }]
|
||||
uplevel [list do_test $tn [list set {} $res2] $res1]
|
||||
set res2 [db eval {
|
||||
SELECT name,mode,mtime,method,quote(data) FROM zipfile($data)
|
||||
}]
|
||||
|
||||
uplevel [list do_test $tn.1 [list set {} $res2] $res1]
|
||||
|
||||
set T "$file.test_zip"
|
||||
set fd [open $T w]
|
||||
fconfigure $fd -translation binary -encoding binary
|
||||
puts -nonewline $fd $data
|
||||
close $fd
|
||||
|
||||
set res3 [
|
||||
db eval { SELECT name,mode,mtime,method,quote(data) FROM zipfile($T) }
|
||||
]
|
||||
|
||||
uplevel [list do_test $tn.2 [list set {} $res3] $res1]
|
||||
}
|
||||
|
||||
forcedelete test.zip
|
||||
@ -271,6 +286,27 @@ do_catchsql_test 3.2 {
|
||||
SELECT rowid FROM x1
|
||||
} {1 {no such column: rowid}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
forcedelete test.zip
|
||||
load_static_extension db zipfile
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE x2 USING zipfile();
|
||||
INSERT INTO x2(name, data) VALUES('dir1/', NULL);
|
||||
INSERT INTO x2(name, data) VALUES('file1', '1234');
|
||||
INSERT INTO x2(name, data) VALUES('dir1/file2', '5678');
|
||||
SELECT name, data FROM x2
|
||||
} {
|
||||
dir1/ {} file1 1234 dir1/file2 5678
|
||||
}
|
||||
|
||||
do_test 4.1 {
|
||||
set data [db one {SELECT zipfile_blob(z) FROM x2 LIMIT 1}]
|
||||
db eval { SELECT name, data FROM zipfile($data) }
|
||||
} {dir1/ {} file1 1234 dir1/file2 5678}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user