]> granicus.if.org Git - php/commitdiff
Implement writing to BLOBs in SQLite3
authorBohwaZ <bohwaz@github.com>
Wed, 17 May 2017 23:54:55 +0000 (11:54 +1200)
committerBohwaZ <bohwaz@github.com>
Wed, 17 May 2017 23:54:55 +0000 (11:54 +1200)
ext/sqlite3/sqlite3.c
ext/sqlite3/tests/sqlite3_30_blobopen.phpt

index 67daa79f88f42045fd5d9f185cc4196c5739f4c5..485c7bdcf8fb168639eb9cb5463db08853d8d9e9 100644 (file)
@@ -1057,13 +1057,36 @@ typedef struct {
        sqlite3_blob *blob;
        size_t           position;
        size_t       size;
+       int          flags;
 } php_stream_sqlite3_data;
 
 static size_t php_sqlite3_stream_write(php_stream *stream, const char *buf, size_t count)
 {
-/*     php_stream_sqlite3_data *sqlite3_stream = (php_stream_sqlite3_data *) stream->abstract; */
+       php_stream_sqlite3_data *sqlite3_stream = (php_stream_sqlite3_data *) stream->abstract;
 
-       return 0;
+       if (sqlite3_stream->flags == 0) {
+               php_error_docref(NULL, E_WARNING, "Can't write to blob stream: is open as read only");
+               return 0;
+       }
+
+       if (sqlite3_stream->position + count > sqlite3_stream->size) {
+               php_error_docref(NULL, E_WARNING, "It is not possible to increase the size of a BLOB");
+               return 0;
+       }
+
+       if (sqlite3_blob_write(sqlite3_stream->blob, buf, count, sqlite3_stream->position) != SQLITE_OK) {
+               return 0;
+       }
+
+       if (sqlite3_stream->position + count >= sqlite3_stream->size) {
+               stream->eof = 1;
+               sqlite3_stream->position = sqlite3_stream->size;
+       }
+       else {
+               sqlite3_stream->position += count;
+       }
+
+       return count;
 }
 
 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 = {
        NULL
 };
 
-/* {{{ proto resource SQLite3::openBlob(string table, string column, int rowid [, string dbname])
+/* {{{ proto resource SQLite3::openBlob(string table, string column, int rowid [, string dbname [, int flags]])
    Open a blob as a stream which we can read / write to. */
 PHP_METHOD(sqlite3, openBlob)
 {
        php_sqlite3_db_object *db_obj;
        zval *object = getThis();
-       char *table, *column, *dbname = "main";
+       char *table, *column, *dbname = "main", *mode = "rb";
        size_t table_len, column_len, dbname_len;
        zend_long rowid, flags = 0;
        sqlite3_blob *blob = NULL;
@@ -1207,7 +1230,7 @@ PHP_METHOD(sqlite3, openBlob)
 
        SQLITE3_CHECK_INITIALIZED(db_obj, db_obj->initialised, SQLite3)
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl|s", &table, &table_len, &column, &column_len, &rowid, &dbname, &dbname_len) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl|sl", &table, &table_len, &column, &column_len, &rowid, &dbname, &dbname_len, &flags) == FAILURE) {
                return;
        }
 
@@ -1218,10 +1241,15 @@ PHP_METHOD(sqlite3, openBlob)
 
        sqlite3_stream = emalloc(sizeof(php_stream_sqlite3_data));
        sqlite3_stream->blob = blob;
+       sqlite3_stream->flags = flags;
        sqlite3_stream->position = 0;
        sqlite3_stream->size = sqlite3_blob_bytes(blob);
 
-       stream = php_stream_alloc(&php_stream_sqlite3_ops, sqlite3_stream, 0, "rb");
+       if (flags != 0) {
+               mode = "r+b";
+       }
+
+       stream = php_stream_alloc(&php_stream_sqlite3_ops, sqlite3_stream, 0, mode);
 
        if (stream) {
                php_stream_to_zval(stream, return_value);
@@ -1921,6 +1949,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3_openblob, 0, 0, 3)
        ZEND_ARG_INFO(0, column)
        ZEND_ARG_INFO(0, rowid)
        ZEND_ARG_INFO(0, dbname)
+       ZEND_ARG_INFO(0, flags)
 ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3_enableexceptions, 0, 0, 0)
index 1daa4b1ffb4240ad42989bd223ec58f07d8e2a19..b581abcdc0575d477e7149ecdde4b1342d848e3e 100644 (file)
@@ -27,6 +27,16 @@ echo "Stream Contents\n";
 var_dump(stream_get_contents($stream));
 echo "Closing Stream\n";
 var_dump(fclose($stream));
+echo "Opening stream in write mode\n";
+$stream = $db->openBlob('test', 'data', 1, 'main', 1);
+var_dump($stream);
+echo "Writing to blob\n";
+var_dump(fwrite($stream, 'ABCD'));
+echo "Stream Contents\n";
+fseek($stream, 0);
+var_dump(stream_get_contents($stream));
+echo "Closing Stream\n";
+var_dump(fclose($stream));
 echo "Closing database\n";
 var_dump($db->close());
 echo "Done\n";
@@ -45,6 +55,14 @@ Stream Contents
 string(9) "TEST TEST"
 Closing Stream
 bool(true)
+Opening stream in write mode
+resource(%d) of type (stream)
+Writing to blob
+int(4)
+Stream Contents
+string(9) "ABCD TEST"
+Closing Stream
+bool(true)
 Closing database
 bool(true)
 Done