Skip to content

Commit cb9481e

Browse files
committed
Freeze results that come from the database
Freeze strings and row records so that we can more easily share results among Ractors
1 parent 6a5d21f commit cb9481e

File tree

4 files changed

+25
-4
lines changed

4 files changed

+25
-4
lines changed

ext/sqlite3/statement.c

+4
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,15 @@ step(VALUE self)
162162
if (internal_encoding) {
163163
val = rb_str_export_to_enc(val, internal_encoding);
164164
}
165+
rb_obj_freeze(val);
165166
}
166167
break;
167168
case SQLITE_BLOB: {
168169
val = rb_str_new(
169170
(const char *)sqlite3_column_blob(stmt, i),
170171
(long)sqlite3_column_bytes(stmt, i)
171172
);
173+
rb_obj_freeze(val);
172174
}
173175
break;
174176
case SQLITE_NULL:
@@ -192,6 +194,8 @@ step(VALUE self)
192194
CHECK(sqlite3_db_handle(ctx->st), value);
193195
}
194196

197+
rb_obj_freeze(list);
198+
195199
return list;
196200
}
197201

lib/sqlite3/database.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def execute sql, bind_vars = [], *args, &block
208208
yield row
209209
end
210210
else
211-
stmt.to_a
211+
stmt.to_a.freeze
212212
end
213213
end
214214
end

test/test_encoding.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def test_blob_is_binary
8282

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

8888
def test_blob_is_ascii8bit
@@ -95,7 +95,7 @@ def test_blob_is_ascii8bit
9595

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

101101
def test_blob_with_eucjp
@@ -108,7 +108,7 @@ def test_blob_with_eucjp
108108

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

114114
def test_db_with_eucjp

test/test_statement.rb

+17
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,23 @@ def teardown
1212
@db.close
1313
end
1414

15+
def test_rows_should_be_frozen
16+
@db.execute 'CREATE TABLE "things" ("float" float, "int" int, "text" blob, "string" string, "nil" string)'
17+
stmt = @db.prepare "INSERT INTO things (float, int, text, string, nil) VALUES (?, ?, ?, ?, ?)"
18+
stmt.execute(1.2, 2, "blob", "string", nil)
19+
stmt.close
20+
21+
rows = @db.execute "SELECT float, int, text, string, nil FROM things"
22+
assert_predicate rows, :frozen?
23+
assert_equal 1, rows.length
24+
row = rows[0]
25+
assert_predicate row, :frozen?
26+
row.each { |item| assert_predicate item, :frozen? }
27+
28+
assert Ractor.shareable?(rows)
29+
assert Ractor.shareable?(row)
30+
end
31+
1532
def test_double_close_does_not_segv
1633
@db.execute 'CREATE TABLE "things" ("number" float NOT NULL)'
1734

0 commit comments

Comments
 (0)