Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions ext/sqlite3/database.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,32 +277,34 @@ last_insert_row_id(VALUE self)
VALUE
sqlite3val2rb(sqlite3_value *val)
{
VALUE rb_val;

switch (sqlite3_value_type(val)) {
case SQLITE_INTEGER:
return LL2NUM(sqlite3_value_int64(val));
rb_val = LL2NUM(sqlite3_value_int64(val));
break;
case SQLITE_FLOAT:
return rb_float_new(sqlite3_value_double(val));
rb_val = rb_float_new(sqlite3_value_double(val));
break;
case SQLITE_TEXT:
return rb_str_new2((const char *)sqlite3_value_text(val));
case SQLITE_TEXT: {
rb_val = rb_utf8_str_new_cstr((const char *)sqlite3_value_text(val));
rb_obj_freeze(rb_val);
break;
}
case SQLITE_BLOB: {
/* Sqlite warns calling sqlite3_value_bytes may invalidate pointer from sqlite3_value_blob,
so we explicitly get the length before getting blob pointer.
Note that rb_str_new apparently create string with ASCII-8BIT (BINARY) encoding,
which is what we want, as blobs are binary
*/
int len = sqlite3_value_bytes(val);
return rb_str_new((const char *)sqlite3_value_blob(val), len);
rb_val = rb_str_new((const char *)sqlite3_value_blob(val), len);
rb_obj_freeze(rb_val);
break;
}
case SQLITE_NULL:
return Qnil;
rb_val = Qnil;
break;
default:
rb_raise(rb_eRuntimeError, "bad type"); /* FIXME */
rb_raise(rb_eRuntimeError, "bad type");
}

return rb_val;
}

void
Expand Down
30 changes: 30 additions & 0 deletions test/test_database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,36 @@ def teardown
@db.close unless @db.closed?
end

def test_custom_function_encoding
@db.execute("CREATE TABLE
sourceTable(
sourceData TEXT);")
@db.execute("INSERT INTO sourceTable
VALUES ('abcde');")

@db.create_function("GetCopy", 1) { |func, value|
func.result = value
}

@db.transaction { |t|
t.execute("CREATE TABLE
afterTable(
beforeData TEXT,
afterData TEXT);".squeeze(" "))

t.execute("INSERT INTO afterTable
SELECT
sourceData,
GetCopy(sourceData)
FROM sourceTable;")
}

assert_equal(1, @db.get_first_value("SELECT 1
FROM afterTable
WHERE beforeData = afterData
LIMIT 1;"))
end

def test_segv
assert_raises { SQLite3::Database.new 1 } # rubocop:disable Minitest/UnspecifiedException
end
Expand Down