downpour 0.0.7 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,6 @@ Downpour is a gem to connect and query a Drizzle or MySql database using the lib
5
5
  == TODO
6
6
  * Do not maintain a list of pending queries and connections in ruby. Mark and sweep. Is this a good idea
7
7
  * Actually honor some options passed in to drizzle_con_create
8
- * Get column info and do stuff
8
+ * Get column type and do stuff.
9
9
  * Create a rails plugin
10
10
  * Result, Column does not have a context. Memory Leak?
@@ -0,0 +1,45 @@
1
+ #include "downpour.h"
2
+ #include "result.h"
3
+
4
+ #define SELF_TYPE drizzle_result_st
5
+ #define RUBY_CLASS DrizzleBufferedResult
6
+
7
+ #define attr(foo, conversion) static VALUE attr_##foo(VALUE self)\
8
+ {\
9
+ read_self_ptr();\
10
+ return conversion(drizzle_result_##foo(self_ptr));\
11
+ }
12
+
13
+ static void buffer_if_needed(drizzle_result_st *self_ptr)
14
+ {
15
+ // Only buffer once
16
+ if(downpour_is_buffered(self_ptr))
17
+ return;
18
+
19
+ CHECK_OK(drizzle_result_buffer(self_ptr));
20
+ }
21
+
22
+ static VALUE next_row(VALUE self)
23
+ {
24
+ read_self_ptr();
25
+
26
+ drizzle_row_t result = drizzle_row_next(self_ptr);
27
+ return downpour_wrap_row(self, self_ptr, result);
28
+ }
29
+
30
+ attr(row_count, UINT2NUM);
31
+
32
+ VALUE downpour_buffered_result_constructor(drizzle_result_st *self_ptr, VALUE connection)
33
+ {
34
+ buffer_if_needed(self_ptr);
35
+ VALUE ret = to_ruby_object(self_ptr, DrizzleBufferedResult, connection, drizzle_result_free, NULL);
36
+ return downpour_include_result_module(self_ptr, ret);
37
+ }
38
+
39
+ void init_drizzle_buffered_result()
40
+ {
41
+ DrizzleBufferedResult = drizzle_gem_create_class_with_private_constructor("BufferedResult", rb_cObject);
42
+ rb_include_module(DrizzleBufferedResult, DrizzleResult);
43
+ rb_define_method(DrizzleBufferedResult, "next_row", next_row, 0);
44
+ define_attr(row_count);
45
+ }
@@ -0,0 +1,50 @@
1
+ #include "downpour.h"
2
+
3
+ #define SELF_TYPE drizzle_column_st
4
+ #define RUBY_CLASS DrizzleColumn
5
+
6
+ #define attr(foo, conversion) static VALUE attr_##foo(VALUE self)\
7
+ {\
8
+ read_self_ptr();\
9
+ return conversion(drizzle_column_##foo(self_ptr));\
10
+ }
11
+
12
+ attr_string(catalog);
13
+ attr_string(db);
14
+ attr_string(table);
15
+ attr_string(orig_table);
16
+ attr_string(name);
17
+ attr_string(orig_name);
18
+ // charset
19
+ attr(size, UINT2NUM);
20
+ attr(max_size, INT2NUM);
21
+ //column type
22
+ //column_type_drizzle
23
+ //flags
24
+ attr(decimals, UINT2NUM);
25
+ //default_value
26
+
27
+ VALUE downpour_column_constructor(drizzle_column_st *self_ptr, VALUE result)
28
+ {
29
+ // Column object is owned by the result. Thus we let the result free it, and the free_method is null
30
+ return to_ruby_object(self_ptr, DrizzleColumn, result, NULL, NULL);
31
+ }
32
+
33
+ void init_drizzle_column()
34
+ {
35
+ DrizzleColumn = drizzle_gem_create_class_with_private_constructor("Column", rb_cObject);
36
+ define_attr(catalog);
37
+ define_attr(db);
38
+ define_attr(table);
39
+ define_attr(orig_table);
40
+ define_attr(name);
41
+ define_attr(orig_name);
42
+ // charset
43
+ define_attr(size);
44
+ define_attr(max_size);
45
+ //column type
46
+ //column_type_drizzle
47
+ //flags
48
+ define_attr(decimals);
49
+ //default_value
50
+ }
@@ -16,7 +16,7 @@
16
16
  return newValue;\
17
17
  }
18
18
 
19
- static VALUE query(VALUE self, VALUE query)
19
+ static drizzle_result_st *create_query(VALUE self, VALUE query)
20
20
  {
21
21
  read_self_ptr();
22
22
 
@@ -27,7 +27,17 @@ static VALUE query(VALUE self, VALUE query)
27
27
 
28
28
  CHECK_OK(retptr);
29
29
 
30
- return downpour_result_constructor(result, self);
30
+ return result;
31
+ }
32
+
33
+ static VALUE query(VALUE self, VALUE query)
34
+ {
35
+ return downpour_buffered_result_constructor(create_query(self, query), self);
36
+ }
37
+
38
+ static VALUE unbuffered_query(VALUE self, VALUE query)
39
+ {
40
+ return downpour_unbuffered_result_constructor(create_query(self, query), self);
31
41
  }
32
42
 
33
43
  static VALUE connection_close(VALUE self)
@@ -63,6 +73,7 @@ void init_drizzle_connection()
63
73
  {
64
74
  DrizzleConnection = drizzle_gem_create_class_with_private_constructor("Connection", rb_cObject);
65
75
  rb_define_method(DrizzleConnection, "query", query, 1);
76
+ rb_define_method(DrizzleConnection, "unbuffered_query", unbuffered_query, 1);
66
77
  define_attr(options);
67
78
  define_attr(error);
68
79
  define_attr(errno);
@@ -4,13 +4,19 @@ VALUE DownpourModule;
4
4
  VALUE DrizzleStatus;
5
5
  VALUE DrizzleConnection;
6
6
  VALUE DrizzleResult;
7
+ VALUE DrizzleBufferedResult;
8
+ VALUE DrizzleUnBufferedResult;
7
9
  VALUE DrizzleQuery;
10
+ VALUE DrizzleColumn;
8
11
 
9
12
  void init_downpour_module();
10
13
  void init_drizzle_status();
11
14
  void init_drizzle_connection();
12
15
  void init_drizzle_result();
16
+ void init_drizzle_buffered_result();
17
+ void init_drizzle_unbuffered_result();
13
18
  void init_drizzle_query();
19
+ void init_drizzle_column();
14
20
 
15
21
  void Init_downpour()
16
22
  {
@@ -18,5 +24,8 @@ void Init_downpour()
18
24
  init_drizzle_status();
19
25
  init_drizzle_connection();
20
26
  init_drizzle_result();
27
+ init_drizzle_buffered_result();
28
+ init_drizzle_unbuffered_result();
21
29
  init_drizzle_query();
30
+ init_drizzle_column();
22
31
  }
@@ -9,7 +9,10 @@ extern VALUE DownpourModule;
9
9
  extern VALUE DrizzleStatus;
10
10
  extern VALUE DrizzleConnection;
11
11
  extern VALUE DrizzleResult;
12
+ extern VALUE DrizzleBufferedResult;
13
+ extern VALUE DrizzleUnBufferedResult;
12
14
  extern VALUE DrizzleQuery;
15
+ extern VALUE DrizzleColumn;
13
16
 
14
17
  // All mark and release methods
15
18
  typedef void (*FREE_METHOD)(void* ptr);
@@ -18,25 +21,30 @@ void *downpour_from_ruby_object(VALUE value);
18
21
  VALUE downpour_to_ruby_object(void *ptr, VALUE klass, VALUE parent, FREE_METHOD free_method, SET_CONTEXT set_context);
19
22
  VALUE downpour_get_ruby_object(void *ptr);
20
23
  VALUE downpour_get_parent(VALUE self);
24
+ void downpour_set_extra_pointer(VALUE self, void *extra_pointer, FREE_METHOD free_extra_pointer);
25
+ void *downpour_get_extra_pointer(VALUE self);
21
26
 
22
27
  // All Constructors
23
28
  VALUE downpour_constructor(drizzle_st *self_ptr);
24
29
  VALUE downpour_connection_constructor(drizzle_con_st *self_ptr, VALUE status);
25
- VALUE downpour_result_constructor(drizzle_result_st *self_ptr, VALUE connection);
30
+ VALUE downpour_buffered_result_constructor(drizzle_result_st *self_ptr, VALUE connection);
31
+ VALUE downpour_unbuffered_result_constructor(drizzle_result_st *self_ptr, VALUE connection);
26
32
  VALUE downpour_query_constructor(drizzle_query_st *self_ptr, VALUE connection);
33
+ VALUE downpour_column_constructor(drizzle_column_st *self_ptr, VALUE result);
34
+ VALUE downpour_include_result_module(drizzle_result_st *self_ptr, VALUE self);
27
35
 
28
36
  VALUE drizzle_gem_create_class_with_private_constructor(const char *name, VALUE super);
29
37
  void drizzle_gem_assert_value_is_ok(drizzle_return_t value);
30
- VALUE drizzle_gem_to_string_array(char **array, long count);
31
38
  const char *drizzle_gem_read_string_with_default(VALUE string, const char *default_value);
32
39
 
33
- #define convert_to_struct(datatype, var_name, value) datatype *var_name; var_name = downpour_from_ruby_object(value)
40
+ #define convert_to_struct(datatype, var_name, value) datatype *var_name = downpour_from_ruby_object(value)
34
41
  #define read_self_ptr() convert_to_struct(SELF_TYPE, self_ptr, self)
35
42
  #define CHECK_OK(value) drizzle_gem_assert_value_is_ok(value)
36
43
  #define rb_call(self, string) rb_funcall(self, rb_intern(string), 0)
37
44
  #define read_string(value, default_value) drizzle_gem_read_string_with_default(value, default_value)
38
45
  #define drizzle_alloc(type) ((type *) malloc(sizeof(type)))
39
46
  #define to_ruby_object(ptr, klass, parent, free_method, set_context) downpour_to_ruby_object(ptr, klass, parent, (FREE_METHOD) (free_method), (SET_CONTEXT) (set_context))
47
+ #define set_extra_pointer(value, ptr, free_method) downpour_set_extra_pointer(value, ptr, (FREE_METHOD) free_method)
40
48
 
41
49
  // Property Macros -> define attr(foo, conversion) and settr_string to use them
42
50
  #define attr_string(foo) attr(foo, rb_str_new2)
@@ -5,17 +5,6 @@ static VALUE do_not_use_this_constructor(VALUE self)
5
5
  rb_raise(rb_eNameError, "private method `new' called for %s:Class.", rb_class2name(CLASS_OF(self)));
6
6
  }
7
7
 
8
- VALUE drizzle_gem_to_string_array(char **array, long count)
9
- {
10
- VALUE ary = rb_ary_new2(count);
11
-
12
- long i;
13
- for(i = 0; i < count; i++)
14
- rb_ary_push(ary, rb_str_new2(array[i]));
15
-
16
- return ary;
17
- }
18
-
19
8
  VALUE drizzle_gem_create_class_with_private_constructor(const char *name, VALUE super)
20
9
  {
21
10
  VALUE ret = rb_define_class_under(DownpourModule, name, super);
@@ -6,6 +6,8 @@ typedef struct DownpourWrapper {
6
6
  struct DownpourWrapper *parent;
7
7
  FREE_METHOD free_method;
8
8
  VALUE rb_object;
9
+ void *extra_pointer;
10
+ FREE_METHOD free_extra_pointer_method;
9
11
  } DownpourWrapper;
10
12
 
11
13
  static void downpour_mark(DownpourWrapper *wrapper)
@@ -16,6 +18,23 @@ static void downpour_mark(DownpourWrapper *wrapper)
16
18
  wrapper->reference_count++;
17
19
  }
18
20
 
21
+ static void exec_free_method(void *ptr, FREE_METHOD free_method)
22
+ {
23
+ if(ptr == NULL || free_method == NULL)
24
+ return;
25
+ free_method(ptr);
26
+ }
27
+
28
+ static void free_extra_pointer(DownpourWrapper *wrapper)
29
+ {
30
+ exec_free_method(wrapper->extra_pointer, wrapper->free_extra_pointer_method);
31
+ }
32
+
33
+ static void free_pointer(DownpourWrapper *wrapper)
34
+ {
35
+ exec_free_method(wrapper->ptr, wrapper->free_method);
36
+ }
37
+
19
38
  static void downpour_release(DownpourWrapper *wrapper)
20
39
  {
21
40
  if(wrapper == NULL)
@@ -24,7 +43,8 @@ static void downpour_release(DownpourWrapper *wrapper)
24
43
  wrapper->reference_count--;
25
44
 
26
45
  if(wrapper->reference_count == 0) {
27
- wrapper->free_method(wrapper->ptr);
46
+ free_extra_pointer(wrapper);
47
+ free_pointer(wrapper);
28
48
  downpour_release(wrapper->parent);
29
49
  free(wrapper);
30
50
  }
@@ -37,6 +57,8 @@ static DownpourWrapper *downpour_wrap_pointer(void *ptr, DownpourWrapper *parent
37
57
  wrapper->parent = parent;
38
58
  wrapper->free_method = free_method;
39
59
  wrapper->reference_count = 0;
60
+ wrapper->extra_pointer = NULL;
61
+ wrapper->free_extra_pointer_method = NULL;
40
62
 
41
63
  downpour_mark(parent);
42
64
  downpour_mark(wrapper);
@@ -101,3 +123,17 @@ VALUE downpour_get_parent(VALUE self)
101
123
 
102
124
  return wrapper->parent->rb_object;
103
125
  }
126
+
127
+ void downpour_set_extra_pointer(VALUE self, void *extra_pointer, FREE_METHOD free_extra_pointer_method)
128
+ {
129
+ DownpourWrapper *wrapper = get_wrapper_from_object(self);
130
+ free_extra_pointer(wrapper);
131
+ wrapper->extra_pointer = extra_pointer;
132
+ wrapper->free_extra_pointer_method = free_extra_pointer_method;
133
+ }
134
+
135
+ void *downpour_get_extra_pointer(VALUE self)
136
+ {
137
+ DownpourWrapper *wrapper = get_wrapper_from_object(self);
138
+ return wrapper->extra_pointer;
139
+ }
@@ -2,18 +2,13 @@
2
2
 
3
3
  #define SELF_TYPE drizzle_query_st
4
4
 
5
- static VALUE get_result(VALUE self)
5
+ static VALUE create_results(VALUE self)
6
6
  {
7
7
  read_self_ptr();
8
8
 
9
- VALUE cached_result = rb_iv_get(self, "@result");
10
- if(cached_result != Qnil)
11
- return cached_result;
12
-
13
9
  drizzle_result_st *result = drizzle_query_result(self_ptr);
14
10
  VALUE connection = downpour_get_parent(self);
15
- VALUE ret = rb_iv_set(self, "@result", downpour_result_constructor(result, connection));
16
- return ret;
11
+ return downpour_buffered_result_constructor(result, connection);
17
12
  }
18
13
 
19
14
  VALUE downpour_query_constructor(drizzle_query_st *self_ptr, VALUE connection)
@@ -24,5 +19,5 @@ VALUE downpour_query_constructor(drizzle_query_st *self_ptr, VALUE connection)
24
19
  void init_drizzle_query()
25
20
  {
26
21
  DrizzleQuery = drizzle_gem_create_class_with_private_constructor("Query", rb_cObject);
27
- rb_define_method(DrizzleQuery, "result", get_result, 0);
22
+ rb_define_private_method(DrizzleQuery, "create_results", create_results, 0);
28
23
  }
@@ -1,4 +1,5 @@
1
1
  #include "downpour.h"
2
+ #include "result.h"
2
3
 
3
4
  #define SELF_TYPE drizzle_result_st
4
5
  #define RUBY_CLASS DrizzleResult
@@ -9,67 +10,93 @@
9
10
  return conversion(drizzle_result_##foo(self_ptr));\
10
11
  }
11
12
 
12
- static uint64_t do_column_count(drizzle_result_st *self_ptr)
13
- {
14
- return drizzle_result_column_count(self_ptr);
15
- }
13
+ typedef struct ResultExtraInfo {
14
+ drizzle_column_st **columns;
15
+ } ResultExtraInfo;
16
16
 
17
- static bool is_buffered_bool(VALUE self)
17
+ static VALUE to_rb_value(char *str, drizzle_column_st *column)
18
18
  {
19
- read_self_ptr();
20
- return self_ptr->options & (DRIZZLE_RESULT_BUFFER_ROW);
21
- }
19
+ if(str == NULL)
20
+ return Qnil;
22
21
 
23
- static VALUE is_buffered(VALUE self)
22
+ #define not_implemented rb_str_new2(str)
23
+
24
+ switch(drizzle_column_type(column)) {
25
+ case DRIZZLE_COLUMN_TYPE_DECIMAL:
26
+ return not_implemented;
27
+
28
+ case DRIZZLE_COLUMN_TYPE_TINY:
29
+ case DRIZZLE_COLUMN_TYPE_SHORT:
30
+ case DRIZZLE_COLUMN_TYPE_LONG:
31
+ return INT2NUM(strtol(str, NULL, 10));
32
+
33
+ case DRIZZLE_COLUMN_TYPE_FLOAT:
34
+ case DRIZZLE_COLUMN_TYPE_DOUBLE:
35
+ return rb_float_new(strtod(str, NULL));
36
+
37
+ case DRIZZLE_COLUMN_TYPE_NULL:
38
+ case DRIZZLE_COLUMN_TYPE_TIMESTAMP:
39
+ case DRIZZLE_COLUMN_TYPE_LONGLONG:
40
+ case DRIZZLE_COLUMN_TYPE_INT24:
41
+ case DRIZZLE_COLUMN_TYPE_DATE:
42
+ case DRIZZLE_COLUMN_TYPE_TIME:
43
+ case DRIZZLE_COLUMN_TYPE_DATETIME:
44
+ case DRIZZLE_COLUMN_TYPE_YEAR:
45
+ case DRIZZLE_COLUMN_TYPE_NEWDATE:
46
+ return not_implemented;
47
+
48
+ case DRIZZLE_COLUMN_TYPE_VARCHAR:
49
+ return rb_str_new2(str);
50
+
51
+ case DRIZZLE_COLUMN_TYPE_BIT:
52
+ case DRIZZLE_COLUMN_TYPE_NEWDECIMAL:
53
+ case DRIZZLE_COLUMN_TYPE_ENUM:
54
+ case DRIZZLE_COLUMN_TYPE_SET:
55
+ case DRIZZLE_COLUMN_TYPE_TINY_BLOB:
56
+ case DRIZZLE_COLUMN_TYPE_MEDIUM_BLOB:
57
+ case DRIZZLE_COLUMN_TYPE_LONG_BLOB:
58
+ case DRIZZLE_COLUMN_TYPE_BLOB:
59
+ case DRIZZLE_COLUMN_TYPE_VAR_STRING:
60
+ case DRIZZLE_COLUMN_TYPE_STRING:
61
+ case DRIZZLE_COLUMN_TYPE_GEOMETRY:
62
+
63
+ default:
64
+ return not_implemented;
65
+ }
66
+ }
67
+
68
+ static VALUE to_results_array(char **array, long count, drizzle_column_st **columns)
24
69
  {
25
- return is_buffered_bool(self) ? Qtrue : Qfalse;
26
- }
70
+ VALUE ary = rb_ary_new2(count);
27
71
 
28
- static void raise_if_buffering_is_not_allowed(VALUE self)
29
- {
30
- if(RTEST(rb_iv_get(self, "@cannot_buffer")))
31
- rb_raise(rb_eIOError, "cannot buffer after reading a row");
32
- }
72
+ long i;
73
+ for(i = 0; i < count; i++)
74
+ rb_ary_push(ary, to_rb_value(array[i], columns[i]));
33
75
 
34
- static void disallow_buffering(VALUE self)
35
- {
36
- rb_iv_set(self, "@cannot_buffer", Qtrue);
76
+ return ary;
37
77
  }
38
78
 
39
- static VALUE buffer_if_needed(VALUE self)
79
+ VALUE downpour_wrap_row(VALUE self, drizzle_result_st *self_ptr, drizzle_row_t row)
40
80
  {
41
- read_self_ptr();
42
-
43
- raise_if_buffering_is_not_allowed(self);
81
+ // No more rows to read :-)
82
+ if(row == NULL)
83
+ return Qnil;
44
84
 
45
- // Only buffer once
46
- if(is_buffered_bool(self))
47
- return Qfalse;
85
+ ResultExtraInfo *extra_info = downpour_get_extra_pointer(self);
48
86
 
49
- CHECK_OK(drizzle_result_buffer(self_ptr));
50
- return Qtrue;
87
+ return to_results_array(row, drizzle_result_column_count(self_ptr), extra_info->columns);
51
88
  }
52
89
 
53
- static VALUE row_count(VALUE self)
90
+ bool downpour_is_buffered(drizzle_result_st *self_ptr)
54
91
  {
55
- rb_call(self, "buffer!");
56
- read_self_ptr();
57
- return UINT2NUM(drizzle_result_row_count(self_ptr));
92
+ return self_ptr->options & (DRIZZLE_RESULT_BUFFER_ROW);
58
93
  }
59
94
 
60
- static VALUE wrap_row(drizzle_result_st *self_ptr, drizzle_row_t row)
95
+ static VALUE is_buffered(VALUE self)
61
96
  {
62
- // No more rows to read :-)
63
- if(row == NULL)
64
- return Qnil;
65
-
66
- return drizzle_gem_to_string_array(row, do_column_count(self_ptr));
67
- }
97
+ read_self_ptr();
68
98
 
69
- static VALUE next_row_buffered(drizzle_result_st *self_ptr)
70
- {
71
- drizzle_row_t result = drizzle_row_next(self_ptr);
72
- return wrap_row(self_ptr, result);
99
+ return downpour_is_buffered(self_ptr) ? Qtrue : Qfalse;
73
100
  }
74
101
 
75
102
  static void buffer_column_if_needed(drizzle_result_st *self_ptr)
@@ -79,34 +106,45 @@ static void buffer_column_if_needed(drizzle_result_st *self_ptr)
79
106
  CHECK_OK(drizzle_column_buffer(self_ptr));
80
107
  }
81
108
 
82
- static drizzle_row_t do_drizzle_row_buffer(drizzle_result_st *self_ptr)
109
+ static drizzle_column_st *next_column(drizzle_result_st *self_ptr)
83
110
  {
84
- drizzle_return_t ret;
85
- drizzle_row_t result = drizzle_row_buffer(self_ptr, &ret);
86
- CHECK_OK(ret);
87
- return result;
111
+ return drizzle_column_next(self_ptr);
88
112
  }
89
113
 
90
- static VALUE next_row_unbuffered(drizzle_result_st *self_ptr)
114
+ static ResultExtraInfo *extra_info(drizzle_result_st *self_ptr)
91
115
  {
92
116
  buffer_column_if_needed(self_ptr);
93
- drizzle_row_t result = do_drizzle_row_buffer(self_ptr);
94
- VALUE parsed = wrap_row(self_ptr, result);
95
- if(result)
96
- drizzle_row_free(self_ptr, result);
97
- return parsed;
117
+
118
+ ResultExtraInfo *result = drizzle_alloc(ResultExtraInfo);
119
+ int i, number_of_columns = drizzle_result_column_count(self_ptr);
120
+ result->columns = malloc(sizeof(drizzle_column_st *) * (number_of_columns + 1));
121
+
122
+ for (i = 0; i < number_of_columns; i++) {
123
+ result->columns[i] = next_column(self_ptr);
124
+ }
125
+ result->columns[number_of_columns] = NULL;
126
+ return result;
98
127
  }
99
128
 
100
- static VALUE next_row(VALUE self)
129
+ static void free_extra_info(ResultExtraInfo *extra_info)
101
130
  {
102
- read_self_ptr();
131
+ int i;
132
+ for (i = 0; extra_info->columns[i] != NULL; i++) {
133
+ drizzle_column_free(extra_info->columns[i]);
134
+ }
135
+ free(extra_info->columns);
136
+ free(extra_info);
137
+ }
103
138
 
104
- disallow_buffering(self);
139
+ static VALUE get_columns_in_array(drizzle_result_st *self_ptr, VALUE self, ResultExtraInfo *extra_info)
140
+ {
141
+ int i, number_of_columns = drizzle_result_column_count(self_ptr);
142
+ VALUE array = rb_ary_new2(number_of_columns);
105
143
 
106
- if(is_buffered_bool(self))
107
- return next_row_buffered(self_ptr);
144
+ for (i = 0; i < number_of_columns; i++)
145
+ rb_ary_push(array, downpour_column_constructor(extra_info->columns[i], self));
108
146
 
109
- return next_row_unbuffered(self_ptr);
147
+ return array;
110
148
  }
111
149
 
112
150
  attr(column_count, UINT2NUM);
@@ -118,18 +156,18 @@ attr_string(sqlstate);
118
156
  attr_string(info);
119
157
  attr_string(error);
120
158
 
121
- VALUE downpour_result_constructor(drizzle_result_st *self_ptr, VALUE connection)
159
+ VALUE downpour_include_result_module(drizzle_result_st *self_ptr, VALUE result)
122
160
  {
123
- return to_ruby_object(self_ptr, DrizzleResult, connection, drizzle_result_free, NULL);
161
+ ResultExtraInfo *info = extra_info(self_ptr);
162
+ set_extra_pointer(result, info, free_extra_info);
163
+ rb_iv_set(result, "@columns", get_columns_in_array(self_ptr, result, info));
164
+ return result;
124
165
  }
125
166
 
126
167
  void init_drizzle_result()
127
168
  {
128
- DrizzleResult = drizzle_gem_create_class_with_private_constructor("Result", rb_cObject);
129
- rb_define_method(DrizzleResult, "row_count", row_count, 0);
130
- rb_define_method(DrizzleResult, "buffer!", buffer_if_needed, 0);
169
+ DrizzleResult = rb_define_module_under(DownpourModule, "Result");
131
170
  rb_define_method(DrizzleResult, "buffered?", is_buffered, 0);
132
- rb_define_method(DrizzleResult, "next_row", next_row, 0);
133
171
  define_attr(column_count);
134
172
  define_attr(insert_id);
135
173
  define_attr(error_code);
@@ -0,0 +1,9 @@
1
+ #ifndef RESULTS_H
2
+ #define RESULTS_H
3
+
4
+ #include "downpour.h"
5
+
6
+ bool downpour_is_buffered(drizzle_result_st *self_ptr);
7
+ VALUE downpour_wrap_row(VALUE self, drizzle_result_st *self_ptr, drizzle_row_t row);
8
+
9
+ #endif
@@ -0,0 +1,53 @@
1
+ #include "downpour.h"
2
+ #include "result.h"
3
+
4
+ #define SELF_TYPE drizzle_result_st
5
+ #define RUBY_CLASS DrizzleUnBufferedResult
6
+
7
+ #define attr(foo, conversion) static VALUE attr_##foo(VALUE self)\
8
+ {\
9
+ read_self_ptr();\
10
+ return conversion(drizzle_result_##foo(self_ptr));\
11
+ }
12
+
13
+ static drizzle_row_t do_drizzle_row_buffer(drizzle_result_st *self_ptr)
14
+ {
15
+ drizzle_return_t ret;
16
+ drizzle_row_t result = drizzle_row_buffer(self_ptr, &ret);
17
+ CHECK_OK(ret);
18
+ return result;
19
+ }
20
+
21
+ static VALUE next_row(VALUE self)
22
+ {
23
+ read_self_ptr();
24
+
25
+ drizzle_row_t result = do_drizzle_row_buffer(self_ptr);
26
+ VALUE parsed = downpour_wrap_row(self, self_ptr, result);
27
+ if(result)
28
+ drizzle_row_free(self_ptr, result);
29
+ return parsed;
30
+ }
31
+
32
+ // Improve this method
33
+ static VALUE end_result(VALUE self)
34
+ {
35
+ read_self_ptr();
36
+ while(do_drizzle_row_buffer(self_ptr) != NULL)
37
+ ; // Do Nothing
38
+ return Qnil;
39
+ }
40
+
41
+ VALUE downpour_unbuffered_result_constructor(drizzle_result_st *self_ptr, VALUE connection)
42
+ {
43
+ VALUE ret = to_ruby_object(self_ptr, DrizzleUnBufferedResult, connection, drizzle_result_free, NULL);
44
+ return downpour_include_result_module(self_ptr, ret);
45
+ }
46
+
47
+ void init_drizzle_unbuffered_result()
48
+ {
49
+ DrizzleUnBufferedResult = drizzle_gem_create_class_with_private_constructor("UnBufferedResult", rb_cObject);
50
+ rb_include_module(DrizzleUnBufferedResult, DrizzleResult);
51
+ rb_define_method(DrizzleUnBufferedResult, "next_row", next_row, 0);
52
+ rb_define_method(DrizzleUnBufferedResult, "close!", end_result, 0);
53
+ }
@@ -1,3 +1,5 @@
1
1
  require 'downpour/downpour'
2
2
  require 'downpour/status'
3
3
  require 'downpour/version'
4
+ require 'downpour/query'
5
+ require 'downpour/result'
@@ -0,0 +1,8 @@
1
+ module Downpour
2
+ class Query
3
+ def result
4
+ return @result if @result
5
+ @result = create_results
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Downpour
2
+ module Result
3
+ attr_reader :columns
4
+ end
5
+ end
@@ -1,3 +1,3 @@
1
1
  module Downpour
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.12"
3
3
  end
@@ -11,3 +11,12 @@ create table Test2 (
11
11
  id int auto_increment primary key,
12
12
  name varchar(20)
13
13
  );
14
+
15
+ drop table if exists TestFieldTypes;
16
+ create table TestFieldTypes (
17
+ null_field int,
18
+ string_field varchar(20),
19
+ int_field int,
20
+ double_field float
21
+ );
22
+ insert into TestFieldTypes values(NULL, 'foo', 42, 8.5);
@@ -0,0 +1,20 @@
1
+ describe "a buffered query" do
2
+
3
+ before(:each) do
4
+ @status = Downpour.create
5
+ @conn = create_connection(@status)
6
+ @results = @conn.query "select * from Test1"
7
+ end
8
+
9
+ it "should count records" do
10
+ @results.row_count.should == 3
11
+ end
12
+
13
+ it "should be able to run a second query" do
14
+ @conn.query "select * from Test2"
15
+ end
16
+
17
+ it "should be buffered" do
18
+ @results.should be_buffered
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ describe "a drizzle result" do
2
+
3
+ before(:each) do
4
+ @status = Downpour.create
5
+ @conn = create_connection(@status)
6
+ @results = @conn.query "select id, name as newName from Test2"
7
+ end
8
+
9
+ it "should fetch all columns" do
10
+ @results.columns.size.should == 2
11
+ end
12
+
13
+ it "should count columns" do
14
+ @results.column_count.should == 2
15
+ end
16
+
17
+ it "should fetch column name" do
18
+ @results.columns[0].name.should == "id"
19
+ @results.columns[1].name.should == "newName"
20
+ end
21
+
22
+ it "should fetch the original name from table" do
23
+ @results.columns[1].orig_name.should == "name"
24
+ end
25
+
26
+ it "should have table name set on column" do
27
+ @results.columns[0].table.should == "Test2"
28
+ end
29
+
30
+ it "should return the same column each time" do
31
+ @results.columns[0].should == @results.columns[0]
32
+ end
33
+ end
@@ -9,12 +9,6 @@ describe "a concurrent query" do
9
9
  end
10
10
 
11
11
  context "when running all" do
12
- it "should buffer all queries" do
13
- @status.run_all!
14
- @query1.result.should be_buffered
15
- @query2.result.should be_buffered
16
- end
17
-
18
12
  it "should run all queries" do
19
13
  @status.run_all!
20
14
  @query1.result.next_row.should == ["foo"]
@@ -43,6 +37,10 @@ describe "a concurrent query" do
43
37
  @status.run!.should be_nil
44
38
  end
45
39
 
40
+ it "should have buffered the results" do
41
+ @status.run!.result.should be_buffered
42
+ end
43
+
46
44
  it "should release pending queries" do
47
45
  query = @status.run!
48
46
  @status.pending_queries.should_not include(query)
@@ -18,14 +18,6 @@ describe "downpour connections" do
18
18
  it "should only accept a string as query" do
19
19
  lambda {@connection.query 42}.should raise_error(TypeError)
20
20
  end
21
-
22
- it "should throw error if you try to read a row then buffer" do
23
- lambda do
24
- q = @connection.query "select * from Test1"
25
- q.next_row
26
- q.buffer!
27
- end.should raise_error(IOError)
28
- end
29
21
  end
30
22
 
31
23
  context "simple attributes" do
@@ -1,49 +1,57 @@
1
- describe "a select query" do
1
+ describe "select queries" do
2
2
 
3
3
  before(:each) do
4
4
  @status = Downpour.create
5
5
  @conn = create_connection(@status)
6
- @results = @conn.query "select * from Test1"
7
6
  end
8
7
 
9
- it "should count records" do
10
- @results.row_count.should == 3
11
- @results.should be_buffered
12
- end
8
+ shared_examples_for "a select query" do
9
+ it "should read all rows" do
10
+ results = @create_results.call "select * from Test1"
11
+ results.next_row.should == ["foo"]
12
+ results.next_row.should == ["bar"]
13
+ results.next_row.should == ["baz"]
14
+ results.next_row.should be_nil
15
+ end
13
16
 
14
- it "should buffer records" do
15
- @results.should_not be_buffered
16
- @results.buffer!
17
- @results.should be_buffered
18
- end
17
+ context "with different data types" do
18
+ before(:each) { @row = @create_results.call("select * from TestFieldTypes").next_row }
19
19
 
20
- it "should only buffer records once" do
21
- @results.buffer!.should be_true
22
- @results.buffer!.should be_false
23
- end
20
+ it "should read nil when there is null in the db" do
21
+ @row[0].should be_nil
22
+ end
24
23
 
25
- shared_examples_for "a read query" do
26
- it "should read all rows" do
27
- @results.next_row.should == ["foo"]
28
- @results.next_row.should == ["bar"]
29
- @results.next_row.should == ["baz"]
30
- @results.next_row.should be_nil
31
- end
24
+ it "should read a string" do
25
+ @row[1].should == "foo"
26
+ end
27
+
28
+ it "should read an integer" do
29
+ @row[2].should == 42
30
+ end
32
31
 
33
- it "should count columns" do
34
- @results.column_count.should == 1
32
+ it "should read a floating point" do
33
+ @row[3].should == 8.5
34
+ end
35
35
  end
36
36
  end
37
37
 
38
- context "without buffering" do
39
- it_should_behave_like "a read query"
40
-
41
- after(:each) {@results.should_not be_buffered}
38
+ context "an buffered select query" do
39
+ before(:each) { @create_results = lambda { |query| @conn.query query }}
40
+ it_should_behave_like "a select query"
42
41
  end
43
42
 
44
- context "with buffering" do
45
- before(:each) { @results.buffer! }
43
+ context "an unbuffered select query" do
44
+ before(:each) { @create_results = lambda { |query| @conn.unbuffered_query query }}
45
+ it_should_behave_like "a select query"
46
+ end
46
47
 
47
- it_should_behave_like "a read query"
48
+ context "a concurrent select query" do
49
+ before(:each) do
50
+ @create_results = lambda do |query|
51
+ @status.add_query @conn, query
52
+ @status.run!.result
53
+ end
54
+ end
55
+ it_should_behave_like "a select query"
48
56
  end
49
57
  end
@@ -0,0 +1,26 @@
1
+ describe "an unbuffered select query" do
2
+
3
+ before(:each) do
4
+ @status = Downpour.create
5
+ @conn = create_connection(@status)
6
+ @results = @conn.unbuffered_query "select * from Test1"
7
+ end
8
+
9
+ it "should be able to run a second query after all rows are read" do
10
+ 4.times { @results.next_row }
11
+ @conn.query "select * from Test2"
12
+ end
13
+
14
+ it "should be able to run another query after closing the query" do
15
+ @results.close!
16
+ @conn.query "select * from Test2"
17
+ end
18
+
19
+ it "should be unbuffered" do
20
+ @results.should_not be_buffered
21
+ end
22
+
23
+ it "should get column count" do
24
+ @results.column_count.should == 1
25
+ end
26
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: downpour
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.7
5
+ version: 0.0.12
6
6
  platform: ruby
7
7
  authors:
8
8
  - Tejas Dinkar
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-06-03 00:00:00 +05:30
13
+ date: 2011-06-12 00:00:00 +05:30
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -45,6 +45,8 @@ extra_rdoc_files:
45
45
  - README.rdoc
46
46
  files:
47
47
  - downpour.gemspec
48
+ - ext/downpour/buffered_result.c
49
+ - ext/downpour/column.c
48
50
  - ext/downpour/connection.c
49
51
  - ext/downpour/downpour.c
50
52
  - ext/downpour/downpour.h
@@ -54,11 +56,17 @@ files:
54
56
  - ext/downpour/module.c
55
57
  - ext/downpour/query.c
56
58
  - ext/downpour/result.c
59
+ - ext/downpour/result.h
57
60
  - ext/downpour/status.c
61
+ - ext/downpour/unbuffered_result.c
58
62
  - lib/downpour.rb
63
+ - lib/downpour/query.rb
64
+ - lib/downpour/result.rb
59
65
  - lib/downpour/status.rb
60
66
  - lib/downpour/version.rb
61
67
  - spec/bootstrap.sql
68
+ - spec/downpour/buffered_spec.rb
69
+ - spec/downpour/column_spec.rb
62
70
  - spec/downpour/concurrent_spec.rb
63
71
  - spec/downpour/connect_type_spec.rb
64
72
  - spec/downpour/connection_spec.rb
@@ -66,6 +74,7 @@ files:
66
74
  - spec/downpour/memory_mgmt_spec.rb
67
75
  - spec/downpour/module_spec.rb
68
76
  - spec/downpour/select_spec.rb
77
+ - spec/downpour/unbuffered_spec.rb
69
78
  - spec/spec_helper.rb
70
79
  - README.rdoc
71
80
  has_rdoc: true
@@ -99,6 +108,8 @@ specification_version: 3
99
108
  summary: A simple, fast Mysql and Drizzle library for Ruby, binding to libdrizzle
100
109
  test_files:
101
110
  - spec/bootstrap.sql
111
+ - spec/downpour/buffered_spec.rb
112
+ - spec/downpour/column_spec.rb
102
113
  - spec/downpour/concurrent_spec.rb
103
114
  - spec/downpour/connect_type_spec.rb
104
115
  - spec/downpour/connection_spec.rb
@@ -106,4 +117,5 @@ test_files:
106
117
  - spec/downpour/memory_mgmt_spec.rb
107
118
  - spec/downpour/module_spec.rb
108
119
  - spec/downpour/select_spec.rb
120
+ - spec/downpour/unbuffered_spec.rb
109
121
  - spec/spec_helper.rb