1# 2017 December 9 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# 12 13package require Tcl 8.6 14 15set testdir [file dirname $argv0] 16source $testdir/tester.tcl 17set testprefix zipfile 18 19ifcapable !vtab { 20 finish_test; return 21} 22if {[catch {load_static_extension db zipfile} error]} { 23 puts "Skipping zipfile tests, hit load error: $error" 24 finish_test; return 25} 26if {[catch {load_static_extension db fileio} error]} { 27 puts "Skipping zipfile tests, hit load error: $error" 28 finish_test; return 29} 30 31proc readfile {f} { 32 set fd [open $f] 33 fconfigure $fd -translation binary -encoding binary 34 set data [read $fd] 35 close $fd 36 set data 37} 38 39unset -nocomplain ::UNZIP 40 41if {[catch {exec unzip} msg]==0 && \ 42 [regexp -line {^UnZip \d+\.\d+ .*? Info-ZIP\.} $msg]} { 43 set ::UNZIP unzip 44 proc fix_stat_mode {name mode} { 45 if {$::tcl_platform(platform)=="windows"} { 46 # 47 # NOTE: Set or unset the write bits of the file permissions 48 # based on the read-only attribute because the Win32 49 # version of UnZip does this. 50 # 51 set writebits 0x12; # 0o22 52 set result $mode 53 if {[file attributes $name -readonly]} { 54 set result [expr {$result | $writebits}] 55 } else { 56 set result [expr {$result & ~$writebits}] 57 } 58 return $result 59 } else { 60 return $mode 61 } 62 } 63 proc do_unzip {file} { 64 forcedelete test_unzip 65 file mkdir test_unzip 66 exec $::UNZIP -d test_unzip $file 67 68 db func modefix fix_stat_mode 69 70 set res [db eval { 71 SELECT replace(name,'test_unzip/',''),modefix(name,mode),mtime,data 72 FROM fsdir('test_unzip') 73 WHERE name!='test_unzip' 74 ORDER BY name 75 }] 76 set res 77 } 78} 79 80 81# The argument is a blob (not a hex string) containing a zip archive. 82# This proc removes the extended timestamp fields from the archive 83# and returns the result. 84# 85proc remove_timestamps {blob} { 86 set hex [binary encode hex $blob] 87 set hex [string map {55540500 00000500} $hex] 88 binary decode hex $hex 89} 90 91 92# Argument $file is the name of a zip archive on disk. This function 93# executes test cases to check that the results of each of the following 94# are the same: 95# 96# SELECT * FROM zipfile($file) 97# SELECT * FROM zipfile( readfile($file) ) 98# SELECT * FROM zipfile( 99# (SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file)) 100# ) 101# 102proc do_zipfile_blob_test {tn file} { 103 104 db func r readfile 105 set q1 {SELECT name,mode,mtime,method,quote(data) FROM zipfile($file)} 106 set q2 {SELECT name,mode,mtime,method,quote(data) FROM zipfile( r($file) )} 107 set q3 {SELECT name,mode,mtime,method,quote(data) FROM zipfile( 108 ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) 109 )} 110 111 112 set r1 [db eval $q1] 113 set r2 [db eval $q2] 114 set r3 [db eval $q3] 115 #puts $r1 116 #puts $r2 117 #puts $r3 118 119 uplevel [list do_test $tn.1 [list set {} $r2] $r1] 120 uplevel [list do_test $tn.2 [list set {} $r3] $r1] 121} 122 123# Argument $file is a zip file on disk. This command runs tests to: 124# 125# 1. Unpack the archive with unix command [unzip] and compare the 126# results to reading the same archive using the zipfile() table 127# valued function. 128# 129# 2. Creates a new archive with the same contents using the zipfile() 130# aggregate function as follows: 131# 132# SELECT writefile('test_unzip.zip', 133# ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) 134# ); 135# 136# Then tests that unpacking the new archive using [unzip] produces 137# the same results as in (1). 138# 139proc do_unzip_test {tn file} { 140 db func sss strip_slash 141 142 db eval { 143 SELECT writefile('test_unzip.zip', 144 ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) 145 ); 146 } 147 148 set r1 [db eval { 149 SELECT sss(name),mode,mtime,data FROM zipfile($file) ORDER BY name 150 }] 151 set r2 [do_unzip $file] 152 set r3 [do_unzip test_unzip.zip] 153 154 uplevel [list do_test $tn.1 [list set {} $r2] $r1] 155 uplevel [list do_test $tn.2 [list set {} $r3] $r1] 156} 157proc strip_slash {in} { regsub {/$} $in {} } 158 159proc do_zip_tests {tn file} { 160 uplevel do_zipfile_blob_test $tn.1 $file 161 uplevel do_unzip_test $tn.2 $file 162} 163 164forcedelete test.zip 165do_execsql_test 1.0 { 166 CREATE VIRTUAL TABLE temp.zz USING zipfile('test.zip'); 167 PRAGMA table_info(zz); 168} { 169 0 name {} 1 {} 1 170 1 mode {} 0 {} 0 171 2 mtime {} 0 {} 0 172 3 sz {} 0 {} 0 173 4 rawdata {} 0 {} 0 174 5 data {} 0 {} 0 175 6 method {} 0 {} 0 176} 177 178do_catchsql_test 1.1.0.1 { 179 INSERT INTO zz(name, mode, mtime, sz, rawdata, method) 180 VALUES('f.txt', '-rw-r--r--', 1000000000, 5, 'abcde', 0); 181} {1 {rawdata must be NULL}} 182do_catchsql_test 1.1.0.2 { 183 INSERT INTO zz(name, mtime, sz, data, method) 184 VALUES('g.txt', 1000000002, 5, '12345', 0); 185} {1 {sz must be NULL}} 186do_catchsql_test 1.1.0.3 { 187 INSERT INTO zz(name, mtime, rawdata, method) 188 VALUES('g.txt', 1000000002, '12345', 0); 189} {1 {rawdata must be NULL}} 190do_catchsql_test 1.1.0.4 { 191 INSERT INTO zz(name, data, method) 192 VALUES('g.txt', '12345', 7); 193} {1 {unknown compression method: 7}} 194 195do_execsql_test 1.1.1 { 196 INSERT INTO zz(name, mode, mtime, data, method) 197 VALUES('f.txt', '-rw-r--r--', 1000000000, 'abcde', 0); 198} 199do_execsql_test 1.1.2 { 200 INSERT INTO zz(name, mode, mtime, data, method) 201 VALUES('g.txt', NULL, 1000000002, '12345', 0); 202} 203 204do_execsql_test 1.2 { 205 SELECT name, mtime, data FROM zipfile('test.zip') 206} { 207 f.txt 1000000000 abcde 208 g.txt 1000000002 12345 209} 210do_zip_tests 1.2a test.zip 211 212do_execsql_test 1.3 { 213 INSERT INTO zz(name, mode, mtime, data) VALUES('h.txt', 214 '-rw-r--r--', 1000000004, 'aaaaaaaaaabbbbbbbbbb' 215 ); 216} 217do_zip_tests 1.3a test.zip 218 219do_execsql_test 1.4 { 220 SELECT name, mtime, data, method FROM zipfile('test.zip'); 221} { 222 f.txt 1000000000 abcde 0 223 g.txt 1000000002 12345 0 224 h.txt 1000000004 aaaaaaaaaabbbbbbbbbb 8 225} 226 227ifcapable json1 { 228 do_execsql_test 1.4.1 { 229 SELECT name, json_extract( zipfile_cds(z) , '$.crc32')!=0 230 FROM zipfile('test.zip'); 231 } { 232 f.txt 1 233 g.txt 1 234 h.txt 1 235 } 236} 237do_catchsql_test 1.4.2 { 238 SELECT zipfile_cds(mode) FROM zipfile('test.zip'); 239} {0 {{} {} {}}} 240 241do_execsql_test 1.5.1 { 242 BEGIN; 243 INSERT INTO zz(name, mode, mtime, data, method) 244 VALUES('i.txt', '-rw-r--r--', 1000000006, 'zxcvb', 0); 245 SELECT name FROM zz; 246 COMMIT; 247} {f.txt g.txt h.txt i.txt} 248do_execsql_test 1.5.2 { 249 SELECT name FROM zz; 250} {f.txt g.txt h.txt i.txt} 251do_execsql_test 1.5.3 { 252 SELECT data FROM zz WHERE name='i.txt'; 253} {zxcvb} 254 255do_execsql_test 1.6.0 { 256 DELETE FROM zz WHERE name='g.txt'; 257 SELECT name FROM zz; 258} {f.txt h.txt i.txt} 259 260do_execsql_test 1.6.1 { 261 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 262} { 263 f.txt 33188 1000000000 abcde 0 264 h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8 265 i.txt 33188 1000000006 zxcvb 0 266} 267do_zip_tests 1.6.1a test.zip 268 269do_execsql_test 1.6.2 { 270 UPDATE zz SET mtime=4 WHERE name='i.txt'; 271 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 272} { 273 f.txt 33188 1000000000 abcde 0 274 h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8 275 i.txt 33188 4 zxcvb 0 276} 277 278if {$::tcl_platform(platform)=="unix"} { 279 set modes -rw-r--r-x 280 set perms 33189 281} else { 282 set modes -rw-r--r--; # no execute bits on Win32 283 set perms 33188 284} 285 286do_execsql_test 1.6.3 { 287 UPDATE zz SET mode=$modes WHERE name='h.txt'; 288 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 289} [string map [list %perms% $perms] { 290 f.txt 33188 1000000000 abcde 0 291 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 292 i.txt 33188 4 zxcvb 0 293}] 294do_zip_tests 1.6.3a test.zip 295 296do_execsql_test 1.6.4 { 297 UPDATE zz SET name = 'blue.txt' WHERE name='f.txt'; 298 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 299} [string map [list %perms% $perms] { 300 blue.txt 33188 1000000000 abcde 0 301 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 302 i.txt 33188 4 zxcvb 0 303}] 304do_zip_tests 1.6.4a test.zip 305 306do_execsql_test 1.6.5 { 307 UPDATE zz SET data = 'edcba' WHERE name='blue.txt'; 308 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 309} [string map [list %perms% $perms] { 310 blue.txt 33188 1000000000 edcba 0 311 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 312 i.txt 33188 4 zxcvb 0 313}] 314 315do_execsql_test 1.6.6 { 316 UPDATE zz SET mode=NULL, data = NULL WHERE name='blue.txt'; 317 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 318} [string map [list %perms% $perms] { 319 blue.txt/ 16877 1000000000 {} 0 320 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 321 i.txt 33188 4 zxcvb 0 322}] 323 324do_catchsql_test 1.6.7 { 325 UPDATE zz SET data=NULL WHERE name='i.txt' 326} {1 {zipfile: mode does not match data}} 327do_execsql_test 1.6.8 { 328 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 329} [string map [list %perms% $perms] { 330 blue.txt/ 16877 1000000000 {} 0 331 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 332 i.txt 33188 4 zxcvb 0 333}] 334 335do_execsql_test 1.6.9 { 336 UPDATE zz SET data = '' WHERE name='i.txt'; 337 SELECT name,mode,mtime,data,method from zipfile('test.zip'); 338} [string map [list %perms% $perms] { 339 blue.txt/ 16877 1000000000 {} 0 340 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 341 i.txt 33188 4 {} 0 342}] 343 344do_execsql_test 1.6.10 { 345 SELECT a.name, a.data 346 FROM zz AS a, zz AS b 347 WHERE a.name=+b.name AND +a.mode=b.mode 348} { 349 blue.txt/ {} 350 h.txt aaaaaaaaaabbbbbbbbbb 351 i.txt {} 352} 353 354do_execsql_test 1.6.11 { 355 SELECT name, data FROM zz WHERE name LIKE '%txt' 356} { 357 h.txt aaaaaaaaaabbbbbbbbbb 358 i.txt {} 359} 360 361do_execsql_test 1.7 { 362 DELETE FROM zz; 363 SELECT * FROM zz; 364} {} 365 366#------------------------------------------------------------------------- 367db close 368forcedelete test.zip 369reset_db 370load_static_extension db fileio 371load_static_extension db zipfile 372do_execsql_test 2.1 { 373 CREATE VIRTUAL TABLE zzz USING zipfile('test.zip'); 374 INSERT INTO zzz(name, mode) VALUES('dirname', 'drwxr-xr-x'); 375 SELECT name, mode, data FROM zzz; 376} {dirname/ 16877 {}} 377do_execsql_test 2.2 { 378 INSERT INTO zzz(name, data) VALUES('dirname2', NULL); 379 INSERT INTO zzz(name, data) VALUES('dirname2/file1.txt', 'abcdefghijklmnop'); 380 SELECT name, mode, data FROM zzz; 381} { 382 dirname/ 16877 {} 383 dirname2/ 16877 {} 384 dirname2/file1.txt 33188 abcdefghijklmnop 385} 386 387do_catchsql_test 2.3 { 388 UPDATE zzz SET name = 'dirname3' WHERE name = 'dirname/'; 389} {0 {}} 390do_execsql_test 2.4 { 391 SELECT name, mode, data FROM zzz; 392} { 393 dirname3/ 16877 {} 394 dirname2/ 16877 {} 395 dirname2/file1.txt 33188 abcdefghijklmnop 396} 397do_zip_tests 2.4a test.zip 398 399# Check that the [unzip] utility can unpack our archive. 400# 401if {[info exists ::UNZIP]} { 402 do_test 2.5.1 { 403 forcedelete dirname 404 forcedelete dirname2 405 if {$::tcl_platform(platform)=="unix"} { 406 set null /dev/null 407 } else { 408 set null NUL 409 } 410 set rc [catch { exec $::UNZIP test.zip > $null } msg] 411 list $rc $msg 412 } {0 {}} 413 do_test 2.5.2 { file isdir dirname3 } 1 414 do_test 2.5.3 { file isdir dirname2 } 1 415 do_test 2.5.4 { file isdir dirname2/file1.txt } 0 416 do_test 2.5.5 { 417 set fd [open dirname2/file1.txt] 418 set data [read $fd] 419 close $fd 420 set data 421 } {abcdefghijklmnop} 422} 423 424#------------------------------------------------------------------------- 425reset_db 426forcedelete test.zip 427load_static_extension db zipfile 428load_static_extension db fileio 429 430do_execsql_test 3.0 { 431 CREATE VIRTUAL TABLE temp.x1 USING zipfile('test.zip'); 432 INSERT INTO x1(name, data) VALUES('dir1/', NULL); 433 INSERT INTO x1(name, data) VALUES('file1', '1234'); 434 INSERT INTO x1(name, data) VALUES('dir1/file2', '5678'); 435} 436foreach {tn fname} { 437 1 dir1 438 2 file1 439 3 dir1/file2 440} { 441 do_catchsql_test 3.1.$tn.0 { 442 INSERT INTO x1(name, data) VALUES($fname, NULL); 443 } [list 1 "duplicate name: \"$fname/\""] 444 do_catchsql_test 3.1.$tn.1 { 445 INSERT INTO x1(name, data) VALUES($fname || '/', NULL); 446 } [list 1 "duplicate name: \"$fname/\""] 447 do_catchsql_test 3.1.$tn.2 { 448 INSERT INTO x1(name, data) VALUES($fname, 'abcd'); 449 } [list 1 "duplicate name: \"$fname\""] 450} 451 452do_catchsql_test 3.2 { 453 SELECT rowid FROM x1 454} {1 {no such column: rowid}} 455 456#------------------------------------------------------------------------- 457# Test some error conditions. 458# 459do_catchsql_test 4.1 { 460 CREATE VIRTUAL TABLE yyy USING zipfile(); 461} {1 {zipfile constructor requires one argument}} 462do_catchsql_test 4.2 { 463 CREATE VIRTUAL TABLE yyy USING zipfile('test.zip', 'test.zip'); 464} {1 {zipfile constructor requires one argument}} 465 466do_catchsql_test 4.3 { 467 SELECT * FROM zipfile() 468} {1 {zipfile() function requires an argument}} 469 470do_catchsql_test 4.4 { 471 SELECT * FROM zipfile('/path/that/does/not/exist') 472} {1 {cannot open file: /path/that/does/not/exist}} 473 474foreach {tn mode} { 475 1 abcd 476 2 brwxrwxrwx 477 3 lrwxrrxrwx 478} { 479 do_catchsql_test 4.5.$tn { 480 WITH m(m) AS ( SELECT $mode) 481 SELECT zipfile('a.txt', m, 1000, 'xyz') FROM m 482 } [list 1 "zipfile: parse error in mode: $mode"] 483} 484 485do_catchsql_test 4.6 { 486 WITH c(name,data) AS ( SELECT 'a.txt', 'abc') 487 SELECT zipfile(name) FROM c 488} {1 {wrong number of arguments to function zipfile()}} 489 490do_catchsql_test 4.7 { 491 WITH c(name,data) AS ( 492 SELECT 'a.txt', 'abc' UNION ALL 493 SELECT NULL, 'def' 494 ) 495 SELECT zipfile(name,data) FROM c 496} {1 {first argument to zipfile() must be non-NULL}} 497 498do_catchsql_test 4.8 { 499 WITH c(name,data,method) AS ( 500 SELECT 'a.txt', 'abc', 0 501 UNION SELECT 'b.txt', 'def', 8 502 UNION SELECT 'c.txt', 'ghi', 16 503 ) 504 SELECT zipfile(name,NULL,NULL,data,method) FROM c 505} {1 {illegal method value: 16}} 506 507do_catchsql_test 4.9 { 508 WITH c(name,data) AS ( 509 SELECT 'a.txt', 'abc' 510 UNION SELECT 'b.txt', 'def' 511 UNION SELECT 'c.txt/', 'ghi' 512 ) 513 SELECT zipfile(name,NULL,NULL,data) FROM c 514} {1 {non-directory name must not end with /}} 515 516#-------------------------------------------------------------------------- 517 518db func rt remove_timestamps 519do_execsql_test 5.0 { 520 WITH c(name,mtime,data) AS ( 521 SELECT 'a.txt', 946684800, 'abc' 522 ) 523 SELECT name,mtime,data FROM zipfile( 524 ( SELECT rt( zipfile(name,NULL,mtime,data,NULL) ) FROM c ) 525 ) 526} { 527 a.txt 946684800 abc 528} 529 530if {[info exists ::UNZIP]} { 531ifcapable datetime { 532 forcedelete test1.zip test2.zip 533 do_test 6.0 { 534 execsql { 535 WITH c(name,mtime,data) AS ( 536 SELECT 'a.txt', 946684800, 'abc' UNION ALL 537 SELECT 'b.txt', 1000000000, 'abc' UNION ALL 538 SELECT 'c.txt', 1111111000, 'abc' 539 ) 540 SELECT writefile('test1.zip', rt( zipfile(name, NULL, mtime, data) ) ), 541 writefile('test2.zip', ( zipfile(name, NULL, mtime, data) ) ) 542 FROM c; 543 } 544 forcedelete test_unzip 545 file mkdir test_unzip 546 exec $::UNZIP -d test_unzip test1.zip 547 548 db eval { 549 SELECT name, strftime('%s', mtime, 'unixepoch', 'localtime') 550 FROM fsdir('test_unzip') WHERE name!='test_unzip' 551 ORDER BY name 552 } 553 } [list {*}{ 554 test_unzip/a.txt 946684800 555 test_unzip/b.txt 1000000000 556 test_unzip/c.txt 1111111000 557 }] 558 559 # fsdir() issue reported on the mailing list on 2018-03-14 by Jack Thaw. 560 do_test 6.0b { 561 db eval { 562 SELECT sum(name LIKE '%/a.txt') 563 FROM (VALUES(1),(2),(3)) CROSS JOIN fsdir('test_unzip') 564 } 565 } {3} 566 567 do_execsql_test 6.1 { 568 SELECT name, mtime, data FROM zipfile('test1.zip') 569 } { 570 a.txt 946684800 abc 571 b.txt 1000000000 abc 572 c.txt 1111111000 abc 573 } 574 575 do_test 6.2 { 576 forcedelete test_unzip 577 file mkdir test_unzip 578 exec $::UNZIP -d test_unzip test2.zip 579 580 db eval { 581 SELECT name, mtime 582 FROM fsdir('test_unzip') WHERE name!='test_unzip' 583 ORDER BY name 584 } 585 } [list {*}{ 586 test_unzip/a.txt 946684800 587 test_unzip/b.txt 1000000000 588 test_unzip/c.txt 1111111000 589 }] 590 591 do_execsql_test 6.3 { 592 SELECT name, mtime, sz, rawdata, data FROM zipfile('test2.zip') 593 } { 594 a.txt 946684800 3 abc abc 595 b.txt 1000000000 3 abc abc 596 c.txt 1111111000 3 abc abc 597 } 598} 599} 600 601#------------------------------------------------------------------------- 602# Force an IO error by truncating the zip archive to zero bytes in size 603# while it is being read. 604forcedelete test.zip 605do_test 7.0 { 606 execsql { 607 WITH c(name,data) AS ( 608 SELECT '1', randomblob(1000000) UNION ALL 609 SELECT '2', randomblob(1000000) UNION ALL 610 SELECT '3', randomblob(1000000) 611 ) 612 SELECT writefile('test.zip', zipfile(name, data) ) FROM c; 613 } 614 615 list [catch { 616 db eval { SELECT name, data FROM zipfile('test.zip') } { 617 if {$name==2} { close [open test.zip w+] } 618 } 619 } msg] $msg 620} {1 {error in fread()}} 621 622forcedelete test.zip 623do_execsql_test 8.0.1 { 624 CREATE VIRTUAL TABLE zz USING zipfile('test.zip'); 625 BEGIN; 626 INSERT INTO zz(name, data) VALUES('a.txt', '1'); 627 INSERT INTO zz(name, data) VALUES('b.txt', '2'); 628 INSERT INTO zz(name, data) VALUES('c.txt', '1'); 629 INSERT INTO zz(name, data) VALUES('d.txt', '2'); 630 SELECT name, data FROM zz; 631} { 632 a.txt 1 b.txt 2 c.txt 1 d.txt 2 633} 634do_test 8.0.2 { 635 db eval { SELECT name, data FROM zz } { 636 if { $data=="2" } { db eval { DELETE FROM zz WHERE name=$name } } 637 } 638 execsql { SELECT name, data FROM zz } 639} {a.txt 1 c.txt 1} 640do_test 8.0.3 { 641 db eval { SELECT name, data FROM zz } { 642 db eval { DELETE FROM zz WHERE name=$name } 643 } 644 execsql { SELECT name, data FROM zz } 645} {} 646execsql COMMIT 647 648do_execsql_test 8.1.1 { 649 CREATE VIRTUAL TABLE nogood USING zipfile('test_unzip'); 650} 651do_catchsql_test 8.1.2 { 652 INSERT INTO nogood(name, data) VALUES('abc', 'def'); 653} {1 {zipfile: failed to open file test_unzip for writing}} 654 655do_execsql_test 8.2.1 { 656 DROP TABLE nogood; 657 BEGIN; 658 CREATE VIRTUAL TABLE nogood USING zipfile('test_unzip'); 659} 660do_catchsql_test 8.2.2 { 661 INSERT INTO nogood(name, data) VALUES('abc', 'def'); 662} {1 {zipfile: failed to open file test_unzip for writing}} 663do_execsql_test 8.2.3 { 664 COMMIT; 665} 666 667forcedelete test.zip 668do_execsql_test 8.3.1 { 669 BEGIN; 670 CREATE VIRTUAL TABLE ok USING zipfile('test.zip'); 671 INSERT INTO ok(name, data) VALUES ('sqlite3', 'elf'); 672 COMMIT; 673} 674 675#------------------------------------------------------------------------- 676# Test that the zipfile aggregate correctly adds and removes "/" from 677# the ends of directory file names. 678do_execsql_test 9.0 { 679 WITH src(nm) AS ( 680 VALUES('dir1') UNION ALL 681 VALUES('dir2/') UNION ALL 682 VALUES('dir3//') UNION ALL 683 VALUES('dir4///') UNION ALL 684 VALUES('/') 685 ) 686 SELECT name FROM zipfile((SELECT zipfile(nm, NULL) FROM src)) 687} {dir1/ dir2/ dir3/ dir4/ /} 688 689#------------------------------------------------------------------------- 690# INSERT OR REPLACE and INSERT OR IGNORE 691# 692catch {db close} 693forcedelete test.zip test.db 694sqlite3 db :memory: 695load_static_extension db zipfile 696load_static_extension db fileio 697 698do_execsql_test 10.0 { 699 CREATE VIRTUAL TABLE z USING zipfile('test.zip'); 700} {} 701do_catchsql_test 10.1 { 702 INSERT INTO z(name,data) VALUES('a0','one'),('a0','two'); 703} {1 {duplicate name: "a0"}} 704do_execsql_test 10.2 { 705 SELECT name, data FROM z; 706} {a0 one} 707do_execsql_test 10.3 { 708 REPLACE INTO z(name,data) VALUES('a0','three'),('a0','four'); 709} {} 710do_execsql_test 10.4 { 711 SELECT name, data FROM z; 712} {a0 four} 713do_execsql_test 10.5 { 714 INSERT OR IGNORE INTO z(name,data) VALUES('a0','five'),('a0','six'); 715} {} 716do_execsql_test 10.6 { 717 SELECT name, data FROM z; 718} {a0 four} 719 720 721finish_test 722