/ Check-in [8ad35d48]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add support for INSERT OR REPLACE and INSERT OR IGNORE on the zipfile extension.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 8ad35d483e4293d5571eeacc20fd26cdc4064fbee7b63d974879d507a0ee5792
User & Date: drh 2018-03-10 14:17:01
Context
2018-03-10
20:25
Fix the second callback argument to the "profile" response of the "trace_v2" method in the TCL interface so that it shows the actual number of nanoseconds for the command, not the address of the variable containing the number of nanoseconds. check-in: 8f9a1251 user: drh tags: trunk
14:17
Add support for INSERT OR REPLACE and INSERT OR IGNORE on the zipfile extension. check-in: 8ad35d48 user: drh tags: trunk
13:21
Improved error messages from the zipfile extension. check-in: f634a7e3 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/zipfile.c.

   264    264     ZipfileCsr *pCsrNext;      /* Next cursor on same virtual table */
   265    265   };
   266    266   
   267    267   typedef struct ZipfileTab ZipfileTab;
   268    268   struct ZipfileTab {
   269    269     sqlite3_vtab base;         /* Base class - must be first */
   270    270     char *zFile;               /* Zip file this table accesses (may be NULL) */
          271  +  sqlite3 *db;               /* Host database connection */
   271    272     u8 *aBuffer;               /* Temporary buffer used for various tasks */
   272    273   
   273    274     ZipfileCsr *pCsrList;      /* List of cursors */
   274    275     i64 iNextCsrid;
   275    276   
   276    277     /* The following are used by write transactions only */
   277    278     ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
................................................................................
   356    357     }
   357    358   
   358    359     rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
   359    360     if( rc==SQLITE_OK ){
   360    361       pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile);
   361    362       if( pNew==0 ) return SQLITE_NOMEM;
   362    363       memset(pNew, 0, nByte+nFile);
          364  +    pNew->db = db;
   363    365       pNew->aBuffer = (u8*)&pNew[1];
   364    366       if( zFile ){
   365    367         pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
   366    368         memcpy(pNew->zFile, zFile, nFile);
   367    369         zipfileDequote(pNew->zFile);
   368    370       }
   369    371     }
................................................................................
  1612   1614       }
  1613   1615   
  1614   1616       /* Check that we're not inserting a duplicate entry */
  1615   1617       if( pOld==0 && rc==SQLITE_OK ){
  1616   1618         ZipfileEntry *p;
  1617   1619         for(p=pTab->pFirstEntry; p; p=p->pNext){
  1618   1620           if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
  1619         -          zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
  1620         -          rc = SQLITE_CONSTRAINT;
         1621  +          switch( sqlite3_vtab_on_conflict(pTab->db) ){
         1622  +            case SQLITE_IGNORE: {
         1623  +              goto zipfile_update_done;
         1624  +            }
         1625  +            case SQLITE_REPLACE: {
         1626  +              pOld = p;
         1627  +              break;
         1628  +            }
         1629  +            default: {
         1630  +              zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
         1631  +              rc = SQLITE_CONSTRAINT;
         1632  +              break;
         1633  +            }
         1634  +          }
  1621   1635             break;
  1622   1636           }
  1623   1637         }
  1624   1638       }
  1625   1639   
  1626   1640       if( rc==SQLITE_OK ){
  1627   1641         /* Create the new CDS record. */
................................................................................
  1657   1671         }
  1658   1672       }
  1659   1673       for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext));
  1660   1674       *pp = (*pp)->pNext;
  1661   1675       zipfileEntryFree(pOld);
  1662   1676     }
  1663   1677   
         1678  +zipfile_update_done:
  1664   1679     sqlite3_free(pFree);
  1665   1680     sqlite3_free(zFree);
  1666   1681     return rc;
  1667   1682   }
  1668   1683   
  1669   1684   static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
  1670   1685     u8 *a = aBuf;

Changes to test/zipfile.test.

   632    632       VALUES('dir2/') UNION ALL
   633    633       VALUES('dir3//') UNION ALL
   634    634       VALUES('dir4///') UNION ALL
   635    635       VALUES('/') 
   636    636     )
   637    637     SELECT name FROM zipfile((SELECT zipfile(nm, NULL) FROM src))
   638    638   } {dir1/ dir2/ dir3/ dir4/ /}
          639  +
          640  +#-------------------------------------------------------------------------
          641  +# INSERT OR REPLACE and INSERT OR IGNORE
          642  +#
          643  +catch {db close}
          644  +forcedelete test.zip test.db
          645  +sqlite3 db :memory:
          646  +load_static_extension db zipfile
          647  +do_execsql_test 10.0 {
          648  +  CREATE VIRTUAL TABLE z USING zipfile('test.zip');
          649  +} {}
          650  +do_catchsql_test 10.1 {
          651  +  INSERT INTO z(name,data) VALUES('a0','one'),('a0','two');
          652  +} {1 {duplicate name: "a0"}}
          653  +do_execsql_test 10.2 {
          654  +  SELECT name, data FROM z;
          655  +} {a0 one}
          656  +do_execsql_test 10.3 {
          657  +  REPLACE INTO z(name,data) VALUES('a0','three'),('a0','four');
          658  +} {}
          659  +do_execsql_test 10.4 {
          660  +  SELECT name, data FROM z;
          661  +} {a0 four}
          662  +do_execsql_test 10.5 {
          663  +  INSERT OR IGNORE INTO z(name,data) VALUES('a0','five'),('a0','six');
          664  +} {}
          665  +do_execsql_test 10.6 {
          666  +  SELECT name, data FROM z;
          667  +} {a0 four}
          668  +
          669  +
   639    670   finish_test