diff --git a/ext/mysql2/extconf.rb b/ext/mysql2/extconf.rb index 70cb3c999..d2ff6f6e2 100644 --- a/ext/mysql2/extconf.rb +++ b/ext/mysql2/extconf.rb @@ -31,6 +31,8 @@ def add_ssl_defines(header) # Missing in RBX (https://github.com/rubinius/rubinius/issues/3771) have_func('rb_wait_for_single_fd') +have_func("rb_enc_interned_str", "ruby.h") + # borrowed from mysqlplus # http://github.com/oldmoe/mysqlplus/blob/master/ext/extconf.rb dirs = ENV.fetch('PATH').split(File::PATH_SEPARATOR) + %w[ diff --git a/ext/mysql2/result.c b/ext/mysql2/result.c index af0b7b4e6..dd7af8adb 100644 --- a/ext/mysql2/result.c +++ b/ext/mysql2/result.c @@ -171,11 +171,18 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo rb_field = rb_intern3(field->name, field->name_length, rb_utf8_encoding()); rb_field = ID2SYM(rb_field); } else { - rb_field = rb_str_new(field->name, field->name_length); - rb_enc_associate(rb_field, conn_enc); - if (default_internal_enc) { +#ifdef HAVE_RB_ENC_INTERNED_STR + rb_field = rb_enc_interned_str(field->name, field->name_length, conn_enc); + if (default_internal_enc && default_internal_enc != conn_enc) { + rb_field = rb_str_to_interned_str(rb_str_export_to_enc(rb_field, default_internal_enc)); + } +#else + rb_field = rb_enc_str_new(field->name, field->name_length, conn_enc); + if (default_internal_enc && default_internal_enc != conn_enc) { rb_field = rb_str_export_to_enc(rb_field, default_internal_enc); } + rb_freeze(rb_field); +#endif } rb_ary_store(wrapper->fields, idx, rb_field); } diff --git a/spec/mysql2/result_spec.rb b/spec/mysql2/result_spec.rb index 5be0326f5..47a4a6de6 100644 --- a/spec/mysql2/result_spec.rb +++ b/spec/mysql2/result_spec.rb @@ -118,6 +118,13 @@ result = @client.query "SELECT 'a', 'b', 'c'" expect(result.fields).to eql(%w[a b c]) end + + it "should return an array of frozen strings" do + result = @client.query "SELECT 'a', 'b', 'c'" + result.fields.each do |f| + expect(f).to be_frozen + end + end end context "#field_types" do