downpour 0.0.7 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -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