MODULE SQLiteBackup; (* Online backup API: backup_init/step/finish/remaining/pagecount. *) FROM SYSTEM IMPORT ADDRESS; FROM SQLite IMPORT SQLiteOk, SQLiteRow, SQLiteDone, sqlite3_open, sqlite3_close, sqlite3_exec, sqlite3_prepare_v2, sqlite3_step, sqlite3_column_int, sqlite3_finalize, sqlite3_backup_init, sqlite3_backup_step, sqlite3_backup_finish, sqlite3_backup_remaining, sqlite3_backup_pagecount, sqlite3_free; VAR ExitCode : INTEGER; src, dst, dst2, bk : ADDRESS; rc, pages : INTEGER; ok : BOOLEAN; PROCEDURE ExecSQL (h : ADDRESS; sql : ARRAY OF CHAR) : BOOLEAN; VAR errmsg : ADDRESS; good : BOOLEAN; BEGIN errmsg := NIL; good := sqlite3_exec(h, sql, NIL, NIL, errmsg) = SQLiteOk; IF errmsg # NIL THEN sqlite3_free(errmsg) END; RETURN good END ExecSQL; PROCEDURE CountRows (h : ADDRESS; want : INTEGER) : BOOLEAN; VAR s : ADDRESS; code, got : INTEGER; good : BOOLEAN; BEGIN s := NIL; got := -1; good := FALSE; code := sqlite3_prepare_v2(h, "SELECT count(*) FROM t;", -1, s, NIL); IF (code = SQLiteOk) AND (s # NIL) THEN IF sqlite3_step(s) = SQLiteRow THEN got := sqlite3_column_int(s, 0); IF sqlite3_step(s) = SQLiteDone THEN good := TRUE END END; IF sqlite3_finalize(s) # SQLiteOk THEN good := FALSE END END; RETURN good AND (got = want) END CountRows; BEGIN ExitCode := 1; src := NIL; dst := NIL; dst2 := NIL; bk := NIL; ok := FALSE; IF (sqlite3_open(":memory:", src) = SQLiteOk) AND (src # NIL) AND (sqlite3_open(":memory:", dst) = SQLiteOk) AND (dst # NIL) AND (sqlite3_open(":memory:", dst2) = SQLiteOk) AND (dst2 # NIL) THEN ok := ExecSQL(src, "CREATE TABLE t(x INTEGER);") AND ExecSQL(src, "INSERT INTO t VALUES(1);") AND ExecSQL(src, "INSERT INTO t VALUES(2);") END; (* Full backup into another in-memory database. *) IF ok THEN bk := sqlite3_backup_init(dst, "main", src, "main"); ok := bk # NIL; IF ok THEN ok := sqlite3_backup_step(bk, -1) = SQLiteDone END; IF ok THEN pages := sqlite3_backup_pagecount(bk); ok := (pages > 0) AND (sqlite3_backup_remaining(bk) = 0) END; IF sqlite3_backup_finish(bk) # SQLiteOk THEN ok := FALSE END; bk := NIL END; IF ok THEN ok := CountRows(dst, 2) END; (* Incremental backup, one page at a time. *) IF ok THEN bk := sqlite3_backup_init(dst2, "main", src, "main"); ok := bk # NIL; IF ok THEN rc := sqlite3_backup_step(bk, 1); WHILE (rc = SQLiteOk) DO rc := sqlite3_backup_step(bk, 1) END; ok := (rc = SQLiteDone) AND (sqlite3_backup_remaining(bk) = 0); IF sqlite3_backup_finish(bk) # SQLiteOk THEN ok := FALSE END; bk := NIL END END; IF ok THEN ok := CountRows(dst2, 2) END; IF bk # NIL THEN IF sqlite3_backup_finish(bk) # SQLiteOk THEN ok := FALSE END END; IF src # NIL THEN IF sqlite3_close(src) # SQLiteOk THEN ok := FALSE END END; IF dst # NIL THEN IF sqlite3_close(dst) # SQLiteOk THEN ok := FALSE END END; IF dst2 # NIL THEN IF sqlite3_close(dst2) # SQLiteOk THEN ok := FALSE END END; IF ok THEN ExitCode := 42 END END SQLiteBackup.