From: Matt Joiner <anacrolix@gmail.com>
Date: Thu, 29 Oct 2020 23:47:50 +0000 (+1100)
Subject: sqlite storage: Force data to be used as a blob
X-Git-Tag: v1.19.0~53
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=fc039262d9f19014fd3a788718011ed6a32f804d;p=btrtrc.git

sqlite storage: Force data to be used as a blob

There's a bug in crawshaw.io/sqlite, and some forks where inserting []byte results in a text type instead of blob. To ensure things work correctly, we coerce data to blob wherever we can. See https://github.com/crawshaw/sqlite/issues/94 and the fork that fixes it.
---

diff --git a/storage/sqlite/sqlite-storage.go b/storage/sqlite/sqlite-storage.go
index 00c56362..fc419c29 100644
--- a/storage/sqlite/sqlite-storage.go
+++ b/storage/sqlite/sqlite-storage.go
@@ -60,10 +60,10 @@ with recursive excess(
 	blob_rowid,
 	data_length
 ) as (
-	select * from (select (select sum(length(data)) from blob) as usage_with, last_used, rowid, length(data) from blob order by last_used, rowid limit 1)
+	select * from (select (select sum(length(cast(data as blob))) from blob) as usage_with, last_used, rowid, length(cast(data as blob)) from blob order by last_used, rowid limit 1)
 		where usage_with >= (select value from setting where name='capacity')
 	union all
-	select usage_with-data_length, blob.last_used, blob.rowid, length(data) from excess join blob
+	select usage_with-data_length, blob.last_used, blob.rowid, length(cast(data as blob)) from excess join blob
 		on blob.rowid=(select rowid from blob where (last_used, rowid) > (excess.last_used, blob_rowid))
 	where usage_with >= (select value from setting where name='capacity')
 ) select * from excess;
@@ -262,7 +262,10 @@ func (i instance) Put(reader io.Reader) (err error) {
 	}
 	i.withConn(func(conn conn) {
 		for range iter.N(10) {
-			err = sqlitex.Exec(conn, "insert or replace into blob(name, data) values(?, ?)", nil, i.location, buf.Bytes())
+			err = sqlitex.Exec(conn,
+				"insert or replace into blob(name, data) values(?, cast(? as blob))",
+				nil,
+				i.location, buf.Bytes())
 			if err, ok := err.(sqlite.Error); ok && err.Code == sqlite.SQLITE_BUSY {
 				log.Print("sqlite busy")
 				time.Sleep(time.Second)
@@ -336,7 +339,7 @@ func (i instance) ReadAt(p []byte, off int64) (n int, err error) {
 			gotRow := false
 			err = sqlitex.Exec(
 				conn,
-				"select substr(data, ?, ?) from blob where name=?",
+				"select substr(cast(data as blob), ?, ?) from blob where name=?",
 				func(stmt *sqlite.Stmt) error {
 					if gotRow {
 						panic("found multiple matching blobs")