diff --git a/third_party/sqlite3/sqlite3.mk b/third_party/sqlite3/sqlite3.mk index e2d6b4925..621393972 100644 --- a/third_party/sqlite3/sqlite3.mk +++ b/third_party/sqlite3/sqlite3.mk @@ -129,6 +129,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): \ OVERRIDE_CFLAGS += \ diff --git a/tool/net/demo/.init.lua b/tool/net/demo/.init.lua index 304d0f89a..19bf04366 100644 --- a/tool/net/demo/.init.lua +++ b/tool/net/demo/.init.lua @@ -9,16 +9,35 @@ HidePath('/usr/share/ssl/') -- LaunchBrowser('/tool/net/demo/index.html') -- sql database (see sql.lua) -db = sqlite3.open_memory() -db:exec[[ - CREATE TABLE test ( - id INTEGER PRIMARY KEY, - content TEXT - ); - INSERT INTO test (content) VALUES ('Hello World'); - INSERT INTO test (content) VALUES ('Hello Lua'); - INSERT INTO test (content) VALUES ('Hello Sqlite3'); -]] +function StoreSqlite(database, path) + local buffer = database:serialize() + return StoreAsset(path, buffer) +end + +function LoadSqlite(path) + local database = sqlite3.open_memory() + local buffer = LoadAsset(path) + database:deserialize(buffer) + return database +end + +database = "database.sqlite3" +-- Check if there is already a database +if GetAssetSize(database) ~= nil then + db = LoadSqlite(database) + db:exec[[ + INSERT INTO test (content) VALUES ('World'); + ]] +else + db = sqlite3.open_memory() + db:exec[[ + CREATE TABLE test ( + id INTEGER PRIMARY KEY, + content TEXT + ); + INSERT INTO test (content) VALUES ('Hello'); + ]] +end -- this intercepts all requests if it's defined function OnHttpRequest() @@ -35,6 +54,11 @@ function OnHttpRequest() SetHeader('Server', 'redbean!') end +function OnServerStop() + -- make sure we store the database on exit + StoreSqlite(db, database) +end + function Adder(x, y) return x + y end diff --git a/tool/net/lsqlite3.c b/tool/net/lsqlite3.c index 0510e736f..610b34293 100644 --- a/tool/net/lsqlite3.c +++ b/tool/net/lsqlite3.c @@ -1683,6 +1683,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, 5, 0); + free(buffer); + return 0; +} + /* ** ======================================================= ** General library functions @@ -1857,6 +1890,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 },