ext/slim_attrib_ext.c in slim-attributes-0.2 vs ext/slim_attrib_ext.c in slim-attributes-0.3
- old
+ new
@@ -1,13 +1,13 @@
#include "ruby.h"
+#include "st.h"
#include <mysql.h>
#include <errmsg.h>
#include <mysqld_error.h>
#define GetMysqlRes(obj) (Check_Type(obj, T_DATA), ((struct mysql_res*)DATA_PTR(obj))->res)
-#define GetLongPtr(obj) (Check_Type(obj, T_DATA), (long*)DATA_PTR(obj))
#define GetCharPtr(obj) (Check_Type(obj, T_DATA), (char*)DATA_PTR(obj))
#define GetCharStarPtr(obj) (Check_Type(obj, T_DATA), (char**)DATA_PTR(obj))
VALUE cRowHash, cClass;
@@ -16,13 +16,15 @@
MYSQL_RES* res;
char freed;
};
// row info
-#define SLIM_IS_NULL (char)1
-#define SLIM_IS_SET (char)2
+#define SLIM_IS_NULL (char)0x01
+#define SLIM_IS_SET (char)0x02
+#define GET_COL_IV_NAME(str, col_number) sprintf(str, "@col_%d", col_number)
+
static VALUE all_hashes(VALUE obj) {
MYSQL_RES *res = GetMysqlRes(obj);
MYSQL_FIELD *fields = mysql_fetch_fields(res);
MYSQL_ROW row;
VALUE all_hashes_ary, col_names_hsh, frh;
@@ -32,11 +34,11 @@
unsigned long *lengths;
char *row_info_space, **pointers_space, *p;
/* hash of column names */
col_names_hsh = rb_hash_new();
- for (i=0; i<nf; i++) {
+ for (i=0; i < nf; i++) {
rb_hash_aset(col_names_hsh, rb_str_new2(fields[i].name), INT2FIX(i));
}
/* array of result rows */
all_hashes_ary = rb_ary_new2(nr);
@@ -55,32 +57,31 @@
}
frh = rb_class_new_instance(0, NULL, cRowHash);
rb_iv_set(frh, "@pointers", Data_Wrap_Struct(cClass, 0, free, pointers_space));
rb_iv_set(frh, "@row_info", Data_Wrap_Struct(cClass, 0, free, row_info_space));
rb_iv_set(frh, "@field_indexes", col_names_hsh);
- rb_iv_set(frh, "@row", rb_ary_new()); // ready to hold fetched fields
rb_ary_store(all_hashes_ary, i, frh);
}
return all_hashes_ary;
}
static VALUE fetch_by_index(VALUE obj, VALUE index) {
- VALUE row_ary, contents;
- char *row_info, **pointers, *start;
+ VALUE contents;
+ char *row_info, **pointers, *start, col_name[16];
long col_number = FIX2LONG(index);
unsigned int length;
row_info = GetCharPtr(rb_iv_get(obj, "@row_info")) + col_number;
if (*row_info == SLIM_IS_NULL) return Qnil; // return nil if null from db
- row_ary = rb_iv_get(obj, "@row");
- if (*row_info == SLIM_IS_SET) return rb_ary_entry(row_ary, col_number); // was set already, return array entry
+ GET_COL_IV_NAME(col_name, col_number);
+ if (*row_info == SLIM_IS_SET) return rb_iv_get(obj, col_name); // was set already, return array entry
pointers = GetCharStarPtr(rb_iv_get(obj, "@pointers"));
start = pointers[col_number];
length = pointers[col_number + 1] - start;
contents = rb_tainted_str_new(start, length);
- rb_ary_store(row_ary, col_number, contents);
+ rb_iv_set(obj, col_name, contents);
*row_info = SLIM_IS_SET;
return contents;
}
static VALUE slim_fetch(VALUE obj, VALUE name) {
@@ -93,28 +94,51 @@
}
static VALUE set_element(VALUE obj, VALUE name, VALUE val) {
VALUE real_hash, hash_lookup;
long col_number;
+ char col_name[16];
real_hash = rb_iv_get(obj, "@real_hash");
if (!NIL_P(real_hash)) return rb_hash_aset(real_hash, name, val);
hash_lookup = rb_hash_aref(rb_iv_get(obj, "@field_indexes"), name);
if (NIL_P(hash_lookup)) return rb_funcall(rb_funcall(obj, rb_intern("to_hash"), 0), rb_intern("[]="), 2, name, val);
col_number = FIX2LONG(hash_lookup);
- rb_ary_store(rb_iv_get(obj, "@row"), col_number, val);
+ GET_COL_IV_NAME(col_name, col_number);
+ rb_iv_set(obj, col_name, val);
GetCharPtr(rb_iv_get(obj, "@row_info"))[col_number] = SLIM_IS_SET;
return val;
}
+static VALUE dup(VALUE obj) {
+ VALUE real_hash, frh, field_indexes;
+ int nf, i;
+ char *row_info_space, col_name[16];
+
+ real_hash = rb_iv_get(obj, "@real_hash");
+ if (!NIL_P(real_hash)) return rb_obj_dup(real_hash);
+
+ field_indexes = rb_iv_get(obj, "@field_indexes");
+ nf = RHASH(field_indexes)->tbl->num_entries;
+ row_info_space = malloc(nf);
+ memcpy(row_info_space, GetCharPtr(rb_iv_get(obj, "@row_info")), nf);
+ for (i=0; i < nf; i++) row_info_space[i] &= ~SLIM_IS_SET; // remove any set flags
+ frh = rb_class_new_instance(0, NULL, cRowHash);
+ rb_iv_set(frh, "@pointers", rb_iv_get(obj, "@pointers"));
+ rb_iv_set(frh, "@row_info", Data_Wrap_Struct(cClass, 0, free, row_info_space));
+ rb_iv_set(frh, "@field_indexes", field_indexes);
+ return frh;
+}
+
void Init_slim_attrib_ext() {
VALUE c = rb_cObject;
c = rb_const_get_at(c, rb_intern("Mysql"));
c = rb_const_get_at(c, rb_intern("Result"));
rb_define_method(c, "all_hashes", (VALUE(*)(ANYARGS))all_hashes, 0);
cRowHash = rb_const_get_at(c, rb_intern("RowHash"));
cClass = rb_define_class("CObjects", cRowHash);
rb_define_private_method(cRowHash, "fetch_by_index", (VALUE(*)(ANYARGS))fetch_by_index, 1);
rb_define_method(cRowHash, "[]", (VALUE(*)(ANYARGS))slim_fetch, 1);
rb_define_method(cRowHash, "[]=", (VALUE(*)(ANYARGS))set_element, 2);
+ rb_define_method(cRowHash, "dup", (VALUE(*)(ANYARGS))dup, 0);
}