Skip to content

Commit e511f15

Browse files
committed
Merge branch 'pull-request/2528'
* pull-request/2528: Change flags to use SQLITE3_OPEN_READ* constants instead of a fake-boolean, add tests on errors Implement writing to BLOBs in SQLite3
2 parents 9c2a1f5 + 626ee74 commit e511f15

File tree

3 files changed

+72
-8
lines changed

3 files changed

+72
-8
lines changed

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ PHP 7.2 UPGRADE NOTES
111111
subpatterns and empty matches by reporting NULL and "" (empty string),
112112
respectively.
113113

114+
- SQLite3:
115+
. Implemented writing to BLOBs.
116+
114117
- Standard:
115118
. Simplified password hashing API updated to support Argon2i hashes when PHP is compiled with libargon2
116119
(https://wiki.php.net/rfc/argon2_password_hash).

ext/sqlite3/sqlite3.c

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,13 +1057,36 @@ typedef struct {
10571057
sqlite3_blob *blob;
10581058
size_t position;
10591059
size_t size;
1060+
int flags;
10601061
} php_stream_sqlite3_data;
10611062

10621063
static size_t php_sqlite3_stream_write(php_stream *stream, const char *buf, size_t count)
10631064
{
1064-
/* php_stream_sqlite3_data *sqlite3_stream = (php_stream_sqlite3_data *) stream->abstract; */
1065+
php_stream_sqlite3_data *sqlite3_stream = (php_stream_sqlite3_data *) stream->abstract;
10651066

1066-
return 0;
1067+
if (sqlite3_stream->flags & SQLITE_OPEN_READONLY) {
1068+
php_error_docref(NULL, E_WARNING, "Can't write to blob stream: is open as read only");
1069+
return 0;
1070+
}
1071+
1072+
if (sqlite3_stream->position + count > sqlite3_stream->size) {
1073+
php_error_docref(NULL, E_WARNING, "It is not possible to increase the size of a BLOB");
1074+
return 0;
1075+
}
1076+
1077+
if (sqlite3_blob_write(sqlite3_stream->blob, buf, count, sqlite3_stream->position) != SQLITE_OK) {
1078+
return 0;
1079+
}
1080+
1081+
if (sqlite3_stream->position + count >= sqlite3_stream->size) {
1082+
stream->eof = 1;
1083+
sqlite3_stream->position = sqlite3_stream->size;
1084+
}
1085+
else {
1086+
sqlite3_stream->position += count;
1087+
}
1088+
1089+
return count;
10671090
}
10681091

10691092
static size_t php_sqlite3_stream_read(php_stream *stream, char *buf, size_t count)
@@ -1190,15 +1213,15 @@ static php_stream_ops php_stream_sqlite3_ops = {
11901213
NULL
11911214
};
11921215

1193-
/* {{{ proto resource SQLite3::openBlob(string table, string column, int rowid [, string dbname])
1216+
/* {{{ proto resource SQLite3::openBlob(string table, string column, int rowid [, string dbname [, int flags]])
11941217
Open a blob as a stream which we can read / write to. */
11951218
PHP_METHOD(sqlite3, openBlob)
11961219
{
11971220
php_sqlite3_db_object *db_obj;
11981221
zval *object = getThis();
1199-
char *table, *column, *dbname = "main";
1222+
char *table, *column, *dbname = "main", *mode = "rb";
12001223
size_t table_len, column_len, dbname_len;
1201-
zend_long rowid, flags = 0;
1224+
zend_long rowid, flags = SQLITE_OPEN_READONLY, sqlite_flags = 0;
12021225
sqlite3_blob *blob = NULL;
12031226
php_stream_sqlite3_data *sqlite3_stream;
12041227
php_stream *stream;
@@ -1207,21 +1230,28 @@ PHP_METHOD(sqlite3, openBlob)
12071230

12081231
SQLITE3_CHECK_INITIALIZED(db_obj, db_obj->initialised, SQLite3)
12091232

1210-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl|s", &table, &table_len, &column, &column_len, &rowid, &dbname, &dbname_len) == FAILURE) {
1233+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl|sl", &table, &table_len, &column, &column_len, &rowid, &dbname, &dbname_len, &flags) == FAILURE) {
12111234
return;
12121235
}
12131236

1214-
if (sqlite3_blob_open(db_obj->db, dbname, table, column, rowid, flags, &blob) != SQLITE_OK) {
1237+
sqlite_flags = (flags & SQLITE_OPEN_READWRITE) ? 1 : 0;
1238+
1239+
if (sqlite3_blob_open(db_obj->db, dbname, table, column, rowid, sqlite_flags, &blob) != SQLITE_OK) {
12151240
php_sqlite3_error(db_obj, "Unable to open blob: %s", sqlite3_errmsg(db_obj->db));
12161241
RETURN_FALSE;
12171242
}
12181243

12191244
sqlite3_stream = emalloc(sizeof(php_stream_sqlite3_data));
12201245
sqlite3_stream->blob = blob;
1246+
sqlite3_stream->flags = flags;
12211247
sqlite3_stream->position = 0;
12221248
sqlite3_stream->size = sqlite3_blob_bytes(blob);
12231249

1224-
stream = php_stream_alloc(&php_stream_sqlite3_ops, sqlite3_stream, 0, "rb");
1250+
if (sqlite_flags != 0) {
1251+
mode = "r+b";
1252+
}
1253+
1254+
stream = php_stream_alloc(&php_stream_sqlite3_ops, sqlite3_stream, 0, mode);
12251255

12261256
if (stream) {
12271257
php_stream_to_zval(stream, return_value);
@@ -1921,6 +1951,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3_openblob, 0, 0, 3)
19211951
ZEND_ARG_INFO(0, column)
19221952
ZEND_ARG_INFO(0, rowid)
19231953
ZEND_ARG_INFO(0, dbname)
1954+
ZEND_ARG_INFO(0, flags)
19241955
ZEND_END_ARG_INFO()
19251956

19261957
ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3_enableexceptions, 0, 0, 0)

ext/sqlite3/tests/sqlite3_30_blobopen.phpt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@ $stream = $db->openBlob('test', 'data', 1);
2525
var_dump($stream);
2626
echo "Stream Contents\n";
2727
var_dump(stream_get_contents($stream));
28+
echo "Writing to read-only stream\n";
29+
var_dump(fwrite($stream, 'ABCD'));
30+
echo "Closing Stream\n";
31+
var_dump(fclose($stream));
32+
echo "Opening stream in write mode\n";
33+
$stream = $db->openBlob('test', 'data', 1, 'main', SQLITE3_OPEN_READWRITE);
34+
var_dump($stream);
35+
echo "Writing to blob\n";
36+
var_dump(fwrite($stream, 'ABCD'));
37+
echo "Stream Contents\n";
38+
fseek($stream, 0);
39+
var_dump(stream_get_contents($stream));
40+
echo "Expanding blob size\n";
41+
var_dump(fwrite($stream, 'ABCD ABCD ABCD'));
2842
echo "Closing Stream\n";
2943
var_dump(fclose($stream));
3044
echo "Closing database\n";
@@ -43,6 +57,22 @@ bool(true)
4357
resource(%d) of type (stream)
4458
Stream Contents
4559
string(9) "TEST TEST"
60+
Writing to read-only stream
61+
62+
Warning: fwrite(): Can't write to blob stream: is open as read only in %s on line %d
63+
int(0)
64+
Closing Stream
65+
bool(true)
66+
Opening stream in write mode
67+
resource(%d) of type (stream)
68+
Writing to blob
69+
int(4)
70+
Stream Contents
71+
string(9) "ABCD TEST"
72+
Expanding blob size
73+
74+
Warning: fwrite(): It is not possible to increase the size of a BLOB in %s on line %d
75+
int(0)
4676
Closing Stream
4777
bool(true)
4878
Closing database

0 commit comments

Comments
 (0)