summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBohwaZ <bohwaz@github.com>2019-06-17 23:28:30 +0200
committerChristoph M. Becker <cmbecker69@gmx.de>2019-06-17 23:34:51 +0200
commitce22ccc77b1cfe3d922ebe485069afc61d784916 (patch)
tree59f884de2a58c9f651052dc6ade3ff796d3f9aa7
parentd924b426c90a16b954b9f17e239a105e7697a1fc (diff)
downloadphp-git-ce22ccc77b1cfe3d922ebe485069afc61d784916.tar.gz
Implement SQLite3 backup API
-rw-r--r--NEWS3
-rw-r--r--UPGRADING2
-rw-r--r--ext/sqlite3/sqlite3.c68
-rw-r--r--ext/sqlite3/tests/sqlite3_38_backup.phpt58
4 files changed, 131 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index 2e6ce32e97..4e8b6f234f 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,9 @@ PHP NEWS
. Fixed bug #78106 (Path resolution fails if opcache disabled during request).
(Nikita)
+- SQLite3:
+ . Implement FR ##70950 (Make SQLite3 Online Backup API available). (BohwaZ)
+
13 Jun 2019, PHP 7.4.0alpha1
- Core:
diff --git a/UPGRADING b/UPGRADING
index 1eaf8fc3d4..4acfa3e775 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -370,6 +370,8 @@ PHP 7.4 UPGRADE NOTES
. Added SQLite3Stmt::getSQL() to retrieve the SQL of the statement. If TRUE is
passed as parameter, query parameters will be replaced in the return value
by their currently bound value, if libsqlite ≥ 3.14 is used.
+ . Added SQLite3::backup() to create database backups via the SQLite3 online
+ backup API.
- Standard
. bool sapi_windows_set_ctrl_handler(callable handler, [, bool add = true]) -
diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c
index 81ce1a0f00..61b032e900 100644
--- a/ext/sqlite3/sqlite3.c
+++ b/ext/sqlite3/sqlite3.c
@@ -1294,6 +1294,63 @@ PHP_METHOD(sqlite3, enableExceptions)
}
/* }}} */
+#if SQLITE_VERSION_NUMBER >= 3006011
+/* {{{ proto bool SQLite3::backup(SQLite3 destination_db[, string source_dbname = "main"[, string destination_dbname = "main"]])
+ Backups the current database to another one. */
+PHP_METHOD(sqlite3, backup)
+{
+ php_sqlite3_db_object *source_obj;
+ php_sqlite3_db_object *destination_obj;
+ char *source_dbname = "main", *destination_dbname = "main";
+ size_t source_dbname_length, destination_dbname_length;
+ zval *source_zval = ZEND_THIS;
+ zval *destination_zval;
+ sqlite3_backup *dbBackup;
+ int rc; // Return code
+
+ source_obj = Z_SQLITE3_DB_P(source_zval);
+ SQLITE3_CHECK_INITIALIZED(source_obj, source_obj->initialised, SQLite3)
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|ss", &destination_zval, php_sqlite3_sc_entry, &source_dbname, &source_dbname_length, &destination_dbname, &destination_dbname_length) == FAILURE) {
+ return;
+ }
+
+ destination_obj = Z_SQLITE3_DB_P(destination_zval);
+
+ SQLITE3_CHECK_INITIALIZED(destination_obj, destination_obj->initialised, SQLite3)
+
+ dbBackup = sqlite3_backup_init(destination_obj->db, destination_dbname, source_obj->db, source_dbname);
+
+ if (dbBackup) {
+ do {
+ rc = sqlite3_backup_step(dbBackup, -1);
+ } while (rc == SQLITE_OK);
+
+ /* Release resources allocated by backup_init(). */
+ rc = sqlite3_backup_finish(dbBackup);
+ }
+ else {
+ rc = sqlite3_errcode(source_obj->db);
+ }
+
+ if (rc != SQLITE_OK) {
+ if (rc == SQLITE_BUSY) {
+ php_sqlite3_error(source_obj, "Backup failed: source database is busy");
+ }
+ else if (rc == SQLITE_LOCKED) {
+ php_sqlite3_error(source_obj, "Backup failed: source database is locked");
+ }
+ else {
+ php_sqlite3_error(source_obj, "Backup failed: %d, %s", rc, sqlite3_errmsg(source_obj->db));
+ }
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+#endif
+
/* {{{ proto int SQLite3Stmt::paramCount()
Returns the number of parameters within the prepared statement. */
PHP_METHOD(sqlite3stmt, paramCount)
@@ -2058,6 +2115,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3_enableexceptions, 0, 0, 0)
ZEND_ARG_INFO(0, enableExceptions)
ZEND_END_ARG_INFO()
+#if SQLITE_VERSION_NUMBER >= 3006011
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3_backup, 0, 0, 1)
+ ZEND_ARG_INFO(0, destination_db)
+ ZEND_ARG_INFO(0, source_dbname)
+ ZEND_ARG_INFO(0, destination_dbname)
+ZEND_END_ARG_INFO()
+#endif
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3stmt_bindparam, 0, 0, 2)
ZEND_ARG_INFO(0, param_number)
ZEND_ARG_INFO(1, param)
@@ -2117,6 +2182,9 @@ static const zend_function_entry php_sqlite3_class_methods[] = {
PHP_ME(sqlite3, createCollation, arginfo_sqlite3_createcollation, ZEND_ACC_PUBLIC)
PHP_ME(sqlite3, openBlob, arginfo_sqlite3_openblob, ZEND_ACC_PUBLIC)
PHP_ME(sqlite3, enableExceptions, arginfo_sqlite3_enableexceptions, ZEND_ACC_PUBLIC)
+#if SQLITE_VERSION_NUMBER >= 3006011
+ PHP_ME(sqlite3, backup, arginfo_sqlite3_backup, ZEND_ACC_PUBLIC)
+#endif
/* Aliases */
PHP_MALIAS(sqlite3, __construct, open, arginfo_sqlite3_open, ZEND_ACC_PUBLIC)
PHP_FE_END
diff --git a/ext/sqlite3/tests/sqlite3_38_backup.phpt b/ext/sqlite3/tests/sqlite3_38_backup.phpt
new file mode 100644
index 0000000000..8ff5189fdc
--- /dev/null
+++ b/ext/sqlite3/tests/sqlite3_38_backup.phpt
@@ -0,0 +1,58 @@
+--TEST--
+SQLite3::backup test
+--SKIPIF--
+<?php require_once(__DIR__ . '/skipif.inc'); ?>
+--FILE--
+<?php
+
+require_once(__DIR__ . '/new_db.inc');
+
+echo "Creating table\n";
+$db->exec('CREATE TABLE test (a, b);');
+$db->exec('INSERT INTO test VALUES (42, \'php\');');
+
+echo "Checking if table has been created\n";
+var_dump($db->querySingle('SELECT COUNT(*) FROM sqlite_master;'));
+
+$db2 = new SQLite3(':memory:');
+
+echo "Backup to DB2\n";
+var_dump($db->backup($db2));
+
+echo "Checking if table has been copied\n";
+var_dump($db2->querySingle('SELECT COUNT(*) FROM sqlite_master;'));
+
+echo "Checking backup contents\n";
+var_dump($db2->querySingle('SELECT a FROM test;'));
+var_dump($db2->querySingle('SELECT b FROM test;'));
+
+echo "Resetting DB2\n";
+
+$db2->close();
+$db2 = new SQLite3(':memory:');
+
+echo "Locking DB1\n";
+var_dump($db->exec('BEGIN EXCLUSIVE;'));
+
+echo "Backup to DB2 (should fail)\n";
+var_dump($db->backup($db2));
+
+?>
+--EXPECTF--
+Creating table
+Checking if table has been created
+int(1)
+Backup to DB2
+bool(true)
+Checking if table has been copied
+int(1)
+Checking backup contents
+int(42)
+string(3) "php"
+Resetting DB2
+Locking DB1
+bool(true)
+Backup to DB2 (should fail)
+
+Warning: SQLite3::backup(): Backup failed: source database is busy in %s on line %d
+bool(false) \ No newline at end of file