slim-attributes 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README +7 -10
  2. data/ext/slim_attrib_ext.c +22 -43
  3. metadata +2 -2
data/README CHANGED
@@ -13,10 +13,13 @@ Installation
13
13
 
14
14
  You're going to need the mysql headers for this to work.
15
15
 
16
- cd vendor/plugins/slim_attributes
17
- ruby extconf.rb --with-mysql-config
18
- make
19
- sudo make install
16
+ Try:
17
+ gem install slim-attributes -- --with-mysql-config
18
+ or:
19
+ gem install slim-attributes
20
+
21
+ then add this to environment.rb:
22
+ require 'slim_attributes'
20
23
 
21
24
 
22
25
  Description
@@ -32,12 +35,6 @@ So this is an alternative implementation of all_hashes that returns a 'fake hash
32
35
 
33
36
  The field contents are then instantiated into Ruby strings on demand - ruby strings are only made if you need them. Note that if you always look at all the columns when you fetch data from the database then this won't necessarily be faster that the unpatched mysql adapter. But it won't be much slower either, and we do expect that most times not all the columns from a result set are accessed.
34
37
 
35
- Note that the 'fake hash' quacks like a hash in many ways, but not all ways. So @attributes in an ActiveRecord object may not behave as you are expecting it to, and it particularly won't work if you try to add a key to it that is not a column name in the result set.
36
-
37
- @attributes["not a column name"] = "something"
38
- => RuntimeError: Key was not a column name from the result set
39
-
40
- Hash has many methods that are not supported by the fake hash, but I found that the ones I have implemented have been sufficient for use in our Rails app. It should be fairly easy to implement most of the missing methods if needed, but I did not wish this patch to be larger than necessary.
41
38
 
42
39
  ===========
43
40
 
@@ -25,12 +25,12 @@ static VALUE all_hashes(VALUE obj) {
25
25
  MYSQL_RES *res = GetMysqlRes(obj);
26
26
  MYSQL_FIELD *fields = mysql_fetch_fields(res);
27
27
  MYSQL_ROW row;
28
- VALUE all_hashes_ary, col_names_hsh, row_ary;
28
+ VALUE all_hashes_ary, col_names_hsh, frh;
29
29
  my_ulonglong nr = mysql_num_rows(res);
30
30
  unsigned int nf = mysql_num_fields(res);
31
- unsigned int i, j, s;
31
+ unsigned int i, j, s, len;
32
32
  unsigned long *lengths;
33
- char *row_space, *row_info_space, **pointers_space;
33
+ char *row_info_space, **pointers_space, *p;
34
34
 
35
35
  /* hash of column names */
36
36
  col_names_hsh = rb_hash_new();
@@ -40,64 +40,46 @@ static VALUE all_hashes(VALUE obj) {
40
40
 
41
41
  /* array of result rows */
42
42
  all_hashes_ary = rb_ary_new2(nr);
43
- for (i=0; i<nr; i++) {
44
- VALUE frh;
45
- frh = rb_class_new_instance(0, NULL, cRowHash);
46
- rb_iv_set(frh, "@field_indexes", col_names_hsh);
43
+ for (i=0; i < nr; i++) {
47
44
  row = mysql_fetch_row(res); // get the row
48
-
49
- row_ary = rb_ary_new();
50
- rb_iv_set(frh, "@row", row_ary); // ready to hold fetched fields
51
-
52
45
  lengths = mysql_fetch_lengths(res); // get lengths
53
46
  for (s=j=0; j < nf; j++) s += lengths[j]; // s = total of lengths
54
- row_space = malloc(s);
55
- pointers_space = malloc((nf + 1) * sizeof(char *));
47
+ pointers_space = malloc((nf + 1) * sizeof(char *) + s); // storage for pointers to data followed by data
48
+ p = *pointers_space = (char *)(pointers_space + nf + 1); // pointer to first data item
56
49
  row_info_space = calloc(nf, 1);
57
- for (s=j=0; j < nf; j++) {
58
- int len = lengths[j];
59
- char *p = row_space + s;
60
- s += len;
61
- pointers_space[j] = p;
50
+ for (j=0; j < nf; j++) {
51
+ len = (unsigned int)lengths[j];
62
52
  if (!row[j]) row_info_space[j] = SLIM_IS_NULL;
63
53
  else memcpy(p, row[j], len); // copy row data in
54
+ pointers_space[j + 1] = p += len;
64
55
  }
65
- pointers_space[nf] = row_space + s;
56
+ frh = rb_class_new_instance(0, NULL, cRowHash);
66
57
  rb_iv_set(frh, "@pointers", Data_Wrap_Struct(cClass, 0, free, pointers_space));
67
58
  rb_iv_set(frh, "@row_info", Data_Wrap_Struct(cClass, 0, free, row_info_space));
68
- rb_iv_set(frh, "@raw_row", Data_Wrap_Struct(cClass, 0, free, row_space)); // @raw_row contains pointer to the the row data
59
+ rb_iv_set(frh, "@field_indexes", col_names_hsh);
60
+ rb_iv_set(frh, "@row", rb_ary_new()); // ready to hold fetched fields
69
61
  rb_ary_store(all_hashes_ary, i, frh);
70
62
  }
71
63
  return all_hashes_ary;
72
64
  }
73
65
 
74
66
  static VALUE fetch_by_index(VALUE obj, VALUE index) {
75
- VALUE row_ary, row_ary_contents, contents, row_info_obj;
76
- char *raw_row, *row_info, **pointers, *start;
77
- long col_number;
67
+ VALUE row_ary, contents;
68
+ char *row_info, **pointers, *start;
69
+ long col_number = FIX2LONG(index);
78
70
  unsigned int length;
79
71
 
80
- col_number = FIX2LONG(index);
81
- row_info_obj = rb_iv_get(obj, "@row_info");
72
+ row_info = GetCharPtr(rb_iv_get(obj, "@row_info")) + col_number;
73
+ if (*row_info == SLIM_IS_NULL) return Qnil; // return nil if null from db
82
74
  row_ary = rb_iv_get(obj, "@row");
83
- if (NIL_P(row_info_obj)) return rb_ary_entry(row_ary, col_number); // was marshalled
84
- else {
85
- row_info = GetCharPtr(row_info_obj);
86
- if (row_info[col_number] == SLIM_IS_SET) return rb_ary_entry(row_ary, col_number); // was set already, return array entry
87
- }
88
-
89
- if (row_info[col_number] == SLIM_IS_NULL) { // return nil if null from db
90
- rb_ary_store(row_ary, col_number, Qnil);
91
- row_info[col_number] = SLIM_IS_SET;
92
- return Qnil;
93
- }
75
+ if (*row_info == SLIM_IS_SET) return rb_ary_entry(row_ary, col_number); // was set already, return array entry
94
76
 
95
77
  pointers = GetCharStarPtr(rb_iv_get(obj, "@pointers"));
96
78
  start = pointers[col_number];
97
79
  length = pointers[col_number + 1] - start;
98
80
  contents = rb_tainted_str_new(start, length);
99
81
  rb_ary_store(row_ary, col_number, contents);
100
- row_info[col_number] = SLIM_IS_SET;
82
+ *row_info = SLIM_IS_SET;
101
83
  return contents;
102
84
  }
103
85
 
@@ -112,7 +94,6 @@ static VALUE slim_fetch(VALUE obj, VALUE name) {
112
94
 
113
95
  static VALUE set_element(VALUE obj, VALUE name, VALUE val) {
114
96
  VALUE real_hash, hash_lookup;
115
- VALUE row_ary, row_info_obj;
116
97
  long col_number;
117
98
 
118
99
  real_hash = rb_iv_get(obj, "@real_hash");
@@ -120,11 +101,9 @@ static VALUE set_element(VALUE obj, VALUE name, VALUE val) {
120
101
 
121
102
  hash_lookup = rb_hash_aref(rb_iv_get(obj, "@field_indexes"), name);
122
103
  if (NIL_P(hash_lookup)) return rb_funcall(rb_funcall(obj, rb_intern("to_hash"), 0), rb_intern("[]="), 2, name, val);
123
- row_ary = rb_iv_get(obj, "@row");
124
104
  col_number = FIX2LONG(hash_lookup);
125
- rb_ary_store(row_ary, col_number, val);
126
- row_info_obj = rb_iv_get(obj, "@row_info");
127
- if (!NIL_P(row_info_obj)) GetCharPtr(row_info_obj)[col_number] = SLIM_IS_SET;
105
+ rb_ary_store(rb_iv_get(obj, "@row"), col_number, val);
106
+ GetCharPtr(rb_iv_get(obj, "@row_info"))[col_number] = SLIM_IS_SET;
128
107
  return val;
129
108
  }
130
109
 
@@ -135,7 +114,7 @@ void Init_slim_attrib_ext() {
135
114
  rb_define_method(c, "all_hashes", (VALUE(*)(ANYARGS))all_hashes, 0);
136
115
  cRowHash = rb_const_get_at(c, rb_intern("RowHash"));
137
116
  cClass = rb_define_class("CObjects", cRowHash);
138
- rb_define_method(cRowHash, "fetch_by_index", (VALUE(*)(ANYARGS))fetch_by_index, 1);
117
+ rb_define_private_method(cRowHash, "fetch_by_index", (VALUE(*)(ANYARGS))fetch_by_index, 1);
139
118
  rb_define_method(cRowHash, "[]", (VALUE(*)(ANYARGS))slim_fetch, 1);
140
119
  rb_define_method(cRowHash, "[]=", (VALUE(*)(ANYARGS))set_element, 2);
141
120
  }
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: slim-attributes
5
5
  version: !ruby/object:Gem::Version
6
- version: "0.1"
7
- date: 2008-04-06 00:00:00 +03:00
6
+ version: "0.2"
7
+ date: 2008-04-09 00:00:00 +03:00
8
8
  summary: Slim attributes boosts speed in Rails/Mysql ActiveRecord Models by avoiding instantiating Hashes for each result row, and lazily instantiating attributes as needed
9
9
  require_paths:
10
10
  - lib