Skip to content

Commit 44aa786

Browse files
committed
Add Pdo\Sqlite::backup()
1 parent 2fd3433 commit 44aa786

File tree

5 files changed

+148
-1
lines changed

5 files changed

+148
-1
lines changed

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ PHP 8.6 UPGRADE NOTES
132132
6. New Functions
133133
========================================
134134

135+
- Pdo_Sqlite:
136+
. Pdo\Sqlite::backup() analogous to Sqlite3::backup().
137+
135138
- Reflection:
136139
. ReflectionConstant::inNamespace()
137140
. Added ReflectionProperty::isReadable() and ReflectionProperty::isWritable().

ext/pdo_sqlite/pdo_sqlite.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,57 @@ PHP_METHOD(Pdo_Sqlite, setAuthorizer)
362362
RETURN_THROWS();
363363
}
364364

365+
PHP_METHOD(Pdo_Sqlite, backup)
366+
{
367+
zval *destination_object;
368+
char *source_dbname = "main", *destination_dbname = "main";
369+
size_t source_dbname_len, destination_dbname_len;
370+
int rc;
371+
372+
ZEND_PARSE_PARAMETERS_START(1, 3)
373+
Z_PARAM_OBJECT_OF_CLASS(destination_object, pdosqlite_ce)
374+
Z_PARAM_OPTIONAL
375+
Z_PARAM_PATH(source_dbname, source_dbname_len)
376+
Z_PARAM_PATH(destination_dbname, destination_dbname_len)
377+
ZEND_PARSE_PARAMETERS_END();
378+
379+
pdo_dbh_t *dbh = Z_PDO_DBH_P(destination_object);
380+
PDO_CONSTRUCT_CHECK;
381+
pdo_sqlite_db_handle *destination_db_handle = dbh->driver_data;
382+
dbh = Z_PDO_DBH_P(ZEND_THIS);
383+
PDO_CONSTRUCT_CHECK;
384+
pdo_sqlite_db_handle *source_db_handle = dbh->driver_data;
385+
386+
sqlite3_backup *dbBackup = sqlite3_backup_init(destination_db_handle->db, destination_dbname, source_db_handle->db, source_dbname);
387+
388+
if (dbBackup) {
389+
do {
390+
rc = sqlite3_backup_step(dbBackup, -1);
391+
} while (rc == SQLITE_OK);
392+
393+
/* Release resources allocated by sqlite3_backup_init(). */
394+
rc = sqlite3_backup_finish(dbBackup);
395+
} else {
396+
rc = sqlite3_errcode(source_db_handle->db);
397+
}
398+
399+
if (rc != SQLITE_OK) {
400+
if (rc == SQLITE_BUSY) {
401+
pdo_raise_impl_error(dbh, NULL, "HY000", "Backup failed: source database is busy");
402+
} else if (rc == SQLITE_LOCKED) {
403+
pdo_raise_impl_error(dbh, NULL, "HY000", "Backup failed: source database is locked");
404+
} else {
405+
char *message;
406+
spprintf(&message, 0, "Backup failed: %s", sqlite3_errmsg(source_db_handle->db));
407+
pdo_raise_impl_error(dbh, NULL, "HY000", message);
408+
efree(message);
409+
}
410+
RETURN_FALSE;
411+
}
412+
413+
RETURN_TRUE;
414+
}
415+
365416
static int php_sqlite_collation_callback(void *context, int string1_len, const void *string1,
366417
int string2_len, const void *string2)
367418
{

ext/pdo_sqlite/pdo_sqlite.stub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,6 @@ public function openBlob(
9494
) {}
9595

9696
public function setAuthorizer(?callable $callback): void {}
97+
98+
public function backup(Sqlite $destination, string $sourceDatabase = "main", string $destinationDatabase = "main"): bool {}
9799
}

ext/pdo_sqlite/pdo_sqlite_arginfo.h

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
--TEST--
2+
Pdo\Sqlite::backup test
3+
--EXTENSIONS--
4+
pdo
5+
pdo_sqlite
6+
--FILE--
7+
<?php
8+
9+
$db = Pdo::connect('sqlite::memory:');
10+
11+
$db->exec('CREATE TABLE test (a, b);');
12+
$db->exec('INSERT INTO test VALUES (42, \'php\');');
13+
14+
$db2 = Pdo::connect('sqlite::memory:');
15+
16+
echo "Backup to DB2\n";
17+
var_dump($db->backup($db2));
18+
19+
echo "Checking if table has been copied\n";
20+
var_dump($db2->query('SELECT COUNT(*) FROM sqlite_master;')->fetchAll());
21+
22+
echo "Checking backup contents\n";
23+
var_dump($db2->query('SELECT a FROM test;')->fetchAll());
24+
var_dump($db2->query('SELECT b FROM test;')->fetchAll());
25+
26+
echo "Resetting DB2\n";
27+
28+
unset($db2);
29+
$db2 = Pdo::connect('sqlite::memory:');
30+
31+
echo "Locking DB1\n";
32+
var_dump($db->exec('BEGIN EXCLUSIVE;'));
33+
34+
echo "Backup to DB2 (should fail)\n";
35+
try {
36+
$db->backup($db2);
37+
} catch (PDOException $e) {
38+
echo $e->getMessage(), "\n";
39+
}
40+
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
41+
var_dump($db->backup($db2));
42+
43+
?>
44+
--EXPECTF--
45+
Backup to DB2
46+
bool(true)
47+
Checking if table has been copied
48+
array(1) {
49+
[0]=>
50+
array(2) {
51+
["COUNT(*)"]=>
52+
int(1)
53+
[0]=>
54+
int(1)
55+
}
56+
}
57+
Checking backup contents
58+
array(1) {
59+
[0]=>
60+
array(2) {
61+
["a"]=>
62+
int(42)
63+
[0]=>
64+
int(42)
65+
}
66+
}
67+
array(1) {
68+
[0]=>
69+
array(2) {
70+
["b"]=>
71+
string(3) "php"
72+
[0]=>
73+
string(3) "php"
74+
}
75+
}
76+
Resetting DB2
77+
Locking DB1
78+
int(1)
79+
Backup to DB2 (should fail)
80+
SQLSTATE[HY000]: General error: Backup failed: source database is busy
81+
82+
Warning: Pdo\Sqlite::backup(): SQLSTATE[HY000]: General error: Backup failed: source database is busy in %s on line %d
83+
bool(false)

0 commit comments

Comments
 (0)