Skip to content

Commit

Permalink
Merge pull request #480 from sparklemotion/freeze-result
Browse files Browse the repository at this point in the history
Freeze results that come from the database
  • Loading branch information
tenderlove committed Jan 24, 2024
2 parents 718b47b + 839c288 commit 44ab2aa
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 4 deletions.
4 changes: 4 additions & 0 deletions ext/sqlite3/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,15 @@ step(VALUE self)
if (internal_encoding) {
val = rb_str_export_to_enc(val, internal_encoding);
}
rb_obj_freeze(val);
}
break;
case SQLITE_BLOB: {
val = rb_str_new(
(const char *)sqlite3_column_blob(stmt, i),
(long)sqlite3_column_bytes(stmt, i)
);
rb_obj_freeze(val);
}
break;
case SQLITE_NULL:
Expand All @@ -192,6 +194,8 @@ step(VALUE self)
CHECK(sqlite3_db_handle(ctx->st), value);
}

rb_obj_freeze(list);

return list;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/sqlite3/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ def execute sql, bind_vars = [], *args, &block
yield row
end
else
stmt.to_a
stmt.to_a.freeze
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions test/test_encoding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def test_blob_is_binary

string = @db.execute("select data from foo").first.first
assert_equal Encoding.find("ASCII-8BIT"), string.encoding
assert_equal str, string.force_encoding("UTF-8")
assert_equal str, string.dup.force_encoding("UTF-8")
end

def test_blob_is_ascii8bit
Expand All @@ -103,7 +103,7 @@ def test_blob_is_ascii8bit

string = @db.execute("select data from foo").first.first
assert_equal Encoding.find("ASCII-8BIT"), string.encoding
assert_equal str, string.force_encoding("UTF-8")
assert_equal str, string.dup.force_encoding("UTF-8")
end

def test_blob_with_eucjp
Expand All @@ -116,7 +116,7 @@ def test_blob_with_eucjp

string = @db.execute("select data from foo").first.first
assert_equal Encoding.find("ASCII-8BIT"), string.encoding
assert_equal str, string.force_encoding("EUC-JP")
assert_equal str, string.dup.force_encoding("EUC-JP")
end

def test_db_with_eucjp
Expand Down
19 changes: 19 additions & 0 deletions test/test_statement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,25 @@ def teardown
@db.close
end

def test_rows_should_be_frozen
@db.execute 'CREATE TABLE "things" ("float" float, "int" int, "text" blob, "string" string, "nil" string)'
stmt = @db.prepare "INSERT INTO things (float, int, text, string, nil) VALUES (?, ?, ?, ?, ?)"
stmt.execute(1.2, 2, "blob", "string", nil)
stmt.close

rows = @db.execute "SELECT float, int, text, string, nil FROM things"
assert_predicate rows, :frozen?
assert_equal 1, rows.length
row = rows[0]
assert_predicate row, :frozen?
row.each { |item| assert_predicate item, :frozen? }

if defined?(Ractor)
assert Ractor.shareable?(rows)
assert Ractor.shareable?(row)
end
end

def test_double_close_does_not_segv
@db.execute 'CREATE TABLE "things" ("number" float NOT NULL)'

Expand Down

0 comments on commit 44ab2aa

Please sign in to comment.