extralite 2.5 → 2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +34 -13
- data/Gemfile +4 -0
- data/Gemfile-bundle +1 -1
- data/LICENSE +1 -1
- data/README.md +1059 -247
- data/Rakefile +18 -0
- data/TODO.md +0 -7
- data/examples/kv_store.rb +49 -0
- data/examples/multi_fiber.rb +16 -0
- data/examples/on_progress.rb +9 -0
- data/examples/pubsub_store_polyphony.rb +194 -0
- data/examples/pubsub_store_threads.rb +204 -0
- data/ext/extralite/changeset.c +463 -0
- data/ext/extralite/common.c +177 -91
- data/ext/extralite/database.c +745 -276
- data/ext/extralite/extconf-bundle.rb +10 -4
- data/ext/extralite/extconf.rb +34 -34
- data/ext/extralite/extralite.h +104 -47
- data/ext/extralite/extralite_ext.c +6 -0
- data/ext/extralite/iterator.c +14 -86
- data/ext/extralite/query.c +171 -264
- data/extralite-bundle.gemspec +1 -1
- data/extralite.gemspec +1 -1
- data/gemspec.rb +10 -11
- data/lib/extralite/version.rb +1 -1
- data/lib/extralite.rb +69 -10
- data/lib/sequel/adapters/extralite.rb +1 -1
- data/test/helper.rb +9 -1
- data/test/perf_argv_transform.rb +74 -0
- data/test/perf_ary.rb +14 -12
- data/test/perf_hash.rb +17 -15
- data/test/perf_hash_prepared.rb +58 -0
- data/test/perf_hash_transform.rb +66 -0
- data/test/perf_polyphony.rb +74 -0
- data/test/test_changeset.rb +161 -0
- data/test/test_database.rb +720 -104
- data/test/test_extralite.rb +2 -2
- data/test/test_iterator.rb +28 -13
- data/test/test_query.rb +352 -110
- data/test/test_sequel.rb +4 -4
- metadata +24 -16
- data/Gemfile.lock +0 -37
- data/test/perf_prepared.rb +0 -64
@@ -6,11 +6,17 @@ $CFLAGS << ' -Wno-undef'
|
|
6
6
|
$CFLAGS << ' -Wno-discarded-qualifiers'
|
7
7
|
$CFLAGS << ' -Wno-unused-function'
|
8
8
|
|
9
|
-
|
10
|
-
$defs <<
|
11
|
-
$defs <<
|
9
|
+
# enable the session extension
|
10
|
+
$defs << '-DSQLITE_ENABLE_SESSION'
|
11
|
+
$defs << '-DSQLITE_ENABLE_PREUPDATE_HOOK'
|
12
|
+
$defs << '-DEXTRALITE_ENABLE_CHANGESET'
|
12
13
|
|
13
|
-
|
14
|
+
$defs << '-DHAVE_SQLITE3_ENABLE_LOAD_EXTENSION'
|
15
|
+
$defs << '-DHAVE_SQLITE3_LOAD_EXTENSION'
|
16
|
+
$defs << '-DHAVE_SQLITE3_PREPARE_V2'
|
17
|
+
$defs << '-DHAVE_SQLITE3_ERROR_OFFSET'
|
18
|
+
$defs << '-DHAVE_SQLITE3SESSION_CHANGESET'
|
14
19
|
|
20
|
+
have_func('usleep')
|
15
21
|
dir_config('extralite_ext')
|
16
22
|
create_makefile('extralite_ext')
|
data/ext/extralite/extconf.rb
CHANGED
@@ -35,60 +35,60 @@ else
|
|
35
35
|
end
|
36
36
|
|
37
37
|
if with_config('sqlcipher')
|
38
|
-
pkg_config(
|
38
|
+
pkg_config('sqlcipher')
|
39
39
|
else
|
40
|
-
pkg_config(
|
40
|
+
pkg_config('sqlite3')
|
41
41
|
end
|
42
42
|
|
43
43
|
# --with-sqlite3-{dir,include,lib}
|
44
44
|
if with_config('sqlcipher')
|
45
45
|
$CFLAGS << ' -DUSING_SQLCIPHER'
|
46
|
-
dir_config(
|
46
|
+
dir_config('sqlcipher', cppflags, ldflags)
|
47
47
|
else
|
48
|
-
dir_config(
|
48
|
+
dir_config('sqlite3', cppflags, ldflags)
|
49
49
|
end
|
50
50
|
|
51
|
-
if RbConfig::CONFIG[
|
51
|
+
if RbConfig::CONFIG['host_os'] =~ /mswin/
|
52
52
|
$CFLAGS << ' -W3'
|
53
53
|
end
|
54
54
|
|
55
|
-
if RUBY_VERSION < '2.7'
|
56
|
-
$CFLAGS << ' -DTAINTING_SUPPORT'
|
57
|
-
end
|
58
|
-
|
59
55
|
# @!visibility private
|
60
56
|
def asplode missing
|
61
57
|
if RUBY_PLATFORM =~ /mingw|mswin/
|
62
|
-
abort "#{missing} is missing. Install SQLite3 from "
|
63
|
-
"http://www.sqlite.org/ first."
|
58
|
+
abort "#{missing} is missing. Install SQLite3 from http://www.sqlite.org/ first."
|
64
59
|
else
|
65
|
-
abort
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
60
|
+
abort <<~error
|
61
|
+
#{missing} is missing. Try 'brew install sqlite3',
|
62
|
+
'yum install sqlite-devel' or 'apt-get install libsqlite3-dev'
|
63
|
+
and check your shared library search path (the location where
|
64
|
+
your sqlite3 shared library is located).
|
65
|
+
error
|
72
66
|
end
|
67
|
+
end
|
73
68
|
|
74
|
-
|
75
|
-
|
69
|
+
asplode('sqlite3.h') unless find_header('sqlite3.h')
|
70
|
+
# find_library 'pthread', 'pthread_create' # 1.8 support. *shrug*
|
76
71
|
|
77
|
-
|
72
|
+
have_library 'dl' # for static builds
|
78
73
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
74
|
+
if with_config('sqlcipher')
|
75
|
+
asplode('sqlcipher') unless find_library 'sqlcipher', 'sqlite3_libversion_number'
|
76
|
+
else
|
77
|
+
asplode('sqlite3') unless find_library 'sqlite3', 'sqlite3_libversion_number'
|
78
|
+
end
|
84
79
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
80
|
+
have_func('sqlite3_enable_load_extension')
|
81
|
+
have_func('sqlite3_load_extension')
|
82
|
+
have_func('sqlite3_prepare_v2')
|
83
|
+
have_func('sqlite3_error_offset')
|
84
|
+
have_func('sqlite3session_changeset')
|
85
|
+
|
86
|
+
if have_type('sqlite3_session', 'sqlite.h')
|
87
|
+
$defs << '-DEXTRALITE_ENABLE_CHANGESET'
|
88
|
+
end
|
89
89
|
|
90
|
-
|
90
|
+
$defs << '-DEXTRALITE_NO_BUNDLE'
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
|
92
|
+
dir_config('extralite_ext')
|
93
|
+
create_makefile('extralite_ext')
|
94
|
+
end
|
data/ext/extralite/extralite.h
CHANGED
@@ -17,12 +17,15 @@
|
|
17
17
|
VALUE s = rb_funcall(obj, rb_intern("inspect"), 0); \
|
18
18
|
printf(": %s\n", StringValueCStr(s)); \
|
19
19
|
}
|
20
|
+
#define CALLER() rb_funcall(rb_mKernel, rb_intern("caller"), 0)
|
21
|
+
#define TRACE_CALLER() INSPECT("caller: ", CALLER())
|
20
22
|
|
21
23
|
#define SAFE(f) (VALUE (*)(VALUE))(f)
|
22
24
|
|
23
25
|
extern VALUE cDatabase;
|
24
26
|
extern VALUE cQuery;
|
25
27
|
extern VALUE cIterator;
|
28
|
+
extern VALUE cChangeset;
|
26
29
|
extern VALUE cBlob;
|
27
30
|
|
28
31
|
extern VALUE cError;
|
@@ -36,54 +39,95 @@ extern ID ID_each;
|
|
36
39
|
extern ID ID_keys;
|
37
40
|
extern ID ID_new;
|
38
41
|
extern ID ID_strip;
|
42
|
+
extern ID ID_to_s;
|
43
|
+
extern ID ID_track;
|
39
44
|
|
40
|
-
extern VALUE
|
45
|
+
extern VALUE SYM_argv;
|
41
46
|
extern VALUE SYM_ary;
|
42
|
-
extern VALUE
|
47
|
+
extern VALUE SYM_hash;
|
48
|
+
|
49
|
+
enum progress_handler_mode {
|
50
|
+
PROGRESS_NONE,
|
51
|
+
PROGRESS_NORMAL,
|
52
|
+
PROGRESS_ONCE,
|
53
|
+
PROGRESS_AT_LEAST_ONCE,
|
54
|
+
};
|
55
|
+
|
56
|
+
struct progress_handler {
|
57
|
+
enum progress_handler_mode mode;
|
58
|
+
VALUE proc;
|
59
|
+
int period;
|
60
|
+
int tick;
|
61
|
+
int tick_count;
|
62
|
+
int call_count;
|
63
|
+
};
|
43
64
|
|
44
65
|
typedef struct {
|
45
|
-
sqlite3
|
46
|
-
VALUE
|
47
|
-
int
|
66
|
+
sqlite3 *sqlite3_db;
|
67
|
+
VALUE trace_proc;
|
68
|
+
int gvl_release_threshold;
|
69
|
+
struct progress_handler progress_handler;
|
48
70
|
} Database_t;
|
49
71
|
|
72
|
+
enum query_mode {
|
73
|
+
QUERY_HASH,
|
74
|
+
QUERY_ARGV,
|
75
|
+
QUERY_ARY
|
76
|
+
};
|
77
|
+
|
50
78
|
typedef struct {
|
51
|
-
VALUE
|
52
|
-
VALUE
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
int
|
79
|
+
VALUE db;
|
80
|
+
VALUE sql;
|
81
|
+
VALUE transform_proc;
|
82
|
+
Database_t *db_struct;
|
83
|
+
sqlite3 *sqlite3_db;
|
84
|
+
sqlite3_stmt *stmt;
|
85
|
+
int eof;
|
86
|
+
int closed;
|
87
|
+
enum query_mode query_mode;
|
58
88
|
} Query_t;
|
59
89
|
|
60
90
|
enum iterator_mode {
|
61
91
|
ITERATOR_HASH,
|
92
|
+
ITERATOR_ARGV,
|
62
93
|
ITERATOR_ARY,
|
63
94
|
ITERATOR_SINGLE_COLUMN
|
64
95
|
};
|
65
96
|
|
66
97
|
typedef struct {
|
67
98
|
VALUE query;
|
68
|
-
enum iterator_mode mode;
|
69
99
|
} Iterator_t;
|
70
100
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
101
|
+
#ifdef EXTRALITE_ENABLE_CHANGESET
|
102
|
+
typedef struct {
|
103
|
+
int changeset_len;
|
104
|
+
void *changeset_ptr;
|
105
|
+
} Changeset_t;
|
106
|
+
#endif
|
107
|
+
|
108
|
+
enum row_mode {
|
109
|
+
ROW_YIELD,
|
110
|
+
ROW_MULTI,
|
111
|
+
ROW_SINGLE
|
75
112
|
};
|
76
113
|
|
77
114
|
typedef struct {
|
78
|
-
VALUE
|
79
|
-
|
80
|
-
|
81
|
-
VALUE
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
115
|
+
VALUE self;
|
116
|
+
VALUE sql;
|
117
|
+
VALUE params;
|
118
|
+
VALUE transform_proc;
|
119
|
+
|
120
|
+
Database_t *db;
|
121
|
+
sqlite3 *sqlite3_db;
|
122
|
+
sqlite3_stmt *stmt;
|
123
|
+
|
124
|
+
int gvl_release_threshold;
|
125
|
+
enum query_mode query_mode;
|
126
|
+
enum row_mode row_mode;
|
127
|
+
int max_rows;
|
128
|
+
|
129
|
+
int eof;
|
130
|
+
int step_count;
|
87
131
|
} query_ctx;
|
88
132
|
|
89
133
|
enum gvl_mode {
|
@@ -93,46 +137,59 @@ enum gvl_mode {
|
|
93
137
|
|
94
138
|
#define ALL_ROWS -1
|
95
139
|
#define SINGLE_ROW -2
|
96
|
-
#define
|
97
|
-
#define
|
98
|
-
#define QUERY_CTX(self, db, stmt, params,
|
99
|
-
|
140
|
+
#define ROW_YIELD_OR_MODE(default) (rb_block_given_p() ? ROW_YIELD : default)
|
141
|
+
#define ROW_MULTI_P(mode) (mode == ROW_MULTI)
|
142
|
+
#define QUERY_CTX(self, sql, db, stmt, params, transform_proc, query_mode, row_mode, max_rows) { \
|
143
|
+
self, \
|
144
|
+
sql, \
|
145
|
+
params, \
|
146
|
+
transform_proc, \
|
147
|
+
db, \
|
148
|
+
db->sqlite3_db, \
|
149
|
+
stmt, \
|
150
|
+
db->gvl_release_threshold, \
|
151
|
+
query_mode, \
|
152
|
+
row_mode, \
|
153
|
+
max_rows, \
|
154
|
+
0, \
|
155
|
+
0 \
|
156
|
+
}
|
157
|
+
|
100
158
|
#define DEFAULT_GVL_RELEASE_THRESHOLD 1000
|
159
|
+
#define DEFAULT_PROGRESS_HANDLER_PERIOD 1000
|
160
|
+
#define DEFAULT_PROGRESS_HANDLER_TICK 10
|
101
161
|
|
102
162
|
extern rb_encoding *UTF8_ENCODING;
|
103
163
|
|
164
|
+
typedef VALUE (*safe_query_impl)(query_ctx *);
|
165
|
+
|
104
166
|
VALUE safe_batch_execute(query_ctx *ctx);
|
105
167
|
VALUE safe_batch_query(query_ctx *ctx);
|
168
|
+
VALUE safe_batch_query_argv(query_ctx *ctx);
|
106
169
|
VALUE safe_batch_query_ary(query_ctx *ctx);
|
107
|
-
VALUE
|
170
|
+
VALUE safe_query_argv(query_ctx *ctx);
|
108
171
|
VALUE safe_query_ary(query_ctx *ctx);
|
109
172
|
VALUE safe_query_changes(query_ctx *ctx);
|
110
173
|
VALUE safe_query_columns(query_ctx *ctx);
|
111
174
|
VALUE safe_query_hash(query_ctx *ctx);
|
112
|
-
VALUE
|
113
|
-
VALUE
|
114
|
-
VALUE
|
115
|
-
|
116
|
-
VALUE Query_each_hash(VALUE self);
|
117
|
-
VALUE Query_each_ary(VALUE self);
|
118
|
-
VALUE Query_each_single_column(VALUE self);
|
119
|
-
|
120
|
-
VALUE Query_next_hash(int argc, VALUE *argv, VALUE self);
|
121
|
-
VALUE Query_next_ary(int argc, VALUE *argv, VALUE self);
|
122
|
-
VALUE Query_next_single_column(int argc, VALUE *argv, VALUE self);
|
175
|
+
VALUE safe_query_single_row_hash(query_ctx *ctx);
|
176
|
+
VALUE safe_query_single_row_argv(query_ctx *ctx);
|
177
|
+
VALUE safe_query_single_row_ary(query_ctx *ctx);
|
123
178
|
|
124
|
-
VALUE
|
125
|
-
VALUE
|
126
|
-
VALUE
|
179
|
+
VALUE Query_each(VALUE self);
|
180
|
+
VALUE Query_next(int argc, VALUE *argv, VALUE self);
|
181
|
+
VALUE Query_to_a(VALUE self);
|
127
182
|
|
128
|
-
void prepare_single_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql);
|
129
|
-
void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql);
|
183
|
+
void prepare_single_stmt(enum gvl_mode mode, sqlite3 *db, sqlite3_stmt **stmt, VALUE sql);
|
184
|
+
void prepare_multi_stmt(enum gvl_mode mode, sqlite3 *db, sqlite3_stmt **stmt, VALUE sql);
|
130
185
|
void bind_all_parameters(sqlite3_stmt *stmt, int argc, VALUE *argv);
|
131
186
|
void bind_all_parameters_from_object(sqlite3_stmt *stmt, VALUE obj);
|
132
187
|
int stmt_iterate(query_ctx *ctx);
|
133
188
|
VALUE cleanup_stmt(query_ctx *ctx);
|
134
189
|
|
190
|
+
void Database_issue_query(Database_t *db, VALUE sql);
|
135
191
|
sqlite3 *Database_sqlite3_db(VALUE self);
|
192
|
+
enum gvl_mode Database_prepare_gvl_mode(Database_t *db);
|
136
193
|
Database_t *self_to_database(VALUE self);
|
137
194
|
|
138
195
|
void *gvl_call(enum gvl_mode mode, void *(*fn)(void *), void *data);
|
@@ -3,6 +3,9 @@
|
|
3
3
|
void Init_ExtraliteDatabase();
|
4
4
|
void Init_ExtraliteQuery();
|
5
5
|
void Init_ExtraliteIterator();
|
6
|
+
#ifdef EXTRALITE_ENABLE_CHANGESET
|
7
|
+
void Init_ExtraliteChangeset();
|
8
|
+
#endif
|
6
9
|
|
7
10
|
void Init_extralite_ext(void) {
|
8
11
|
rb_ext_ractor_safe(true);
|
@@ -10,4 +13,7 @@ void Init_extralite_ext(void) {
|
|
10
13
|
Init_ExtraliteDatabase();
|
11
14
|
Init_ExtraliteQuery();
|
12
15
|
Init_ExtraliteIterator();
|
16
|
+
#ifdef EXTRALITE_ENABLE_CHANGESET
|
17
|
+
Init_ExtraliteChangeset();
|
18
|
+
#endif
|
13
19
|
}
|
data/ext/extralite/iterator.c
CHANGED
@@ -9,23 +9,24 @@
|
|
9
9
|
|
10
10
|
VALUE cIterator;
|
11
11
|
|
12
|
-
VALUE SYM_hash;
|
13
|
-
VALUE SYM_ary;
|
14
|
-
VALUE SYM_single_column;
|
15
|
-
|
16
12
|
static size_t Iterator_size(const void *ptr) {
|
17
13
|
return sizeof(Iterator_t);
|
18
14
|
}
|
19
15
|
|
20
16
|
static void Iterator_mark(void *ptr) {
|
21
17
|
Iterator_t *iterator = ptr;
|
22
|
-
|
18
|
+
rb_gc_mark_movable(iterator->query);
|
19
|
+
}
|
20
|
+
|
21
|
+
static void Iterator_compact(void *ptr) {
|
22
|
+
Iterator_t *iterator = ptr;
|
23
|
+
iterator->query = rb_gc_location(iterator->query);
|
23
24
|
}
|
24
25
|
|
25
26
|
static const rb_data_type_t Iterator_type = {
|
26
27
|
"Iterator",
|
27
|
-
{Iterator_mark, free, Iterator_size,},
|
28
|
-
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
28
|
+
{Iterator_mark, free, Iterator_size, Iterator_compact},
|
29
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
|
29
30
|
};
|
30
31
|
|
31
32
|
static VALUE Iterator_allocate(VALUE klass) {
|
@@ -40,14 +41,6 @@ static inline Iterator_t *self_to_iterator(VALUE obj) {
|
|
40
41
|
return iterator;
|
41
42
|
}
|
42
43
|
|
43
|
-
static inline enum iterator_mode symbol_to_mode(VALUE sym) {
|
44
|
-
if (sym == SYM_hash) return ITERATOR_HASH;
|
45
|
-
if (sym == SYM_ary) return ITERATOR_ARY;
|
46
|
-
if (sym == SYM_single_column) return ITERATOR_SINGLE_COLUMN;
|
47
|
-
|
48
|
-
rb_raise(cError, "Invalid iterator mode");
|
49
|
-
}
|
50
|
-
|
51
44
|
/* Initializes an iterator using the given query object and iteration mode. The
|
52
45
|
* iteration mode is one of: `:hash`, `:ary`, or `:single_column`. An iterator
|
53
46
|
* is normally returned from one of the methods `Query#each`/`Query#each_hash`,
|
@@ -60,28 +53,12 @@ static inline enum iterator_mode symbol_to_mode(VALUE sym) {
|
|
60
53
|
* @param mode [Symbol] iteration mode
|
61
54
|
* @return [void]
|
62
55
|
*/
|
63
|
-
VALUE Iterator_initialize(VALUE self, VALUE query
|
56
|
+
VALUE Iterator_initialize(VALUE self, VALUE query) {
|
64
57
|
Iterator_t *iterator = self_to_iterator(self);
|
65
|
-
|
66
58
|
iterator->query = query;
|
67
|
-
iterator->mode = symbol_to_mode(mode);
|
68
|
-
|
69
59
|
return Qnil;
|
70
60
|
}
|
71
61
|
|
72
|
-
typedef VALUE (*each_method)(VALUE);
|
73
|
-
|
74
|
-
inline each_method mode_to_each_method(enum iterator_mode mode) {
|
75
|
-
switch (mode) {
|
76
|
-
case ITERATOR_ARY:
|
77
|
-
return Query_each_ary;
|
78
|
-
case ITERATOR_SINGLE_COLUMN:
|
79
|
-
return Query_each_single_column;
|
80
|
-
default:
|
81
|
-
return Query_each_hash;
|
82
|
-
}
|
83
|
-
}
|
84
|
-
|
85
62
|
/* Iterates through the associated query's result set using the iteration mode
|
86
63
|
* set when initialized. Each row would be passed to the given block according
|
87
64
|
* to the iteration mode, i.e. as a hash, an array, or a single value. In
|
@@ -93,26 +70,12 @@ inline each_method mode_to_each_method(enum iterator_mode mode) {
|
|
93
70
|
VALUE Iterator_each(VALUE self) {
|
94
71
|
if (rb_block_given_p()) {
|
95
72
|
Iterator_t *iterator = self_to_iterator(self);
|
96
|
-
|
97
|
-
method(iterator->query);
|
73
|
+
Query_each(iterator->query);
|
98
74
|
}
|
99
75
|
|
100
76
|
return self;
|
101
77
|
}
|
102
78
|
|
103
|
-
typedef VALUE (*next_method)(int, VALUE *, VALUE);
|
104
|
-
|
105
|
-
inline next_method mode_to_next_method(enum iterator_mode mode) {
|
106
|
-
switch (mode) {
|
107
|
-
case ITERATOR_ARY:
|
108
|
-
return Query_next_ary;
|
109
|
-
case ITERATOR_SINGLE_COLUMN:
|
110
|
-
return Query_next_single_column;
|
111
|
-
default:
|
112
|
-
return Query_next_hash;
|
113
|
-
}
|
114
|
-
}
|
115
|
-
|
116
79
|
/* Returns the next 1 or more rows from the associated query's result set
|
117
80
|
* according to the iteration mode, i.e. as a hash, an array or a single value.
|
118
81
|
*
|
@@ -131,25 +94,11 @@ inline next_method mode_to_next_method(enum iterator_mode mode) {
|
|
131
94
|
*/
|
132
95
|
VALUE Iterator_next(int argc, VALUE *argv, VALUE self) {
|
133
96
|
Iterator_t *iterator = self_to_iterator(self);
|
134
|
-
|
135
|
-
VALUE result = method(argc, argv, iterator->query);
|
97
|
+
VALUE result = Query_next(argc, argv, iterator->query);
|
136
98
|
|
137
99
|
return rb_block_given_p() ? self : result;
|
138
100
|
}
|
139
101
|
|
140
|
-
typedef VALUE (*to_a_method)(VALUE);
|
141
|
-
|
142
|
-
inline to_a_method mode_to_to_a_method(enum iterator_mode mode) {
|
143
|
-
switch (mode) {
|
144
|
-
case ITERATOR_ARY:
|
145
|
-
return Query_to_a_ary;
|
146
|
-
case ITERATOR_SINGLE_COLUMN:
|
147
|
-
return Query_to_a_single_column;
|
148
|
-
default:
|
149
|
-
return Query_to_a_hash;
|
150
|
-
}
|
151
|
-
}
|
152
|
-
|
153
102
|
/* Returns all rows from the associated query's result set according to the
|
154
103
|
* iteration mode, i.e. as a hash, an array or a single value.
|
155
104
|
*
|
@@ -157,19 +106,7 @@ inline to_a_method mode_to_to_a_method(enum iterator_mode mode) {
|
|
157
106
|
*/
|
158
107
|
VALUE Iterator_to_a(VALUE self) {
|
159
108
|
Iterator_t *iterator = self_to_iterator(self);
|
160
|
-
|
161
|
-
return method(iterator->query);
|
162
|
-
}
|
163
|
-
|
164
|
-
inline VALUE mode_to_symbol(Iterator_t *iterator) {
|
165
|
-
switch (iterator->mode) {
|
166
|
-
case ITERATOR_ARY:
|
167
|
-
return SYM_ary;
|
168
|
-
case ITERATOR_SINGLE_COLUMN:
|
169
|
-
return SYM_single_column;
|
170
|
-
default:
|
171
|
-
return SYM_hash;
|
172
|
-
}
|
109
|
+
return Query_to_a(iterator->query);
|
173
110
|
}
|
174
111
|
|
175
112
|
/* Returns a short string representation of the iterator instance, including the
|
@@ -179,9 +116,8 @@ inline VALUE mode_to_symbol(Iterator_t *iterator) {
|
|
179
116
|
*/
|
180
117
|
VALUE Iterator_inspect(VALUE self) {
|
181
118
|
VALUE cname = rb_class_name(CLASS_OF(self));
|
182
|
-
VALUE sym = mode_to_symbol(self_to_iterator(self));
|
183
119
|
|
184
|
-
return rb_sprintf("#<%"PRIsVALUE":%p
|
120
|
+
return rb_sprintf("#<%"PRIsVALUE":%p>", cname, (void*)self);
|
185
121
|
}
|
186
122
|
|
187
123
|
void Init_ExtraliteIterator(void) {
|
@@ -192,17 +128,9 @@ void Init_ExtraliteIterator(void) {
|
|
192
128
|
|
193
129
|
rb_include_module(cIterator, rb_mEnumerable);
|
194
130
|
|
195
|
-
rb_define_method(cIterator, "initialize", Iterator_initialize,
|
131
|
+
rb_define_method(cIterator, "initialize", Iterator_initialize, 1);
|
196
132
|
rb_define_method(cIterator, "each", Iterator_each, 0);
|
197
133
|
rb_define_method(cIterator, "inspect", Iterator_inspect, 0);
|
198
134
|
rb_define_method(cIterator, "next", Iterator_next, -1);
|
199
135
|
rb_define_method(cIterator, "to_a", Iterator_to_a, 0);
|
200
|
-
|
201
|
-
SYM_hash = ID2SYM(rb_intern("hash"));
|
202
|
-
SYM_ary = ID2SYM(rb_intern("ary"));
|
203
|
-
SYM_single_column = ID2SYM(rb_intern("single_column"));
|
204
|
-
|
205
|
-
rb_gc_register_mark_object(SYM_hash);
|
206
|
-
rb_gc_register_mark_object(SYM_ary);
|
207
|
-
rb_gc_register_mark_object(SYM_single_column);
|
208
136
|
}
|