/ Check-in [8ad35d48]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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 Unified Diffs Ignore Whitespace Patch

Changes to ext/misc/zipfile.c.

264
265
266
267
268
269
270

271
272
273
274
275
276
277
...
356
357
358
359
360
361
362

363
364
365
366
367
368
369
....
1612
1613
1614
1615
1616
1617
1618









1619
1620



1621
1622
1623
1624
1625
1626
1627
....
1657
1658
1659
1660
1661
1662
1663

1664
1665
1666
1667
1668
1669
1670
  ZipfileCsr *pCsrNext;      /* Next cursor on same virtual table */
};

typedef struct ZipfileTab ZipfileTab;
struct ZipfileTab {
  sqlite3_vtab base;         /* Base class - must be first */
  char *zFile;               /* Zip file this table accesses (may be NULL) */

  u8 *aBuffer;               /* Temporary buffer used for various tasks */

  ZipfileCsr *pCsrList;      /* List of cursors */
  i64 iNextCsrid;

  /* The following are used by write transactions only */
  ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
................................................................................
  }

  rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
  if( rc==SQLITE_OK ){
    pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile);
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, nByte+nFile);

    pNew->aBuffer = (u8*)&pNew[1];
    if( zFile ){
      pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
      memcpy(pNew->zFile, zFile, nFile);
      zipfileDequote(pNew->zFile);
    }
  }
................................................................................
    }

    /* Check that we're not inserting a duplicate entry */
    if( pOld==0 && rc==SQLITE_OK ){
      ZipfileEntry *p;
      for(p=pTab->pFirstEntry; p; p=p->pNext){
        if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){









          zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
          rc = SQLITE_CONSTRAINT;



          break;
        }
      }
    }

    if( rc==SQLITE_OK ){
      /* Create the new CDS record. */
................................................................................
      }
    }
    for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext));
    *pp = (*pp)->pNext;
    zipfileEntryFree(pOld);
  }


  sqlite3_free(pFree);
  sqlite3_free(zFree);
  return rc;
}

static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
  u8 *a = aBuf;







>







 







>







 







>
>
>
>
>
>
>
>
>
|
|
>
>
>







 







>







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
...
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
....
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
....
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
  ZipfileCsr *pCsrNext;      /* Next cursor on same virtual table */
};

typedef struct ZipfileTab ZipfileTab;
struct ZipfileTab {
  sqlite3_vtab base;         /* Base class - must be first */
  char *zFile;               /* Zip file this table accesses (may be NULL) */
  sqlite3 *db;               /* Host database connection */
  u8 *aBuffer;               /* Temporary buffer used for various tasks */

  ZipfileCsr *pCsrList;      /* List of cursors */
  i64 iNextCsrid;

  /* The following are used by write transactions only */
  ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
................................................................................
  }

  rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
  if( rc==SQLITE_OK ){
    pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile);
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, nByte+nFile);
    pNew->db = db;
    pNew->aBuffer = (u8*)&pNew[1];
    if( zFile ){
      pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
      memcpy(pNew->zFile, zFile, nFile);
      zipfileDequote(pNew->zFile);
    }
  }
................................................................................
    }

    /* Check that we're not inserting a duplicate entry */
    if( pOld==0 && rc==SQLITE_OK ){
      ZipfileEntry *p;
      for(p=pTab->pFirstEntry; p; p=p->pNext){
        if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
          switch( sqlite3_vtab_on_conflict(pTab->db) ){
            case SQLITE_IGNORE: {
              goto zipfile_update_done;
            }
            case SQLITE_REPLACE: {
              pOld = p;
              break;
            }
            default: {
              zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
              rc = SQLITE_CONSTRAINT;
              break;
            }
          }
          break;
        }
      }
    }

    if( rc==SQLITE_OK ){
      /* Create the new CDS record. */
................................................................................
      }
    }
    for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext));
    *pp = (*pp)->pNext;
    zipfileEntryFree(pOld);
  }

zipfile_update_done:
  sqlite3_free(pFree);
  sqlite3_free(zFree);
  return rc;
}

static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
  u8 *a = aBuf;

Changes to test/zipfile.test.

632
633
634
635
636
637
638































639
    VALUES('dir2/') UNION ALL
    VALUES('dir3//') UNION ALL
    VALUES('dir4///') UNION ALL
    VALUES('/') 
  )
  SELECT name FROM zipfile((SELECT zipfile(nm, NULL) FROM src))
} {dir1/ dir2/ dir3/ dir4/ /}































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
    VALUES('dir2/') UNION ALL
    VALUES('dir3//') UNION ALL
    VALUES('dir4///') UNION ALL
    VALUES('/') 
  )
  SELECT name FROM zipfile((SELECT zipfile(nm, NULL) FROM src))
} {dir1/ dir2/ dir3/ dir4/ /}

#-------------------------------------------------------------------------
# INSERT OR REPLACE and INSERT OR IGNORE
#
catch {db close}
forcedelete test.zip test.db
sqlite3 db :memory:
load_static_extension db zipfile
do_execsql_test 10.0 {
  CREATE VIRTUAL TABLE z USING zipfile('test.zip');
} {}
do_catchsql_test 10.1 {
  INSERT INTO z(name,data) VALUES('a0','one'),('a0','two');
} {1 {duplicate name: "a0"}}
do_execsql_test 10.2 {
  SELECT name, data FROM z;
} {a0 one}
do_execsql_test 10.3 {
  REPLACE INTO z(name,data) VALUES('a0','three'),('a0','four');
} {}
do_execsql_test 10.4 {
  SELECT name, data FROM z;
} {a0 four}
do_execsql_test 10.5 {
  INSERT OR IGNORE INTO z(name,data) VALUES('a0','five'),('a0','six');
} {}
do_execsql_test 10.6 {
  SELECT name, data FROM z;
} {a0 four}


finish_test