Skip to content

Commit

Permalink
Intern column names so we always get the same string
Browse files Browse the repository at this point in the history
When we get column names back from the database, it's very common to
always return the same strings. This patch uses Ruby's "interned string"
API so that we're always getting the same string objects back from the database.

Fixes: #155
  • Loading branch information
tenderlove committed Jan 24, 2024
1 parent 44ab2aa commit 7757522
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
3 changes: 1 addition & 2 deletions ext/sqlite3/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,7 @@ column_name(VALUE self, VALUE index)
VALUE ret = Qnil;

if (name) {
ret = SQLITE3_UTF8_STR_NEW2(name);
rb_obj_freeze(ret);
ret = rb_enc_interned_str_cstr(name, rb_utf8_encoding());
}
return ret;
}
Expand Down
16 changes: 16 additions & 0 deletions test/test_statement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,22 @@ def test_raises_type_error
end
end

def test_column_names_are_deduped
@db.execute 'CREATE TABLE "things" ("float" float, "int" int, "text" blob, "string" string, "nil" string)'
stmt = @db.prepare 'SELECT float, int, text, string, nil FROM things'
assert_equal ["float", "int", "text", "string", "nil"], stmt.columns
columns = stmt.columns
stmt.close

stmt = @db.prepare 'SELECT float, int, text, string, nil FROM things'
# Make sure this new statement returns the same interned strings
stmt.columns.each_with_index do |str, i|
assert_same columns[i], str
end
ensure
stmt&.close
end

def test_insert_duplicate_records
@db.execute 'CREATE TABLE "things" ("name" varchar(20) CONSTRAINT "index_things_on_name" UNIQUE)'
stmt = @db.prepare("INSERT INTO things(name) VALUES(?)")
Expand Down

0 comments on commit 7757522

Please sign in to comment.