Class: Amalgalite::SQLite3::Blob

Inherits:
Object
  • Object
show all
Defined in:
ext/amalgalite/c/amalgalite_blob.c,
ext/amalgalite/c/amalgalite_blob.c

Overview

The Blob class enables incremental IO on blob items. If you do not need incremental IO on a binary object, then you do not need to use Blob.

Instance Method Summary collapse

Constructor Details

#new(database, table_name, column_name, row_id, flag) ⇒ Blob

Create a new Blob object and associate it with the approriate, database, table, column and row. flag indicates if the Blob is to be opened for writing “w” or reading “r”.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'ext/amalgalite/c/amalgalite_blob.c', line 21

VALUE am_sqlite3_blob_initialize( VALUE self, VALUE db, VALUE db_name, VALUE table_name, VALUE column_name, VALUE rowid, VALUE flag) 
{
    am_sqlite3_blob *am_blob;
    int              rc;
    am_sqlite3      *am_db;
    char            *zDb      = StringValuePtr( db_name );
    char            *zTable   = StringValuePtr( table_name );
    char            *zColumn  = StringValuePtr( column_name );
    sqlite3_int64    iRow     = NUM2SQLINT64( rowid )  ;
    VALUE            flag_str = StringValue( flag );
    int              flags    = 0;

    /* extract the blob struct */
    Data_Get_Struct(self, am_sqlite3_blob, am_blob);
    
    /* extract the sqlite3 db struct */
    Data_Get_Struct(db, am_sqlite3, am_db);

    /* make sure that the flags are valid, only 'r' or 'w' are allowed */
    if ( ( RSTRING_LEN( flag_str ) != 1) || 
         ( ( 'r' != RSTRING_PTR( flag_str )[0] ) && 
           ( 'w' != RSTRING_PTR( flag_str )[0] ))) {
        rb_raise( eAS_Error, "Error opening Blob in db = %s, table = %s, column = %s, rowid = %lu.  Invalid flag '%s'.  Must be either 'w' or 'r'\n",
                             zDb, zTable, zColumn, (unsigned long)iRow, RSTRING_PTR( flag_str ));
    }

    /* switch to write mode */
    if ( 'w' == RSTRING_PTR( flag_str )[0] ) { 
        flags = 1;
    }

    /* open the blob and associate the db to it */
    rc = sqlite3_blob_open( am_db->db, zDb, zTable, zColumn, iRow, flags, &( am_blob->blob ) );
    if ( SQLITE_OK != rc ) {
        rb_raise( eAS_Error, "Error opening Blob in db = %s, table = %s, column = %s, rowid = %lu : [SQLITE_ERROR %d] %s\n", zDb, zTable, zColumn, (unsigned long)iRow, rc, sqlite3_errmsg( am_db->db) );  
    }
    am_blob->length = sqlite3_blob_bytes( am_blob->blob );
    am_blob->db = am_db->db;

    /* if a block is given then yield self and close the blob when done */
    if ( rb_block_given_p() ) {
        rb_yield( self );
        am_sqlite3_blob_close( self );
        return Qnil;
    } else {
        return self;
    }
}

Instance Method Details

#closenil

Closes the blob.

Returns:

  • (nil)


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'ext/amalgalite/c/amalgalite_blob.c', line 76

VALUE am_sqlite3_blob_close( VALUE self )
{
    am_sqlite3_blob *am_blob;
    int              rc;
    
    Data_Get_Struct(self, am_sqlite3_blob, am_blob);
    rc = sqlite3_blob_close( am_blob->blob );
    if ( SQLITE_OK != rc ) {
        rb_raise(eAS_Error, "Error closing blob: [SQLITE_ERROR %d] %s\n",
                rc, sqlite3_errmsg( am_blob->db ));
    }


    return Qnil;
}

#lengthObject

Returns the number of bytes in the blob.



99
100
101
102
103
104
105
106
# File 'ext/amalgalite/c/amalgalite_blob.c', line 99

VALUE am_sqlite3_blob_length( VALUE self )
{
    am_sqlite3_blob *am_blob;

    Data_Get_Struct(self, am_sqlite3_blob, am_blob);

    return INT2FIX( am_blob->length );
}

#read(int) ⇒ String containting int number of bytes

returns int number of bytes as a String from the database

Returns:

  • (String containting int number of bytes)


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'ext/amalgalite/c/amalgalite_blob.c', line 114

VALUE am_sqlite3_blob_read( VALUE self, VALUE length )
{
    am_sqlite3_blob *am_blob;
    int             rc;
    int              n = NUM2INT( length );
    void           *buf = NULL;
    VALUE          result;

    Data_Get_Struct(self, am_sqlite3_blob, am_blob);

    /* we have to be exact on the number of bytes to read.  n + current_offset
     * cannot be larger than the blob's length
     */
    if ( (n + am_blob->current_offset > am_blob->length)) {
        n = am_blob->length - am_blob->current_offset;
    }

    if ( am_blob->current_offset == am_blob->length ) {
        return Qnil;
    }

    buf = (void *)malloc( n );
    rc = sqlite3_blob_read( am_blob->blob, buf, n, am_blob->current_offset); 

    if ( rc != SQLITE_OK ) {
        rb_raise(eAS_Error, "Error reading %d bytes blob at offset %d: [SQLITE_ERROR %d] %s\n",
                n, am_blob->current_offset, rc, sqlite3_errmsg( am_blob->db ));
    }

    am_blob->current_offset += n;

    result = rb_str_new( (char*)buf, n );
    free( buf );
    return result;

}

#write(buf) ⇒ Integer

writes the contents of the string buffer to the blob and returns the number of bytes written.

Returns:

  • (Integer)


159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'ext/amalgalite/c/amalgalite_blob.c', line 159

VALUE am_sqlite3_blob_write( VALUE self, VALUE buf )
{
    am_sqlite3_blob *am_blob;
    int              rc;
    VALUE            str = StringValue( buf );
    int              n   = (int)RSTRING_LEN( str );
    char            *chk_buf = NULL;

    Data_Get_Struct(self, am_sqlite3_blob, am_blob);

    rc = sqlite3_blob_write( am_blob->blob, RSTRING_PTR(str), n, am_blob->current_offset); 

    if ( rc  != SQLITE_OK ) {
        rb_raise(eAS_Error, "Error writing %d bytes blob at offset %d: [SQLITE_ERROR %d] %s\n",
                n, am_blob->current_offset, rc, sqlite3_errmsg( am_blob->db ));
    }

    chk_buf = (char *) malloc( n  + 1);
    chk_buf[n] = '\0';
    sqlite3_blob_read( am_blob->blob, chk_buf, n, 0);

    am_blob->current_offset += n;

    return INT2FIX( n );

}