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.
- data/README.rdoc +1 -1
- data/ext/downpour/buffered_result.c +45 -0
- data/ext/downpour/column.c +50 -0
- data/ext/downpour/connection.c +13 -2
- data/ext/downpour/downpour.c +9 -0
- data/ext/downpour/downpour.h +11 -3
- data/ext/downpour/helpers.c +0 -11
- data/ext/downpour/memory_allocation.c +37 -1
- data/ext/downpour/query.c +3 -8
- data/ext/downpour/result.c +104 -66
- data/ext/downpour/result.h +9 -0
- data/ext/downpour/unbuffered_result.c +53 -0
- data/lib/downpour.rb +2 -0
- data/lib/downpour/query.rb +8 -0
- data/lib/downpour/result.rb +5 -0
- data/lib/downpour/version.rb +1 -1
- data/spec/bootstrap.sql +9 -0
- data/spec/downpour/buffered_spec.rb +20 -0
- data/spec/downpour/column_spec.rb +33 -0
- data/spec/downpour/concurrent_spec.rb +4 -6
- data/spec/downpour/connection_spec.rb +0 -8
- data/spec/downpour/select_spec.rb +39 -31
- data/spec/downpour/unbuffered_spec.rb +26 -0
- metadata +14 -2
data/README.rdoc
CHANGED
@@ -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
|
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
|
+
}
|
data/ext/downpour/connection.c
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
return newValue;\
|
17
17
|
}
|
18
18
|
|
19
|
-
static
|
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
|
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);
|
data/ext/downpour/downpour.c
CHANGED
@@ -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
|
}
|
data/ext/downpour/downpour.h
CHANGED
@@ -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
|
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
|
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)
|
data/ext/downpour/helpers.c
CHANGED
@@ -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
|
-
|
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
|
+
}
|
data/ext/downpour/query.c
CHANGED
@@ -2,18 +2,13 @@
|
|
2
2
|
|
3
3
|
#define SELF_TYPE drizzle_query_st
|
4
4
|
|
5
|
-
static VALUE
|
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
|
-
|
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
|
-
|
22
|
+
rb_define_private_method(DrizzleQuery, "create_results", create_results, 0);
|
28
23
|
}
|
data/ext/downpour/result.c
CHANGED
@@ -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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
}
|
13
|
+
typedef struct ResultExtraInfo {
|
14
|
+
drizzle_column_st **columns;
|
15
|
+
} ResultExtraInfo;
|
16
16
|
|
17
|
-
static
|
17
|
+
static VALUE to_rb_value(char *str, drizzle_column_st *column)
|
18
18
|
{
|
19
|
-
|
20
|
-
|
21
|
-
}
|
19
|
+
if(str == NULL)
|
20
|
+
return Qnil;
|
22
21
|
|
23
|
-
|
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
|
-
|
26
|
-
}
|
70
|
+
VALUE ary = rb_ary_new2(count);
|
27
71
|
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
35
|
-
{
|
36
|
-
rb_iv_set(self, "@cannot_buffer", Qtrue);
|
76
|
+
return ary;
|
37
77
|
}
|
38
78
|
|
39
|
-
|
79
|
+
VALUE downpour_wrap_row(VALUE self, drizzle_result_st *self_ptr, drizzle_row_t row)
|
40
80
|
{
|
41
|
-
|
42
|
-
|
43
|
-
|
81
|
+
// No more rows to read :-)
|
82
|
+
if(row == NULL)
|
83
|
+
return Qnil;
|
44
84
|
|
45
|
-
|
46
|
-
if(is_buffered_bool(self))
|
47
|
-
return Qfalse;
|
85
|
+
ResultExtraInfo *extra_info = downpour_get_extra_pointer(self);
|
48
86
|
|
49
|
-
|
50
|
-
return Qtrue;
|
87
|
+
return to_results_array(row, drizzle_result_column_count(self_ptr), extra_info->columns);
|
51
88
|
}
|
52
89
|
|
53
|
-
|
90
|
+
bool downpour_is_buffered(drizzle_result_st *self_ptr)
|
54
91
|
{
|
55
|
-
|
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
|
95
|
+
static VALUE is_buffered(VALUE self)
|
61
96
|
{
|
62
|
-
|
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
|
-
|
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
|
109
|
+
static drizzle_column_st *next_column(drizzle_result_st *self_ptr)
|
83
110
|
{
|
84
|
-
|
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
|
114
|
+
static ResultExtraInfo *extra_info(drizzle_result_st *self_ptr)
|
91
115
|
{
|
92
116
|
buffer_column_if_needed(self_ptr);
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
129
|
+
static void free_extra_info(ResultExtraInfo *extra_info)
|
101
130
|
{
|
102
|
-
|
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
|
-
|
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
|
-
|
107
|
-
|
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
|
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
|
159
|
+
VALUE downpour_include_result_module(drizzle_result_st *self_ptr, VALUE result)
|
122
160
|
{
|
123
|
-
|
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 =
|
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,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
|
+
}
|
data/lib/downpour.rb
CHANGED
data/lib/downpour/version.rb
CHANGED
data/spec/bootstrap.sql
CHANGED
@@ -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 "
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
34
|
-
|
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 "
|
39
|
-
|
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 "
|
45
|
-
before(:each) { @
|
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
|
-
|
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.
|
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-
|
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
|