Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix encoding for values passed to custom functions #488

Merged
merged 1 commit into from
Jan 27, 2024
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.
Jump to
Jump to file
Failed to load files.
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