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

Added accessor methods for MYSQL_FIELD char * table and char *db #1267

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 114 additions & 2 deletions ext/mysql2/result.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ static void rb_mysql_result_mark(void * wrapper) {
mysql2_result_wrapper * w = wrapper;
if (w) {
rb_gc_mark(w->fields);
rb_gc_mark(w->tables);
rb_gc_mark(w->dbs);
rb_gc_mark(w->rows);
rb_gc_mark(w->encoding);
rb_gc_mark(w->client);
Expand Down Expand Up @@ -190,6 +192,74 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo
return rb_field;
}

static VALUE rb_mysql_result_fetch_table(VALUE self, unsigned int idx) {
VALUE rb_table;
GET_RESULT(self);

if (wrapper->tables == Qnil) {
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
wrapper->tables = rb_ary_new2(wrapper->numberOfFields);
}

rb_table = rb_ary_entry(wrapper->tables, idx);
if (rb_table == Qnil) {
MYSQL_FIELD *field = NULL;
rb_encoding *default_internal_enc = rb_default_internal_encoding();
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);

field = mysql_fetch_field_direct(wrapper->result, idx);
#ifdef HAVE_RB_ENC_INTERNED_STR
rb_table = rb_enc_interned_str(field->table, field->table_length, conn_enc);
if (default_internal_enc && default_internal_enc != conn_enc) {
rb_table = rb_str_to_interned_str(rb_str_export_to_enc(rb_table, default_internal_enc));
}
#else
rb_table = rb_enc_str_new(field->table, field->table_length, conn_enc);
if (default_internal_enc && default_internal_enc != conn_enc) {
rb_table = rb_str_export_to_enc(rb_table, default_internal_enc);
}
rb_obj_freeze(rb_table);
#endif
rb_ary_store(wrapper->tables, idx, rb_table);
}

return rb_table;
}

static VALUE rb_mysql_result_fetch_db(VALUE self, unsigned int idx) {
VALUE rb_db;
GET_RESULT(self);

if (wrapper->dbs == Qnil) {
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
wrapper->dbs = rb_ary_new2(wrapper->numberOfFields);
}

rb_db = rb_ary_entry(wrapper->dbs, idx);
if (rb_db == Qnil) {
MYSQL_FIELD *field = NULL;
rb_encoding *default_internal_enc = rb_default_internal_encoding();
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);

field = mysql_fetch_field_direct(wrapper->result, idx);
#ifdef HAVE_RB_ENC_INTERNED_STR
rb_db = rb_enc_interned_str(field->db, field->db_length, conn_enc);
if (default_internal_enc && default_internal_enc != conn_enc) {
rb_db = rb_str_to_interned_str(rb_str_export_to_enc(rb_db, default_internal_enc));
}
#else
rb_db = rb_enc_str_new(field->db, field->db_length, conn_enc);
if (default_internal_enc && default_internal_enc != conn_enc) {
rb_db = rb_str_export_to_enc(rb_db, default_internal_enc);
}
rb_obj_freeze(rb_db);
#endif
rb_ary_store(wrapper->dbs, idx, rb_db);
}

return rb_db;
}

static VALUE rb_mysql_result_fetch_field_type(VALUE self, unsigned int idx) {
VALUE rb_field_type;
GET_RESULT(self);
Expand Down Expand Up @@ -365,7 +435,7 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
int enc_index;

enc_name = (field.charsetnr-1 < MYSQL2_CHARSETNR_SIZE) ? mysql2_mysql_enc_to_rb[field.charsetnr-1] : NULL;

if (enc_name != NULL) {
/* use the field encoding we were able to match */
enc_index = rb_enc_find_index(enc_name);
Expand Down Expand Up @@ -899,6 +969,44 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
return wrapper->fields;
}

static VALUE rb_mysql_result_fetch_tables(VALUE self) {
unsigned int i = 0;

GET_RESULT(self);

if (wrapper->tables == Qnil) {
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
wrapper->tables = rb_ary_new2(wrapper->numberOfFields);
}

if ((my_ulonglong)RARRAY_LEN(wrapper->tables) != wrapper->numberOfFields) {
for (i=0; i<wrapper->numberOfFields; i++) {
rb_mysql_result_fetch_table(self, i);
}
}

return wrapper->tables;
}

static VALUE rb_mysql_result_fetch_dbs(VALUE self) {
unsigned int i = 0;

GET_RESULT(self);

if (wrapper->dbs == Qnil) {
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
wrapper->dbs = rb_ary_new2(wrapper->numberOfFields);
}

if ((my_ulonglong)RARRAY_LEN(wrapper->dbs) != wrapper->numberOfFields) {
for (i=0; i<wrapper->numberOfFields; i++) {
rb_mysql_result_fetch_db(self, i);
}
}

return wrapper->dbs;
}

static VALUE rb_mysql_result_fetch_field_types(VALUE self) {
unsigned int i = 0;

Expand Down Expand Up @@ -1137,6 +1245,8 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
wrapper->result = r;
wrapper->fields = Qnil;
wrapper->fieldTypes = Qnil;
wrapper->tables = Qnil;
wrapper->dbs = Qnil;
wrapper->rows = Qnil;
wrapper->encoding = encoding;
wrapper->streamingComplete = 0;
Expand Down Expand Up @@ -1176,9 +1286,11 @@ void init_mysql2_result() {
cMysql2Result = rb_define_class_under(mMysql2, "Result", rb_cObject);
rb_undef_alloc_func(cMysql2Result);
rb_global_variable(&cMysql2Result);

rb_define_method(cMysql2Result, "each", rb_mysql_result_each, -1);
rb_define_method(cMysql2Result, "fields", rb_mysql_result_fetch_fields, 0);
rb_define_method(cMysql2Result, "tables", rb_mysql_result_fetch_tables, 0);
rb_define_method(cMysql2Result, "dbs", rb_mysql_result_fetch_dbs, 0);
rb_define_method(cMysql2Result, "field_types", rb_mysql_result_fetch_field_types, 0);
rb_define_method(cMysql2Result, "free", rb_mysql_result_free_, 0);
rb_define_method(cMysql2Result, "count", rb_mysql_result_count, 0);
Expand Down
2 changes: 2 additions & 0 deletions ext/mysql2/result.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
typedef struct {
VALUE fields;
VALUE fieldTypes;
VALUE tables;
VALUE dbs;
VALUE rows;
VALUE client;
VALUE encoding;
Expand Down
41 changes: 41 additions & 0 deletions spec/mysql2/result_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,47 @@
end
end

context "#tables" do
let(:test_result) { @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1") }

it "method should exist" do
expect(test_result).to respond_to(:tables)
end

it "should return an array of table names in proper order" do
result = @client.query("SELECT id, bit_test, single_bit_test FROM mysql2_test ORDER BY id DESC LIMIT 1")
expect(result.tables).to eql(%w[mysql2_test mysql2_test mysql2_test])
end

it "should return an array of frozen strings" do
result = @client.query "SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1"
result.tables.each do |f|
expect(f).to be_frozen
end
end
end

context "#dbs" do
let(:test_result) { @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1") }

it "method should exist" do
expect(test_result).to respond_to(:dbs)
end

it "should return an array of database names in proper order" do
db = DatabaseCredentials['root']['database']
result = @client.query("SELECT id, bit_test, single_bit_test FROM mysql2_test ORDER BY id DESC LIMIT 1")
expect(result.dbs).to eql([db, db, db])
end

it "should return an array of frozen strings" do
result = @client.query "SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1"
result.dbs.each do |f|
expect(f).to be_frozen
end
end
end

context "streaming" do
it "should maintain a count while streaming" do
result = @client.query('SELECT 1', stream: true, cache_rows: false)
Expand Down