mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Merge all of the trunk enchancements into the bedrock branch.
FossilOrigin-Name: ba2174bdca7d1d1aadf0a4de1e01aeba3d95b6656cb9ecdff88b00cfbef8f3a9
This commit is contained in:
@@ -1986,9 +1986,9 @@ static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){
|
||||
** leave an error in the Fts5Index object.
|
||||
*/
|
||||
static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){
|
||||
const int nTomb = pIter->pSeg->nPgTombstone;
|
||||
const i64 nTomb = (i64)pIter->pSeg->nPgTombstone;
|
||||
if( nTomb>0 ){
|
||||
int nByte = SZ_FTS5TOMBSTONEARRAY(nTomb+1);
|
||||
i64 nByte = SZ_FTS5TOMBSTONEARRAY(nTomb+1);
|
||||
Fts5TombstoneArray *pNew;
|
||||
pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte);
|
||||
if( pNew ){
|
||||
@@ -2481,18 +2481,20 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
|
||||
fts5DataRelease(pIter->pLeaf);
|
||||
pIter->pLeaf = pLast;
|
||||
pIter->iLeafPgno = pgnoLast;
|
||||
iOff = fts5LeafFirstRowidOff(pLast);
|
||||
if( iOff>pLast->szLeaf ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
return;
|
||||
}
|
||||
iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
|
||||
pIter->iLeafOffset = iOff;
|
||||
if( p->rc==SQLITE_OK ){
|
||||
iOff = fts5LeafFirstRowidOff(pLast);
|
||||
if( iOff>pLast->szLeaf ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
return;
|
||||
}
|
||||
iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
|
||||
pIter->iLeafOffset = iOff;
|
||||
|
||||
if( fts5LeafIsTermless(pLast) ){
|
||||
pIter->iEndofDoclist = pLast->nn+1;
|
||||
}else{
|
||||
pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast);
|
||||
if( fts5LeafIsTermless(pLast) ){
|
||||
pIter->iEndofDoclist = pLast->nn+1;
|
||||
}else{
|
||||
pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5845,7 +5847,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
|
||||
}
|
||||
|
||||
nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel);
|
||||
assert( nByte==SZ_FTS5STRUCTURE(pStruct->nLevel+2) );
|
||||
assert( nByte==(i64)SZ_FTS5STRUCTURE(pStruct->nLevel+2) );
|
||||
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
|
||||
|
||||
if( pNew ){
|
||||
@@ -8284,19 +8286,27 @@ static int fts5TestUtf8(const char *z, int n){
|
||||
/*
|
||||
** This function is also purely an internal test. It does not contribute to
|
||||
** FTS functionality, or even the integrity-check, in any way.
|
||||
**
|
||||
** This function sets output variable (*pbFail) to true if the test fails. Or
|
||||
** leaves it unchanged if the test succeeds.
|
||||
*/
|
||||
static void fts5TestTerm(
|
||||
Fts5Index *p,
|
||||
Fts5Buffer *pPrev, /* Previous term */
|
||||
const char *z, int n, /* Possibly new term to test */
|
||||
u64 expected,
|
||||
u64 *pCksum
|
||||
u64 *pCksum,
|
||||
int *pbFail
|
||||
){
|
||||
int rc = p->rc;
|
||||
if( pPrev->n==0 ){
|
||||
fts5BufferSet(&rc, pPrev, n, (const u8*)z);
|
||||
}else
|
||||
if( rc==SQLITE_OK && (pPrev->n!=n || memcmp(pPrev->p, z, n)) ){
|
||||
if( *pbFail==0
|
||||
&& rc==SQLITE_OK
|
||||
&& (pPrev->n!=n || memcmp(pPrev->p, z, n))
|
||||
&& (p->pHash==0 || p->pHash->nEntry==0)
|
||||
){
|
||||
u64 cksum3 = *pCksum;
|
||||
const char *zTerm = (const char*)&pPrev->p[1]; /* term sans prefix-byte */
|
||||
int nTerm = pPrev->n-1; /* Size of zTerm in bytes */
|
||||
@@ -8346,7 +8356,7 @@ static void fts5TestTerm(
|
||||
fts5BufferSet(&rc, pPrev, n, (const u8*)z);
|
||||
|
||||
if( rc==SQLITE_OK && cksum3!=expected ){
|
||||
rc = FTS5_CORRUPT;
|
||||
*pbFail = 1;
|
||||
}
|
||||
*pCksum = cksum3;
|
||||
}
|
||||
@@ -8355,7 +8365,7 @@ static void fts5TestTerm(
|
||||
|
||||
#else
|
||||
# define fts5TestDlidxReverse(x,y,z)
|
||||
# define fts5TestTerm(u,v,w,x,y,z)
|
||||
# define fts5TestTerm(t,u,v,w,x,y,z)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -8613,6 +8623,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
|
||||
/* Used by extra internal tests only run if NDEBUG is not defined */
|
||||
u64 cksum3 = 0; /* Checksum based on contents of indexes */
|
||||
Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */
|
||||
int bTestFail = 0;
|
||||
#endif
|
||||
const int flags = FTS5INDEX_QUERY_NOOUTPUT;
|
||||
|
||||
@@ -8655,7 +8666,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
|
||||
char *z = (char*)fts5MultiIterTerm(pIter, &n);
|
||||
|
||||
/* If this is a new term, query for it. Update cksum3 with the results. */
|
||||
fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
|
||||
fts5TestTerm(p, &term, z, n, cksum2, &cksum3, &bTestFail);
|
||||
if( p->rc ) break;
|
||||
|
||||
if( eDetail==FTS5_DETAIL_NONE ){
|
||||
@@ -8673,7 +8684,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
|
||||
}
|
||||
}
|
||||
}
|
||||
fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
|
||||
fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3, &bTestFail);
|
||||
|
||||
fts5MultiIterFree(pIter);
|
||||
if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ){
|
||||
@@ -8682,11 +8693,17 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
|
||||
"fts5: checksum mismatch for table \"%s\"", p->pConfig->zName
|
||||
);
|
||||
}
|
||||
|
||||
fts5StructureRelease(pStruct);
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* In SQLITE_DEBUG builds, expensive extra checks were run as part of
|
||||
** the integrity-check above. If no other errors were detected, but one
|
||||
** of these tests failed, set the result to SQLITE_CORRUPT_VTAB here. */
|
||||
if( p->rc==SQLITE_OK && bTestFail ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}
|
||||
fts5BufferFree(&term);
|
||||
#endif
|
||||
|
||||
fts5StructureRelease(pStruct);
|
||||
fts5BufferFree(&poslist);
|
||||
return fts5IndexReturn(p);
|
||||
}
|
||||
|
@@ -6644,7 +6644,7 @@ do_test 48.0 {
|
||||
|
||||
do_catchsql_test 48.1 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
} {1 {database disk image is malformed}}
|
||||
} {1 {fts5: corruption on page 1, segment 1, table "t1"}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -10106,7 +10106,7 @@ do_test 68.0 {
|
||||
do_catchsql_test 68.1 {
|
||||
PRAGMA reverse_unordered_selects=ON;
|
||||
INSERT INTO t1(t1) SELECT x FROM t2;
|
||||
} {1 {database disk image is malformed}}
|
||||
} {1 {fts5: corruption on page 1, segment 1, table "t1"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -15909,8 +15909,220 @@ do_catchsql_test 82.4 {
|
||||
SAVEPOINT b;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 83.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 24576 pagesize 4096 filename crash-c4a4c5492615bd.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 06 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 00 ................
|
||||
| 96: 00 00 00 00 0d 00 00 00 06 0e 0f 00 0f aa 0f 53 ...............S
|
||||
| 112: 0e e8 0e 8b 0e 33 0e 0f 00 01 00 00 00 00 00 00 .....3..........
|
||||
| 3584: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 ................
|
||||
| 3600: 06 06 17 11 11 01 31 74 61 62 6c 65 62 62 62 62 ......1tablebbbb
|
||||
| 3616: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 62 62 .CREATE TABLE bb
|
||||
| 3632: 28 61 29 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65 (a)V.......table
|
||||
| 3648: 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66 t1_configt1_conf
|
||||
| 3664: 69 67 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 ig.CREATE TABLE
|
||||
| 3680: 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 't1_config'(k PR
|
||||
| 3696: 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 57 49 IMARY KEY, v) WI
|
||||
| 3712: 54 48 4f 55 54 20 52 4f 57 49 44 5b 04 07 17 21 THOUT ROWID[...!
|
||||
| 3728: 21 01 81 01 74 61 62 6c 65 74 31 5f 64 6f 63 73 !...tablet1_docs
|
||||
| 3744: 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 04 43 52 izet1_docsize.CR
|
||||
| 3760: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64 EATE TABLE 't1_d
|
||||
| 3776: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 ocsize'(id INTEG
|
||||
| 3792: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3808: 73 7a 20 42 4c 4f 42 29 69 03 07 17 19 19 01 81 sz BLOB)i.......
|
||||
| 3824: 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 -tablet1_idxt1_i
|
||||
| 3840: 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 dx.CREATE TABLE
|
||||
| 3856: 27 74 31 5f 69 64 78 27 28 73 65 67 69 64 2c 20 't1_idx'(segid,
|
||||
| 3872: 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d term, pgno, PRIM
|
||||
| 3888: 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 74 ARY KEY(segid, t
|
||||
| 3904: 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 4f erm)) WITHOUT RO
|
||||
| 3920: 57 49 44 55 02 07 17 1b 1b 01 81 01 74 61 62 6c WIDU........tabl
|
||||
| 3936: 65 74 31 5f 64 61 74 61 74 31 5f 64 61 74 61 02 et1_datat1_data.
|
||||
| 3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
|
||||
| 3968: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45 _data'(id INTEGE
|
||||
| 3984: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 R PRIMARY KEY, b
|
||||
| 4000: 6c 6f 63 6b 20 42 4c 4f 42 29 54 01 07 17 11 11 lock BLOB)T.....
|
||||
| 4016: 08 81 15 74 61 62 6c 65 74 31 74 31 43 52 45 41 ...tablet1t1CREA
|
||||
| 4032: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 TE VIRTUAL TABLE
|
||||
| 4048: 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 28 61 t1 USING fts5(a
|
||||
| 4064: 2c 62 2c 70 72 65 66 69 78 3d 22 31 2c 32 2c 33 ,b,prefix=.1,2,3
|
||||
| 4080: 2c 34 22 2c 20 63 6f 6e 74 65 6e 74 3d 22 22 29 ,4., content=..)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 0b 6a 00 37 09 4c 02 0f e7 09 4c 0f c6 0f a4 ..j.7.L....L....
|
||||
| 16: 0f 88 0f 6d 0f 4b 0f 2c 0f 0e 0e ec 0e cd 0e ad ...m.K.,........
|
||||
| 32: 0e 8e 0e 6c 0e 4b 0e 29 0e 08 0d e6 0d c4 0d b5 ...l.K.)........
|
||||
| 48: 0d 97 0d 76 0d 54 0d 31 0d 15 0c f3 0c d3 0c b5 ...v.T.1........
|
||||
| 64: 0c 95 0c 73 0c 54 0c 32 0c 10 0b ee 0b cc 0b b0 ...s.T.2........
|
||||
| 80: 0b 8d 0b 7e 0b 48 0b 2e 0b 00 4a ef fa cc 0a ad ...~.H....J.....
|
||||
| 96: 0a 8c 0a 6d 0a 4d 0a 2b 0a 0c 09 00 00 00 00 00 ...m.M.+........
|
||||
| 2368: 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 03 00 ................
|
||||
| 2384: 30 00 00 00 01 01 03 35 00 03 01 01 12 02 01 12 0......5........
|
||||
| 2400: 03 01 11 1c 8c 80 80 80 80 10 03 00 3e 00 00 00 ............>...
|
||||
| 2416: 17 01 05 05 34 74 61 62 6c 03 02 03 01 04 77 68 ....4tabl.....wh
|
||||
| 2432: 65 72 03 02 06 09 1b 8c 80 80 80 80 0f 03 00 3c er.............<
|
||||
| 2448: 00 00 00 16 05 34 66 74 73 34 03 02 02 01 04 6e .....4fts4.....n
|
||||
| 2464: 75 6d 62 03 07 01 04 09 1b 8c 80 80 80 80 0e 03 umb.............
|
||||
| 2480: 00 3c 00 00 00 16 04 33 74 68 65 03 06 01 01 04 .<.....3the.....
|
||||
| 2496: 01 03 77 68 65 03 02 04 04 0a 1b 8c 80 80 80 80 ..whe...........
|
||||
| 2512: 0d 03 00 3c 00 00 00 16 04 33 6e 75 6d 03 06 01 ...<.....3num...
|
||||
| 2528: 01 05 01 03 74 61 62 03 02 03 04 0a 19 8c 80 80 ....tab.........
|
||||
| 2544: 80 80 0c 03 00 38 00 00 00 14 03 32 77 68 03 02 .....8.....2wh..
|
||||
| 2560: 04 00 04 33 66 74 73 03 02 02 04 07 18 8c 80 80 ...3fts.........
|
||||
| 2576: 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 03 02 .....6.....2ta..
|
||||
| 2592: 03 02 01 68 03 06 01 01 04 04 07 1b 8c 80 80 80 ...h............
|
||||
| 2608: 80 0a 03 00 3c 00 00 00 16 03 32 6e 75 03 06 01 ....<.....2nu...
|
||||
| 2624: 01 05 01 02 6f 66 03 06 01 01 06 04 09 19 8c 80 ....of..........
|
||||
| 2640: 80 80 80 09 03 00 38 00 00 00 14 03 32 66 74 03 ......8.....2ft.
|
||||
| 2656: 02 02 01 02 69 73 02 06 01 01 03 04 07 18 8c 80 ....is..........
|
||||
| 2672: 80 80 22 08 03 00 36 00 00 00 13 02 31 74 03 08 ......6.....1t..
|
||||
| 2688: 03 01 01 04 01 01 77 03 02 04 04 09 1a 8c 80 80 ......w.........
|
||||
| 2704: 80 80 07 03 00 3a 00 00 00 15 02 31 6e 03 08 01 .....:.....1n...
|
||||
| 2720: 01 02 05 01 01 6f 03 06 01 01 06 04 09 18 8c 80 .....o..........
|
||||
| 2736: 80 80 80 06 03 00 36 00 00 00 13 04 02 31 66 03 ......6......1f.
|
||||
| 2752: 02 02 01 01 69 03 06 01 01 03 05 06 1c 8c 80 80 ....i...........
|
||||
| 2768: 80 80 05 03 00 3e 00 00 00 17 04 30 74 68 65 03 .....>.....0the.
|
||||
| 2784: 06 01 01 04 01 05 77 68 65 72 65 03 02 04 0a 15 ......where.....
|
||||
| 2800: 8c 80 80 80 80 04 03 00 30 00 00 00 11 01 01 06 ........0.......
|
||||
| 2816: 06 30 74 61 62 6c 65 03 01 f3 07 1c 8c 80 80 80 .0table.........
|
||||
| 2832: 80 03 03 00 3e 00 00 00 17 07 30 6e 75 6d 62 65 ....>.....0numbe
|
||||
| 2848: 72 03 06 01 01 05 01 02 6f 66 03 06 04 0d 13 8c r.......of......
|
||||
| 2864: 80 80 80 80 02 03 00 2c 00 00 00 0f 01 01 03 02 .......,........
|
||||
| 2880: 30 6e 03 06 01 01 02 07 1b 8c 80 80 80 80 01 03 0n..............
|
||||
| 2896: 00 3c 00 00 00 16 08 30 66 74 73 34 61 75 78 03 .<.....0fts4aux.
|
||||
| 2912: 02 02 01 02 69 73 03 06 04 0c 00 00 00 14 2a 00 ....is........*.
|
||||
| 2928: 00 00 01 01 02 24 00 02 01 01 12 02 01 12 08 88 .....$..........
|
||||
| 2944: 80 80 80 80 12 03 00 16 00 00 00 05 02 1c 88 80 ................
|
||||
| 2960: 80 80 80 11 03 00 3e 00 00 00 17 05 34 72 6f 77 ......>.....4row
|
||||
| 2976: 73 02 06 01 01 05 01 04 74 68 65 72 02 02 04 0b s.......ther....
|
||||
| 2992: 15 88 80 80 80 80 10 03 00 30 00 00 00 11 02 01 .........0......
|
||||
| 3008: 01 07 05 34 62 65 74 77 02 02 04 08 1b 88 80 80 ...4betw........
|
||||
| 3024: 80 80 0f 03 00 3c 00 00 00 16 04 04 33 72 6f 77 .....<......3row
|
||||
| 3040: 02 06 01 01 05 01 03 74 68 65 02 08 05 0a 1b 88 .......the......
|
||||
| 3056: 80 80 80 80 0e 03 00 3c 00 00 00 16 01 01 02 04 .......<........
|
||||
| 3072: 33 61 72 65 02 02 b3 01 03 62 65 74 02 02 07 08 3are.....bet....
|
||||
| 3088: 1b 88 80 80 80 80 0d 03 00 3c 00 00 00 16 03 32 .........<.....2
|
||||
| 3104: 74 68 02 08 02 01 01 07 00 04 33 61 6e 64 02 06 th........3and..
|
||||
| 3120: 04 0a 1b 88 80 80 80 80 0c 03 00 3c 00 00 00 16 ...........<....
|
||||
| 3136: 03 32 69 6e 02 06 01 01 06 01 02 72 6f 02 06 01 .2in.......ro...
|
||||
| 3152: 01 05 04 09 18 88 80 80 80 80 0b 03 00 36 00 0f .............6..
|
||||
| 3168: f0 13 02 03 32 61 72 02 02 03 01 02 62 65 02 02 ....2ar.....be..
|
||||
| 3184: 03 05 07 1b 88 80 80 80 80 0a 03 00 3c dd 00 00 ............<...
|
||||
| 3200: 18 c2 31 74 02 08 02 01 01 07 00 03 32 61 6e 02 ..1t........2an.
|
||||
| 3216: 06 01 01 04 09 19 88 80 80 80 80 09 03 00 38 00 ..............8.
|
||||
| 3232: 00 00 14 02 31 6e 02 06 01 01 03 01 01 72 02 06 ....1n.......r..
|
||||
| 3248: 01 01 05 04 08 17 88 80 80 80 80 08 03 00 34 00 ..............4.
|
||||
| 3264: 00 00 12 02 31 62 02 02 04 01 01 69 02 06 01 01 ....1b.....i....
|
||||
| 3280: 06 04 06 19 88 80 90 80 80 07 03 00 38 00 00 00 ............8...
|
||||
| 3296: 14 04 02 31 32 02 02 05 01 01 61 02 08 03 01 01 ...12.....a.....
|
||||
| 3312: 02 05 06 1b 88 80 80 80 80 06 03 00 3c 00 00 00 ............<...
|
||||
| 3328: 16 06 30 74 68 65 72 65 02 02 02 00 02 31 31 02 ..0there.....11.
|
||||
| 3344: 06 01 01 04 0a 15 88 80 80 80 80 05 03 00 30 00 ..............0.
|
||||
| 3360: 00 00 11 01 01 05 04 30 74 68 65 02 06 01 01 07 .......0the.....
|
||||
| 3376: 07 1c 88 80 80 80 80 04 03 00 3e 00 00 00 17 01 ..........>.....
|
||||
| 3392: 01 06 02 30 6e 02 06 01 01 03 01 04 72 6f 77 73 ...0n.......rows
|
||||
| 3408: 02 06 07 08 1b 88 80 80 80 80 03 03 00 3c 00 00 .............<..
|
||||
| 3424: 00 16 08 30 62 65 74 77 65 65 6e 02 02 04 01 02 ...0between.....
|
||||
| 3440: 69 6e 02 06 04 0c 1a 88 80 80 80 80 02 03 00 3a in.............:
|
||||
| 3456: 00 00 00 15 04 30 61 6e 64 02 06 01 01 02 02 02 .....0and.......
|
||||
| 3472: 72 65 02 02 03 04 0a 17 88 80 80 80 80 01 03 00 re..............
|
||||
| 3488: 34 00 00 0c 52 02 30 31 02 06 01 01 04 01 01 32 4...R.01.......2
|
||||
| 3504: 02 02 05 04 08 08 84 80 80 80 80 12 03 00 16 00 ................
|
||||
| 3520: 00 00 05 04 1b 84 80 80 80 80 11 03 00 3c 00 00 .............<..
|
||||
| 3536: 00 16 05 34 74 61 62 6c 01 06 00 f1 05 02 03 65 ...4tabl.......e
|
||||
| 3552: 72 6d 01 02 04 0b 1b 84 80 80 80 80 10 03 00 3c rm.............<
|
||||
| 3568: 00 00 00 16 05 34 65 61 63 68 01 02 03 01 04 70 .....4each.....p
|
||||
| 3584: 72 65 73 01 02 05 04 09 1a 84 80 80 80 80 0f 03 res.............
|
||||
| 3600: 00 3a 00 00 00 15 04 33 74 65 72 01 02 04 02 02 .:.....3ter.....
|
||||
| 3616: 68 65 01 06 01 01 03 04 08 1b 84 80 80 80 80 0e he..............
|
||||
| 3632: 03 00 3c 00 00 00 16 04 33 70 72 65 01 02 05 01 ..<.....3pre....
|
||||
| 3648: 03 74 61 62 01 06 01 01 05 04 08 1a 84 80 80 80 .tab............
|
||||
| 3664: 80 0d 03 00 3a 00 00 00 15 04 33 66 6f 72 01 02 ....:.....3for..
|
||||
| 3680: 02 02 02 74 73 01 06 01 01 04 04 08 1b 84 80 80 ...ts...........
|
||||
| 3696: 80 80 0c 03 00 3c 00 00 00 16 03 32 74 68 01 06 .....<.....2th..
|
||||
| 3712: 01 01 03 00 04 33 65 61 63 01 02 03 04 09 18 74 .....3eac......t
|
||||
| 3728: 80 80 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 .......6.....2ta
|
||||
| 3744: 01 06 01 01 05 02 01 65 01 02 04 04 09 19 84 80 .......e........
|
||||
| 3760: 80 80 80 0a 03 00 38 00 00 00 14 03 32 69 6e 01 ......8.....2in.
|
||||
| 3776: 06 01 01 02 11 02 70 62 01 02 05 04 09 18 84 80 ......pb........
|
||||
| 3792: 80 80 80 09 03 00 36 00 00 00 13 03 32 66 6f 01 ......6.....2fo.
|
||||
| 3808: 02 02 02 01 74 01 06 01 01 04 04 07 1b 84 80 80 ....t...........
|
||||
| 3824: 80 80 08 03 00 3c 0d c0 00 16 12 31 74 01 0a 04 .....<.....1t...
|
||||
| 3840: 01 01 03 04 00 03 32 65 61 01 02 03 04 0a 17 84 ......2ea.......
|
||||
| 3856: 80 80 80 80 07 03 00 34 00 00 00 12 02 31 69 01 .......4.....1i.
|
||||
| 3872: 06 01 01 02 01 01 70 01 02 05 04 08 18 84 80 80 ......p.........
|
||||
| 3888: 80 80 06 03 00 36 00 00 00 13 02 31 65 01 02 03 .....6.....1e...
|
||||
| 3904: 01 01 66 01 08 02 5b 01 04 04 06 1b 84 80 80 80 ..f...[.........
|
||||
| 3920: 80 05 03 00 3c 00 00 00 16 05 30 74 65 72 6d 01 ....<.....0term.
|
||||
| 3936: 02 04 02 02 68 65 01 06 01 01 03 04 09 14 84 80 ....he..........
|
||||
| 3952: 80 80 80 04 03 00 2e 00 00 00 10 06 30 74 61 62 ............0tab
|
||||
| 3968: 6c 65 01 06 01 01 05 04 15 84 80 80 80 80 03 03 le..............
|
||||
| 3984: 00 30 00 00 00 11 01 f8 30 70 72 65 73 65 6e 74 .0......0present
|
||||
| 4000: 01 02 05 05 1b 84 80 80 80 80 02 03 00 3c 00 00 .............<..
|
||||
| 4016: 00 16 04 30 66 74 73 01 06 01 01 04 01 02 69 6e ...0fts.......in
|
||||
| 4032: 01 06 01 01 04 0a 1a 84 80 80 80 80 01 03 00 3a ...............:
|
||||
| 4048: 00 00 00 15 05 30 65 61 63 68 01 02 03 01 03 66 .....0each.....f
|
||||
| 4064: 6f 72 01 02 02 04 09 06 01 03 00 12 03 0b 0f 00 or..............
|
||||
| 4080: 00 08 8c 80 80 80 80 11 03 00 16 00 00 00 05 04 ................
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 32 0e 4f 00 0f fa 0f f1 0f e9 0f e1 ....2.O.........
|
||||
| 16: 0f d8 0f d1 0f c9 0f c1 0f b9 0f b1 0f a9 0f a0 ................
|
||||
| 32: 0f 98 0f 90 0f 87 0f 80 0f 78 0f 71 0f 68 0f 5f .........x.q.h._
|
||||
| 48: 0f 56 0f 4d 0f 41 0f 38 0f 2f 0f 26 0f 1d 0f 13 .V.M.A.8./.&....
|
||||
| 64: 0f 0a 0f 01 0e f7 0e ee 0e e6 0e dd 0e d6 0e cd ................
|
||||
| 80: 0e c3 0e ba 0e b0 0e a8 0e 9f 0e 96 0e 00 00 00 ................
|
||||
| 3648: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
|
||||
| 3664: 04 01 10 01 03 34 74 20 07 04 02 4e 01 03 34 1e .....4t ...N..4.
|
||||
| 3680: 09 04 01 12 01 03 33 74 68 1c 08 04 01 10 01 03 ......3th.......
|
||||
| 3696: 33 6e 1a 08 04 01 10 01 03 32 77 18 08 04 01 10 3n.......2w.....
|
||||
| 3712: 01 03 32 74 16 08 04 01 10 01 03 32 6e 14 07 04 ..2t.......2n...
|
||||
| 3728: 01 0e 01 03 32 12 08 04 01 10 01 03 31 74 10 08 ....2.......1t..
|
||||
| 3744: 04 01 10 01 03 31 6e 0e 07 04 01 0e 01 03 31 0c .....1n.......1.
|
||||
| 3760: 09 04 01 12 01 03 30 74 68 0a 08 04 01 10 01 03 ......0th.......
|
||||
| 3776: 30 74 08 19 04 01 12 01 03 30 6e 75 06 08 04 01 0t.......0nu....
|
||||
| 3792: 10 01 03 30 6e 04 06 04 01 0c 01 03 02 08 04 01 ...0n...........
|
||||
| 3808: 10 01 02 34 72 22 07 04 01 0e 01 02 34 20 08 04 ...4r.......4 ..
|
||||
| 3824: 01 10 01 02 33 72 1e 09 04 01 12 01 02 33 61 72 ....3r.......3ar
|
||||
| 3840: 1c 08 04 01 10 01 02 32 74 1a 08 04 01 10 01 02 .......2t.......
|
||||
| 3856: 32 69 18 09 04 01 12 01 02 32 60 82 16 08 04 01 2i.......2`.....
|
||||
| 3872: 10 01 02 31 74 14 08 04 01 10 01 02 31 6e 12 08 ...1t.......1n..
|
||||
| 3888: 04 01 10 01 02 31 62 10 08 04 01 10 01 02 31 32 .....1b.......12
|
||||
| 3904: 0e 0b 04 01 16 01 02 30 74 68 65 72 0c 08 04 01 .......0ther....
|
||||
| 3920: 10 01 02 30 74 0a 08 04 01 10 01 02 30 6e 08 08 ...0t.......0n..
|
||||
| 3936: 04 01 10 01 02 30 62 06 08 04 01 10 01 02 30 61 .....0b.......0a
|
||||
| 3952: 04 06 04 01 0c 01 02 02 07 04 09 10 01 34 74 22 .............4t.
|
||||
| 3968: 06 04 09 0e 01 34 20 08 04 09 12 01 33 74 65 1e .....4 .....3te.
|
||||
| 3984: 07 04 09 10 01 33 70 1c 07 04 09 10 01 33 66 1a .....3p......3f.
|
||||
| 4000: 08 04 09 12 01 32 74 68 18 07 04 09 10 01 32 74 .....2th......2t
|
||||
| 4016: 16 07 04 09 10 01 32 69 14 07 04 09 10 01 32 66 ......2i......2f
|
||||
| 4032: 12 07 04 09 10 01 31 74 10 07 04 09 10 01 31 69 ......1t......1i
|
||||
| 4048: 0e 06 04 09 0e 01 31 0c 08 04 09 12 01 30 74 65 ......1......0te
|
||||
| 4064: 0a 07 04 09 10 01 30 74 08 07 04 09 10 01 30 70 ......0t......0p
|
||||
| 4080: 06 08 04 09 12 01 30 66 74 04 05 04 09 0c 01 02 ......0ft.......
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 05 03 03 00 10 ................
|
||||
| 4080: 03 05 05 02 03 00 10 04 06 05 01 03 00 10 04 04 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0a 00 00 00 02 0f eb 00 0f eb 0f f4 00 00 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 08 03 15 01 70 ...............p
|
||||
| 4080: 67 83 7a 18 0b 03 1b 01 76 65 72 73 69 6f 6e 04 g.z.....version.
|
||||
| page 6 offset 20480
|
||||
| 0: 0d 00 00 00 03 0f f2 00 0f fc 0f 00 00 00 00 00 ................
|
||||
| 4080: 00 00 03 03 02 01 03 03 02 02 01 02 02 01 02 09 ................
|
||||
| end crash-c4a4c5492615bd.db
|
||||
}]} {}
|
||||
|
||||
|
||||
do_catchsql_test 83.1 {
|
||||
SELECT * FROM t1('R*R*R*R*R*R*R*R*') WHERE (a,b)<=(current_date,0 BETWEEN 'a'<>11 AND '') ORDER BY rowid DESC;
|
||||
} {/.*fts5: corruption found/}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
@@ -90,5 +90,58 @@ do_execsql_test 3.7 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
proc hex_to_blob {hex} {
|
||||
binary encode hex $hex
|
||||
}
|
||||
db func hex_to_blob hex_to_blob
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x, content='', contentless_delete=1);
|
||||
BEGIN;
|
||||
INSERT INTO x1(rowid, x) VALUES(1, 'a b c d e f g h');
|
||||
INSERT INTO x1(rowid, x) VALUES(2, 'a b c d e f g h');
|
||||
COMMIT;
|
||||
DELETE FROM x1 WHERE rowid=1;
|
||||
}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
SELECT hex(block) FROM x1_data WHERE id=10
|
||||
} {
|
||||
00000000FF00000101010200010101010101010102
|
||||
}
|
||||
|
||||
do_execsql_test 4.2.1 {
|
||||
UPDATE x1_data SET block=
|
||||
X'00000000FF00000101010200010101010101819C9B95A8000102'
|
||||
WHERE id=10;
|
||||
}
|
||||
|
||||
do_catchsql_test 4.2.2 {
|
||||
SELECT * FROM x1('c d e');
|
||||
} {1 {out of memory}}
|
||||
|
||||
do_execsql_test 4.3.1 {
|
||||
UPDATE x1_data SET block=
|
||||
X'00000000FF000001010102000101010101019282AFF9A0000102'
|
||||
WHERE id=10;
|
||||
}
|
||||
|
||||
do_catchsql_test 4.3.2 {
|
||||
SELECT * FROM x1('c d e');
|
||||
} {1 {out of memory}}
|
||||
|
||||
do_execsql_test 4.4.1 {
|
||||
UPDATE x1_data SET block=
|
||||
X'00000000FF000001010102000101010101018181808080130102'
|
||||
WHERE id=10;
|
||||
}
|
||||
|
||||
do_catchsql_test 4.3.2 {
|
||||
SELECT * FROM x1('c d e');
|
||||
} {1 {out of memory}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
@@ -37,6 +37,12 @@ do_execsql_test 2.1 {
|
||||
INSERT INTO yy(yy) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 2.1 {
|
||||
INSERT INTO yy(yy) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
|
@@ -40,4 +40,53 @@ do_execsql_test 1.2 {
|
||||
SELECT * FROM t1 LEFT JOIN vt ON (vt MATCH 'abc')
|
||||
} {1 abc 2 abc}
|
||||
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES(14);
|
||||
}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT * FROM vt LEFT JOIN t1 ON vt.rowid = 1;
|
||||
} {
|
||||
abc 14
|
||||
xyz {}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts5(a,b);
|
||||
INSERT INTO t0(a,b)VALUES(1,0);
|
||||
CREATE TABLE t1(x);
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
SELECT * FROM t0 LEFT JOIN t1;
|
||||
} {1 0 {}}
|
||||
|
||||
breakpoint
|
||||
do_catchsql_test 2.2 {
|
||||
SELECT * FROM t0 LEFT JOIN t1 ON t0.b MATCH '1';
|
||||
} {1 {no query solution}}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
SELECT * FROM t0 LEFT JOIN t1 ON +b MATCH '1';
|
||||
} {1 0 {}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts5(c0, c1);
|
||||
INSERT INTO t0(c0,c1) VALUES (1,0);
|
||||
}
|
||||
|
||||
do_catchsql_test 3.1 {
|
||||
SELECT * FROM t0
|
||||
LEFT JOIN ( SELECT 0 AS col_0 )
|
||||
ON ((((t0.c1 MATCH '1')AND(CASE WHEN t0.c0 THEN CAST(t0.c1 AS INTEGER) ELSE 1 END))));
|
||||
} {1 {no query solution}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@@ -14,6 +14,13 @@
|
||||
** on stdout when its key interfaces are called. This is intended for
|
||||
** interactive analysis and debugging of virtual table interfaces.
|
||||
**
|
||||
** To build this extension as a separately loaded shared library or
|
||||
** DLL, use compiler command-lines similar to the following:
|
||||
**
|
||||
** (linux) gcc -fPIC -shared vtablog.c -o vtablog.so
|
||||
** (mac) clang -fPIC -dynamiclib vtablog.c -o vtablog.dylib
|
||||
** (windows) cl vtablog.c -link -dll -out:vtablog.dll
|
||||
**
|
||||
** Usage example:
|
||||
**
|
||||
** .load ./vtablog
|
||||
@@ -435,6 +442,39 @@ static int vtablogFilter(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return an sqlite3_index_info operator name in static space.
|
||||
** The name is possibly overwritten on subsequent calls.
|
||||
*/
|
||||
static char *vtablogOpName(unsigned char op){
|
||||
static char zUnknown[30];
|
||||
char *zOut;
|
||||
switch( op ){
|
||||
case SQLITE_INDEX_CONSTRAINT_EQ: zOut = "EQ"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_GT: zOut = "GT"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_LE: zOut = "LE"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_LT: zOut = "LT"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_GE: zOut = "GE"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_MATCH: zOut = "MATCH"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_LIKE: zOut = "LIKE"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_GLOB: zOut = "GLOB"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_REGEXP: zOut = "REGEXP"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_NE: zOut = "NE"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_ISNOT: zOut = "ISNOT"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: zOut = "ISNOTNULL"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_ISNULL: zOut = "ISNULL"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_IS: zOut = "IS"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_LIMIT: zOut = "LIMIT"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_OFFSET: zOut = "OFFSET"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_FUNCTION: zOut = "FUNCTION"; break;
|
||||
default:
|
||||
sqlite3_snprintf(sizeof(zUnknown),zUnknown,"%d",op);
|
||||
zOut = zUnknown;
|
||||
break;
|
||||
}
|
||||
return zOut;
|
||||
}
|
||||
|
||||
/*
|
||||
** SQLite will invoke this method one or more times while planning a query
|
||||
** that uses the vtablog virtual table. This routine needs to create
|
||||
@@ -451,14 +491,23 @@ static int vtablogBestIndex(
|
||||
printf(" colUsed: 0x%016llx\n", p->colUsed);
|
||||
printf(" nConstraint: %d\n", p->nConstraint);
|
||||
for(i=0; i<p->nConstraint; i++){
|
||||
sqlite3_value *pVal = 0;
|
||||
int rc = sqlite3_vtab_rhs_value(p, i, &pVal);
|
||||
printf(
|
||||
" constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
|
||||
" constraint[%d]: col=%d termid=%d op=%s usabled=%d coll=%s rhs=",
|
||||
i,
|
||||
p->aConstraint[i].iColumn,
|
||||
p->aConstraint[i].iTermOffset,
|
||||
p->aConstraint[i].op,
|
||||
vtablogOpName(p->aConstraint[i].op),
|
||||
p->aConstraint[i].usable,
|
||||
sqlite3_vtab_collation(p,i));
|
||||
sqlite3_vtab_collation(p,i)
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
vtablogQuote(pVal);
|
||||
printf("\n");
|
||||
}else{
|
||||
printf("N/A\n");
|
||||
}
|
||||
}
|
||||
printf(" nOrderBy: %d\n", p->nOrderBy);
|
||||
for(i=0; i<p->nOrderBy; i++){
|
||||
|
@@ -1135,6 +1135,12 @@ static void resetCursor(RtreeCursor *pCsr){
|
||||
pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
|
||||
pCsr->pReadAux = pStmt;
|
||||
|
||||
/* The following will only fail if the previous sqlite3_step() call failed,
|
||||
** in which case the error has already been caught. This statement never
|
||||
** encounters an error within an sqlite3_column_xxx() function, as it
|
||||
** calls sqlite3_column_value(), which does not use malloc(). So it is safe
|
||||
** to ignore the error code here. */
|
||||
sqlite3_reset(pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -99,5 +99,24 @@ do_execsql_test rtreeH-300 {
|
||||
ORDER BY id;
|
||||
} {box-48,48 box-49,48 box-48,49 xbox-49,49}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test rtreeH-300 {
|
||||
CREATE TABLE t0(c0);
|
||||
INSERT INTO t0(c0) VALUES (NULL);
|
||||
INSERT INTO t0(c0) VALUES (1);
|
||||
CREATE VIRTUAL TABLE t1 USING rtree(c0, c1, c2, +c3 BLOB );
|
||||
INSERT INTO t1(c2, c3, c0) VALUES (1, 2, 1);
|
||||
}
|
||||
|
||||
do_execsql_test rtreeH-310 {
|
||||
SELECT 1 FROM t1 WHERE t1.c3;
|
||||
} {1}
|
||||
|
||||
do_execsql_test rtreeH-320 {
|
||||
SELECT * FROM t0 WHERE NOT EXISTS (
|
||||
SELECT 1 FROM t1 WHERE t1.c3 OR t0.c0 ISNULL
|
||||
);
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
88
ext/session/sessionI.test
Normal file
88
ext/session/sessionI.test
Normal file
@@ -0,0 +1,88 @@
|
||||
# 2015 July 14
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix sessionI
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 1.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
|
||||
}
|
||||
} {}
|
||||
|
||||
set C [changeset_from_sql {
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
INSERT INTO t1 VALUES(2, 'two');
|
||||
INSERT INTO t1 VALUES(3, 'three');
|
||||
INSERT INTO t1 VALUES(4, 'four');
|
||||
INSERT INTO t1 VALUES(5, 'five');
|
||||
INSERT INTO t1 VALUES(6, 'six');
|
||||
}]
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
1 one 2 two 3 three 4 four 5 five 6 six
|
||||
}
|
||||
|
||||
proc xFilter {data} {
|
||||
foreach {op tname flag pk old new} $data {}
|
||||
if {$op=="INSERT"} {
|
||||
set ipk [lindex $new 1]
|
||||
return [expr $ipk % 2]
|
||||
}
|
||||
return 1
|
||||
}
|
||||
proc xConflict {args} {
|
||||
}
|
||||
|
||||
sqlite3changeset_apply_v3 db2 $C xConflict xFilter
|
||||
|
||||
do_execsql_test -db db2 1.2 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
1 one 3 three 5 five
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 1.3 {
|
||||
DELETE FROM t1
|
||||
}
|
||||
sqlite3changeset_apply_v3 db2 $C xConflict
|
||||
|
||||
do_execsql_test -db db2 1.4 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
1 one 2 two 3 three 4 four 5 five 6 six
|
||||
}
|
||||
|
||||
proc xFilter2 {data} {
|
||||
return 0
|
||||
}
|
||||
do_execsql_test -db db2 1.5 {
|
||||
DELETE FROM t1
|
||||
}
|
||||
sqlite3changeset_apply_v3 db2 $C xConflict xFilter2
|
||||
do_execsql_test -db db2 1.6 {
|
||||
SELECT * FROM t1
|
||||
} { }
|
||||
|
||||
finish_test
|
@@ -5213,6 +5213,10 @@ static int sessionChangesetApply(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
const char *zTab /* Table name */
|
||||
),
|
||||
int(*xFilterIter)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
sqlite3_changeset_iter *p
|
||||
),
|
||||
int(*xConflict)(
|
||||
void *pCtx, /* Copy of fifth arg to _apply() */
|
||||
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
|
||||
@@ -5353,6 +5357,9 @@ static int sessionChangesetApply(
|
||||
** next change. A log message has already been issued. */
|
||||
if( schemaMismatch ) continue;
|
||||
|
||||
/* If this is a call to apply_v3(), invoke xFilterIter here. */
|
||||
if( xFilterIter && 0==xFilterIter(pCtx, pIter) ) continue;
|
||||
|
||||
rc = sessionApplyOneWithRetry(db, pIter, &sApply, xConflict, pCtx);
|
||||
}
|
||||
|
||||
@@ -5420,6 +5427,87 @@ static int sessionChangesetApply(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called by all six sqlite3changeset_apply() variants:
|
||||
**
|
||||
** + sqlite3changeset_apply()
|
||||
** + sqlite3changeset_apply_v2()
|
||||
** + sqlite3changeset_apply_v3()
|
||||
** + sqlite3changeset_apply_strm()
|
||||
** + sqlite3changeset_apply_strm_v2()
|
||||
** + sqlite3changeset_apply_strm_v3()
|
||||
**
|
||||
** Arguments passed to this function are as follows:
|
||||
**
|
||||
** db:
|
||||
** Database handle to apply changeset to main database of.
|
||||
**
|
||||
** nChangeset/pChangeset:
|
||||
** These are both passed zero for the streaming variants. For the normal
|
||||
** apply() functions, these are passed the size of and the buffer containing
|
||||
** the changeset, respectively.
|
||||
**
|
||||
** xInput/pIn:
|
||||
** These are both passed zero for the normal variants. For the streaming
|
||||
** apply() functions, these are passed the input callback and context
|
||||
** pointer, respectively.
|
||||
**
|
||||
** xFilter:
|
||||
** The filter function as passed to apply() or apply_v2() (to filter by
|
||||
** table name), if any. This is always NULL for apply_v3() calls.
|
||||
**
|
||||
** xFilterIter:
|
||||
** The filter function as passed to apply_v3(), if any.
|
||||
**
|
||||
** xConflict:
|
||||
** The conflict handler callback (must not be NULL).
|
||||
**
|
||||
** pCtx:
|
||||
** The context pointer passed to the xFilter and xConflict handler callbacks.
|
||||
**
|
||||
** ppRebase, pnRebase:
|
||||
** Zero for apply(). The rebase changeset output pointers, if any, for
|
||||
** apply_v2() and apply_v3().
|
||||
**
|
||||
** flags:
|
||||
** Zero for apply(). The flags parameter for apply_v2() and apply_v3().
|
||||
*/
|
||||
static int sessionChangesetApplyV23(
|
||||
sqlite3 *db, /* Apply change to "main" db of this handle */
|
||||
int nChangeset, /* Size of changeset in bytes */
|
||||
void *pChangeset, /* Changeset blob */
|
||||
int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
|
||||
void *pIn, /* First arg for xInput */
|
||||
int(*xFilter)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
const char *zTab /* Table name */
|
||||
),
|
||||
int(*xFilterIter)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
sqlite3_changeset_iter *p /* Handle describing current change */
|
||||
),
|
||||
int(*xConflict)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
|
||||
sqlite3_changeset_iter *p /* Handle describing change and conflict */
|
||||
),
|
||||
void *pCtx, /* First argument passed to xConflict */
|
||||
void **ppRebase, int *pnRebase,
|
||||
int flags
|
||||
){
|
||||
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
|
||||
int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
|
||||
int rc = sessionChangesetStart(
|
||||
&pIter, xInput, pIn, nChangeset, pChangeset, bInverse, 1
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionChangesetApply(db, pIter,
|
||||
xFilter, xFilterIter, xConflict, pCtx, ppRebase, pnRebase, flags
|
||||
);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Apply the changeset passed via pChangeset/nChangeset to the main
|
||||
** database attached to handle "db".
|
||||
@@ -5441,17 +5529,39 @@ int sqlite3changeset_apply_v2(
|
||||
void **ppRebase, int *pnRebase,
|
||||
int flags
|
||||
){
|
||||
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
|
||||
int bInv = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
|
||||
int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset, bInv, 1);
|
||||
return sessionChangesetApplyV23(db,
|
||||
nChangeset, pChangeset, 0, 0,
|
||||
xFilter, 0, xConflict, pCtx,
|
||||
ppRebase, pnRebase, flags
|
||||
);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionChangesetApply(
|
||||
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
|
||||
);
|
||||
}
|
||||
|
||||
return rc;
|
||||
/*
|
||||
** Apply the changeset passed via pChangeset/nChangeset to the main
|
||||
** database attached to handle "db".
|
||||
*/
|
||||
int sqlite3changeset_apply_v3(
|
||||
sqlite3 *db, /* Apply change to "main" db of this handle */
|
||||
int nChangeset, /* Size of changeset in bytes */
|
||||
void *pChangeset, /* Changeset blob */
|
||||
int(*xFilter)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
sqlite3_changeset_iter *p /* Handle describing current change */
|
||||
),
|
||||
int(*xConflict)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
|
||||
sqlite3_changeset_iter *p /* Handle describing change and conflict */
|
||||
),
|
||||
void *pCtx, /* First argument passed to xConflict */
|
||||
void **ppRebase, int *pnRebase,
|
||||
int flags
|
||||
){
|
||||
return sessionChangesetApplyV23(db,
|
||||
nChangeset, pChangeset, 0, 0,
|
||||
0, xFilter, xConflict, pCtx,
|
||||
ppRebase, pnRebase, flags
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5474,8 +5584,10 @@ int sqlite3changeset_apply(
|
||||
),
|
||||
void *pCtx /* First argument passed to xConflict */
|
||||
){
|
||||
return sqlite3changeset_apply_v2(
|
||||
db, nChangeset, pChangeset, xFilter, xConflict, pCtx, 0, 0, 0
|
||||
return sessionChangesetApplyV23(db,
|
||||
nChangeset, pChangeset, 0, 0,
|
||||
xFilter, 0, xConflict, pCtx,
|
||||
0, 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5484,6 +5596,29 @@ int sqlite3changeset_apply(
|
||||
** attached to handle "db". Invoke the supplied conflict handler callback
|
||||
** to resolve any conflicts encountered while applying the change.
|
||||
*/
|
||||
int sqlite3changeset_apply_v3_strm(
|
||||
sqlite3 *db, /* Apply change to "main" db of this handle */
|
||||
int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
|
||||
void *pIn, /* First arg for xInput */
|
||||
int(*xFilter)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
sqlite3_changeset_iter *p
|
||||
),
|
||||
int(*xConflict)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
|
||||
sqlite3_changeset_iter *p /* Handle describing change and conflict */
|
||||
),
|
||||
void *pCtx, /* First argument passed to xConflict */
|
||||
void **ppRebase, int *pnRebase,
|
||||
int flags
|
||||
){
|
||||
return sessionChangesetApplyV23(db,
|
||||
0, 0, xInput, pIn,
|
||||
0, xFilter, xConflict, pCtx,
|
||||
ppRebase, pnRebase, flags
|
||||
);
|
||||
}
|
||||
int sqlite3changeset_apply_v2_strm(
|
||||
sqlite3 *db, /* Apply change to "main" db of this handle */
|
||||
int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
|
||||
@@ -5501,15 +5636,11 @@ int sqlite3changeset_apply_v2_strm(
|
||||
void **ppRebase, int *pnRebase,
|
||||
int flags
|
||||
){
|
||||
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
|
||||
int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
|
||||
int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse, 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionChangesetApply(
|
||||
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
|
||||
);
|
||||
}
|
||||
return rc;
|
||||
return sessionChangesetApplyV23(db,
|
||||
0, 0, xInput, pIn,
|
||||
xFilter, 0, xConflict, pCtx,
|
||||
ppRebase, pnRebase, flags
|
||||
);
|
||||
}
|
||||
int sqlite3changeset_apply_strm(
|
||||
sqlite3 *db, /* Apply change to "main" db of this handle */
|
||||
@@ -5526,8 +5657,10 @@ int sqlite3changeset_apply_strm(
|
||||
),
|
||||
void *pCtx /* First argument passed to xConflict */
|
||||
){
|
||||
return sqlite3changeset_apply_v2_strm(
|
||||
db, xInput, pIn, xFilter, xConflict, pCtx, 0, 0, 0
|
||||
return sessionChangesetApplyV23(db,
|
||||
0, 0, xInput, pIn,
|
||||
xFilter, 0, xConflict, pCtx,
|
||||
0, 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -1145,13 +1145,22 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
|
||||
** the changeset passed via the second and third arguments.
|
||||
**
|
||||
** The fourth argument (xFilter) passed to these functions is the "filter
|
||||
** callback". If it is not NULL, then for each table affected by at least one
|
||||
** change in the changeset, the filter callback is invoked with
|
||||
** the table name as the second argument, and a copy of the context pointer
|
||||
** passed as the sixth argument as the first. If the "filter callback"
|
||||
** returns zero, then no attempt is made to apply any changes to the table.
|
||||
** Otherwise, if the return value is non-zero or the xFilter argument to
|
||||
** is NULL, all changes related to the table are attempted.
|
||||
** callback". This may be passed NULL, in which case all changes in the
|
||||
** changeset are applied to the database. For sqlite3changeset_apply() and
|
||||
** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once
|
||||
** for each table affected by at least one change in the changeset. In this
|
||||
** case the table name is passed as the second argument, and a copy of
|
||||
** the context pointer passed as the sixth argument to apply() or apply_v2()
|
||||
** as the first. If the "filter callback" returns zero, then no attempt is
|
||||
** made to apply any changes to the table. Otherwise, if the return value is
|
||||
** non-zero, all changes related to the table are attempted.
|
||||
**
|
||||
** For sqlite3_changeset_apply_v3(), the xFilter callback is invoked once
|
||||
** per change. The second argument in this case is an sqlite3_changeset_iter
|
||||
** that may be queried using the usual APIs for the details of the current
|
||||
** change. If the "filter callback" returns zero in this case, then no attempt
|
||||
** is made to apply the current change. If it returns non-zero, the change
|
||||
** is applied.
|
||||
**
|
||||
** For each table that is not excluded by the filter callback, this function
|
||||
** tests that the target database contains a compatible table. A table is
|
||||
@@ -1172,11 +1181,11 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
|
||||
** one such warning is issued for each table in the changeset.
|
||||
**
|
||||
** For each change for which there is a compatible table, an attempt is made
|
||||
** to modify the table contents according to the UPDATE, INSERT or DELETE
|
||||
** change. If a change cannot be applied cleanly, the conflict handler
|
||||
** function passed as the fifth argument to sqlite3changeset_apply() may be
|
||||
** invoked. A description of exactly when the conflict handler is invoked for
|
||||
** each type of change is below.
|
||||
** to modify the table contents according to each UPDATE, INSERT or DELETE
|
||||
** change that is not excluded by a filter callback. If a change cannot be
|
||||
** applied cleanly, the conflict handler function passed as the fifth argument
|
||||
** to sqlite3changeset_apply() may be invoked. A description of exactly when
|
||||
** the conflict handler is invoked for each type of change is below.
|
||||
**
|
||||
** Unlike the xFilter argument, xConflict may not be passed NULL. The results
|
||||
** of passing anything other than a valid function pointer as the xConflict
|
||||
@@ -1327,6 +1336,23 @@ int sqlite3changeset_apply_v2(
|
||||
void **ppRebase, int *pnRebase, /* OUT: Rebase data */
|
||||
int flags /* SESSION_CHANGESETAPPLY_* flags */
|
||||
);
|
||||
int sqlite3changeset_apply_v3(
|
||||
sqlite3 *db, /* Apply change to "main" db of this handle */
|
||||
int nChangeset, /* Size of changeset in bytes */
|
||||
void *pChangeset, /* Changeset blob */
|
||||
int(*xFilter)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
sqlite3_changeset_iter *p /* Handle describing change */
|
||||
),
|
||||
int(*xConflict)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
|
||||
sqlite3_changeset_iter *p /* Handle describing change and conflict */
|
||||
),
|
||||
void *pCtx, /* First argument passed to xConflict */
|
||||
void **ppRebase, int *pnRebase, /* OUT: Rebase data */
|
||||
int flags /* SESSION_CHANGESETAPPLY_* flags */
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags for sqlite3changeset_apply_v2
|
||||
@@ -1746,6 +1772,23 @@ int sqlite3changeset_apply_v2_strm(
|
||||
void **ppRebase, int *pnRebase,
|
||||
int flags
|
||||
);
|
||||
int sqlite3changeset_apply_v3_strm(
|
||||
sqlite3 *db, /* Apply change to "main" db of this handle */
|
||||
int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
|
||||
void *pIn, /* First arg for xInput */
|
||||
int(*xFilter)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
sqlite3_changeset_iter *p
|
||||
),
|
||||
int(*xConflict)(
|
||||
void *pCtx, /* Copy of sixth arg to _apply() */
|
||||
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
|
||||
sqlite3_changeset_iter *p /* Handle describing change and conflict */
|
||||
),
|
||||
void *pCtx, /* First argument passed to xConflict */
|
||||
void **ppRebase, int *pnRebase,
|
||||
int flags
|
||||
);
|
||||
int sqlite3changeset_concat_strm(
|
||||
int (*xInputA)(void *pIn, void *pData, int *pnData),
|
||||
void *pInA,
|
||||
|
@@ -525,6 +525,65 @@ static int test_obj_eq_string(Tcl_Obj *p, const char *z){
|
||||
return (nObj==n && (n==0 || 0==memcmp(zObj, z, n)));
|
||||
}
|
||||
|
||||
static Tcl_Obj *testIterData(sqlite3_changeset_iter *pIter){
|
||||
Tcl_Obj *pVar = 0;
|
||||
int nCol; /* Number of columns in table */
|
||||
int nCol2; /* Number of columns in table */
|
||||
int op; /* SQLITE_INSERT, UPDATE or DELETE */
|
||||
const char *zTab; /* Name of table change applies to */
|
||||
Tcl_Obj *pOld; /* Vector of old.* values */
|
||||
Tcl_Obj *pNew; /* Vector of new.* values */
|
||||
int bIndirect;
|
||||
|
||||
char *zPK;
|
||||
unsigned char *abPK;
|
||||
int i;
|
||||
|
||||
sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
|
||||
pVar = Tcl_NewObj();
|
||||
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(
|
||||
op==SQLITE_INSERT ? "INSERT" :
|
||||
op==SQLITE_UPDATE ? "UPDATE" :
|
||||
"DELETE", -1
|
||||
));
|
||||
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1));
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect));
|
||||
|
||||
zPK = ckalloc(nCol+1);
|
||||
memset(zPK, 0, nCol+1);
|
||||
sqlite3changeset_pk(pIter, &abPK, &nCol2);
|
||||
assert( nCol==nCol2 );
|
||||
for(i=0; i<nCol; i++){
|
||||
zPK[i] = (abPK[i] ? 'X' : '.');
|
||||
}
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zPK, -1));
|
||||
ckfree(zPK);
|
||||
|
||||
pOld = Tcl_NewObj();
|
||||
if( op!=SQLITE_INSERT ){
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_old(pIter, i, &pVal);
|
||||
test_append_value(pOld, pVal);
|
||||
}
|
||||
}
|
||||
pNew = Tcl_NewObj();
|
||||
if( op!=SQLITE_DELETE ){
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_new(pIter, i, &pVal);
|
||||
test_append_value(pNew, pVal);
|
||||
}
|
||||
}
|
||||
Tcl_ListObjAppendElement(0, pVar, pOld);
|
||||
Tcl_ListObjAppendElement(0, pVar, pNew);
|
||||
|
||||
return pVar;
|
||||
}
|
||||
|
||||
|
||||
static int test_filter_handler(
|
||||
void *pCtx, /* Pointer to TestConflictHandler structure */
|
||||
const char *zTab /* Table name */
|
||||
@@ -544,6 +603,29 @@ static int test_filter_handler(
|
||||
Tcl_BackgroundError(interp);
|
||||
}
|
||||
|
||||
Tcl_DecrRefCount(pEval);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int test_filter_v3_handler(
|
||||
void *pCtx, /* Pointer to TestConflictHandler structure */
|
||||
sqlite3_changeset_iter *pIter
|
||||
){
|
||||
TestConflictHandler *p = (TestConflictHandler *)pCtx;
|
||||
int res = 1;
|
||||
Tcl_Obj *pEval = 0;
|
||||
Tcl_Interp *interp = p->interp;
|
||||
|
||||
pEval = Tcl_DuplicateObj(p->pFilterScript);
|
||||
Tcl_IncrRefCount(pEval);
|
||||
Tcl_ListObjAppendElement(0, pEval, testIterData(pIter));
|
||||
|
||||
if( TCL_OK!=Tcl_EvalObjEx(interp, pEval, TCL_EVAL_GLOBAL)
|
||||
|| TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &res)
|
||||
){
|
||||
Tcl_BackgroundError(interp);
|
||||
}
|
||||
|
||||
Tcl_DecrRefCount(pEval);
|
||||
return res;
|
||||
}
|
||||
@@ -781,7 +863,7 @@ static int testStreamInput(
|
||||
|
||||
|
||||
static int SQLITE_TCLAPI testSqlite3changesetApply(
|
||||
int bV2,
|
||||
int iVersion,
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
@@ -798,11 +880,13 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
|
||||
int nRebase = 0;
|
||||
int flags = 0; /* Flags for apply_v2() */
|
||||
|
||||
assert( iVersion==1 || iVersion==2 || iVersion==3 );
|
||||
|
||||
memset(&sStr, 0, sizeof(sStr));
|
||||
sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
|
||||
|
||||
/* Check for the -nosavepoint, -invert or -ignorenoop switches */
|
||||
if( bV2 ){
|
||||
if( iVersion==2 || iVersion==3 ){
|
||||
while( objc>1 ){
|
||||
const char *z1 = Tcl_GetString(objv[1]);
|
||||
int n = (int)strlen(z1);
|
||||
@@ -827,7 +911,7 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
|
||||
|
||||
if( objc!=4 && objc!=5 ){
|
||||
const char *zMsg;
|
||||
if( bV2 ){
|
||||
if( iVersion==2 || iVersion==3 ){
|
||||
zMsg = "?-nosavepoint? ?-inverse? ?-ignorenoop? "
|
||||
"DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?";
|
||||
}else{
|
||||
@@ -847,30 +931,49 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
|
||||
ctx.interp = interp;
|
||||
|
||||
if( sStr.nStream==0 ){
|
||||
if( bV2==0 ){
|
||||
rc = sqlite3changeset_apply(db, (int)nChangeset, pChangeset,
|
||||
(objc==5)?test_filter_handler:0, test_conflict_handler, (void *)&ctx
|
||||
);
|
||||
}else{
|
||||
rc = sqlite3changeset_apply_v2(db, (int)nChangeset, pChangeset,
|
||||
(objc==5)?test_filter_handler:0, test_conflict_handler, (void *)&ctx,
|
||||
&pRebase, &nRebase, flags
|
||||
);
|
||||
switch( iVersion ){
|
||||
case 1:
|
||||
rc = sqlite3changeset_apply(db, (int)nChangeset, pChangeset,
|
||||
(objc==5)?test_filter_handler:0, test_conflict_handler, (void*)&ctx
|
||||
);
|
||||
break;
|
||||
case 2:
|
||||
rc = sqlite3changeset_apply_v2(db, (int)nChangeset, pChangeset,
|
||||
(objc==5)?test_filter_handler:0, test_conflict_handler, (void*)&ctx,
|
||||
&pRebase, &nRebase, flags
|
||||
);
|
||||
break;
|
||||
case 3:
|
||||
rc = sqlite3changeset_apply_v3(db, (int)nChangeset, pChangeset,
|
||||
(objc==5)?test_filter_v3_handler:0, test_conflict_handler,
|
||||
(void*)&ctx, &pRebase, &nRebase, flags
|
||||
);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
sStr.aData = (unsigned char*)pChangeset;
|
||||
sStr.nData = (int)nChangeset;
|
||||
if( bV2==0 ){
|
||||
rc = sqlite3changeset_apply_strm(db, testStreamInput, (void*)&sStr,
|
||||
(objc==5) ? test_filter_handler : 0,
|
||||
test_conflict_handler, (void *)&ctx
|
||||
);
|
||||
}else{
|
||||
rc = sqlite3changeset_apply_v2_strm(db, testStreamInput, (void*)&sStr,
|
||||
(objc==5) ? test_filter_handler : 0,
|
||||
test_conflict_handler, (void *)&ctx,
|
||||
&pRebase, &nRebase, flags
|
||||
);
|
||||
switch( iVersion ){
|
||||
case 1:
|
||||
rc = sqlite3changeset_apply_strm(db, testStreamInput, (void*)&sStr,
|
||||
(objc==5) ? test_filter_handler : 0,
|
||||
test_conflict_handler, (void *)&ctx
|
||||
);
|
||||
break;
|
||||
case 2:
|
||||
rc = sqlite3changeset_apply_v2_strm(db, testStreamInput, (void*)&sStr,
|
||||
(objc==5) ? test_filter_handler : 0,
|
||||
test_conflict_handler, (void *)&ctx,
|
||||
&pRebase, &nRebase, flags
|
||||
);
|
||||
break;
|
||||
case 3:
|
||||
rc = sqlite3changeset_apply_v3_strm(db, testStreamInput, (void*)&sStr,
|
||||
(objc==5) ? test_filter_v3_handler : 0,
|
||||
test_conflict_handler, (void *)&ctx,
|
||||
&pRebase, &nRebase, flags
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -878,7 +981,7 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
|
||||
return test_session_error(interp, rc, 0);
|
||||
}else{
|
||||
Tcl_ResetResult(interp);
|
||||
if( bV2 && pRebase ){
|
||||
if( (iVersion==2 || iVersion==3) && pRebase ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pRebase, nRebase));
|
||||
}
|
||||
}
|
||||
@@ -895,7 +998,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_apply(
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
return testSqlite3changesetApply(0, clientData, interp, objc, objv);
|
||||
return testSqlite3changesetApply(1, clientData, interp, objc, objv);
|
||||
}
|
||||
/*
|
||||
** sqlite3changeset_apply_v2 DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?
|
||||
@@ -906,7 +1009,18 @@ static int SQLITE_TCLAPI test_sqlite3changeset_apply_v2(
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
return testSqlite3changesetApply(1, clientData, interp, objc, objv);
|
||||
return testSqlite3changesetApply(2, clientData, interp, objc, objv);
|
||||
}
|
||||
/*
|
||||
** sqlite3changeset_apply_v3 DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_sqlite3changeset_apply_v3(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
return testSqlite3changesetApply(3, clientData, interp, objc, objv);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1039,64 +1153,6 @@ static int SQLITE_TCLAPI test_sqlite3changeset_concat(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Tcl_Obj *testIterData(sqlite3_changeset_iter *pIter){
|
||||
Tcl_Obj *pVar = 0;
|
||||
int nCol; /* Number of columns in table */
|
||||
int nCol2; /* Number of columns in table */
|
||||
int op; /* SQLITE_INSERT, UPDATE or DELETE */
|
||||
const char *zTab; /* Name of table change applies to */
|
||||
Tcl_Obj *pOld; /* Vector of old.* values */
|
||||
Tcl_Obj *pNew; /* Vector of new.* values */
|
||||
int bIndirect;
|
||||
|
||||
char *zPK;
|
||||
unsigned char *abPK;
|
||||
int i;
|
||||
|
||||
sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
|
||||
pVar = Tcl_NewObj();
|
||||
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(
|
||||
op==SQLITE_INSERT ? "INSERT" :
|
||||
op==SQLITE_UPDATE ? "UPDATE" :
|
||||
"DELETE", -1
|
||||
));
|
||||
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1));
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect));
|
||||
|
||||
zPK = ckalloc(nCol+1);
|
||||
memset(zPK, 0, nCol+1);
|
||||
sqlite3changeset_pk(pIter, &abPK, &nCol2);
|
||||
assert( nCol==nCol2 );
|
||||
for(i=0; i<nCol; i++){
|
||||
zPK[i] = (abPK[i] ? 'X' : '.');
|
||||
}
|
||||
Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zPK, -1));
|
||||
ckfree(zPK);
|
||||
|
||||
pOld = Tcl_NewObj();
|
||||
if( op!=SQLITE_INSERT ){
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_old(pIter, i, &pVal);
|
||||
test_append_value(pOld, pVal);
|
||||
}
|
||||
}
|
||||
pNew = Tcl_NewObj();
|
||||
if( op!=SQLITE_DELETE ){
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_new(pIter, i, &pVal);
|
||||
test_append_value(pNew, pVal);
|
||||
}
|
||||
}
|
||||
Tcl_ListObjAppendElement(0, pVar, pOld);
|
||||
Tcl_ListObjAppendElement(0, pVar, pNew);
|
||||
|
||||
return pVar;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3session_foreach VARNAME CHANGESET SCRIPT
|
||||
*/
|
||||
@@ -1877,6 +1933,7 @@ int TestSession_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3changeset_concat", test_sqlite3changeset_concat },
|
||||
{ "sqlite3changeset_apply", test_sqlite3changeset_apply },
|
||||
{ "sqlite3changeset_apply_v2", test_sqlite3changeset_apply_v2 },
|
||||
{ "sqlite3changeset_apply_v3", test_sqlite3changeset_apply_v3 },
|
||||
{ "sqlite3changeset_apply_replace_all",
|
||||
test_sqlite3changeset_apply_replace_all },
|
||||
{ "sql_exec_changeset", test_sql_exec_changeset },
|
||||
|
@@ -39,10 +39,11 @@
|
||||
########################################################################
|
||||
default: all
|
||||
#default: quick
|
||||
MAKEFILE := $(lastword $(MAKEFILE_LIST))
|
||||
CLEAN_FILES :=
|
||||
DISTCLEAN_FILES := config.make
|
||||
MAKING_CLEAN := $(if $(filter %clean,$(MAKECMDGOALS)),1,0)
|
||||
MAKEFILE = $(lastword $(MAKEFILE_LIST))
|
||||
MAKEFILE.fiddle = fiddle.make
|
||||
CLEAN_FILES =
|
||||
DISTCLEAN_FILES = config.make
|
||||
MAKING_CLEAN = $(if $(filter %clean,$(MAKECMDGOALS)),1,0)
|
||||
.PHONY: clean distclean
|
||||
clean:
|
||||
-rm -f $(CLEAN_FILES)
|
||||
@@ -53,17 +54,17 @@ distclean: clean
|
||||
########################################################################
|
||||
# Special-case builds for which we require certain pre-conditions
|
||||
# which, if not met, may cause warnings or fatal errors in the build.
|
||||
# This also affects the default optimization level flags. Note that
|
||||
# the fiddle targets are in this list because they are used for
|
||||
# generating sqlite.org/fiddle.
|
||||
OPTIMIZED_TARGETS := dist snapshot fiddle fiddle.debug
|
||||
# This also affects the default optimization level flags. The fiddle
|
||||
# targets are in this list because they are used for generating
|
||||
# sqlite.org/fiddle.
|
||||
OPTIMIZED_TARGETS = dist snapshot fiddle fiddle.debug
|
||||
|
||||
ifeq (1,$(MAKING_CLEAN))
|
||||
bin.wasm-strip := echo "not stripping"
|
||||
bin.wasm-opt := irrelevant
|
||||
bin.emcc := irrelevant
|
||||
bin.bash := irrelevant
|
||||
emcc.version := unknown
|
||||
bin.wasm-strip = echo "not stripping"
|
||||
bin.wasm-opt = irrelevant
|
||||
bin.emcc = irrelevant
|
||||
bin.bash = irrelevant
|
||||
emcc.version = unknown
|
||||
else
|
||||
# Include config.make and perform some bootstrapping...
|
||||
ifeq (,$(wildcard ./config.make))
|
||||
@@ -76,7 +77,7 @@ else
|
||||
ifeq (,$(bin.emcc))
|
||||
$(error Configure script did not find emcc)
|
||||
endif
|
||||
emcc.version := $(shell $(bin.emcc) --version | sed -n 1p | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
|
||||
emcc.version = $(shell $(bin.emcc) --version | sed -n 1p | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
|
||||
$(info using emcc version [$(emcc.version)])
|
||||
ifeq (,$(bin.wasm-strip))
|
||||
####################################################################
|
||||
@@ -98,7 +99,7 @@ else
|
||||
ifneq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
|
||||
$(error Cannot make release-quality binary because wasm-strip is not available.)
|
||||
endif
|
||||
bin.wasm-strip := echo "not wasm-stripping"
|
||||
bin.wasm-strip = echo "not wasm-stripping"
|
||||
endif
|
||||
ifeq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
|
||||
$(info ==============================================================)
|
||||
@@ -108,7 +109,7 @@ else
|
||||
endif
|
||||
endif
|
||||
# ^^^ end of are-we-MAKING_CLEAN
|
||||
maybe-wasm-strip := $(bin.wasm-strip)
|
||||
maybe-wasm-strip = $(bin.wasm-strip)
|
||||
|
||||
########################################################################
|
||||
# JS_BUILD_NAMES exists for documentation purposes only. It enumerates
|
||||
@@ -118,7 +119,7 @@ maybe-wasm-strip := $(bin.wasm-strip)
|
||||
#
|
||||
# - sqlite3-wasmfs = WASMFS-capable library build
|
||||
#
|
||||
JS_BUILD_NAMES := sqlite3 sqlite3-wasmfs
|
||||
JS_BUILD_NAMES = sqlite3 sqlite3-wasmfs
|
||||
|
||||
########################################################################
|
||||
# JS_BUILD_MODES exists for documentation purposes only. It enumerates
|
||||
@@ -140,31 +141,31 @@ JS_BUILD_NAMES := sqlite3 sqlite3-wasmfs
|
||||
# that persistent storage (OPFS) is not available in these builds.
|
||||
# These builds are UNTESTED and UNSUPPORTED!
|
||||
#
|
||||
JS_BUILD_MODES := vanilla esm bunder-friendly node
|
||||
JS_BUILD_MODES = vanilla esm bunder-friendly node
|
||||
|
||||
########################################################################
|
||||
# dir.top = the top dir of the canonical build tree, where
|
||||
# sqlite3.[ch] live.
|
||||
dir.top := ../..
|
||||
dir.top = ../..
|
||||
# Maintenance reminder: some Emscripten flags require absolute paths
|
||||
# but we want relative paths for most stuff simply to reduce
|
||||
# noise. The $(abspath...) GNU make function can transform relative
|
||||
# paths to absolute.
|
||||
dir.wasm := $(patsubst %/,%,$(dir $(MAKEFILE)))
|
||||
dir.api := api
|
||||
dir.jacc := jaccwabyt
|
||||
dir.common := common
|
||||
dir.fiddle := fiddle
|
||||
dir.fiddle-debug := fiddle-debug
|
||||
dir.tool := $(dir.top)/tool
|
||||
dir.wasm = $(patsubst %/,%,$(dir $(MAKEFILE)))
|
||||
dir.api = api
|
||||
dir.jacc = jaccwabyt
|
||||
dir.common = common
|
||||
dir.fiddle = fiddle
|
||||
dir.fiddle-debug = fiddle-debug
|
||||
dir.tool = $(dir.top)/tool
|
||||
# dir.dout = output dir for deliverables
|
||||
dir.dout := $(dir.wasm)/jswasm
|
||||
dir.dout = $(dir.wasm)/jswasm
|
||||
# dir.tmp = output dir for intermediary build files, as opposed to
|
||||
# end-user deliverables.
|
||||
dir.tmp := $(dir.wasm)/bld
|
||||
dir.wasmfs := $(dir.dout)
|
||||
dir.tmp = $(dir.wasm)/bld
|
||||
dir.wasmfs = $(dir.dout)
|
||||
|
||||
MKDIR.bld := $(dir.tmp)
|
||||
MKDIR.bld = $(dir.tmp)
|
||||
$(MKDIR.bld):
|
||||
@mkdir -p $@ $(dir.dout)
|
||||
|
||||
@@ -188,17 +189,17 @@ CLEAN_FILES += *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~ $(dir.fiddle)/*~
|
||||
# $(sqlite3.canonical.c) must point to the sqlite3.c in
|
||||
# the sqlite3 canonical source tree, as that source file
|
||||
# is required for certain utility and test code.
|
||||
sqlite3.canonical.c := $(dir.top)/sqlite3.c
|
||||
sqlite3.canonical.c = $(dir.top)/sqlite3.c
|
||||
sqlite3.c ?= $(firstword $(wildcard $(dir.top)/sqlite3-see.c) $(sqlite3.canonical.c))
|
||||
sqlite3.h := $(dir.top)/sqlite3.h
|
||||
sqlite3.h = $(dir.top)/sqlite3.h
|
||||
|
||||
ifeq (1,$(MAKING_CLEAN))
|
||||
SQLITE_C_IS_SEE := 0
|
||||
SQLITE_C_IS_SEE = 0
|
||||
else
|
||||
ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c)))
|
||||
SQLITE_C_IS_SEE := 0
|
||||
SQLITE_C_IS_SEE = 0
|
||||
else
|
||||
SQLITE_C_IS_SEE := 1
|
||||
SQLITE_C_IS_SEE = 1
|
||||
$(info This is an SEE build)
|
||||
endif
|
||||
endif
|
||||
@@ -216,19 +217,19 @@ $(sqlite3.c): $(sqlite3.h)
|
||||
# barebones=1 disables all "extraneous" stuff from sqlite3-wasm.c, the
|
||||
# goal being to create a WASM file with only the core APIs.
|
||||
ifeq (1,$(barebones))
|
||||
wasm-bare-bones := 1
|
||||
wasm-bare-bones = 1
|
||||
$(info ==============================================================)
|
||||
$(info == This is a bare-bones build. It trades away features for)
|
||||
$(info == a smaller .wasm file.)
|
||||
$(info ==============================================================)
|
||||
else
|
||||
wasm-bare-bones := 0
|
||||
wasm-bare-bones = 0
|
||||
endif
|
||||
# undefine barebones # relatively new gmake feature, not ubiquitous
|
||||
|
||||
# Common options for building sqlite3-wasm.c and speedtest1.c.
|
||||
# Explicit ENABLEs...
|
||||
SQLITE_OPT.common := \
|
||||
SQLITE_OPT.common = \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_TEMP_STORE=2 \
|
||||
-DSQLITE_ENABLE_MATH_FUNCTIONS \
|
||||
@@ -249,7 +250,7 @@ SQLITE_OPT.common := \
|
||||
SQLITE_OPT.common += -DSQLITE_WASM_ENABLE_C_TESTS
|
||||
|
||||
# Extra flags for full-featured builds...
|
||||
SQLITE_OPT.full-featured := \
|
||||
SQLITE_OPT.full-featured = \
|
||||
-DSQLITE_ENABLE_BYTECODE_VTAB \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB \
|
||||
@@ -265,12 +266,12 @@ SQLITE_OPT.full-featured := \
|
||||
|
||||
ifeq (0,$(wasm-bare-bones))
|
||||
# The so-called canonical build is full-featured:
|
||||
SQLITE_OPT := \
|
||||
SQLITE_OPT = \
|
||||
$(SQLITE_OPT.common) \
|
||||
$(SQLITE_OPT.full-featured)
|
||||
else
|
||||
# The so-called bare-bones build is exactly that:
|
||||
SQLITE_OPT := \
|
||||
SQLITE_OPT = \
|
||||
$(SQLITE_OPT.common) \
|
||||
-DSQLITE_WASM_BARE_BONES
|
||||
# SQLITE_WASM_BARE_BONES tells sqlite3-wasm.c to explicitly omit
|
||||
@@ -345,10 +346,10 @@ endif
|
||||
# See example_extra_init.c for an example implementation.
|
||||
########################################################################
|
||||
sqlite3_wasm_extra_init.c ?= $(wildcard sqlite3_wasm_extra_init.c)
|
||||
cflags.wasm_extra_init :=
|
||||
cflags.wasm_extra_init =
|
||||
ifneq (,$(sqlite3_wasm_extra_init.c))
|
||||
$(info Enabling SQLITE_EXTRA_INIT via $(sqlite3_wasm_extra_init.c).)
|
||||
cflags.wasm_extra_init := -DSQLITE_WASM_EXTRA_INIT
|
||||
cflags.wasm_extra_init = -DSQLITE_WASM_EXTRA_INIT
|
||||
endif
|
||||
|
||||
#########################################################################
|
||||
@@ -362,7 +363,7 @@ endif
|
||||
# end result is that the generated JS files may have static version
|
||||
# info from $(bin.version-info) which differ from their runtime-emitted
|
||||
# version info (e.g. from sqlite3_libversion()).
|
||||
bin.version-info := $(dir.top)/version-info
|
||||
bin.version-info = $(dir.top)/version-info
|
||||
.NOTPARALLEL: $(bin.version-info)
|
||||
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
|
||||
$(MAKE) -C $(dir.top) version-info
|
||||
@@ -373,7 +374,7 @@ $(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
|
||||
# don't need for all builds. That app's -k flag is of particular
|
||||
# importance here, as it allows us to retain the opening comment
|
||||
# block(s), which contain the license header and version info.
|
||||
bin.stripccomments := $(dir.tool)/stripccomments
|
||||
bin.stripccomments = $(dir.tool)/stripccomments
|
||||
$(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
|
||||
$(CC) -o $@ $<
|
||||
DISTCLEAN_FILES += $(bin.stripccomments)
|
||||
@@ -410,7 +411,7 @@ DISTCLEAN_FILES += $(bin.stripccomments)
|
||||
#
|
||||
# -D... flags which should be included in all invocations should be
|
||||
# appended to $(SQLITE.CALL.C-PP.FILTER.global).
|
||||
bin.c-pp := ./c-pp
|
||||
bin.c-pp = ./c-pp
|
||||
$(bin.c-pp): c-pp.c $(sqlite3.c) # $(MAKEFILE)
|
||||
$(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \
|
||||
@@ -429,13 +430,13 @@ define SQLITE.CALL.C-PP.FILTER
|
||||
$(2): $(1) $$(MAKEFILE_LIST) $$(bin.c-pp)
|
||||
@mkdir -p $$(dir $$@)
|
||||
$$(bin.c-pp) -f $(1) -o $$@ $(3) $(SQLITE.CALL.C-PP.FILTER.global)
|
||||
#CLEAN_FILES += $(2)
|
||||
CLEAN_FILES += $(2)
|
||||
endef
|
||||
# /end SQLITE.CALL.C-PP.FILTER
|
||||
########################################################################
|
||||
|
||||
# cflags.common = C compiler flags for all builds
|
||||
cflags.common := -I. -I$(dir $(sqlite3.c))
|
||||
cflags.common = -I. -I$(dir $(sqlite3.c))
|
||||
# emcc.WASM_BIGINT = 1 for BigInt (C int64) support, else 0. The API
|
||||
# disables certain features if BigInt is not enabled and such builds
|
||||
# _are not tested_ on any regular basis.
|
||||
@@ -456,9 +457,24 @@ else
|
||||
emcc_opt ?= -Oz
|
||||
endif
|
||||
|
||||
# Our JS code installs bindings of each sqlite3_...() WASM export. The
|
||||
# generated Emscripten JS file does the same using its own framework,
|
||||
# but we don't use those results and can speed up lib init, and reduce
|
||||
# memory cost a bit, by stripping them out. Emscripten-side changes
|
||||
# can "break" this, causing this to be a no-op, but the worst that can
|
||||
# happen in that case is that it doesn't actually strip anything,
|
||||
# leading to slightly larger JS files.
|
||||
#
|
||||
# This snippet is intended to be used in makefile targets which
|
||||
# generate an Emscripten module and where $@ is the module's .js/.mjs
|
||||
# file.
|
||||
SQLITE.strip-createExportWrapper = \
|
||||
sed -i -e '/^.*= \(_sqlite3\|_fiddle\)[^=]* = createExportWrapper/d' $@ || exit; \
|
||||
echo '(Probably) stripped out extraneous createExportWrapper() parts.'
|
||||
|
||||
# When passing emcc_opt from the CLI, += and re-assignment have no
|
||||
# effect, so emcc_opt+=-g3 doesn't work. So...
|
||||
emcc_opt_full := $(emcc_opt) -g3
|
||||
emcc_opt_full = $(emcc_opt) -g3
|
||||
# ^^^ ALWAYS use -g3. See below for why.
|
||||
#
|
||||
# ^^^ -flto improves runtime speed at -O0 considerably but doubles
|
||||
@@ -489,31 +505,28 @@ emcc_opt_full := $(emcc_opt) -g3
|
||||
########################################################################
|
||||
# EXPORTED_FUNCTIONS.* = files for use with Emscripten's
|
||||
# -sEXPORTED_FUNCTION flag.
|
||||
EXPORTED_FUNCTIONS.api.core := $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core
|
||||
EXPORTED_FUNCTIONS.api.in := $(EXPORTED_FUNCTIONS.api.core)
|
||||
EXPORTED_FUNCTIONS.api.core = $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core
|
||||
EXPORTED_FUNCTIONS.api.in = $(EXPORTED_FUNCTIONS.api.core)
|
||||
ifeq (1,$(SQLITE_C_IS_SEE))
|
||||
EXPORTED_FUNCTIONS.api.in += $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-see
|
||||
endif
|
||||
ifeq (0,$(wasm-bare-bones))
|
||||
EXPORTED_FUNCTIONS.api.in += $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
|
||||
endif
|
||||
EXPORTED_FUNCTIONS.api := $(dir.tmp)/EXPORTED_FUNCTIONS.api
|
||||
EXPORTED_FUNCTIONS.api = $(dir.tmp)/EXPORTED_FUNCTIONS.api
|
||||
$(EXPORTED_FUNCTIONS.api): $(MKDIR.bld) $(EXPORTED_FUNCTIONS.api.in) $(sqlite3.c) $(MAKEFILE)
|
||||
cat $(EXPORTED_FUNCTIONS.api.in) > $@
|
||||
|
||||
########################################################################
|
||||
# sqlite3-license-version.js = generated JS file with the license
|
||||
# header and version info.
|
||||
sqlite3-license-version.js := $(dir.tmp)/sqlite3-license-version.js
|
||||
# sqlite3-license-version-header.js = JS file containing only the
|
||||
# license header.
|
||||
sqlite3-license-version-header.js := $(dir.api)/sqlite3-license-version-header.js
|
||||
sqlite3-license-version.js = $(dir.tmp)/sqlite3-license-version.js
|
||||
# sqlite3-api-build-version.js = generated JS file which populates the
|
||||
# sqlite3.version object using $(bin.version-info).
|
||||
sqlite3-api-build-version.js := $(dir.tmp)/sqlite3-api-build-version.js
|
||||
sqlite3-api-build-version.js = $(dir.tmp)/sqlite3-api-build-version.js
|
||||
# sqlite3-api.jses = the list of JS files which make up
|
||||
# $(sqlite3-api.js.in), in the order they need to be assembled.
|
||||
sqlite3-api.jses := $(sqlite3-license-version.js)
|
||||
sqlite3-api.jses = $(sqlite3-license-version.js)
|
||||
# sqlite3-api-prologue.js: initial bootstrapping bits:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-api-prologue.js
|
||||
# whwhasm.js and jaccwabyt.js: Low-level utils, mostly replacing
|
||||
@@ -547,13 +560,13 @@ sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
|
||||
# SOAP.js is an external API file which is part of our distribution
|
||||
# but not part of the sqlite3-api.js amalgamation. It's a component of
|
||||
# the first OPFS VFS and necessarily an external file.
|
||||
SOAP.js := $(dir.api)/sqlite3-opfs-async-proxy.js
|
||||
SOAP.js.bld := $(dir.dout)/$(notdir $(SOAP.js))
|
||||
SOAP.js = $(dir.api)/sqlite3-opfs-async-proxy.js
|
||||
SOAP.js.bld = $(dir.dout)/$(notdir $(SOAP.js))
|
||||
#
|
||||
# $(sqlite3-api.ext.jses) = API-related files which are standalone files,
|
||||
# not part of the amalgamation.
|
||||
#
|
||||
sqlite3-api.ext.jses := $(SOAP.js.bld)
|
||||
sqlite3-api.ext.jses = $(SOAP.js.bld)
|
||||
$(SOAP.js.bld): $(SOAP.js)
|
||||
cp $< $@
|
||||
|
||||
@@ -573,17 +586,12 @@ $(SOAP.js.bld): $(SOAP.js)
|
||||
# Sidebar: some of the imports are used soley by the Emscripten glue,
|
||||
# which the sqlite3 JS code does not rely on.
|
||||
#
|
||||
# We build $(sqlite3-api*.*) "because we can" and because it might be
|
||||
# a useful point of experimentation for some clients, but the
|
||||
# above-described caveat may well make them unusable for real-life
|
||||
# clients.
|
||||
#
|
||||
# sqlite3-api.js.in = the generated sqlite3-api.js before it gets
|
||||
# sqlite3-api.js.in = the amalgamated sqlite3-api.js before it gets
|
||||
# preprocessed. It contains all of $(sqlite3-api.jses) but none of the
|
||||
# Emscripten-specific headers and footers.
|
||||
sqlite3-api.js.in := $(dir.tmp)/sqlite3-api.c-pp.js
|
||||
sqlite3-api.js.in = $(dir.tmp)/sqlite3-api.c-pp.js
|
||||
$(sqlite3-api.js.in): $(MKDIR.bld) $(sqlite3-api.jses) $(MAKEFILE)
|
||||
@echo "Making $@..."
|
||||
@echo "Making $@ ..."
|
||||
@for i in $(sqlite3-api.jses); do \
|
||||
echo "/* BEGIN FILE: $$i */"; \
|
||||
cat $$i; \
|
||||
@@ -592,7 +600,7 @@ $(sqlite3-api.js.in): $(MKDIR.bld) $(sqlite3-api.jses) $(MAKEFILE)
|
||||
|
||||
########################################################################
|
||||
# emcc flags for .c/.o/.wasm/.js.
|
||||
emcc.flags :=
|
||||
emcc.flags =
|
||||
ifeq (1,$(emcc.verbose))
|
||||
emcc.flags += -v
|
||||
# -v is _very_ loud but also informative about what it's doing
|
||||
@@ -601,25 +609,25 @@ endif
|
||||
|
||||
########################################################################
|
||||
# emcc flags for .c/.o.
|
||||
emcc.cflags :=
|
||||
emcc.cflags =
|
||||
emcc.cflags += -std=c99 -fPIC
|
||||
# -------------^^^^^^^^ we need c99 for $(sqlite3-wasm.c), primarily
|
||||
# for variadic macros and snprintf() to implement
|
||||
# sqlite3_wasm_enum_json().
|
||||
# sqlite3__wasm_enum_json().
|
||||
emcc.cflags += -I. -I$(dir.top)
|
||||
########################################################################
|
||||
# emcc flags specific to building .js/.wasm files...
|
||||
emcc.jsflags := -fPIC
|
||||
emcc.jsflags = -fPIC
|
||||
emcc.jsflags += --no-entry
|
||||
emcc.jsflags += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
|
||||
emcc.jsflags += -sMODULARIZE
|
||||
emcc.jsflags += -sDYNAMIC_EXECUTION=0
|
||||
emcc.jsflags += -sNO_POLYFILL
|
||||
emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.api)
|
||||
emcc.exportedRuntimeMethods := \
|
||||
-sEXPORTED_RUNTIME_METHODS=wasmMemory,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAP64,HEAPU64
|
||||
emcc.exportedRuntimeMethods = \
|
||||
-sEXPORTED_RUNTIME_METHODS=wasmMemory
|
||||
# wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY
|
||||
# Emscripten 4.0.7 (2025-04-15) stops exporting HEAP* by default
|
||||
# Emscripten 4.0.7 (2025-04-15) stops exporting HEAP* by default.
|
||||
emcc.jsflags += $(emcc.exportedRuntimeMethods)
|
||||
emcc.jsflags += -sUSE_CLOSURE_COMPILER=0
|
||||
emcc.jsflags += -sIMPORTED_MEMORY
|
||||
@@ -641,10 +649,10 @@ emcc.jsflags += -sSTRICT_JS=0
|
||||
# tools should be installing, e.g. __syscall_geteuid32
|
||||
|
||||
# -sENVIRONMENT values for the various build modes:
|
||||
emcc.environment.vanilla := web,worker
|
||||
emcc.environment.bundler-friendly := $(emcc.environment.vanilla)
|
||||
emcc.environment.esm := $(emcc.environment.vanilla)
|
||||
emcc.environment.node := node
|
||||
emcc.environment.vanilla = web,worker
|
||||
emcc.environment.bundler-friendly = $(emcc.environment.vanilla)
|
||||
emcc.environment.esm = $(emcc.environment.vanilla)
|
||||
emcc.environment.node = node
|
||||
# Note that adding ",node" to the list for the other builds causes
|
||||
# Emscripten to generate code which confuses node: it cannot reliably
|
||||
# determine whether the build is for a browser or for node.
|
||||
@@ -666,12 +674,12 @@ emcc.environment.node := node
|
||||
# supported in all configurations (#21071)."
|
||||
# https://github.com/emscripten-core/emscripten/blob/main/ChangeLog.md
|
||||
emcc.jsflags += -sALLOW_MEMORY_GROWTH
|
||||
emcc.INITIAL_MEMORY.128 := 134217728
|
||||
emcc.INITIAL_MEMORY.96 := 100663296
|
||||
emcc.INITIAL_MEMORY.64 := 67108864
|
||||
emcc.INITIAL_MEMORY.32 := 33554432
|
||||
emcc.INITIAL_MEMORY.16 := 16777216
|
||||
emcc.INITIAL_MEMORY.8 := 8388608
|
||||
emcc.INITIAL_MEMORY.128 = 134217728
|
||||
emcc.INITIAL_MEMORY.96 = 100663296
|
||||
emcc.INITIAL_MEMORY.64 = 67108864
|
||||
emcc.INITIAL_MEMORY.32 = 33554432
|
||||
emcc.INITIAL_MEMORY.16 = 16777216
|
||||
emcc.INITIAL_MEMORY.8 = 8388608
|
||||
emcc.INITIAL_MEMORY ?= 16
|
||||
ifeq (,$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY)))
|
||||
$(error emcc.INITIAL_MEMORY must be one of: 8, 16, 32, 64, 96, 128 (megabytes))
|
||||
@@ -704,7 +712,7 @@ emcc.jsflags += -sSTACK_SIZE=512KB
|
||||
# symbols: we cannot "delete" the Emscripten-defined
|
||||
# $(sqlite3.js.init-func) from vanilla builds (as opposed to ESM
|
||||
# builds) because it's declared with "var".
|
||||
sqlite3.js.init-func := sqlite3InitModule
|
||||
sqlite3.js.init-func = sqlite3InitModule
|
||||
emcc.jsflags += -sEXPORT_NAME=$(sqlite3.js.init-func)
|
||||
emcc.jsflags += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr.
|
||||
#emcc.jsflags += -sSTRICT # fails due to missing __syscall_...()
|
||||
@@ -772,17 +780,17 @@ $(sqlite3-api-build-version.js): $(MKDIR.bld) $(bin.version-info) $(MAKEFILE)
|
||||
#
|
||||
# Maintenance reminder: there are awk binaries out there which do not
|
||||
# support -e SCRIPT.
|
||||
$(sqlite3-license-version.js): $(MKDIR.bld) $(sqlite3.h) $(sqlite3-license-version-header.js) \
|
||||
$(MAKEFILE)
|
||||
$(sqlite3-license-version.js): $(MKDIR.bld) $(sqlite3.h) \
|
||||
$(dir.api)/sqlite3-license-version-header.js $(MAKEFILE)
|
||||
@echo "Making $@..."; { \
|
||||
cat $(sqlite3-license-version-header.js); \
|
||||
cat $(dir.api)/sqlite3-license-version-header.js; \
|
||||
echo '/*'; \
|
||||
echo '** This code was built from sqlite3 version...'; \
|
||||
echo "**"; \
|
||||
awk '/define SQLITE_VERSION/{$$1=""; print "**" $$0}' $(sqlite3.h); \
|
||||
awk '/define SQLITE_SOURCE_ID/{$$1=""; print "**" $$0}' $(sqlite3.h); \
|
||||
echo "**"; \
|
||||
echo "** Using the Emscripten SDK version $(emcc.version)."; \
|
||||
echo "** with the help of Emscripten SDK version $(emcc.version)."; \
|
||||
echo '*/'; \
|
||||
} > $@
|
||||
|
||||
@@ -794,9 +802,9 @@ $(sqlite3-license-version.js): $(MKDIR.bld) $(sqlite3.h) $(sqlite3-license-versi
|
||||
# --post-js injects code which runs after the WASM module is loaded
|
||||
# and includes the entirety of the library plus some
|
||||
# Emscripten-specific post-bootstrapping code.
|
||||
pre-js.js.in := $(dir.api)/pre-js.c-pp.js
|
||||
post-js.js.in := $(dir.tmp)/post-js.c-pp.js
|
||||
post-jses.js := \
|
||||
pre-js.js.in = $(dir.api)/pre-js.c-pp.js
|
||||
post-js.js.in = $(dir.tmp)/post-js.c-pp.js
|
||||
post-jses.js = \
|
||||
$(dir.api)/post-js-header.js \
|
||||
$(sqlite3-api.js.in) \
|
||||
$(dir.api)/post-js-footer.js
|
||||
@@ -812,10 +820,10 @@ $(post-js.js.in): $(MKDIR.bld) $(post-jses.js) $(MAKEFILE)
|
||||
# Undocumented Emscripten feature: if the target file extension is
|
||||
# "mjs", it defaults to ES6 module builds:
|
||||
# https://github.com/emscripten-core/emscripten/issues/14383
|
||||
sqlite3.wasm := $(dir.dout)/sqlite3.wasm
|
||||
sqlite3-wasm.c := $(dir.api)/sqlite3-wasm.c
|
||||
sqlite3-wasm.cfiles := $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
|
||||
sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
|
||||
sqlite3.wasm = $(dir.dout)/sqlite3.wasm
|
||||
sqlite3-wasm.c = $(dir.api)/sqlite3-wasm.c
|
||||
sqlite3-wasm.cfiles = $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
|
||||
sqlite3-wasmfs.cfiles = $(sqlite3-wasm.cfiles)
|
||||
# sqlite3-wasm.o vs sqlite3-wasm.c: building against the latter
|
||||
# (predictably) results in a slightly faster binary. We're close
|
||||
# enough to the target speed requirements that the 500ms makes a
|
||||
@@ -860,17 +868,9 @@ if [ x1 = x$(1) ]; then \
|
||||
fi
|
||||
endef
|
||||
|
||||
sqlite3-api.js := $(dir.dout)/sqlite3-api.js
|
||||
sqlite3.js := $(dir.dout)/sqlite3.js
|
||||
sqlite3-api.mjs := $(dir.dout)/sqlite3-api.mjs
|
||||
sqlite3.mjs := $(dir.dout)/sqlite3.mjs
|
||||
sqlite3-api-bundler-friendly.mjs := $(dir.dout)/sqlite3-api-bundler-friendly.mjs
|
||||
sqlite3-bundler-friendly.mjs := $(dir.dout)/sqlite3-bundler-friendly.mjs
|
||||
sqlite3-api-node.mjs := $(dir.dout)/sqlite3-api-node.mjs
|
||||
sqlite3-node.mjs := $(dir.dout)/sqlite3-node.mjs
|
||||
sqlite3-api-wasmfs.mjs := $(dir.tmp)/sqlite3-api-wasmfs.mjs
|
||||
sqlite3-wasmfs.mjs := $(dir.wasmfs)/sqlite3-wasmfs.mjs
|
||||
EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
|
||||
sqlite3.js = $(dir.dout)/sqlite3.js
|
||||
sqlite3.mjs = $(dir.dout)/sqlite3.mjs
|
||||
EXPORTED_FUNCTIONS.fiddle = $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
|
||||
|
||||
# The various -D... values used by *.c-pp.js include:
|
||||
#
|
||||
@@ -904,24 +904,10 @@ EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
|
||||
# build time).
|
||||
$(sqlite3.wasm): $(sqlite3.js)
|
||||
$(sqlite3.mjs): $(sqlite3.js)
|
||||
$(sqlite3-bundler-friendly.mjs): $(sqlite3.mjs)
|
||||
$(sqlite3-node.mjs): $(sqlite3.mjs)
|
||||
$(dir.dout)/sqlite3-bundler-friendly.mjs: $(sqlite3.mjs)
|
||||
$(dir.dout)/sqlite3-node.mjs: $(sqlite3.mjs)
|
||||
#CLEAN_FILES += $(sqlite3.wasm)
|
||||
|
||||
########################################################################
|
||||
# We need separate copies of certain supplementary JS files for the
|
||||
# bundler-friendly build. Concretely, any supplemental JS files which
|
||||
# themselves use importScripts() or Workers or URL() constructors
|
||||
# which refer to other in-tree (m)JS files require a bundler-friendly
|
||||
# copy.
|
||||
sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js
|
||||
sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js
|
||||
sqlite3-worker1.js := $(dir.dout)/sqlite3-worker1.js
|
||||
sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js
|
||||
sqlite3-worker1-promiser.mjs := $(dir.dout)/sqlite3-worker1-promiser.mjs
|
||||
sqlite3-worker1-bundler-friendly.mjs := $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs
|
||||
sqlite3-worker1-promiser-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js
|
||||
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
# This block MUST come between the above definitions of
|
||||
# sqlite3-...js/mjs and the $(eval) calls below this block which use
|
||||
@@ -934,7 +920,10 @@ ifneq (1,$(MAKING_CLEAN))
|
||||
# the $ references in those languages made it just as illegible as the
|
||||
# native makefile code. Somewhat surprisingly, moving that code generation
|
||||
# to C makes it slightly less illegible than the previous 3 options.
|
||||
bin.mkwb := ./mkwasmbuilds
|
||||
#
|
||||
# Maintenance note: the various $(c-pp.D.XYZ) vars are defined in this
|
||||
# step.
|
||||
bin.mkwb = ./mkwasmbuilds
|
||||
$(bin.mkwb): $(bin.mkwb).c $(MAKEFILE)
|
||||
$(CC) -o $@ $<
|
||||
DISTCLEAN_FILES += $(bin.mkwb)
|
||||
@@ -946,45 +935,60 @@ DISTCLEAN_FILES += $(bin.mkwb)
|
||||
endif
|
||||
DISTCLEAN_FILES += .wasmbuilds.make
|
||||
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js)))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.mjs),\
|
||||
########################################################################
|
||||
# We need separate copies of certain supplementary JS files for the
|
||||
# bundler-friendly build. Concretely, any supplemental JS files which
|
||||
# themselves use importScripts() or Workers or URL() constructors
|
||||
# which refer to other in-tree (m)JS files require a bundler-friendly
|
||||
# copy. Bundler-friendly builds replace certain references to string
|
||||
# vars/expressions with string literals, as bundler tools are static
|
||||
# code analyzers and cannot cope with the former.
|
||||
#
|
||||
# Most of what follows is the generation of those copies.
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(dir.api)/sqlite3-worker1.c-pp.js,\
|
||||
$(dir.dout)/sqlite3-worker1.js))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(dir.api)/sqlite3-worker1.c-pp.js,\
|
||||
$(dir.dout)/sqlite3-worker1-bundler-friendly.mjs,\
|
||||
$(c-pp.D.sqlite3-bundler-friendly)))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js)))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\
|
||||
$(sqlite3-worker1-promiser-bundler-friendly.js),\
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(dir.api)/sqlite3-worker1-promiser.c-pp.js,\
|
||||
$(dir.dout)/sqlite3-worker1-promiser.js))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(dir.api)/sqlite3-worker1-promiser.c-pp.js,\
|
||||
$(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js,\
|
||||
$(c-pp.D.sqlite3-bundler-friendly)))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.mjs),\
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(dir.api)/sqlite3-worker1-promiser.c-pp.js,\
|
||||
$(dir.dout)/sqlite3-worker1-promiser.mjs,\
|
||||
-Dtarget=es6-module -Dtarget=es6-bundler-friendly))
|
||||
$(sqlite3-bundler-friendly.mjs): $(sqlite3-worker1-bundler-friendly.mjs) \
|
||||
$(sqlite3-worker1-promiser-bundler-friendly.js)
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.js))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.mjs,\
|
||||
-Dtarget=es6-module))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser.html))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser-esm.html,\
|
||||
-Dtarget=es6-module))
|
||||
all: $(sqlite3-worker1.js) \
|
||||
$(sqlite3-worker1-promiser.js) $(sqlite3-worker1-promiser.mjs)
|
||||
|
||||
demo-worker1-promiser.html: $(sqlite3-worker1-promiser.js) demo-worker1-promiser.js
|
||||
$(dir.dout)/sqlite3-bundler-friendly.mjs: \
|
||||
$(dir.dout)/sqlite3-worker1-bundler-friendly.mjs \
|
||||
$(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js
|
||||
|
||||
demo-worker1-promiser.html: $(dir.dout)/sqlite3-worker1-promiser.js demo-worker1-promiser.js
|
||||
demo-worker1-promiser-esm.html: $(sqlite3-worker1-promiser.mjs) demo-worker1-promiser.mjs
|
||||
all: demo-worker1-promiser.html demo-worker1-promiser-esm.html
|
||||
|
||||
sqlite3-api.ext.jses += \
|
||||
$(sqlite3-worker1-promiser.mjs) \
|
||||
$(sqlite3-worker1-bundler-friendly.mjs) \
|
||||
$(sqlite3-worker1.js)
|
||||
$(dir.dout)/sqlite3-worker1-promiser.mjs \
|
||||
$(dir.dout)/sqlite3-worker1-promiser.js \
|
||||
$(dir.dout)/sqlite3-worker1-bundler-friendly.mjs \
|
||||
$(dir.dout)/sqlite3-worker1.js
|
||||
all quick: $(sqlite3-api.ext.jses)
|
||||
q: quick
|
||||
|
||||
########################################################################
|
||||
# batch-runner.js is part of one of the test apps which reads in SQL
|
||||
# dumps generated by $(speedtest1) and executes them.
|
||||
dir.sql := sql
|
||||
speedtest1 := ../../speedtest1
|
||||
speedtest1.c := ../../test/speedtest1.c
|
||||
speedtest1.sql := $(dir.sql)/speedtest1.sql
|
||||
speedtest1.cliflags := --size 10 --big-transactions
|
||||
dir.sql = sql
|
||||
speedtest1 = ../../speedtest1
|
||||
speedtest1.c = ../../test/speedtest1.c
|
||||
speedtest1.sql = $(dir.sql)/speedtest1.sql
|
||||
speedtest1.cliflags = --size 10 --big-transactions
|
||||
$(speedtest1):
|
||||
$(MAKE) -C ../.. speedtest1
|
||||
$(speedtest1.sql): $(speedtest1) $(MAKEFILE)
|
||||
@@ -1005,8 +1009,8 @@ batch: batch-runner.list
|
||||
#
|
||||
# emcc.speedtest1.common = emcc flags used by multiple builds of speedtest1
|
||||
# emcc.speedtest1 = emcc flags used by main build of speedtest1
|
||||
emcc.speedtest1.common := $(emcc_opt_full)
|
||||
emcc.speedtest1 := -I. -I$(dir $(sqlite3.canonical.c))
|
||||
emcc.speedtest1.common = $(emcc_opt_full)
|
||||
emcc.speedtest1 = -I. -I$(dir $(sqlite3.canonical.c))
|
||||
emcc.speedtest1 += -sENVIRONMENT=web
|
||||
emcc.speedtest1 += -sALLOW_MEMORY_GROWTH
|
||||
emcc.speedtest1 += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
|
||||
@@ -1019,7 +1023,7 @@ emcc.speedtest1.common += -Wno-limited-postlink-optimizations
|
||||
emcc.speedtest1.common += -Wno-unused-main
|
||||
# ^^^^ -Wno-unused-main is for emcc 3.1.52+. speedtest1 has a wasm_main() which is
|
||||
# exported and called by the JS code.
|
||||
EXPORTED_FUNCTIONS.speedtest1 := $(abspath $(dir.tmp)/EXPORTED_FUNCTIONS.speedtest1)
|
||||
EXPORTED_FUNCTIONS.speedtest1 = $(abspath $(dir.tmp)/EXPORTED_FUNCTIONS.speedtest1)
|
||||
emcc.speedtest1.common += -sSTACK_SIZE=512KB
|
||||
emcc.speedtest1.common += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.speedtest1)
|
||||
emcc.speedtest1.common += $(emcc.exportedRuntimeMethods)
|
||||
@@ -1028,8 +1032,8 @@ emcc.speedtest1.common += -sDYNAMIC_EXECUTION=0
|
||||
emcc.speedtest1.common += --minify 0
|
||||
emcc.speedtest1.common += -sEXPORT_NAME=$(sqlite3.js.init-func)
|
||||
emcc.speedtest1.common += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
|
||||
speedtest1.exit-runtime0 := -sEXIT_RUNTIME=0
|
||||
speedtest1.exit-runtime1 := -sEXIT_RUNTIME=1
|
||||
speedtest1.exit-runtime0 = -sEXIT_RUNTIME=0
|
||||
speedtest1.exit-runtime1 = -sEXIT_RUNTIME=1
|
||||
# Re -sEXIT_RUNTIME=1 vs 0: if it's 1 and speedtest1 crashes, we get
|
||||
# this error from emscripten:
|
||||
#
|
||||
@@ -1050,10 +1054,9 @@ speedtest1.exit-runtime1 := -sEXIT_RUNTIME=1
|
||||
$(EXPORTED_FUNCTIONS.speedtest1): $(MKDIR.bld) $(EXPORTED_FUNCTIONS.api.core)
|
||||
@echo "Making $@ ..."
|
||||
@{ echo _wasm_main; cat $(EXPORTED_FUNCTIONS.api.core); } > $@
|
||||
speedtest1.js := $(dir.dout)/speedtest1.js
|
||||
speedtest1.wasm := $(dir.dout)/speedtest1.wasm
|
||||
emcc.flags.speedtest1-vanilla := $(cflags.common) -DSQLITE_SPEEDTEST1_WASM
|
||||
speedtest1.cfiles := $(speedtest1.c) $(sqlite3-wasm.c)
|
||||
speedtest1.js = $(dir.dout)/speedtest1.js
|
||||
emcc.flags.speedtest1-vanilla = $(cflags.common) -DSQLITE_SPEEDTEST1_WASM
|
||||
speedtest1.cfiles = $(speedtest1.c) $(sqlite3-wasm.c)
|
||||
$(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
|
||||
$(pre-post-speedtest1-vanilla.deps) \
|
||||
$(EXPORTED_FUNCTIONS.speedtest1)
|
||||
@@ -1067,14 +1070,13 @@ $(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
|
||||
-USQLITE_C -DSQLITE_C=$(sqlite3.canonical.c) \
|
||||
$(speedtest1.exit-runtime0) \
|
||||
-o $@ $(speedtest1.cfiles) -lm
|
||||
$(maybe-wasm-strip) $(speedtest1.wasm)
|
||||
sed -i -e '/^var _sqlite3.*createExportWrapper/d' $@
|
||||
chmod -x $(speedtest1.wasm)
|
||||
ls -la $@ $(speedtest1.wasm)
|
||||
@chmod -x $(basename $@).wasm
|
||||
@$(maybe-wasm-strip) $(basename $@).wasm
|
||||
@$(SQLITE.strip-createExportWrapper)
|
||||
@ls -la $@ $(speedtest1.wasm)
|
||||
|
||||
speedtest1: $(speedtest1.js)
|
||||
all: speedtest1
|
||||
#CLEAN_FILES += $(speedtest1.js) $(speedtest1.wasm)
|
||||
# end speedtest1.js
|
||||
########################################################################
|
||||
|
||||
@@ -1099,7 +1101,7 @@ $(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.sqlit
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.html,tester1.html))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.sqlite3-esm)))
|
||||
tester1: tester1.js tester1.mjs tester1.html tester1-esm.html
|
||||
# Note that we do not include $(sqlite3-bundler-friendly.mjs) in this
|
||||
# Note that we do not include $(dir.dout)/sqlite3-bundler-friendly.mjs in this
|
||||
# because bundlers are client-specific.
|
||||
all quick: tester1
|
||||
quick: $(sqlite3.js)
|
||||
@@ -1111,7 +1113,7 @@ quick: $(sqlite3.js)
|
||||
# painful.
|
||||
|
||||
.PHONY: o0 o1 o2 o3 os oz
|
||||
emcc-opt-extra :=
|
||||
emcc-opt-extra =
|
||||
#ifeq (1,$(wasm-bare-bones))
|
||||
#emcc-opt-extra += -flto
|
||||
# ^^^^ -flto can have a considerably performance boost at -O0 but
|
||||
@@ -1139,7 +1141,7 @@ oz: clean
|
||||
# Sub-makes...
|
||||
|
||||
# sqlite.org/fiddle application...
|
||||
include fiddle.make
|
||||
include $(MAKEFILE.fiddle)
|
||||
|
||||
# Only add wasmfs if wasmfs.enable=1 or we're running (dist)clean
|
||||
ifneq (,$(filter wasmfs,$(MAKECMDGOALS)))
|
||||
@@ -1157,16 +1159,17 @@ ifeq (1,$(wasmfs.enable))
|
||||
# little benefit.
|
||||
#
|
||||
########################################################################
|
||||
# Some platforms do not support the WASMFS build. Raspberry Pi OS is one
|
||||
# of them. As such platforms are discovered, add their (uname -m) name
|
||||
# to PLATFORMS_WITH_NO_WASMFS to exclude the wasmfs build parts.
|
||||
PLATFORMS_WITH_NO_WASMFS := aarch64 # add any others here
|
||||
THIS_ARCH := $(shell /usr/bin/uname -m)
|
||||
# Some platforms do not support the WASMFS build. Raspberry Pi OS is
|
||||
# one of them (or was when that comment was initially written). As
|
||||
# such platforms are discovered, add their (uname -m) name to
|
||||
# PLATFORMS_WITH_NO_WASMFS to exclude the wasmfs build parts.
|
||||
PLATFORMS_WITH_NO_WASMFS = aarch64 # add any others here
|
||||
THIS_ARCH = $(shell /usr/bin/uname -m)
|
||||
ifneq (,$(filter $(THIS_ARCH),$(PLATFORMS_WITH_NO_WASMFS)))
|
||||
$(info This platform does not support the WASMFS build.)
|
||||
HAVE_WASMFS := 0
|
||||
HAVE_WASMFS = 0
|
||||
else
|
||||
HAVE_WASMFS := 1
|
||||
HAVE_WASMFS = 1
|
||||
include wasmfs.make
|
||||
endif
|
||||
endif
|
||||
@@ -1204,7 +1207,7 @@ update-docs:
|
||||
echo "Pass wasm.docs.home=/path/to/wasm/docs/checkout or edit this makefile to suit."; \
|
||||
exit 127
|
||||
else
|
||||
wasm.docs.jswasm := $(wasm.docs.home)/jswasm
|
||||
wasm.docs.jswasm = $(wasm.docs.home)/jswasm
|
||||
update-docs: $(bin.stripccomments) $(sqlite3.js) $(sqlite3.wasm)
|
||||
@echo "Copying files to the /wasm docs. Be sure to use an -Oz build for this!"
|
||||
cp $(sqlite3.wasm) $(wasm.docs.jswasm)/.
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
This file contains the so-called OO #1 API wrapper for the sqlite3
|
||||
WASM build. It requires that sqlite3-api-glue.js has already run
|
||||
and it installs its deliverable as globalThis.sqlite3.oo1.
|
||||
and it installs its deliverable as sqlite3.oo1.
|
||||
*/
|
||||
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
const toss3 = (...args)=>{throw new sqlite3.SQLite3Error(...args)};
|
||||
@@ -37,6 +37,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
it.
|
||||
*/
|
||||
const __ptrMap = new WeakMap();
|
||||
/**
|
||||
A Set of oo1.DB or oo1.Stmt objects which are proxies for
|
||||
(sqlite3*) resp. (sqlite3_stmt*) pointers which themselves are
|
||||
owned elsewhere. Objects in this Set do not own their underlying
|
||||
handle and that handle must be guaranteed (by the client) to
|
||||
outlive the proxy. DB.close()/Stmt.finalize() methods will remove
|
||||
the object from this Set _instead_ of closing/finalizing the
|
||||
pointer. These proxies are primarily intended as a way to briefly
|
||||
wrap an (sqlite3[_stmt]*) object as an oo1.DB/Stmt without taking
|
||||
over ownership, to take advantage of simplifies usage compared to
|
||||
the C API while not imposing any change of ownership.
|
||||
|
||||
See DB.wrapHandle() and Stmt.wrapHandle().
|
||||
*/
|
||||
const __doesNotOwnHandle = new Set();
|
||||
/**
|
||||
Map of DB instances to objects, each object being a map of Stmt
|
||||
wasm pointers to Stmt objects.
|
||||
@@ -234,73 +249,89 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
};
|
||||
}
|
||||
const opt = ctor.normalizeArgs(...args);
|
||||
let fn = opt.filename, vfsName = opt.vfs, flagsStr = opt.flags;
|
||||
if(('string'!==typeof fn && 'number'!==typeof fn)
|
||||
|| 'string'!==typeof flagsStr
|
||||
|| (vfsName && ('string'!==typeof vfsName && 'number'!==typeof vfsName))){
|
||||
sqlite3.config.error("Invalid DB ctor args",opt,arguments);
|
||||
toss3("Invalid arguments for DB constructor.");
|
||||
}
|
||||
let fnJs = ('number'===typeof fn) ? wasm.cstrToJs(fn) : fn;
|
||||
const vfsCheck = ctor._name2vfs[fnJs];
|
||||
if(vfsCheck){
|
||||
vfsName = vfsCheck.vfs;
|
||||
fn = fnJs = vfsCheck.filename(fnJs);
|
||||
}
|
||||
let pDb, oflags = 0;
|
||||
if( flagsStr.indexOf('c')>=0 ){
|
||||
oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
|
||||
}
|
||||
if( flagsStr.indexOf('w')>=0 ) oflags |= capi.SQLITE_OPEN_READWRITE;
|
||||
if( 0===oflags ) oflags |= capi.SQLITE_OPEN_READONLY;
|
||||
oflags |= capi.SQLITE_OPEN_EXRESCODE;
|
||||
const stack = wasm.pstack.pointer;
|
||||
try {
|
||||
const pPtr = wasm.pstack.allocPtr() /* output (sqlite3**) arg */;
|
||||
let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || 0);
|
||||
pDb = wasm.peekPtr(pPtr);
|
||||
checkSqlite3Rc(pDb, rc);
|
||||
capi.sqlite3_extended_result_codes(pDb, 1);
|
||||
if(flagsStr.indexOf('t')>=0){
|
||||
capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT,
|
||||
__dbTraceToConsole, pDb);
|
||||
//sqlite3.config.debug("DB ctor",opt);
|
||||
let pDb;
|
||||
if( (pDb = opt['sqlite3*']) ){
|
||||
/* This property ^^^^^ is very specifically NOT DOCUMENTED and
|
||||
NOT part of the public API. This is a back door for functions
|
||||
like DB.wrapDbHandle(). */
|
||||
//sqlite3.config.debug("creating proxy db from",opt);
|
||||
if( !opt['sqlite3*:takeOwnership'] ){
|
||||
/* This is object does not own its handle. */
|
||||
__doesNotOwnHandle.add(this);
|
||||
}
|
||||
}catch( e ){
|
||||
if( pDb ) capi.sqlite3_close_v2(pDb);
|
||||
throw e;
|
||||
}finally{
|
||||
wasm.pstack.restore(stack);
|
||||
this.filename = capi.sqlite3_db_filename(pDb,'main');
|
||||
}else{
|
||||
let fn = opt.filename, vfsName = opt.vfs, flagsStr = opt.flags;
|
||||
if(('string'!==typeof fn && 'number'!==typeof fn)
|
||||
|| 'string'!==typeof flagsStr
|
||||
|| (vfsName && ('string'!==typeof vfsName && 'number'!==typeof vfsName))){
|
||||
sqlite3.config.error("Invalid DB ctor args",opt,arguments);
|
||||
toss3("Invalid arguments for DB constructor.");
|
||||
}
|
||||
let fnJs = ('number'===typeof fn) ? wasm.cstrToJs(fn) : fn;
|
||||
const vfsCheck = ctor._name2vfs[fnJs];
|
||||
if(vfsCheck){
|
||||
vfsName = vfsCheck.vfs;
|
||||
fn = fnJs = vfsCheck.filename(fnJs);
|
||||
}
|
||||
let oflags = 0;
|
||||
if( flagsStr.indexOf('c')>=0 ){
|
||||
oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
|
||||
}
|
||||
if( flagsStr.indexOf('w')>=0 ) oflags |= capi.SQLITE_OPEN_READWRITE;
|
||||
if( 0===oflags ) oflags |= capi.SQLITE_OPEN_READONLY;
|
||||
oflags |= capi.SQLITE_OPEN_EXRESCODE;
|
||||
const stack = wasm.pstack.pointer;
|
||||
try {
|
||||
const pPtr = wasm.pstack.allocPtr() /* output (sqlite3**) arg */;
|
||||
let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || 0);
|
||||
pDb = wasm.peekPtr(pPtr);
|
||||
checkSqlite3Rc(pDb, rc);
|
||||
capi.sqlite3_extended_result_codes(pDb, 1);
|
||||
if(flagsStr.indexOf('t')>=0){
|
||||
capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT,
|
||||
__dbTraceToConsole, pDb);
|
||||
}
|
||||
}catch( e ){
|
||||
if( pDb ) capi.sqlite3_close_v2(pDb);
|
||||
throw e;
|
||||
}finally{
|
||||
wasm.pstack.restore(stack);
|
||||
}
|
||||
this.filename = fnJs;
|
||||
}
|
||||
this.filename = fnJs;
|
||||
__ptrMap.set(this, pDb);
|
||||
__stmtMap.set(this, Object.create(null));
|
||||
try{
|
||||
if( !opt['sqlite3*'] ){
|
||||
try{
|
||||
//#if enable-see
|
||||
dbCtorApplySEEKey(this,opt);
|
||||
dbCtorApplySEEKey(this,opt);
|
||||
//#endif
|
||||
// Check for per-VFS post-open SQL/callback...
|
||||
const pVfs = capi.sqlite3_js_db_vfs(pDb)
|
||||
|| toss3("Internal error: cannot get VFS for new db handle.");
|
||||
const postInitSql = __vfsPostOpenCallback[pVfs];
|
||||
if(postInitSql){
|
||||
/**
|
||||
Reminder: if this db is encrypted and the client did _not_ pass
|
||||
in the key, any init code will fail, causing the ctor to throw.
|
||||
We don't actually know whether the db is encrypted, so we cannot
|
||||
sensibly apply any heuristics which skip the init code only for
|
||||
encrypted databases for which no key has yet been supplied.
|
||||
*/
|
||||
if(postInitSql instanceof Function){
|
||||
postInitSql(this, sqlite3);
|
||||
}else{
|
||||
checkSqlite3Rc(
|
||||
pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
|
||||
);
|
||||
// Check for per-VFS post-open SQL/callback...
|
||||
const pVfs = capi.sqlite3_js_db_vfs(pDb)
|
||||
|| toss3("Internal error: cannot get VFS for new db handle.");
|
||||
const postInitSql = __vfsPostOpenCallback[pVfs];
|
||||
if(postInitSql){
|
||||
/**
|
||||
Reminder: if this db is encrypted and the client did _not_ pass
|
||||
in the key, any init code will fail, causing the ctor to throw.
|
||||
We don't actually know whether the db is encrypted, so we cannot
|
||||
sensibly apply any heuristics which skip the init code only for
|
||||
encrypted databases for which no key has yet been supplied.
|
||||
*/
|
||||
if(postInitSql instanceof Function){
|
||||
postInitSql(this, sqlite3);
|
||||
}else{
|
||||
checkSqlite3Rc(
|
||||
pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
this.close();
|
||||
throw e;
|
||||
}
|
||||
}catch(e){
|
||||
this.close();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -403,7 +434,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
- `vfs`: the VFS fname
|
||||
|
||||
//#if enable-see
|
||||
|
||||
SEE-capable builds optionally support ONE of the following
|
||||
additional options:
|
||||
|
||||
@@ -429,7 +459,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
is supplied and the database is encrypted, execution of the
|
||||
post-initialization SQL will fail, causing the constructor to
|
||||
throw.
|
||||
|
||||
//#endif enable-see
|
||||
|
||||
The `filename` and `vfs` arguments may be either JS strings or
|
||||
@@ -457,8 +486,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
/**
|
||||
Internal-use enum for mapping JS types to DB-bindable types.
|
||||
These do not (and need not) line up with the SQLITE_type
|
||||
values. All values in this enum must be truthy and distinct
|
||||
but they need not be numbers.
|
||||
values. All values in this enum must be truthy and (mostly)
|
||||
distinct but they need not be numbers.
|
||||
*/
|
||||
const BindTypes = {
|
||||
null: 1,
|
||||
@@ -467,7 +496,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
boolean: 4,
|
||||
blob: 5
|
||||
};
|
||||
BindTypes['undefined'] == BindTypes.null;
|
||||
if(wasm.bigIntEnabled){
|
||||
BindTypes.bigint = BindTypes.number;
|
||||
}
|
||||
@@ -486,26 +514,30 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
- `db`: the DB object which created the statement.
|
||||
|
||||
- `columnCount`: the number of result columns in the query, or 0
|
||||
for queries which cannot return results. This property is a proxy
|
||||
for sqlite3_column_count() and its use in loops should be avoided
|
||||
because of the call overhead associated with that. The
|
||||
`columnCount` is not cached when the Stmt is created because a
|
||||
schema change made via a separate db connection between this
|
||||
statement's preparation and when it is stepped may invalidate it.
|
||||
for queries which cannot return results. This property is a
|
||||
read-only proxy for sqlite3_column_count() and its use in loops
|
||||
should be avoided because of the call overhead associated with
|
||||
that. The `columnCount` is not cached when the Stmt is created
|
||||
because a schema change made between this statement's preparation
|
||||
and when it is stepped may invalidate it.
|
||||
|
||||
- `parameterCount`: the number of bindable parameters in the query.
|
||||
- `parameterCount`: the number of bindable parameters in the
|
||||
query. Like `columnCount`, this property is ready-only and is a
|
||||
proxy for a C API call.
|
||||
|
||||
As a general rule, most methods of this class will throw if
|
||||
called on an instance which has been finalized. For brevity's
|
||||
sake, the method docs do not all repeat this warning.
|
||||
*/
|
||||
const Stmt = function(){
|
||||
const Stmt = function(/*oo1db, stmtPtr, BindTypes [,takeOwnership=true] */){
|
||||
if(BindTypes!==arguments[2]){
|
||||
toss3(capi.SQLITE_MISUSE, "Do not call the Stmt constructor directly. Use DB.prepare().");
|
||||
}
|
||||
this.db = arguments[0];
|
||||
__ptrMap.set(this, arguments[1]);
|
||||
this.parameterCount = capi.sqlite3_bind_parameter_count(this.pointer);
|
||||
if( arguments.length>3 && !arguments[3] ){
|
||||
__doesNotOwnHandle.add(this);
|
||||
}
|
||||
};
|
||||
|
||||
/** Throws if the given DB has been closed, else it is returned. */
|
||||
@@ -698,10 +730,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
},
|
||||
/**
|
||||
Finalizes all open statements and closes this database
|
||||
connection. This is a no-op if the db has already been
|
||||
closed. After calling close(), `this.pointer` will resolve to
|
||||
`undefined`, so that can be used to check whether the db
|
||||
instance is still opened.
|
||||
connection (with one exception noted below). This is a no-op if
|
||||
the db has already been closed. After calling close(),
|
||||
`this.pointer` will resolve to `undefined`, and that can be
|
||||
used to check whether the db instance is still opened.
|
||||
|
||||
If this.onclose.before is a function then it is called before
|
||||
any close-related cleanup.
|
||||
@@ -721,14 +753,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
all, will never trigger close(), so onclose handlers are not a
|
||||
reliable way to implement close-time cleanup or maintenance of
|
||||
a db.
|
||||
|
||||
If this instance was created using DB.wrapHandle() and does not
|
||||
own this.pointer then it does not close the db handle but it
|
||||
does perform all other work, such as calling onclose callbacks
|
||||
and disassociating this object from this.pointer.
|
||||
*/
|
||||
close: function(){
|
||||
if(this.pointer){
|
||||
const pDb = this.pointer;
|
||||
if(pDb){
|
||||
if(this.onclose && (this.onclose.before instanceof Function)){
|
||||
try{this.onclose.before(this)}
|
||||
catch(e){/*ignore*/}
|
||||
}
|
||||
const pDb = this.pointer;
|
||||
Object.keys(__stmtMap.get(this)).forEach((k,s)=>{
|
||||
if(s && s.pointer){
|
||||
try{s.finalize()}
|
||||
@@ -737,7 +774,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
});
|
||||
__ptrMap.delete(this);
|
||||
__stmtMap.delete(this);
|
||||
capi.sqlite3_close_v2(pDb);
|
||||
if( !__doesNotOwnHandle.delete(this) ){
|
||||
capi.sqlite3_close_v2(pDb);
|
||||
}
|
||||
if(this.onclose && (this.onclose.after instanceof Function)){
|
||||
try{this.onclose.after(this)}
|
||||
catch(e){/*ignore*/}
|
||||
@@ -1450,9 +1489,63 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
*/
|
||||
checkRc: function(resultCode){
|
||||
return checkSqlite3Rc(this, resultCode);
|
||||
}
|
||||
},
|
||||
}/*DB.prototype*/;
|
||||
|
||||
/**
|
||||
Returns a new oo1.DB instance which wraps the given (sqlite3*)
|
||||
WASM pointer, optionally with or without taking over ownership of
|
||||
that pointer.
|
||||
|
||||
The first argument must be either a non-NULL (sqlite3*) WASM
|
||||
pointer.
|
||||
|
||||
The second argument, defaulting to false, specifies ownership of
|
||||
the first argument. If it is truthy, the returned object will
|
||||
pass that pointer to sqlite3_close() when its close() method is
|
||||
called, otherwise it will not.
|
||||
|
||||
Throws if pDb is not a non-0 WASM pointer.
|
||||
|
||||
The caller MUST GUARANTEE that the passed-in handle will outlive
|
||||
the returned object, i.e. that it will not be closed. If it is closed,
|
||||
this object will hold a stale pointer and results are undefined.
|
||||
|
||||
Aside from its lifetime, the proxy is to be treated as any other
|
||||
DB instance, including the requirement of calling close() on
|
||||
it. close() will free up internal resources owned by the proxy
|
||||
and disassociate the proxy from that handle but will not
|
||||
actually close the proxied db handle unless this function is
|
||||
passed a thruthy second argument.
|
||||
|
||||
To stress:
|
||||
|
||||
- DO NOT call sqlite3_close() (or similar) on the being-proxied
|
||||
pointer while a proxy is active.
|
||||
|
||||
- ALWAYS eventually call close() on the returned object. If the
|
||||
proxy does not own the underlying handle then its MUST be
|
||||
closed BEFORE the being-proxied handle is closed.
|
||||
|
||||
Design notes:
|
||||
|
||||
- wrapHandle() "could" accept a DB object instance as its first
|
||||
argument and proxy thatDb.pointer but there is currently no use
|
||||
case where doing so would be useful, so it does not allow
|
||||
that. That restriction may be lifted in a future version.
|
||||
*/
|
||||
DB.wrapHandle = function(pDb, takeOwnership=false){
|
||||
if( !pDb || !wasm.isPtr(pDb) ){
|
||||
throw new sqlite3.SQLite3Error(capi.SQLITE_MISUSE,
|
||||
"Argument must be a WASM sqlite3 pointer");
|
||||
}
|
||||
return new DB({
|
||||
/* This ctor call style is very specifically internal-use-only.
|
||||
It is not documented and may change at any time. */
|
||||
"sqlite3*": pDb,
|
||||
"sqlite3*:takeOwnership": !!takeOwnership
|
||||
});
|
||||
};
|
||||
|
||||
/** Throws if the given Stmt has been finalized, else stmt is
|
||||
returned. */
|
||||
@@ -1474,8 +1567,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
case BindTypes.string:
|
||||
return t;
|
||||
case BindTypes.bigint:
|
||||
if(wasm.bigIntEnabled) return t;
|
||||
/* else fall through */
|
||||
return wasm.bigIntEnabled ? t : undefined;
|
||||
default:
|
||||
return util.isBindableTypedArray(v) ? BindTypes.blob : undefined;
|
||||
}
|
||||
@@ -1641,12 +1733,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
This method always throws if called when it is illegal to do
|
||||
so. Namely, when triggered via a per-row callback handler of a
|
||||
DB.exec() call.
|
||||
|
||||
If Stmt does not own its underlying (sqlite3_stmt*) (see
|
||||
Stmt.wrapHandle()) then this function will not pass it to
|
||||
sqlite3_finalize().
|
||||
*/
|
||||
finalize: function(){
|
||||
if(this.pointer){
|
||||
const ptr = this.pointer;
|
||||
if(ptr){
|
||||
affirmNotLockedByExec(this,'finalize()');
|
||||
const rc = capi.sqlite3_finalize(this.pointer);
|
||||
delete __stmtMap.get(this.db)[this.pointer];
|
||||
const rc = (__doesNotOwnHandle.delete(this)
|
||||
? 0
|
||||
: capi.sqlite3_finalize(ptr));
|
||||
delete __stmtMap.get(this.db)[ptr];
|
||||
__ptrMap.delete(this);
|
||||
__execLock.delete(this);
|
||||
__stmtMayGet.delete(this);
|
||||
@@ -2134,6 +2233,64 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
set: ()=>toss3("The columnCount property is read-only.")
|
||||
});
|
||||
|
||||
Object.defineProperty(Stmt.prototype, 'parameterCount', {
|
||||
enumerable: false,
|
||||
get: function(){return capi.sqlite3_bind_parameter_count(this.pointer)},
|
||||
set: ()=>toss3("The parameterCount property is read-only.")
|
||||
});
|
||||
|
||||
/**
|
||||
The Stmt counterpart of oo1.DB.wrapHandle(), this creates a Stmt
|
||||
instance which wraps a WASM (sqlite3_stmt*) in the oo1 API,
|
||||
optionally with or without taking over ownership of that pointer.
|
||||
|
||||
The first argument must be an oo1.DB instance[^1].
|
||||
|
||||
The second argument must be a valid WASM (sqlite3_stmt*), as
|
||||
produced by sqlite3_prepare_v2() and sqlite3_prepare_v3().
|
||||
|
||||
The third argument, defaulting to false, specifies whether the
|
||||
returned Stmt object takes over ownership of the underlying
|
||||
(sqlite3_stmt*). If true, the returned object's finalize() method
|
||||
will finalize that handle, else it will not. If it is false,
|
||||
ownership of pStmt is unchanged and pStmt MUST outlive the
|
||||
returned object or results are undefined.
|
||||
|
||||
This function throws if the arguments are invalid. On success it
|
||||
returns a new Stmt object which wraps the given statement
|
||||
pointer.
|
||||
|
||||
Like all Stmt objects, the finalize() method must eventually be
|
||||
called on the returned object to free up internal resources,
|
||||
regardless of whether this function's third argument is true or
|
||||
not.
|
||||
|
||||
[^1]: The first argument cannot be a (sqlite3*) because the
|
||||
resulting Stmt object requires a parent DB object. It is not yet
|
||||
determined whether it would be of general benefit to refactor the
|
||||
DB/Stmt pair internals to communicate in terms of the underlying
|
||||
(sqlite3*) rather than a DB object. If so, we could laxen the
|
||||
first argument's requirement and allow an (sqlite3*). Because
|
||||
DB.wrapHandle() enables multiple DB objects to proxy the same
|
||||
(sqlite3*), we cannot unambiguously translate the first arugment
|
||||
from (sqlite3*) to DB instances for us with this function's first
|
||||
argument.
|
||||
*/
|
||||
Stmt.wrapHandle = function(oo1db, pStmt, takeOwnership=false){
|
||||
let ctor = Stmt;
|
||||
if( !(oo1db instanceof DB) || !oo1db.pointer ){
|
||||
throw new sqlite3.SQLite3Error(sqlite3.SQLITE_MISUSE,
|
||||
"First argument must be an opened "+
|
||||
"sqlite3.oo1.DB instance");
|
||||
}
|
||||
if( !pStmt || !wasm.isPtr(pStmt) ){
|
||||
throw new sqlite3.SQLite3Error(sqlite3.SQLITE_MISUSE,
|
||||
"Second argument must be a WASM "+
|
||||
"sqlite3_stmt pointer");
|
||||
}
|
||||
return new Stmt(oo1db, pStmt, BindTypes, !!takeOwnership);
|
||||
}
|
||||
|
||||
/** The OO API's public namespace. */
|
||||
sqlite3.oo1 = {
|
||||
DB,
|
||||
|
@@ -134,22 +134,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
const config = Object.assign(Object.create(null),{
|
||||
exports: undefined,
|
||||
memory: undefined,
|
||||
bigIntEnabled: (()=>{
|
||||
if('undefined'!==typeof Module){
|
||||
/* Emscripten module will contain HEAPU64 when built with
|
||||
-sWASM_BIGINT=1, else it will not.
|
||||
|
||||
As of emsdk 3.1.55, when building in strict mode, HEAPxyz
|
||||
are only available if _explicitly_ included in the exports,
|
||||
else they are not. We do not (as of 2024-03-04) use -sSTRICT
|
||||
for the canonical builds.
|
||||
*/
|
||||
if( !!Module.HEAPU64 ) return true;
|
||||
/* Else fall through and hope for the best. Nobody _really_
|
||||
builds this without BigInt support, do they? */
|
||||
}
|
||||
return !!globalThis.BigInt64Array;
|
||||
})(),
|
||||
bigIntEnabled: !!globalThis.BigInt64Array,
|
||||
debug: console.debug.bind(console),
|
||||
warn: console.warn.bind(console),
|
||||
error: console.error.bind(console),
|
||||
|
@@ -1,15 +1,16 @@
|
||||
# Gets filtered by the configure script
|
||||
# config.make.in gets filtered by the top-most configure script to
|
||||
# create config.make.
|
||||
bin.bash = @BIN_BASH@
|
||||
bin.emcc = @EMCC_WRAPPER@
|
||||
bin.wasm-strip = @BIN_WASM_STRIP@
|
||||
bin.wasm-opt = @BIN_WASM_OPT@
|
||||
|
||||
SHELL := $(bin.bash)
|
||||
SHELL = $(bin.bash)
|
||||
|
||||
# The following overrides can be uncommented to test various
|
||||
# validation and if/else branches the makefile code:
|
||||
#
|
||||
#bin.bash :=
|
||||
#bin.emcc :=
|
||||
#bin.wasm-strip :=
|
||||
#bin.wasm-opt :=
|
||||
#bin.bash =
|
||||
#bin.emcc =
|
||||
#bin.wasm-strip =
|
||||
#bin.wasm-opt =
|
||||
|
@@ -11,7 +11,7 @@
|
||||
# distinctly different zip file and top directory name to distinguish
|
||||
# them from release builds.
|
||||
#######################################################################
|
||||
MAKEFILE.dist := $(lastword $(MAKEFILE_LIST))
|
||||
MAKEFILE.dist = $(lastword $(MAKEFILE_LIST))
|
||||
|
||||
########################################################################
|
||||
# Chicken/egg situation: we need $(bin.version-info) to get the
|
||||
@@ -20,16 +20,16 @@ MAKEFILE.dist := $(lastword $(MAKEFILE_LIST))
|
||||
# have to use a temporary name for the archive until we can get
|
||||
# that binary built.
|
||||
ifeq (1,$(SQLITE_C_IS_SEE))
|
||||
dist-name-extra := -see
|
||||
dist-name-extra = -see
|
||||
else
|
||||
dist-name-extra :=
|
||||
dist-name-extra =
|
||||
endif
|
||||
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
|
||||
dist-name-prefix := sqlite-wasm$(dist-name-extra)
|
||||
dist-name-prefix = sqlite-wasm$(dist-name-extra)
|
||||
else
|
||||
dist-name-prefix := sqlite-wasm$(dist-name-extra)-snapshot-$(shell /usr/bin/date +%Y%m%d)
|
||||
dist-name-prefix = sqlite-wasm$(dist-name-extra)-snapshot-$(shell /usr/bin/date +%Y%m%d)
|
||||
endif
|
||||
dist-name := $(dist-name-prefix)-TEMP
|
||||
dist-name = $(dist-name-prefix)-TEMP
|
||||
|
||||
########################################################################
|
||||
# dist.build must be the name of a target which triggers the build of
|
||||
@@ -45,10 +45,10 @@ dist-name := $(dist-name-prefix)-TEMP
|
||||
# reason not to.
|
||||
dist.build ?= oz
|
||||
|
||||
dist-dir.top := $(dist-name)
|
||||
dist-dir.jswasm := $(dist-dir.top)/$(notdir $(dir.dout))
|
||||
dist-dir.common := $(dist-dir.top)/common
|
||||
dist.top.extras := \
|
||||
dist-dir.top = $(dist-name)
|
||||
dist-dir.jswasm = $(dist-dir.top)/$(notdir $(dir.dout))
|
||||
dist-dir.common = $(dist-dir.top)/common
|
||||
dist.top.extras = \
|
||||
demo-123.html demo-123-worker.html demo-123.js \
|
||||
tester1.html tester1-worker.html tester1-esm.html \
|
||||
tester1.js tester1.mjs \
|
||||
@@ -56,9 +56,9 @@ dist.top.extras := \
|
||||
demo-worker1.html demo-worker1.js \
|
||||
demo-worker1-promiser.html demo-worker1-promiser.js \
|
||||
demo-worker1-promiser-esm.html demo-worker1-promiser.mjs
|
||||
dist.jswasm.extras := $(sqlite3.wasm) \
|
||||
dist.jswasm.extras = $(sqlite3.wasm) \
|
||||
$(sqlite3-api.ext.jses)
|
||||
dist.common.extras := \
|
||||
dist.common.extras = \
|
||||
$(wildcard $(dir.common)/*.css) \
|
||||
$(dir.common)/SqliteTestUtil.js
|
||||
|
||||
@@ -77,12 +77,12 @@ $(bin.stripccomments) $(2) < $(1) > $(dist-dir.jswasm)/$(notdir $(1)) || exit;
|
||||
endef
|
||||
# STRIP_K1.js = list of JS files which need to be passed through
|
||||
# $(bin.stripcomments) with a single -k flag.
|
||||
STRIP_K1.js := $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js) \
|
||||
STRIP_K1.js = $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js) \
|
||||
$(sqlite3-worker1-bundler-friendly.js) \
|
||||
$(sqlite3-api.ext.jses)
|
||||
# STRIP_K2.js = list of JS files which need to be passed through
|
||||
# $(bin.stripcomments) with two -k flags.
|
||||
STRIP_K2.js := $(sqlite3.js) $(sqlite3.mjs) \
|
||||
STRIP_K2.js = $(sqlite3.js) $(sqlite3.mjs) \
|
||||
$(sqlite3-bundler-friendly.mjs) $(sqlite3-node.mjs)
|
||||
########################################################################
|
||||
# dist: create the end-user deliverable archive.
|
||||
@@ -104,8 +104,8 @@ STRIP_K2.js := $(sqlite3.js) $(sqlite3.mjs) \
|
||||
# to know that it's in a regex or string literal. Because of that,
|
||||
# comment-stripping is currently disabled, which means the builds will
|
||||
# be significantly larger than before.
|
||||
#apply_comment_stripper := false
|
||||
apply_comment_stripper := true
|
||||
#apply_comment_stripper = false
|
||||
apply_comment_stripper = true
|
||||
# ^^^ shell command true or false
|
||||
dist: \
|
||||
$(bin.stripccomments) $(bin.version-info) \
|
||||
|
@@ -3,13 +3,12 @@
|
||||
#
|
||||
# Intended to include'd by ./GNUmakefile.
|
||||
#######################################################################
|
||||
MAKEFILE.fiddle := $(lastword $(MAKEFILE_LIST))
|
||||
|
||||
########################################################################
|
||||
# shell.c and its build flags...
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
make-np-0 := make -C $(dir.top) -n -p
|
||||
make-np-1 := sed -e 's/(TOP)/(dir.top)/g'
|
||||
make-np-0 = make -C $(dir.top) -n -p
|
||||
make-np-1 = sed -e 's/(TOP)/(dir.top)/g'
|
||||
# Extract SHELL_OPT and SHELL_DEP from the top-most makefile and import
|
||||
# them as vars here...
|
||||
$(eval $(shell $(make-np-0) | grep -e '^SHELL_OPT ' | $(make-np-1)))
|
||||
@@ -27,7 +26,7 @@ endif
|
||||
# /shell.c
|
||||
########################################################################
|
||||
|
||||
EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
|
||||
EXPORTED_FUNCTIONS.fiddle = $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
|
||||
fiddle.emcc-flags = \
|
||||
$(emcc.cflags) $(emcc_opt_full) \
|
||||
--minify 0 \
|
||||
@@ -40,9 +39,8 @@ fiddle.emcc-flags = \
|
||||
-sWASM_BIGINT=$(emcc.WASM_BIGINT) \
|
||||
-sEXPORT_NAME=$(sqlite3.js.init-func) \
|
||||
-Wno-limited-postlink-optimizations \
|
||||
$(emcc.exportedRuntimeMethods) \
|
||||
$(emcc.exportedRuntimeMethods),FS \
|
||||
-sEXPORTED_FUNCTIONS=@$(abspath $(EXPORTED_FUNCTIONS.fiddle)) \
|
||||
-sEXPORTED_RUNTIME_METHODS=FS,wasmMemory \
|
||||
$(SQLITE_OPT.full-featured) \
|
||||
$(SQLITE_OPT.common) \
|
||||
$(SHELL_OPT) \
|
||||
@@ -53,12 +51,12 @@ fiddle.emcc-flags = \
|
||||
|
||||
# Flags specifically for debug builds of fiddle. Performance suffers
|
||||
# greatly in debug builds.
|
||||
fiddle.emcc-flags.debug := $(fiddle.emcc-flags) \
|
||||
fiddle.emcc-flags.debug = $(fiddle.emcc-flags) \
|
||||
-DSQLITE_DEBUG \
|
||||
-DSQLITE_ENABLE_SELECTTRACE \
|
||||
-DSQLITE_ENABLE_WHERETRACE
|
||||
|
||||
fiddle.EXPORTED_FUNCTIONS.in := \
|
||||
fiddle.EXPORTED_FUNCTIONS.in = \
|
||||
EXPORTED_FUNCTIONS.fiddle.in \
|
||||
$(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core \
|
||||
$(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
|
||||
@@ -67,10 +65,7 @@ $(EXPORTED_FUNCTIONS.fiddle): $(MKDIR.bld) $(fiddle.EXPORTED_FUNCTIONS.in) \
|
||||
$(MAKEFILE.fiddle)
|
||||
sort -u $(fiddle.EXPORTED_FUNCTIONS.in) > $@
|
||||
|
||||
fiddle.cses := $(dir.top)/shell.c $(sqlite3-wasm.c)
|
||||
|
||||
fiddle: $(fiddle-module.js) $(fiddle-module.js.debug)
|
||||
fiddle.debug: $(fiddle-module.js.debug)
|
||||
fiddle.cses = $(dir.top)/shell.c $(sqlite3-wasm.c)
|
||||
|
||||
clean: clean-fiddle
|
||||
clean-fiddle:
|
||||
@@ -84,10 +79,9 @@ clean-fiddle:
|
||||
all: fiddle
|
||||
|
||||
########################################################################
|
||||
# fiddle_remote is the remote destination for the fiddle app. It
|
||||
# must be a [user@]HOST:/path for rsync.
|
||||
# Note that the target "should probably" contain a symlink of
|
||||
# index.html -> fiddle.html.
|
||||
# fiddle_remote is the remote destination for the fiddle app. It must
|
||||
# be a [user@]HOST:/path for rsync. The target "should probably"
|
||||
# contain a symlink of index.html -> fiddle.html.
|
||||
fiddle_remote ?=
|
||||
ifeq (,$(fiddle_remote))
|
||||
ifneq (,$(wildcard /home/stephan))
|
||||
@@ -154,11 +148,6 @@ push-fiddle: fiddle
|
||||
# because certain execution environments disallow those constructs.
|
||||
# This flag is not strictly necessary, however.
|
||||
#
|
||||
# -sWASM_BIGINT is UNTESTED but "should" allow the int64-using C APIs
|
||||
# to work with JS/wasm, insofar as the JS environment supports the
|
||||
# BigInt type. That support requires an extremely recent browser:
|
||||
# Safari didn't get that support until late 2020.
|
||||
#
|
||||
# --no-entry: for compiling library code with no main(). If this is
|
||||
# not supplied and the code has a main(), it is called as part of the
|
||||
# module init process. Note that main() is #if'd out of shell.c
|
||||
@@ -180,14 +169,15 @@ push-fiddle: fiddle
|
||||
# minification makes little difference in terms of overall
|
||||
# distributable size.
|
||||
#
|
||||
# --minify 0: disables minification of the generated JS code,
|
||||
# regardless of optimization level. Minification of the JS has
|
||||
# minimal overall effect in the larger scheme of things and results
|
||||
# in JS files which can neither be edited nor viewed as text files in
|
||||
# Fossil (which flags them as binary because of their extreme line
|
||||
# lengths). Interestingly, whether or not the comments in the
|
||||
# generated JS file get stripped is unaffected by this setting and
|
||||
# depends entirely on the optimization level. Higher optimization
|
||||
# --minify 0: supposedly disables minification of the generated JS
|
||||
# code, regardless of optimization level, but that's not quite true:
|
||||
# search the main makefile for wasm-strip for details. Minification
|
||||
# of the JS has minimal overall effect in the larger scheme of things
|
||||
# and results in JS files which can neither be edited nor viewed as
|
||||
# text files in Fossil (which flags them as binary because of their
|
||||
# extreme line lengths). Interestingly, whether or not the comments
|
||||
# in the generated JS file get stripped is unaffected by this setting
|
||||
# and depends entirely on the optimization level. Higher optimization
|
||||
# levels reduce the size of the JS considerably even without
|
||||
# minification.
|
||||
#
|
||||
|
@@ -11,18 +11,17 @@
|
||||
*************************************************************************
|
||||
**
|
||||
** This app's single purpose is to emit parts of the Makefile code for
|
||||
** building sqlite3's WASM build. The main motivation is to generate
|
||||
** code which "can" be created via GNU Make's eval command but is
|
||||
** sqlite3's canonical WASM build. The main motivation is to generate
|
||||
** code which "could" be created via GNU Make's eval command but is
|
||||
** highly illegible when constructed that way. Attempts to write this
|
||||
** app in Bash and TCL have suffered from the problem that both
|
||||
** require escaping $ symbols, making the resulting script code as
|
||||
** illegible as the eval spaghetti we want to get away from. Writing
|
||||
** it in C is, somewhat surprisingly, _slightly_ less illegible than
|
||||
** writing it in bash, tcl, or native Make code.
|
||||
** app in Bash and TCL have suffered from the problem that those
|
||||
** languages require escaping $ symbols, making the resulting script
|
||||
** code as illegible as the eval spaghetti we want to get away
|
||||
** from. Maintaining it in C is, somewhat surprisingly, _slightly_
|
||||
** less illegible than writing it in bash, tcl, or native Make code.
|
||||
**
|
||||
** The emitted makefile code is not standalone - it depends on
|
||||
** variables and $(call)able functions from the main makefile.
|
||||
**
|
||||
*/
|
||||
|
||||
#undef NDEBUG
|
||||
@@ -33,38 +32,145 @@
|
||||
|
||||
#define pf printf
|
||||
#define ps puts
|
||||
/* Very common printf() args combo. */
|
||||
#define zNM zName, zMode
|
||||
|
||||
/*
|
||||
** Valid names for the zName arguments.
|
||||
** Valid build names. Each build is a combination of one of these and
|
||||
** one of JS_BUILD_MODES, but only certain combinations are legal.
|
||||
** This macro and JS_BUILD_MODES exist solely for documentation
|
||||
** purposes: they are not expanded into code anywhere.
|
||||
*/
|
||||
#define JS_BUILD_NAMES sqlite3 sqlite3-wasmfs
|
||||
/*
|
||||
** Valid names for the zMode arguments of the "sqlite3" build. For the
|
||||
** "sqlite3-wasmfs" build, only "esm" (ES6 Module) is legal.
|
||||
** Valid build modes. For the "sqlite3-wasmfs" build, only "esm" (ES6
|
||||
** Module) is legal.
|
||||
*/
|
||||
#define JS_BUILD_MODES vanilla esm bundler-friendly node
|
||||
/* Separator to help eyeballs find the different sections */
|
||||
|
||||
/* Separator to help eyeballs find the different output sections */
|
||||
static const char * zBanner =
|
||||
"\n########################################################################\n";
|
||||
|
||||
/*
|
||||
** Flags for use with BuildDef::flags and the 3rd argument to
|
||||
** mk_pre_post().
|
||||
**
|
||||
** Maintenance reminder: do not combine flags within this enum,
|
||||
** e.g. LIBMODE_BUNDLER_FRIENDLY=0x02|LIBMODE_ESM, as that will lead
|
||||
** to breakage in some of the flag checks.
|
||||
*/
|
||||
enum LibModeFlags {
|
||||
/* Indicates an ESM module build. */
|
||||
LIBMODE_ESM = 0x01,
|
||||
/* Indicates a "bundler-friendly" build mode. */
|
||||
LIBMODE_BUNDLER_FRIENDLY = 0x02,
|
||||
/* Indicates that this build is unsupported. Such builds are not
|
||||
** added to the 'all' target. The unsupported builds exist primarily
|
||||
** for experimentation's sake. */
|
||||
LIBMODE_UNSUPPORTED = 0x04,
|
||||
/* Indicates a node.js-for-node.js build (untested and
|
||||
** unsupported). */
|
||||
LIBMODE_NODEJS = 0x08,
|
||||
/* Indicates a wasmfs build (untested and unsupported). */
|
||||
LIBMODE_WASMFS = 0x10
|
||||
};
|
||||
|
||||
/*
|
||||
** Info needed for building one combination of JS_BUILD_NAMES and
|
||||
** JS_BUILD_MODE, noting that only a subset of those combinations are
|
||||
** legal/sensical.
|
||||
*/
|
||||
struct BuildDef {
|
||||
const char *zName; /* Name from JS_BUILD_NAMES */
|
||||
const char *zMode; /* Name from JS_BUILD_MODES */
|
||||
int flags; /* Flags from LibModeFlags */
|
||||
const char *zJsOut; /* Name of generated sqlite3.js/.mjs */
|
||||
/* TODO: dynamically determine zJsOut based on zName, zMode, and
|
||||
flags. */
|
||||
const char *zCmppD; /* Extra -D... flags for c-pp */
|
||||
const char *zEmcc; /* Extra flags for emcc */
|
||||
};
|
||||
typedef struct BuildDef BuildDef;
|
||||
|
||||
/*
|
||||
** The set of WASM builds for the library (as opposed to the apps
|
||||
** (fiddle, speedtest1)). This array must end with an empty sentinel
|
||||
** entry. Their order is mostly insignificant, but some makefile vars
|
||||
** used by some builds are set up by prior builds. Because of that,
|
||||
** the (sqlite3, vanilla), (sqlite3, esm), and (sqlite3,
|
||||
** bundler-friendly) builds should be defined first (in that order).
|
||||
*/
|
||||
const BuildDef aBuildDefs[] = {
|
||||
{/* Core build */
|
||||
"sqlite3", "vanilla", 0, "$(sqlite3.js)", 0, 0},
|
||||
|
||||
{/* Core ESM */
|
||||
"sqlite3", "esm", LIBMODE_ESM, "$(sqlite3.mjs)",
|
||||
"-Dtarget=es6-module", 0},
|
||||
|
||||
{/* Core bundler-friendly build. Untested and "not really"
|
||||
** supported, but required by the downstream npm subproject.
|
||||
** Testing these would require special-purpose node-based tools and
|
||||
** custom test apps. Or we can pass them off as-is to the npm
|
||||
** subproject and they spot failures pretty quickly ;). */
|
||||
"sqlite3", "bundler-friendly",
|
||||
LIBMODE_BUNDLER_FRIENDLY | LIBMODE_ESM,
|
||||
"$(dir.dout)/sqlite3-bundler-friendly.mjs",
|
||||
"$(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly", 0},
|
||||
|
||||
{/* node.js mode. Untested and unsupported. */
|
||||
"sqlite3", "node", LIBMODE_UNSUPPORTED | LIBMODE_NODEJS,
|
||||
"$(dir.dout)/sqlite3-node.mjs",
|
||||
"$(c-pp.D.sqlite3-bundler-friendly) -Dtarget=node", 0},
|
||||
|
||||
{/* Wasmfs build. Fully unsupported and largely untested. */
|
||||
"sqlite3-wasmfs", "esm" ,
|
||||
LIBMODE_UNSUPPORTED | LIBMODE_WASMFS | LIBMODE_ESM,
|
||||
"$(dir.wasmfs)/sqlite3-wasmfs.mjs",
|
||||
"$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs",
|
||||
"-sEXPORT_ES6 -sUSE_ES6_IMPORT_META"},
|
||||
|
||||
{/*End-of-list sentinel*/0,0,0,0,0,0}
|
||||
};
|
||||
|
||||
/*
|
||||
** Emits common vars needed by the rest of the emitted code (but not
|
||||
** needed by makefile code outside of these generated pieces).
|
||||
*/
|
||||
static void mk_prologue(void){
|
||||
/* A 0-terminated list of makefile vars which we expect to have been
|
||||
** set up by this point in the build process. */
|
||||
char const * aRequiredVars[] = {
|
||||
"dir.top",
|
||||
"dir.api", "dir.dout", "dir.tmp",
|
||||
"sqlite3-license-version.js",
|
||||
"MAKEFILE", "MAKEFILE_LIST",
|
||||
/* Fiddle... */
|
||||
"dir.fiddle", "dir.fiddle-debug",
|
||||
"MAKEFILE.fiddle",
|
||||
"EXPORTED_FUNCTIONS.fiddle",
|
||||
/*"just-testing",*/
|
||||
0
|
||||
};
|
||||
char const * zVar;
|
||||
int i;
|
||||
pf("%s# Build setup sanity checks...\n", zBanner);
|
||||
for( i = 0; (zVar = aRequiredVars[i]); ++i ){
|
||||
pf("ifeq (,$(%s))\n", zVar);
|
||||
pf(" $(error build process error: expecting make var $$(%s) to "
|
||||
"have been set up by now)\n", zVar);
|
||||
ps("endif");
|
||||
}
|
||||
pf("%s", zBanner);
|
||||
ps("# extern-post-js* and extern-pre-js* are files for use with");
|
||||
ps("# Emscripten's --extern-pre-js and --extern-post-js flags.");
|
||||
ps("extern-pre-js.js := $(dir.api)/extern-pre-js.js");
|
||||
ps("extern-post-js.js.in := $(dir.api)/extern-post-js.c-pp.js");
|
||||
ps("extern-pre-js.js = $(dir.api)/extern-pre-js.js");
|
||||
ps("extern-post-js.js.in = $(dir.api)/extern-post-js.c-pp.js");
|
||||
ps("# Emscripten flags for --[extern-][pre|post]-js=... for the");
|
||||
ps("# various builds.");
|
||||
ps("pre-post-common.flags := --extern-pre-js=$(sqlite3-license-version.js)");
|
||||
ps("# pre-post-jses.deps.* = a list of dependencies for the");
|
||||
ps("# --[extern-][pre/post]-js files.");
|
||||
ps("pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)");
|
||||
ps("pre-post-common.flags = --extern-pre-js=$(sqlite3-license-version.js)");
|
||||
ps("# pre-post-jses.deps.* = a list of dependencies for the\n"
|
||||
"# --[extern-][pre/post]-js files.");
|
||||
ps("pre-post-jses.deps.common = $(extern-pre-js.js) $(sqlite3-license-version.js)");
|
||||
|
||||
{
|
||||
/* SQLITE.CALL.WASM-OPT = shell code to run $(1) (source wasm file
|
||||
@@ -127,7 +233,7 @@ static void mk_prologue(void){
|
||||
"\t\techo -n 'After wasm-opt: '; \\\n"
|
||||
"\t\tls -l $(1); \\\n"
|
||||
"\telse \\\n"
|
||||
"\t\techo 'WARNING: ignoring wasm-opt failure'; \\\n"
|
||||
"\t\techo 'WARNING: ignoring wasm-opt failure for $(1)'; \\\n"
|
||||
"\tfi\n",
|
||||
zOptFlags
|
||||
);
|
||||
@@ -136,28 +242,6 @@ static void mk_prologue(void){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Flags for use with the 3rd argument to mk_pre_post() and
|
||||
** mk_lib_mode().
|
||||
**
|
||||
** Maintenance reminder: do not combine flags within this enum,
|
||||
** e.g. LIBMODE_BUNDLER_FRIENDLY=0x02|LIBMODE_ESM, as that will lead
|
||||
** to breakage in some of the flag checks.
|
||||
*/
|
||||
enum LibModeFlags {
|
||||
/* Indicates an ESM module build. */
|
||||
LIBMODE_ESM = 0x01,
|
||||
/* Indicates a "bundler-friendly" build mode. */
|
||||
LIBMODE_BUNDLER_FRIENDLY = 0x02,
|
||||
/* Indicates to _not_ add this build to the 'all' target. */
|
||||
LIBMODE_DONT_ADD_TO_ALL = 0x04,
|
||||
/* Indicates a node.js-for-node.js build (untested and
|
||||
** unsupported). */
|
||||
LIBMODE_NODEJS = 0x08,
|
||||
/* Indicates a wasmfs build (untested and unsupported). */
|
||||
LIBMODE_WASMFS = 0x10
|
||||
};
|
||||
|
||||
/*
|
||||
** Emits makefile code for setting up values for the --pre-js=FILE,
|
||||
** --post-js=FILE, and --extern-post-js=FILE emcc flags, as well as
|
||||
@@ -165,24 +249,26 @@ enum LibModeFlags {
|
||||
*/
|
||||
static void mk_pre_post(const char *zName /* build name */,
|
||||
const char *zMode /* build mode */,
|
||||
int flags /* LIBMODE_... mask */,
|
||||
const char *zCmppD /* optional -D flags for c-pp for the
|
||||
** --pre/--post-js files. */){
|
||||
/* Very common printf() args combo. */
|
||||
#define zNM zName, zMode
|
||||
|
||||
pf("%s# Begin --pre/--post flags for %s-%s\n", zBanner, zNM);
|
||||
pf("c-pp.D.%s-%s := %s\n", zNM, zCmppD ? zCmppD : "");
|
||||
pf("c-pp.D.%s-%s = %s\n", zNM, zCmppD ? zCmppD : "");
|
||||
pf("pre-post-%s-%s.flags ?=\n", zNM);
|
||||
|
||||
/* --pre-js=... */
|
||||
pf("pre-js.js.%s-%s := $(dir.tmp)/pre-js.%s-%s.js\n",
|
||||
pf("pre-js.js.%s-%s = $(dir.tmp)/pre-js.%s-%s.js\n",
|
||||
zNM, zNM);
|
||||
pf("$(pre-js.js.%s-%s): $(MAKEFILE_LIST)\n", zNM);
|
||||
pf("$(pre-js.js.%s-%s): $(MAKEFILE_LIST) $(sqlite3-license-version.js)\n", zNM);
|
||||
#if 1
|
||||
pf("$(eval $(call SQLITE.CALL.C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.%s-%s),"
|
||||
"$(c-pp.D.%s-%s)))\n", zNM, zNM);
|
||||
#else
|
||||
/* This part is needed if/when we re-enable the custom
|
||||
** Module.instantiateModule() impl in api/pre-js.c-pp.js. */
|
||||
pf("pre-js.js.%s-%s.intermediary := $(dir.tmp)/pre-js.%s-%s.intermediary.js\n",
|
||||
pf("pre-js.js.%s-%s.intermediary = $(dir.tmp)/pre-js.%s-%s.intermediary.js\n",
|
||||
zNM, zNM);
|
||||
pf("$(eval $(call SQLITE.CALL.C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.%s-%s.intermediary),"
|
||||
"$(c-pp.D.%s-%s) -Dcustom-Module.instantiateModule))\n", zNM, zNM);
|
||||
@@ -200,17 +286,17 @@ static void mk_pre_post(const char *zName /* build name */,
|
||||
#endif
|
||||
|
||||
/* --post-js=... */
|
||||
pf("post-js.js.%s-%s := $(dir.tmp)/post-js.%s-%s.js\n", zNM, zNM);
|
||||
pf("post-js.js.%s-%s = $(dir.tmp)/post-js.%s-%s.js\n", zNM, zNM);
|
||||
pf("$(eval $(call SQLITE.CALL.C-PP.FILTER,$(post-js.js.in),"
|
||||
"$(post-js.js.%s-%s),$(c-pp.D.%s-%s)))\n", zNM, zNM);
|
||||
|
||||
/* --extern-post-js=... */
|
||||
pf("extern-post-js.js.%s-%s := $(dir.tmp)/extern-post-js.%s-%s.js\n", zNM, zNM);
|
||||
pf("extern-post-js.js.%s-%s = $(dir.tmp)/extern-post-js.%s-%s.js\n", zNM, zNM);
|
||||
pf("$(eval $(call SQLITE.CALL.C-PP.FILTER,$(extern-post-js.js.in),$(extern-post-js.js.%s-%s),"
|
||||
"$(c-pp.D.%s-%s)))\n", zNM, zNM);
|
||||
|
||||
/* Combined flags for use with emcc... */
|
||||
pf("pre-post-common.flags.%s-%s := "
|
||||
pf("pre-post-common.flags.%s-%s = "
|
||||
"$(pre-post-common.flags) "
|
||||
"--post-js=$(post-js.js.%s-%s) "
|
||||
"--extern-post-js=$(extern-post-js.js.%s-%s)\n", zNM, zNM, zNM);
|
||||
@@ -219,30 +305,29 @@ static void mk_pre_post(const char *zName /* build name */,
|
||||
"--pre-js=$(pre-js.js.%s-%s)\n", zNM, zNM, zNM);
|
||||
|
||||
/* Set up deps... */
|
||||
pf("pre-post-jses.%s-%s.deps := $(pre-post-jses.deps.common) "
|
||||
pf("pre-post-jses.%s-%s.deps = $(pre-post-jses.deps.common) "
|
||||
"$(post-js.js.%s-%s) $(extern-post-js.js.%s-%s)\n",
|
||||
zNM, zNM, zNM);
|
||||
pf("pre-post-%s-%s.deps := $(pre-post-jses.%s-%s.deps) $(dir.tmp)/pre-js.%s-%s.js\n",
|
||||
pf("pre-post-%s-%s.deps = $(pre-post-jses.%s-%s.deps) $(dir.tmp)/pre-js.%s-%s.js\n",
|
||||
zNM, zNM, zNM);
|
||||
pf("# End --pre/--post flags for %s-%s%s", zNM, zBanner);
|
||||
#undef zNM
|
||||
}
|
||||
|
||||
/*
|
||||
** Emits rules for the fiddle builds.
|
||||
**
|
||||
*/
|
||||
static void mk_fiddle(){
|
||||
static void mk_fiddle(void){
|
||||
int i = 0;
|
||||
|
||||
mk_pre_post("fiddle-module","vanilla", 0, 0);
|
||||
mk_pre_post("fiddle-module","vanilla", 0);
|
||||
for( ; i < 2; ++i ){
|
||||
/* 0==normal, 1==debug */
|
||||
const char *zTail = i ? ".debug" : "";
|
||||
const char *zDir = i ? "$(dir.fiddle-debug)" : "$(dir.fiddle)";
|
||||
|
||||
pf("%s# Begin fiddle%s\n", zBanner, zTail);
|
||||
pf("fiddle-module.js%s := %s/fiddle-module.js\n", zTail, zDir);
|
||||
pf("fiddle-module.wasm%s := "
|
||||
"$(subst .js,.wasm,$(fiddle-module.js%s))\n", zTail, zTail);
|
||||
pf("fiddle-module.js%s = %s/fiddle-module.js\n", zTail, zDir);
|
||||
pf("$(fiddle-module.js%s):%s $(MAKEFILE_LIST) $(MAKEFILE.fiddle) "
|
||||
"$(EXPORTED_FUNCTIONS.fiddle) "
|
||||
"$(fiddle.cses) $(pre-post-fiddle-module-vanilla.deps) "
|
||||
@@ -254,7 +339,9 @@ static void mk_fiddle(){
|
||||
pf("\t$(bin.emcc) -o $@ $(fiddle.emcc-flags%s) "
|
||||
"$(pre-post-fiddle-module-vanilla.flags) $(fiddle.cses)\n",
|
||||
zTail);
|
||||
pf("\t$(maybe-wasm-strip) $(fiddle-module.wasm%s)\n", zTail);
|
||||
ps("\t@chmod -x $(basename $@).wasm");
|
||||
ps("\t@$(maybe-wasm-strip) $(basename $@).wasm");
|
||||
ps("\t@$(SQLITE.strip-createExportWrapper)");
|
||||
pf("\t@cp -p $(SOAP.js) $(dir $@)\n");
|
||||
if( 1==i ){/*fiddle.debug*/
|
||||
pf("\tcp -p $(dir.fiddle)/index.html "
|
||||
@@ -263,13 +350,13 @@ static void mk_fiddle(){
|
||||
"$(dir $@)\n");
|
||||
}
|
||||
pf("\t@for i in %s/*.*js %s/*.html %s/*.wasm; do \\\n"
|
||||
"\t\ttest -f $${i} || continue; \\\n"
|
||||
"\t\ttest -f $${i} || continue; \\\n"
|
||||
"\t\tgzip < $${i} > $${i}.gz; \\\n"
|
||||
"\tdone\n", zDir, zDir, zDir);
|
||||
if( 0==i ){
|
||||
ps("fiddle: $(fiddle-module.js)");
|
||||
}else{
|
||||
ps("fiddle-debug: $(fiddle-module-debug.js)");
|
||||
ps("fiddle-debug: $(fiddle-module.js.debug)");
|
||||
}
|
||||
pf("# End fiddle%s%s", zTail, zBanner);
|
||||
}
|
||||
@@ -280,138 +367,110 @@ static void mk_fiddle(){
|
||||
** by the combination of zName and zMode, each of which must be values
|
||||
** from JS_BUILD_NAMES resp. JS_BUILD_MODES.
|
||||
*/
|
||||
static void mk_lib_mode(const char *zName /* build name */,
|
||||
const char *zMode /* build mode */,
|
||||
int flags /* LIBMODE_... mask */,
|
||||
const char *zApiJsOut /* name of generated sqlite3-api.js/.mjs */,
|
||||
const char *zJsOut /* name of generated sqlite3.js/.mjs */,
|
||||
const char *zCmppD /* extra -D flags for c-pp */,
|
||||
const char *zEmcc /* extra flags for emcc */){
|
||||
static void mk_lib_mode(const BuildDef * pB){
|
||||
const char * zWasmOut = "$(basename $@).wasm"
|
||||
/* The various targets named X.js or X.mjs (zJsOut) also generate
|
||||
** X.wasm, and we need that part of the name to perform some
|
||||
** post-processing after Emscripten generates X.wasm. */;
|
||||
assert( zName );
|
||||
assert( zMode );
|
||||
assert( zApiJsOut );
|
||||
assert( zJsOut );
|
||||
if( !zCmppD ) zCmppD = "";
|
||||
if( !zEmcc ) zEmcc = "";
|
||||
assert( pB->zName );
|
||||
assert( pB->zMode );
|
||||
assert( pB->zJsOut );
|
||||
/* Very common printf() args combo. */
|
||||
#define zNM pB->zName, pB->zMode
|
||||
|
||||
pf("%s# Begin build [%s-%s]\n", zBanner, zNM);
|
||||
pf("# zApiJsOut=%s\n# zJsOut=%s\n# zCmppD=%s\n", zApiJsOut, zJsOut, zCmppD);
|
||||
pf("$(info Setting up build [%s-%s]: %s)\n", zNM, zJsOut);
|
||||
mk_pre_post(zNM, flags, zCmppD);
|
||||
pf("%s# Begin build [%s-%s]. flags=0x%02x\n", zBanner, zNM, pB->flags);
|
||||
pf("# zJsOut=%s\n# zCmppD=%s\n", pB->zJsOut,
|
||||
pB->zCmppD ? pB->zCmppD : "<none>");
|
||||
pf("$(info Setting up build [%s-%s]: %s)\n", zNM, pB->zJsOut);
|
||||
mk_pre_post(zNM, pB->zCmppD);
|
||||
pf("\nemcc.flags.%s.%s ?=\n", zNM);
|
||||
if( zEmcc[0] ){
|
||||
pf("emcc.flags.%s.%s += %s\n", zNM, zEmcc);
|
||||
if( pB->zEmcc && pB->zEmcc[0] ){
|
||||
pf("emcc.flags.%s.%s += %s\n", zNM, pB->zEmcc);
|
||||
}
|
||||
pf("$(eval $(call SQLITE.CALL.C-PP.FILTER, $(sqlite3-api.js.in), %s, %s))\n",
|
||||
zApiJsOut, zCmppD);
|
||||
|
||||
/* target zJsOut */
|
||||
pf("%s: %s $(MAKEFILE_LIST) $(sqlite3-wasm.cfiles) $(EXPORTED_FUNCTIONS.api) "
|
||||
/* target pB->zJsOut */
|
||||
pf("%s: $(MAKEFILE_LIST) $(sqlite3-wasm.cfiles) $(EXPORTED_FUNCTIONS.api) "
|
||||
"$(pre-post-%s-%s.deps) "
|
||||
"$(sqlite3-api.ext.jses)"
|
||||
/* ^^^ maintenance reminder: we set these as deps so that they
|
||||
get copied into place early. That allows the developer to
|
||||
reload the base-most test pages while the later-stage builds
|
||||
are still compiling, which is especially helpful when running
|
||||
builds with long build times (like -Oz). */
|
||||
** get copied into place early. That allows the developer to
|
||||
** reload the base-most test pages while the later-stage builds
|
||||
** are still compiling, which is especially helpful when running
|
||||
** builds with long build times (like -Oz). */
|
||||
"\n",
|
||||
zJsOut, zApiJsOut, zNM);
|
||||
pB->zJsOut, zNM);
|
||||
pf("\t@echo \"Building $@ ...\"\n");
|
||||
if( LIBMODE_UNSUPPORTED & pB->flags ){
|
||||
ps("\t@echo 'ACHTUNG: $@ is an unsupported build. "
|
||||
"Use at your own risk.'");
|
||||
}
|
||||
pf("\t$(bin.emcc) -o $@ $(emcc_opt_full) $(emcc.flags) \\\n");
|
||||
pf("\t\t$(emcc.jsflags) -sENVIRONMENT=$(emcc.environment.%s) \\\n", zMode);
|
||||
pf("\t\t$(emcc.jsflags) -sENVIRONMENT=$(emcc.environment.%s) \\\n",
|
||||
pB->zMode);
|
||||
pf("\t\t$(pre-post-%s-%s.flags) \\\n", zNM);
|
||||
pf("\t\t$(emcc.flags.%s) $(emcc.flags.%s.%s) \\\n", zName, zNM);
|
||||
pf("\t\t$(emcc.flags.%s) $(emcc.flags.%s.%s) \\\n", pB->zName, zNM);
|
||||
pf("\t\t$(cflags.common) $(SQLITE_OPT) \\\n"
|
||||
"\t\t$(cflags.%s) $(cflags.%s.%s) \\\n"
|
||||
"\t\t$(cflags.wasm_extra_init) $(sqlite3-wasm.cfiles)\n", zName, zNM);
|
||||
if( (LIBMODE_ESM & flags) || (LIBMODE_NODEJS & flags) ){
|
||||
"\t\t$(cflags.wasm_extra_init) $(sqlite3-wasm.cfiles)\n", pB->zName, zNM);
|
||||
if( (LIBMODE_ESM & pB->flags) || (LIBMODE_NODEJS & pB->flags) ){
|
||||
/* TODO? Replace this $(call) with the corresponding makefile
|
||||
** code. OTOH, we also use this $(call) in the speedtest1-wasmfs
|
||||
** build, which is not part of the rules emitted by this
|
||||
** program. */
|
||||
pf("\t@$(call SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT,1,%d)\n",
|
||||
(LIBMODE_WASMFS & flags) ? 1 : 0);
|
||||
(LIBMODE_WASMFS & pB->flags) ? 1 : 0);
|
||||
}
|
||||
pf("\t@chmod -x %s; \\\n"
|
||||
"\t\t$(maybe-wasm-strip) %s;\n",
|
||||
zWasmOut, zWasmOut);
|
||||
pf("\t@chmod -x %s\n", zWasmOut);
|
||||
pf("\t@$(maybe-wasm-strip) %s\n", zWasmOut);
|
||||
pf("\t@$(call SQLITE.CALL.WASM-OPT,%s)\n", zWasmOut);
|
||||
pf("\t@sed -i -e '/^var _sqlite3.*createExportWrapper/d' %s || exit; \\\n"
|
||||
/* ^^^^^^ reminder: Mac/BSD sed has no -i flag */
|
||||
"\t\techo 'Stripped out createExportWrapper() parts.'\n",
|
||||
zJsOut) /* Our JS code installs bindings of each WASM export. The
|
||||
generated Emscripten JS file does the same using its
|
||||
own framework, but we don't use those results and can
|
||||
speed up lib init, and reduce memory cost
|
||||
considerably, by stripping them out. */;
|
||||
ps("\t@$(SQLITE.strip-createExportWrapper)");
|
||||
/*
|
||||
** The above $(bin.emcc) call will write zJsOut and will create a
|
||||
** like-named .wasm file (zWasmOut). That .wasm file name gets
|
||||
** hard-coded into zJsOut so we need to, for some cases, patch
|
||||
** zJsOut to use the name sqlite3.wasm instead. Note that the
|
||||
** The above $(bin.emcc) call will write pB->zJsOut, a.k.a. $@, and
|
||||
** will create a like-named .wasm file (zWasmOut). That .wasm file
|
||||
** name gets hard-coded into $@ so we need to, for some cases, patch
|
||||
** zJsOut to use the name sqlite3.wasm instead. Note that the
|
||||
** resulting .wasm file is identical for all builds for which zEmcc
|
||||
** is empty.
|
||||
*/
|
||||
if( (LIBMODE_BUNDLER_FRIENDLY & flags)
|
||||
|| (LIBMODE_NODEJS & flags) ){
|
||||
pf("\t@echo 'Patching $@ for %s.wasm...'; \\\n", zName);
|
||||
if( (LIBMODE_BUNDLER_FRIENDLY & pB->flags) ){
|
||||
pf("\t@echo 'Patching $@ for %s.wasm...'; \\\n", pB->zName);
|
||||
pf("\t\trm -f %s; \\\n", zWasmOut);
|
||||
pf("\t\tsed -i -e 's/%s-%s.wasm/%s.wasm/g' $@ || exit;\n",
|
||||
/* ^^^^^^ reminder: Mac/BSD sed has no -i flag */
|
||||
zNM, zName);
|
||||
/* ^^^^^^ reminder: Mac/BSD sed has no -i flag but this
|
||||
** build process explicitly requires a Linux system. */
|
||||
zNM, pB->zName);
|
||||
pf("\t@ls -la $@\n");
|
||||
if( LIBMODE_BUNDLER_FRIENDLY & flags ){
|
||||
if( LIBMODE_BUNDLER_FRIENDLY & pB->flags ){
|
||||
/* Avoid a 3rd occurrence of the bug fixed by 65798c09a00662a3,
|
||||
** which was (in two cases) caused by makefile refactoring and
|
||||
** not recognized until after a release was made with the broken
|
||||
** sqlite3-bundler-friendly.mjs: */
|
||||
** sqlite3-bundler-friendly.mjs (which is used by the npm
|
||||
** subproject but is otherwise untested/unsupported): */
|
||||
pf("\t@if grep -e '^ *importScripts(' $@; "
|
||||
"then echo 'ERROR: bug fixed in 65798c09a00662a3 has re-appeared'; "
|
||||
"exit 1; fi;\n");
|
||||
}
|
||||
|
||||
}else{
|
||||
pf("\t@ls -la %s $@\n", zWasmOut);
|
||||
}
|
||||
if( 0==(LIBMODE_DONT_ADD_TO_ALL & flags) ){
|
||||
pf("all: %s\n", zJsOut);
|
||||
if( 0==(LIBMODE_UNSUPPORTED & pB->flags) ){
|
||||
pf("all: %s\n", pB->zJsOut);
|
||||
}
|
||||
pf("# End build [%s-%s]%s", zNM, zBanner);
|
||||
#undef zNM
|
||||
}
|
||||
|
||||
int main(void){
|
||||
int rc = 0;
|
||||
const BuildDef *pB = &aBuildDefs[0];
|
||||
pf("# What follows was GENERATED by %s. Edit at your own risk.\n", __FILE__);
|
||||
mk_prologue();
|
||||
mk_lib_mode("sqlite3", "vanilla", 0,
|
||||
"$(sqlite3-api.js)", "$(sqlite3.js)", 0, 0);
|
||||
mk_lib_mode("sqlite3", "esm", LIBMODE_ESM,
|
||||
"$(sqlite3-api.mjs)", "$(sqlite3.mjs)",
|
||||
"-Dtarget=es6-module", 0);
|
||||
mk_lib_mode("sqlite3", "bundler-friendly",
|
||||
LIBMODE_BUNDLER_FRIENDLY | LIBMODE_ESM,
|
||||
"$(sqlite3-api-bundler-friendly.mjs)",
|
||||
"$(sqlite3-bundler-friendly.mjs)",
|
||||
"$(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly", 0);
|
||||
mk_lib_mode("sqlite3" , "node",
|
||||
LIBMODE_NODEJS | LIBMODE_DONT_ADD_TO_ALL,
|
||||
"$(sqlite3-api-node.mjs)", "$(sqlite3-node.mjs)",
|
||||
"$(c-pp.D.sqlite3-bundler-friendly) -Dtarget=node", 0);
|
||||
mk_lib_mode("sqlite3-wasmfs", "esm" ,
|
||||
LIBMODE_WASMFS | LIBMODE_ESM | LIBMODE_DONT_ADD_TO_ALL,
|
||||
/* The sqlite3-wasmfs build is optional and needs to be invoked
|
||||
** conditionally using info we don't have here. */
|
||||
"$(sqlite3-api-wasmfs.mjs)", "$(sqlite3-wasmfs.mjs)",
|
||||
"$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs",
|
||||
"-sEXPORT_ES6 -sUSE_ES6_IMPORT_META");
|
||||
|
||||
for( ; pB->zName; ++pB ){
|
||||
mk_lib_mode( pB );
|
||||
}
|
||||
mk_fiddle();
|
||||
mk_pre_post("speedtest1","vanilla", 0, 0);
|
||||
mk_pre_post("speedtest1-wasmfs","esm", 0,
|
||||
mk_pre_post("speedtest1","vanilla", 0);
|
||||
mk_pre_post("speedtest1-wasmfs","esm",
|
||||
"$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs");
|
||||
return rc;
|
||||
}
|
||||
|
@@ -23,11 +23,10 @@
|
||||
</figure>
|
||||
<div class="emscripten" id="module-status">Downloading...</div>
|
||||
<div class="emscripten">
|
||||
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
|
||||
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
|
||||
</div><!-- /emscripten bits -->
|
||||
<div class='warning'>This page starts running the main exe when it loads, which will
|
||||
block the UI until it finishes! Adding UI controls to manually configure and start it
|
||||
are TODO.</div>
|
||||
block the UI until it finishes!</div>
|
||||
</div>
|
||||
<div class='warning'>Achtung: running it with the dev tools open may
|
||||
<em>drastically</em> slow it down. For faster results, keep the dev
|
||||
@@ -118,7 +117,7 @@
|
||||
argv.push("--vfs", vfs);
|
||||
log2('',"Using VFS:",vfs);
|
||||
if('kvvfs' === vfs){
|
||||
forceSize = 2 /* 5 uses approx. 4.96mb */;
|
||||
forceSize = 2 /* >2 is too big as of mid-2025 */;
|
||||
dbFile = 'session';
|
||||
log2('warning',"kvvfs VFS: forcing --size",forceSize,
|
||||
"and filename '"+dbFile+"'.");
|
||||
|
@@ -41,7 +41,7 @@
|
||||
|
||||
ES6 worker module build:
|
||||
|
||||
./c-pp -f tester1.c-pp.js -o tester1-esm.js -Dtarget=es6-module
|
||||
./c-pp -f tester1.c-pp.js -o tester1-esm.mjs -Dtarget=es6-module
|
||||
*/
|
||||
//#if target=es6-module
|
||||
import {default as sqlite3InitModule} from './jswasm/sqlite3.mjs';
|
||||
@@ -221,7 +221,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
else if(filter instanceof Function) pass = filter(err);
|
||||
else if('string' === typeof filter) pass = (err.message === filter);
|
||||
if(!pass){
|
||||
throw new Error(msg || ("Filter rejected this exception: "+err.message));
|
||||
throw new Error(msg || ("Filter rejected this exception: <<"+err.message+">>"));
|
||||
}
|
||||
return this;
|
||||
},
|
||||
@@ -1209,6 +1209,104 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
.t({
|
||||
name: "oo1.DB/Stmt.wrapDbHandle()",
|
||||
test: function(sqlite3){
|
||||
/* Maintenance reminder: this function is early in the list to
|
||||
demonstrate that the wrappers for this.db created by this
|
||||
function do not interfere with downstream tests, e.g. by
|
||||
closing this.db.pointer. */
|
||||
//sqlite3.config.debug("Proxying",this.db);
|
||||
const misuseMsg = "SQLITE_MISUSE: Argument must be a WASM sqlite3 pointer";
|
||||
T.mustThrowMatching(()=>sqlite3.oo1.DB.wrapHandle(this.db), misuseMsg)
|
||||
.mustThrowMatching(()=>sqlite3.oo1.DB.wrapHandle(0), misuseMsg);
|
||||
let dw = sqlite3.oo1.DB.wrapHandle(this.db.pointer);
|
||||
//sqlite3.config.debug('dw',dw);
|
||||
T.assert( dw, '!!dw' )
|
||||
.assert( dw instanceof sqlite3.oo1.DB, 'dw is-a oo1.DB' )
|
||||
.assert( dw.pointer, 'dw.pointer' )
|
||||
.assert( dw.pointer === this.db.pointer, 'dw.pointer===db.pointer' )
|
||||
.assert( dw.filename === this.db.filename, 'dw.filename===db.filename' );
|
||||
|
||||
T.assert( dw === dw.exec("select 1") );
|
||||
let q;
|
||||
try {
|
||||
q = dw.prepare("select 1");
|
||||
T.assert( q.step() )
|
||||
.assert( !q.step() );
|
||||
}finally{
|
||||
if( q ) q.finalize();
|
||||
}
|
||||
dw.close();
|
||||
T.assert( !dw.pointer )
|
||||
.assert( this.db === this.db.exec("select 1") );
|
||||
dw = undefined;
|
||||
|
||||
let pDb = 0, pStmt = 0;
|
||||
const stack = wasm.pstack.pointer;
|
||||
try {
|
||||
const ppOut = wasm.pstack.allocPtr();
|
||||
T.assert( 0===wasm.peekPtr(ppOut) );
|
||||
let rc = capi.sqlite3_open_v2( ":memory:", ppOut,
|
||||
capi.SQLITE_OPEN_CREATE
|
||||
| capi.SQLITE_OPEN_READWRITE,
|
||||
0);
|
||||
T.assert( 0===rc, 'open_v2()' );
|
||||
pDb = wasm.peekPtr(ppOut);
|
||||
wasm.pokePtr(ppOut, 0);
|
||||
T.assert( pDb>0, 'pDb>0' );
|
||||
const pTmp = pDb;
|
||||
dw = sqlite3.oo1.DB.wrapHandle(pDb, true);
|
||||
pDb = 0;
|
||||
//sqlite3.config.debug("dw",dw);
|
||||
T.assert( pTmp===dw.pointer, 'pDb===dw.pointer' );
|
||||
T.assert( dw.filename === "", "dw.filename == "+dw.filename );
|
||||
let q = dw.prepare("select 1");
|
||||
try {
|
||||
T.assert( q.step(), "step()" );
|
||||
T.assert( !q.step(), "!step()" );
|
||||
}finally{
|
||||
q.finalize();
|
||||
q = undefined;
|
||||
}
|
||||
T.assert( dw===dw.exec("select 1") );
|
||||
dw.affirmOpen();
|
||||
const select1 = "select 1";
|
||||
rc = capi.sqlite3_prepare_v2( dw, select1, -1, ppOut, 0 );
|
||||
T.assert( 0===rc, 'prepare_v2() rc='+rc );
|
||||
pStmt = wasm.peekPtr(ppOut);
|
||||
T.assert( pStmt && wasm.isPtr(pStmt), 'pStmt is valid?' );
|
||||
try {
|
||||
//log( "capi.sqlite3_sql() =",capi.sqlite3_sql(pStmt));
|
||||
T.assert( select1 === capi.sqlite3_sql(pStmt), 'SQL mismatch' );
|
||||
q = sqlite3.oo1.Stmt.wrapHandle(dw, pStmt, false);
|
||||
//log("q@"+pStmt+" does not own handle");
|
||||
T.assert( q.step(), "step()" )
|
||||
.assert( !q.step(), "!step()" );
|
||||
q.finalize();
|
||||
q = undefined;
|
||||
T.assert( select1 === capi.sqlite3_sql(pStmt), 'SQL mismatch'
|
||||
/* This will fail if we've mismanaged pStmt's lifetime */);
|
||||
q = sqlite3.oo1.Stmt.wrapHandle(dw, pStmt, true);
|
||||
pStmt = 0;
|
||||
q.reset();
|
||||
T.assert( q.step(), "step()" )
|
||||
.assert( !q.step(), "!step()" );
|
||||
}finally{
|
||||
if( pStmt ) capi.sqlite3_finalize(pStmt)
|
||||
if( q ) q.finalize();
|
||||
}
|
||||
|
||||
}finally{
|
||||
wasm.pstack.restore(stack);
|
||||
if( pDb ){ capi.sqlite3_close_v2(pDb); }
|
||||
else if( dw ){ dw.close(); }
|
||||
}
|
||||
}
|
||||
})/*oo1.DB/Stmt.wrapHandle()*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
.t('sqlite3_db_config() and sqlite3_db_status()', function(sqlite3){
|
||||
let rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, 0, 0);
|
||||
@@ -1268,6 +1366,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
/columnCount property is read-only/)
|
||||
.assert(1===st.columnCount)
|
||||
.assert(0===st.parameterCount)
|
||||
.assert(0===capi.sqlite3_bind_parameter_count(st))
|
||||
.mustThrow(()=>st.bind(1,null))
|
||||
.assert(true===st.step())
|
||||
.assert(3 === st.get(0))
|
||||
@@ -1490,6 +1589,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
let st = db.prepare("update t set b=:b where a='blob'");
|
||||
try {
|
||||
T.assert(0===st.columnCount)
|
||||
.assert(1===st.parameterCount)
|
||||
.assert(1===capi.sqlite3_bind_parameter_count(st))
|
||||
.assert( false===st.isReadOnly() );
|
||||
const ndx = st.getParamIndex(':b');
|
||||
T.assert(1===ndx);
|
||||
@@ -3329,6 +3430,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
db.exec("create table t(a)");
|
||||
const stmt = db.prepare("insert into t(a) values($a)");
|
||||
T.assert( 1===capi.sqlite3_bind_parameter_count(stmt) )
|
||||
.assert( 1===stmt.parameterCount )
|
||||
.assert( 1===capi.sqlite3_bind_parameter_index(stmt, "$a") )
|
||||
.assert( 0===capi.sqlite3_bind_parameter_index(stmt, ":a") )
|
||||
.assert( 1===stmt.getParamIndex("$a") )
|
||||
|
@@ -5,31 +5,28 @@
|
||||
# sqlite3.wasm. It is intended to be "include"d from the main
|
||||
# GNUMakefile.
|
||||
########################################################################
|
||||
MAKEFILE.wasmfs := $(lastword $(MAKEFILE_LIST))
|
||||
MAKEFILE.wasmfs = $(lastword $(MAKEFILE_LIST))
|
||||
# ensure that the following message starts on line 10 or higher for proper
|
||||
# $(warning) alignment!
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
$(warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
|
||||
$(warning !! The WASMFS build is not well-supported. WASMFS is a proverbial)
|
||||
$(warning !! moving target, sometimes changing in incompatible ways between)
|
||||
$(warning !! Emscripten versions. This build is provided for adventurous folks)
|
||||
$(warning !! and is not a supported deliverable of the SQLite project.)
|
||||
$(warning !! The WASMFS build is unsupported. Use at your own risk.
|
||||
$(warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
|
||||
endif
|
||||
|
||||
sqlite3-wasmfs.js := $(dir.wasmfs)/sqlite3-wasmfs.js
|
||||
sqlite3-wasmfs.wasm := $(dir.wasmfs)/sqlite3-wasmfs.wasm
|
||||
sqlite3-wasmfs.js = $(dir.wasmfs)/sqlite3-wasmfs.js
|
||||
sqlite3-wasmfs.wasm = $(dir.wasmfs)/sqlite3-wasmfs.wasm
|
||||
|
||||
########################################################################
|
||||
# emcc flags for .c/.o.
|
||||
cflags.sqlite3-wasmfs :=
|
||||
cflags.sqlite3-wasmfs =
|
||||
cflags.sqlite3-wasmfs += -std=c99 -fPIC
|
||||
cflags.sqlite3-wasmfs += -pthread
|
||||
cflags.sqlite3-wasmfs += -DSQLITE_ENABLE_WASMFS
|
||||
|
||||
########################################################################
|
||||
# emcc flags specific to building the final .js/.wasm file...
|
||||
emcc.flags.sqlite3-wasmfs :=
|
||||
emcc.flags.sqlite3-wasmfs =
|
||||
emcc.flags.sqlite3-wasmfs += \
|
||||
-sEXPORTED_RUNTIME_METHODS=wasmMemory
|
||||
# wasmMemory ==> for -sIMPORTED_MEMORY
|
||||
@@ -43,7 +40,7 @@ emcc.flags.sqlite3-wasmfs += -Wno-limited-postlink-optimizations
|
||||
emcc.flags.sqlite3-wasmfs += -sMEMORY64=0
|
||||
emcc.flags.sqlite3-wasmfs += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.128)
|
||||
# ^^^^ 64MB is not enough for WASMFS/OPFS test runs using batch-runner.js
|
||||
sqlite3-wasmfs.fsflags := -pthread -sWASMFS \
|
||||
sqlite3-wasmfs.fsflags = -pthread -sWASMFS \
|
||||
-sPTHREAD_POOL_SIZE=1 \
|
||||
-sERROR_ON_UNDEFINED_SYMBOLS=0 -sLLD_REPORT_UNDEFINED
|
||||
# ^^^^^ why undefined symbols are necessary for the wasmfs build is anyone's guess.
|
||||
@@ -53,10 +50,9 @@ emcc.flags.sqlite3-wasmfs += -sALLOW_MEMORY_GROWTH=0
|
||||
# USE_PTHREADS + ALLOW_MEMORY_GROWTH may run non-wasm code slowly,
|
||||
# see https://github.com/WebAssembly/design/issues/1271 [-Wpthreads-mem-growth]
|
||||
# And, indeed, it runs slowly if memory is permitted to grow.
|
||||
#emcc.flags.sqlite3-wasmfs.vanilla :=
|
||||
#emcc.flags.sqlite3-wasmfs.esm := -sEXPORT_ES6 -sUSE_ES6_IMPORT_META
|
||||
all: $(sqlite3-wasmfs.mjs)
|
||||
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(MAKEFILE.wasmfs)
|
||||
#emcc.flags.sqlite3-wasmfs.vanilla =
|
||||
#emcc.flags.sqlite3-wasmfs.esm = -sEXPORT_ES6 -sUSE_ES6_IMPORT_META
|
||||
$(sqlite3-wasmfs.js) $(dir.wasmfs)/sqlite3-wasmfs.mjs: $(MAKEFILE.wasmfs)
|
||||
########################################################################
|
||||
# Build quirk: we cannot build BOTH .js and .mjs with our current
|
||||
# build infrastructure because the supplemental *.worker.js files get
|
||||
@@ -68,31 +64,31 @@ $(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(MAKEFILE.wasmfs)
|
||||
# names is that it means that the corresponding .wasm file is also
|
||||
# built/saved multiple times. It is likely that anyone wanting to use
|
||||
# WASMFS will want an ES6 module, so that's what we build here.
|
||||
wasmfs.build.ext := mjs
|
||||
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(SOAP.js.bld)
|
||||
wasmfs.build.ext = mjs
|
||||
$(sqlite3-wasmfs.js) $(dir.wasmfs)/sqlite3-wasmfs.mjs: $(SOAP.js.bld)
|
||||
ifeq (js,$(wasmfs.build.ext))
|
||||
$(sqlite3-wasmfs.wasm): $(sqlite3-wasmfs.js)
|
||||
wasmfs: $(sqlite3-wasmfs.js)
|
||||
else
|
||||
$(sqlite3-wasmfs.wasm): $(sqlite3-wasmfs.mjs)
|
||||
wasmfs: $(sqlite3-wasmfs.mjs)
|
||||
$(sqlite3-wasmfs.wasm): $(dir.wasmfs)/sqlite3-wasmfs.mjs
|
||||
wasmfs: $(dir.wasmfs)/sqlite3-wasmfs.mjs
|
||||
endif
|
||||
all: wasmfs
|
||||
|
||||
########################################################################
|
||||
# speedtest1 for wasmfs.
|
||||
speedtest1-wasmfs.mjs := $(dir.wasmfs)/speedtest1-wasmfs.mjs
|
||||
speedtest1-wasmfs.wasm := $(subst .mjs,.wasm,$(speedtest1-wasmfs.mjs))
|
||||
emcc.flags.speedtest1-wasmfs := $(sqlite3-wasmfs.fsflags)
|
||||
speedtest1-wasmfs.mjs = $(dir.wasmfs)/speedtest1-wasmfs.mjs
|
||||
speedtest1-wasmfs.wasm = $(subst .mjs,.wasm,$(speedtest1-wasmfs.mjs))
|
||||
emcc.flags.speedtest1-wasmfs = $(sqlite3-wasmfs.fsflags)
|
||||
emcc.flags.speedtest1-wasmfs += $(SQLITE_OPT)
|
||||
emcc.flags.speedtest1-wasmfs += -sALLOW_MEMORY_GROWTH=0
|
||||
emcc.flags.speedtest1-wasmfs += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.128)
|
||||
#$(eval $(call call-make-pre-js,speedtest1-wasmfs,ems))
|
||||
#$(info speedtest DEPS=pre-post-sqlite3-wasmfs-esm.deps=$(pre-post-sqlite3-wasmfs-esm.deps))
|
||||
$(speedtest1-wasmfs.mjs): $(speedtest1.cfiles) $(sqlite3-wasmfs.js) \
|
||||
$(MAKEFILE) $(MAKEFILE.wasmfs) \
|
||||
$(pre-post-sqlite3-wasmfs-esm.deps) \
|
||||
$(MAKEFILE) $(MAKEFILE.wasmfs) $(pre-post-sqlite3-wasmfs-esm.deps) \
|
||||
$(EXPORTED_FUNCTIONS.speedtest1)
|
||||
@echo "Building $@ ..."
|
||||
$(emcc.bin) \
|
||||
$(bin.emcc) \
|
||||
$(pre-post-sqlite3-wasmfs-esm.flags) \
|
||||
$(cflags.common) \
|
||||
$(cflags.sqlite3-wasmfs) \
|
||||
|
Reference in New Issue
Block a user