Proof of concept of sqlite serialization (#436)

* Proof of concept of sqlite serialization

This is a minimal proof of concept in order to show that it is easily possible to store the sqlite database within the zip file itself not requiring creating an external file first. Changes include compiling the sqlite library with the serialization flag, adding serialize/deserialize to the lua sqlite library and demonstrating the work via the redbean demo.

* Change demo for sqlite serialization

As explained in https://github.com/jart/cosmopolitan/pull/436#issuecomment-1164706893 the original use case is not possible with sqlite serialization, as an in-memory database cannot be shared across multiple processes. Thereby, this use case simply creates a backup of the in-memory database created in '.init.lua' and loads it to do a query.

* Fix sqlite3_deserialize parameters

The call to the sqlite3 library for the deserilization wasn't fully correct. This should fix the size parameters.
This commit is contained in:
Daniel Oltmanns 2022-10-05 16:09:53 +02:00 committed by GitHub
parent edb8fef06c
commit afc07b9339
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 0 deletions

View file

@ -125,6 +125,7 @@ THIRD_PARTY_SQLITE3_FLAGS = \
-DSQLITE_HAVE_C99_MATH_FUNCS \
-DSQLITE_ENABLE_MATH_FUNCTIONS \
-DSQLITE_ENABLE_JSON1 \
-DSQLITE_ENABLE_DESERIALIZE \
$(THIRD_PARTY_SQLITE3_A_OBJS): private \
OVERRIDE_CFLAGS += \

View file

@ -0,0 +1,13 @@
if GetAssetSize("backup.sqlite3") == nil then
Write("no backup exists. call <a href='sql-backupstore.lua'>sql-backupstore.lua</a> first.")
return
end
backup = sqlite3.open_memory()
buffer = LoadAsset("backup.sqlite3")
backup:deserialize(buffer)
-- See .init.lua for CREATE TABLE setup.
for row in backup:nrows("SELECT * FROM test") do
Write(row.id.." "..row.content.."<br>")
end

View file

@ -0,0 +1,4 @@
buffer = db:serialize()
StoreAsset("backup.sqlite3", buffer)
Write("backup created. size: "..GetAssetSize("backup.sqlite3"))

View file

@ -1695,6 +1695,39 @@ static int db_gc(lua_State *L) {
return 0;
}
static int db_serialize(lua_State *L) {
sdb *db = lsqlite_getdb(L, 1);
sqlite_int64 size = 0;
if (db->db == NULL) /* ignore closed databases */
return 0;
char *buffer = (char *)sqlite3_serialize(db->db, "main", &size, 0);
if (buffer == NULL) /* ignore failed database serialization */
return 0;
lua_pushlstring(L, buffer, size);
free(buffer);
return 1;
}
static int db_deserialize(lua_State *L) {
sdb *db = lsqlite_getdb(L, 1);
size_t size = 0;
if (db->db == NULL) /* ignore closed databases */
return 0;
const char *buffer = luaL_checklstring(L, 2, &size);
if (buffer == NULL || size == 0) /* ignore empty database content */
return 0;
sqlite3_deserialize(db->db, "main", buffer, size, size, 0);
free(buffer);
return 0;
}
/*
** =======================================================
** General library functions
@ -1864,6 +1897,9 @@ static const luaL_Reg dblib[] = {
{"close", db_close },
{"close_vm", db_close_vm },
{"serialize", db_serialize },
{"deserialize", db_deserialize },
{"__tostring", db_tostring },
{"__gc", db_gc },

View file

@ -138,6 +138,8 @@ o/$(MODE)/tool/net/.init.lua.zip.o \
o/$(MODE)/tool/net/demo/.init.lua.zip.o \
o/$(MODE)/tool/net/demo/.reload.lua.zip.o \
o/$(MODE)/tool/net/demo/sql.lua.zip.o \
o/$(MODE)/tool/net/demo/sql-backup.lua.zip.o \
o/$(MODE)/tool/net/demo/sql-backupstore.lua.zip.o \
o/$(MODE)/tool/net/demo/unix-unix.lua.zip.o \
o/$(MODE)/tool/net/demo/unix-rawsocket.lua.zip.o \
o/$(MODE)/tool/net/demo/unix-subprocess.lua.zip.o \
@ -187,6 +189,8 @@ o/$(MODE)/tool/net/redbean-demo.com.dbg: \
$(TOOL_NET_REDBEAN_LUA_MODULES) \
o/$(MODE)/tool/net/net.pkg \
o/$(MODE)/tool/net/demo/sql.lua.zip.o \
o/$(MODE)/tool/net/demo/sql-backup.lua.zip.o \
o/$(MODE)/tool/net/demo/sql-backupstore.lua.zip.o \
o/$(MODE)/tool/net/demo/unix-unix.lua.zip.o \
o/$(MODE)/tool/net/demo/unix-rawsocket.lua.zip.o \
o/$(MODE)/tool/net/demo/unix-subprocess.lua.zip.o \