diff --git a/blob.go b/blob.go index a30abf6..5ecc35f 100644 --- a/blob.go +++ b/blob.go @@ -118,8 +118,8 @@ func (b *Blob) WriteTo(w io.Writer) (n int64, err error) { return 0, nil } + want := int64(1024 * 1024) avail := b.bytes - b.offset - want := int64(65536) if want > avail { want = avail } @@ -175,8 +175,11 @@ func (b *Blob) Write(p []byte) (n int, err error) { // // https://www.sqlite.org/c3ref/blob_write.html func (b *Blob) ReadFrom(r io.Reader) (n int64, err error) { + want := int64(1024 * 1024) avail := b.bytes - b.offset - want := int64(65536) + if l, ok := r.(*io.LimitedReader); ok && want > l.N { + want = l.N + } if want > avail { want = avail } diff --git a/driver/driver.go b/driver/driver.go index f788be4..2b733f0 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -479,11 +479,7 @@ func (r *rows) Next(dest []driver.Value) error { case sqlite3.TEXT: dest[i] = stringOrTime(r.Stmt.ColumnRawText(i)) case sqlite3.NULL: - if buf, ok := dest[i].([]byte); ok { - dest[i] = buf[0:0] - } else { - dest[i] = nil - } + dest[i] = nil default: panic(util.AssertErr()) } diff --git a/embed/README.md b/embed/README.md index e5a64c4..d55a7b9 100644 --- a/embed/README.md +++ b/embed/README.md @@ -1,6 +1,6 @@ # Embeddable WASM build of SQLite -This folder includes an embeddable WASM build of SQLite 3.43.2 for use with +This folder includes an embeddable WASM build of SQLite 3.44.0 for use with [`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3). The following optional features are compiled in: diff --git a/embed/sqlite3.wasm b/embed/sqlite3.wasm index e2633ef..6901953 100755 Binary files a/embed/sqlite3.wasm and b/embed/sqlite3.wasm differ diff --git a/sqlite3/date.patch b/sqlite3/date.patch deleted file mode 100644 index 4b29c69..0000000 --- a/sqlite3/date.patch +++ /dev/null @@ -1,57 +0,0 @@ ---- sqlite3.c.orig -+++ sqlite3.c -@@ -340,6 +340,7 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ - p->iJD = sqlite3StmtCurrentTime(context); - if( p->iJD>0 ){ - p->validJD = 1; -+ p->tzSet = 1; - return 0; - }else{ - return 1; -@@ -355,6 +356,7 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ - static void setRawDateNumber(DateTime *p, double r){ - p->s = r; - p->rawS = 1; -+ p->tzSet = 1; - if( r>=0.0 && r<5373484.5 ){ - p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); - p->validJD = 1; -@@ -572,6 +574,7 @@ static int toLocaltime( - time_t t; - struct tm sLocal; - int iYearDiff; -+ DateTime x; - - /* Initialize the contents of sLocal to avoid a compiler warning. */ - memset(&sLocal, 0, sizeof(sLocal)); -@@ -585,7 +588,7 @@ static int toLocaltime( - ** SQLite attempts to map the year into an equivalent year within this - ** range, do the calculation, then map the year back. - */ -- DateTime x = *p; -+ x = *p; - computeYMD_HMS(&x); - iYearDiff = (2000 + x.Y%4) - x.Y; - x.Y += iYearDiff; -@@ -610,8 +613,13 @@ static int toLocaltime( - p->validHMS = 1; - p->validJD = 0; - p->rawS = 0; -+ p->tzSet = 0; - p->validTZ = 0; - p->isError = 0; -+ x = *p; -+ computeJD(&x); -+ p->tz = (x.iJD-p->iJD)/60000; -+ if( abs(p->tz)>= 900 ) p->tz = 0; - return SQLITE_OK; - } - #endif /* SQLITE_OMIT_LOCALTIME */ -@@ -781,6 +789,7 @@ static int parseModifier( - p->validJD = 1; - p->tzSet = 1; - } -+ p->tz = 0; - rc = SQLITE_OK; - } - #endif diff --git a/sqlite3/download.sh b/sqlite3/download.sh index 020407b..0e8bb91 100755 --- a/sqlite3/download.sh +++ b/sqlite3/download.sh @@ -3,7 +3,7 @@ set -euo pipefail cd -P -- "$(dirname -- "$0")" -curl -#OL "https://sqlite.org/2023/sqlite-amalgamation-3430200.zip" +curl -#OL "https://sqlite.org/2023/sqlite-amalgamation-3440000.zip" unzip -d . sqlite-amalgamation-*.zip mv sqlite-amalgamation-*/sqlite3* . rm -rf sqlite-amalgamation-* @@ -12,24 +12,24 @@ cat *.patch | patch --posix mkdir -p ext/ cd ext/ -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/ext/misc/decimal.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/ext/misc/uint.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/ext/misc/uuid.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/ext/misc/base64.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/ext/misc/regexp.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/ext/misc/series.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/ext/misc/anycollseq.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/decimal.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/uint.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/uuid.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/base64.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/regexp.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/series.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/anycollseq.c" cd ~- cd ../vfs/tests/mptest/testdata/ -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/mptest/mptest.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/mptest/config01.test" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/mptest/config02.test" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/mptest/crash01.test" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/mptest/crash02.subtest" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/mptest/multiwrite01.test" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/mptest.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/config01.test" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/config02.test" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/crash01.test" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/crash02.subtest" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/multiwrite01.test" cd ~- cd ../vfs/tests/speedtest1/testdata/ -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.43.2/test/speedtest1.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/test/speedtest1.c" cd ~- \ No newline at end of file diff --git a/sqlite3/isoweek.patch b/sqlite3/isoweek.patch new file mode 100644 index 0000000..2aade5e --- /dev/null +++ b/sqlite3/isoweek.patch @@ -0,0 +1,34 @@ +# ISO week date specifiers. +# https://sqlite.org/forum/forumpost/73d99e4497e8e6a7 +--- sqlite3.c.orig ++++ sqlite3.c +@@ -1373,6 +1373,29 @@ static void strftimeFunc( + sqlite3_str_appendchar(&sRes, 1, c); + break; + } ++ case 'V': /* Fall thru */ ++ case 'G': { ++ DateTime y = x; ++ computeJD(&y); ++ y.validYMD = 0; ++ /* Adjust date to Thursday this week: ++ The number in parentheses is 0 for Monday, 3 for Thursday */ ++ y.iJD += (3 - (((y.iJD+43200000)/86400000) % 7))*86400000; ++ computeYMD(&y); ++ if( cf=='G' ){ ++ sqlite3_str_appendf(&sRes,"%04d",y.Y); ++ }else{ ++ int nDay; /* Number of days since 1st day of year */ ++ i64 tJD = y.iJD; ++ y.validJD = 0; ++ y.M = 1; ++ y.D = 1; ++ computeJD(&y); ++ nDay = (int)((tJD-y.iJD+43200000)/86400000); ++ sqlite3_str_appendf(&sRes,"%02d",nDay/7+1); ++ } ++ break; ++ } + case 'Y': { + sqlite3_str_appendf(&sRes,"%04d",x.Y); + break; diff --git a/sqlite3/time.c b/sqlite3/time.c index 890c4aa..44e40ca 100644 --- a/sqlite3/time.c +++ b/sqlite3/time.c @@ -28,7 +28,7 @@ static int time_collation(void *pArg, int nKey1, const void *pKey1, int nKey2, } static void json_time_func(sqlite3_context *context, int argc, - sqlite3_value **argv) { + sqlite3_value **argv) { DateTime x; if (isDate(context, argc, argv, &x)) return; if (x.tzSet && x.tz) { diff --git a/sqlite3/timezone.patch b/sqlite3/timezone.patch new file mode 100644 index 0000000..9063c90 --- /dev/null +++ b/sqlite3/timezone.patch @@ -0,0 +1,45 @@ +# Set UTC timezone, compute local offset. +--- sqlite3.c.orig ++++ sqlite3.c +@@ -340,6 +340,7 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ + p->iJD = sqlite3StmtCurrentTime(context); + if( p->iJD>0 ){ + p->validJD = 1; ++ p->tzSet = 1; + return 0; + }else{ + return 1; +@@ -355,6 +356,7 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ + static void setRawDateNumber(DateTime *p, double r){ + p->s = r; + p->rawS = 1; ++ p->tzSet = 1; + if( r>=0.0 && r<5373484.5 ){ + p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); + p->validJD = 1; +@@ -731,7 +733,16 @@ static int parseModifier( + ** show local time. + */ + if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){ +- rc = toLocaltime(p, pCtx); ++ if( p->tzSet!=0 || p->tz==0 ) { ++ rc = toLocaltime(p, pCtx); ++ i64 iOrigJD = p->iJD; ++ p->tzSet = 0; ++ computeJD(p); ++ p->tz = (p->iJD-iOrigJD)/60000; ++ if( abs(p->tz)>= 900 ) p->tz = 0; ++ } else { ++ rc = 0; ++ } + } + break; + } +@@ -781,6 +792,7 @@ static int parseModifier( + p->validJD = 1; + p->tzSet = 1; + } ++ p->tz = 0; + rc = SQLITE_OK; + } + #endif diff --git a/tests/time_test.go b/tests/time_test.go index 0b398df..27b750c 100644 --- a/tests/time_test.go +++ b/tests/time_test.go @@ -207,52 +207,6 @@ func TestDB_timeCollation(t *testing.T) { } } -func TestDB_jsonTime(t *testing.T) { - t.Parallel() - - reference := time.Date(2013, 10, 7, 4, 23, 19, 120_000_000, time.FixedZone("", -4*3600)) - - db, err := driver.Open(":memory:", nil) - if err != nil { - t.Fatal(err) - } - defer db.Close() - - _, err = db.Exec(`CREATE TABLE IF NOT EXISTS times (tstamp)`) - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec(`INSERT INTO times VALUES (?), (?), (?)`, - reference, - sqlite3.TimeFormatUnixFrac.Encode(reference), - sqlite3.TimeFormatJulianDay.Encode(reference)) - if err != nil { - t.Fatal(err) - } - - rows, err := db.Query(` - SELECT - json_time(tstamp, 'auto', 'subsec'), - json_time(tstamp, 'auto') - FROM times`) - if err != nil { - t.Fatal(err) - } - defer rows.Close() - - for rows.Next() { - var t0, t1 time.Time - rows.Scan(&t0, &t1) - if want := reference; !t0.Equal(want) { - t.Errorf("got %v, want %v", t0, want) - } - if want := reference.Truncate(time.Second); !t1.Equal(want) { - t.Errorf("got %v, want %v", t1, want) - } - } -} - func TestDB_isoWeek(t *testing.T) { t.Parallel() diff --git a/vfs/tests/mptest/testdata/mptest.wasm.bz2 b/vfs/tests/mptest/testdata/mptest.wasm.bz2 index b0061cb..0d973a6 100644 --- a/vfs/tests/mptest/testdata/mptest.wasm.bz2 +++ b/vfs/tests/mptest/testdata/mptest.wasm.bz2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25ccdde5ddab41213abda7ecf6dd95c2966acaef5a645f9f35c170a84697556e -size 509445 +oid sha256:74294bf19d213056ef5ffb7a980c3a7de5d029d0621ded53394d3055dfc4f604 +size 513604 diff --git a/vfs/tests/speedtest1/testdata/speedtest1.wasm.bz2 b/vfs/tests/speedtest1/testdata/speedtest1.wasm.bz2 index a776a2e..33ab49a 100644 --- a/vfs/tests/speedtest1/testdata/speedtest1.wasm.bz2 +++ b/vfs/tests/speedtest1/testdata/speedtest1.wasm.bz2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4306d2a8c460f24955bb944923837800c887ee4080d725777392b834b7567bab -size 524003 +oid sha256:966754393264cc43eb931ece22941d0d607e7e776e26c26b548209d2264d01a1 +size 527530