Skip to content

Commit 208aea1

Browse files
author
BohwaZ
committed
Implement writing to BLOBs in SQLite3
1 parent 2649a9e commit 208aea1

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed

ext/sqlite3/sqlite3.c

Lines changed: 35 additions & 6 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 == 0) {
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,13 +1213,13 @@ 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;
12011224
zend_long rowid, flags = 0;
12021225
sqlite3_blob *blob = NULL;
@@ -1207,7 +1230,7 @@ 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

@@ -1218,10 +1241,15 @@ PHP_METHOD(sqlite3, openBlob)
12181241

12191242
sqlite3_stream = emalloc(sizeof(php_stream_sqlite3_data));
12201243
sqlite3_stream->blob = blob;
1244+
sqlite3_stream->flags = flags;
12211245
sqlite3_stream->position = 0;
12221246
sqlite3_stream->size = sqlite3_blob_bytes(blob);
12231247

1224-
stream = php_stream_alloc(&php_stream_sqlite3_ops, sqlite3_stream, 0, "rb");
1248+
if (flags != 0) {
1249+
mode = "r+b";
1250+
}
1251+
1252+
stream = php_stream_alloc(&php_stream_sqlite3_ops, sqlite3_stream, 0, mode);
12251253

12261254
if (stream) {
12271255
php_stream_to_zval(stream, return_value);
@@ -1921,6 +1949,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3_openblob, 0, 0, 3)
19211949
ZEND_ARG_INFO(0, column)
19221950
ZEND_ARG_INFO(0, rowid)
19231951
ZEND_ARG_INFO(0, dbname)
1952+
ZEND_ARG_INFO(0, flags)
19241953
ZEND_END_ARG_INFO()
19251954

19261955
ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3_enableexceptions, 0, 0, 0)

ext/sqlite3/tests/sqlite3_30_blobopen.phpt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ echo "Stream Contents\n";
2727
var_dump(stream_get_contents($stream));
2828
echo "Closing Stream\n";
2929
var_dump(fclose($stream));
30+
echo "Opening stream in write mode\n";
31+
$stream = $db->openBlob('test', 'data', 1, 'main', 1);
32+
var_dump($stream);
33+
echo "Writing to blob\n";
34+
var_dump(fwrite($stream, 'ABCD'));
35+
echo "Stream Contents\n";
36+
fseek($stream, 0);
37+
var_dump(stream_get_contents($stream));
38+
echo "Closing Stream\n";
39+
var_dump(fclose($stream));
3040
echo "Closing database\n";
3141
var_dump($db->close());
3242
echo "Done\n";
@@ -45,6 +55,14 @@ Stream Contents
4555
string(9) "TEST TEST"
4656
Closing Stream
4757
bool(true)
58+
Opening stream in write mode
59+
resource(%d) of type (stream)
60+
Writing to blob
61+
int(4)
62+
Stream Contents
63+
string(9) "ABCD TEST"
64+
Closing Stream
65+
bool(true)
4866
Closing database
4967
bool(true)
5068
Done

0 commit comments

Comments
 (0)