sequel_pg 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,3 @@
1
+ === 1.0.0
2
+
3
+ * Initial Public Release
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Jeremy Evans
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
data/README.rdoc ADDED
@@ -0,0 +1,138 @@
1
+ = sequel_pg
2
+
3
+ sequel_pg overwrites the inner loop of the Sequel postgres adapter
4
+ row fetching code with a C version. The C version is significantly
5
+ faster (2-6x) than the pure ruby version that Sequel uses by default.
6
+
7
+ == Real world difference
8
+
9
+ The speed up that sequel_pg gives you depends on what you are
10
+ selecting, but it should be noticable whenever many rows are selected.
11
+ Here's an example that shows the difference it makes on a couple of
12
+ models:
13
+
14
+ $ irb -r model -r benchmark
15
+ irb(main):001:0> Track.count
16
+ => 140854
17
+ irb(main):002:0> Album.count
18
+ => 5579
19
+ irb(main):003:0> puts Benchmark.measure{Track.each{}}
20
+ 10.740000 0.190000 10.930000 ( 11.875343)
21
+ => nil
22
+ irb(main):004:0> puts Benchmark.measure{10.times{Album.each{}}}
23
+ 7.920000 0.070000 7.990000 ( 8.482130)
24
+ => nil
25
+ irb(main):005:0> require '/data/code/sequel_pg/ext/sequel_pg/sequel_pg'
26
+ => true
27
+ irb(main):006:0> puts Benchmark.measure{Track.each{}}
28
+ 2.360000 0.400000 2.760000 ( 3.723098)
29
+ => nil
30
+ irb(main):007:0> puts Benchmark.measure{10.times{Album.each{}}}
31
+ 1.300000 0.190000 1.490000 ( 2.001393)
32
+ => nil
33
+
34
+ Here's an example that uses a modified version of swift's benchmarks
35
+ (http://github.com/shanna/swift/tree/master/benchmarks/):
36
+
37
+ benchmark sys user total real rss
38
+ sequel #select 0.090000 2.020000 2.110000 2.246688 46.54m
39
+ sequel_pg #select 0.000000 0.250000 0.250000 0.361999 7.33m
40
+
41
+ == Installing the gem
42
+
43
+ gem install sequel_pg
44
+
45
+ The standard gem requires compiling from source, so you need a working
46
+ compiler toolchain. Since few Windows users have a working compiler
47
+ toolchain, a windows binary gem is available that works on both 1.8
48
+ and 1.9.
49
+
50
+ == Running the specs
51
+
52
+ sequel_pg doesn't ship with it's own specs. It's designed to
53
+ replace a part of Sequel, so it just uses Sequel's specs.
54
+ Specifically, the spec_postgres spec from Sequel.
55
+
56
+ == Reporting issues/bugs
57
+
58
+ sequel_pg uses GitHub Issues for tracking issues/bugs:
59
+
60
+ http://github.com/jeremyevans/sequel_pg/issues
61
+
62
+ == Contributing
63
+
64
+ The source code is on GitHub:
65
+
66
+ http://github.com/jeremyevans/sequel_pg
67
+
68
+ To get a copy:
69
+
70
+ git clone git://github.com/jeremyevans/sequel_pg.git
71
+
72
+ There are only a few requirements, which you should probably
73
+ have before considering use of the library:
74
+
75
+ * Rake
76
+ * Sequel
77
+ * pg
78
+ * libpq headers and library
79
+
80
+ == Building
81
+
82
+ To build the library from a git checkout, after installing the
83
+ requirements:
84
+
85
+ rake build
86
+
87
+ == Platforms Supported
88
+
89
+ sequel_pg has been tested on the following:
90
+
91
+ === Operating Systems/Platforms
92
+
93
+ * Linux (i386)
94
+ * OpenBSD (amd64, i386)
95
+ * Windows XP (i386)
96
+
97
+ === Compiler Versions
98
+
99
+ * gcc (3.3.5, 4.2.1, 4.4.3)
100
+
101
+ === Ruby Versions
102
+
103
+ * jruby cext branch (compiles but untested and unusable, as pg itself
104
+ doesn't compile yet)
105
+ * rbx head
106
+ * ruby 1.8.6
107
+ * ruby 1.8.7
108
+ * ruby 1.9.1
109
+ * ruby 1.9.2
110
+ * ruby head
111
+
112
+ If your platform, compiler version, or ruby version is not listed
113
+ above, please test and send me a report including:
114
+
115
+ * Your operating system and platform (e.g. i386, x86_64/amd64)
116
+ * Your compiler
117
+ * Your ruby version
118
+
119
+ == Known Issues
120
+
121
+ * You must be using the ISO PostgreSQL date format (which is the
122
+ default). Using the SQL, POSTGRESQL, or GERMAN date formats will
123
+ result in incorrect date/timestamp handling. In addition to
124
+ PostgreSQL defaulting to ISO, Sequel also manually sets the
125
+ date format to ISO by default, so unless you are overriding that
126
+ setting (via Sequel::Postgres.use_iso_date_format = false), you
127
+ should be OK.
128
+ * Adding your own type conversion procs to Sequel::Postgres::PG_TYPES
129
+ does not have an effect with this plugin, since the type conversion
130
+ is done in C.
131
+ * The named_timezones plugin does not integrate with sequel_pg, since
132
+ sequel_pg does it's own timestamp conversions. The :local and :utc
133
+ settings for database_timestamp and application_timestamp do work,
134
+ as does setting the datetime_class to DateTime.
135
+
136
+ == Author
137
+
138
+ Jeremy Evans <code@jeremyevans.net>
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require "rake"
2
+ require "rake/clean"
3
+
4
+ CLEAN.include %w'**.rbc rdoc'
5
+
6
+ desc "Do a full cleaning"
7
+ task :distclean do
8
+ CLEAN.include %w'tmp pkg sequel_pg*.gem lib'
9
+ Rake::Task[:clean].invoke
10
+ end
11
+
12
+ desc "Build the gem"
13
+ task :gem do
14
+ sh %{gem build sequel_pg.gemspec}
15
+ end
16
+
17
+ begin
18
+ require 'rake/extensiontask'
19
+ Rake::ExtensionTask.new('sequel_pg')
20
+ rescue LoadError
21
+ end
@@ -0,0 +1,16 @@
1
+ require 'mkmf'
2
+ $CFLAGS << " -Wall " unless RUBY_PLATFORM =~ /solaris/
3
+ dir_config('pg', ENV["POSTGRES_INCLUDE"] || (IO.popen("pg_config --includedir").readline.chomp rescue nil),
4
+ ENV["POSTGRES_LIB"] || (IO.popen("pg_config --libdir").readline.chomp rescue nil))
5
+
6
+ if enable_config("static-build")
7
+ # Link against all required libraries for static build, if they are available
8
+ have_library('gdi32', 'CreateDC') && append_library($libs, 'gdi32')
9
+ have_library('secur32') && append_library($libs, 'secur32')
10
+ end
11
+
12
+ if (have_library('pq') || have_library('libpq') || have_library('ms/libpq')) && have_header('libpq-fe.h')
13
+ create_makefile("sequel_pg")
14
+ else
15
+ puts 'Could not find PostgreSQL build environment (libraries & headers): Makefile not created'
16
+ end
@@ -0,0 +1,357 @@
1
+ #include <string.h>
2
+ #include <stdio.h>
3
+ #include <math.h>
4
+ #include <libpq-fe.h>
5
+ #include <ruby.h>
6
+
7
+ #if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
8
+ #define SPG_ENCODING 1
9
+ #include <ruby/encoding.h>
10
+ #endif
11
+
12
+ #define SPG_MAX_FIELDS 256
13
+ #define SPG_MILLISECONDS_PER_DAY 86400000000.0
14
+ #define SPG_MINUTES_PER_DAY 1440.0
15
+ #define SPG_SECONDS_PER_DAY 86400.0
16
+
17
+ #define SPG_DT_ADD_USEC if (usec != 0) { dt = rb_funcall(dt, spg_id_op_plus, 1, rb_float_new(usec/SPG_MILLISECONDS_PER_DAY)); }
18
+
19
+ #define SPG_NO_TZ 0
20
+ #define SPG_DB_LOCAL 1
21
+ #define SPG_DB_UTC 2
22
+ #define SPG_APP_LOCAL 4
23
+ #define SPG_APP_UTC 8
24
+
25
+ static VALUE spg_Sequel;
26
+ static VALUE spg_Blob;
27
+ static VALUE spg_BigDecimal;
28
+ static VALUE spg_Date;
29
+
30
+ static VALUE spg_sym_utc;
31
+ static VALUE spg_sym_local;
32
+
33
+ static ID spg_id_new;
34
+ static ID spg_id_local;
35
+ static ID spg_id_year;
36
+ static ID spg_id_month;
37
+ static ID spg_id_day;
38
+ static ID spg_id_output_identifier;
39
+ static ID spg_id_datetime_class;
40
+ static ID spg_id_application_timezone;
41
+ static ID spg_id_database_timezone;
42
+ static ID spg_id_op_plus;
43
+ static ID spg_id_utc;
44
+ static ID spg_id_utc_offset;
45
+ static ID spg_id_localtime;
46
+ static ID spg_id_new_offset;
47
+
48
+ static ID spg_id_columns;
49
+ static ID spg_id_encoding;
50
+
51
+ #if SPG_ENCODING
52
+ static int enc_get_index(VALUE val)
53
+ {
54
+ int i = ENCODING_GET_INLINED(val);
55
+ if (i == ENCODING_INLINE_MAX) {
56
+ i = NUM2INT(rb_ivar_get(val, spg_id_encoding));
57
+ }
58
+ return i;
59
+ }
60
+ #endif
61
+
62
+ static VALUE spg_time(const char *s) {
63
+ VALUE now;
64
+ int hour, minute, second, tokens;
65
+ char subsec[7];
66
+ int usec = 0;
67
+
68
+ tokens = sscanf(s, "%2d:%2d:%2d.%s", &hour, &minute, &second, subsec);
69
+ if(tokens == 4) {
70
+ usec = atoi(subsec);
71
+ usec *= (int) pow(10, (6 - strlen(subsec)));
72
+ } else if(tokens < 3) {
73
+ rb_raise(rb_eArgError, "unexpected time format");
74
+ }
75
+
76
+ now = rb_funcall(rb_cTime, spg_id_new, 0);
77
+ return rb_funcall(rb_cTime, spg_id_local, 6, rb_funcall(now, spg_id_year, 0), rb_funcall(now, spg_id_month, 0), rb_funcall(now, spg_id_day, 0), INT2NUM(hour), INT2NUM(minute), INT2NUM(second), INT2NUM(usec));
78
+ }
79
+
80
+ static VALUE spg_date(const char *s) {
81
+ int year, month, day;
82
+
83
+ if(3 != sscanf(s, "%d-%2d-%2d", &year, &month, &day)) {
84
+ rb_raise(rb_eArgError, "unexpected date format");
85
+ }
86
+
87
+ return rb_funcall(spg_Date, spg_id_new, 3, INT2NUM(year), INT2NUM(month), INT2NUM(day));
88
+ }
89
+
90
+ static VALUE spg_timestamp(const char *s) {
91
+ VALUE dtc, dt, rtz;
92
+ int tz = SPG_NO_TZ;
93
+ int year, month, day, hour, min, sec, usec, tokens, pos, utc_offset;
94
+ int check_offset = 0;
95
+ int offset_hour = 0;
96
+ int offset_minute = 0;
97
+ int offset_seconds = 0;
98
+ double offset_fraction = 0.0;
99
+ char subsec[7];
100
+
101
+ if (0 != strchr(s, '.')) {
102
+ tokens = sscanf(s, "%d-%2d-%2d %2d:%2d:%2d.%s%n", &year, &month, &day, &hour, &min, &sec, subsec, &pos);
103
+ if (tokens == 8) {
104
+ check_offset = 1;
105
+ }
106
+ if(tokens != 7) {
107
+ rb_raise(rb_eArgError, "unexpected datetime format");
108
+ }
109
+ usec = atoi(subsec);
110
+ usec *= (int) pow(10, (6 - strlen(subsec)));
111
+ } else {
112
+ tokens = sscanf(s, "%d-%2d-%2d %2d:%2d:%2d%n", &year, &month, &day, &hour, &min, &sec, &pos);
113
+ if (tokens == 3) {
114
+ hour = 0;
115
+ min = 0;
116
+ sec = 0;
117
+ } else if (tokens == 7) {
118
+ check_offset = 1;
119
+ } else if (tokens != 6) {
120
+ rb_raise(rb_eArgError, "unexpected datetime format");
121
+ }
122
+ usec = 0;
123
+ }
124
+
125
+ if (check_offset) {
126
+ if(sscanf(s + pos, "%3d:%2d", &offset_hour, &offset_minute) == 0) {
127
+ /* No offset found */
128
+ check_offset = 0;
129
+ }
130
+ }
131
+
132
+ /* Get values of datetime_class, database_timezone, and application_timezone */
133
+ dtc = rb_funcall(spg_Sequel, spg_id_datetime_class, 0);
134
+ rtz = rb_funcall(spg_Sequel, spg_id_database_timezone, 0);
135
+ if (rtz == spg_sym_local) {
136
+ tz += SPG_DB_LOCAL;
137
+ } else if (rtz == spg_sym_utc) {
138
+ tz += SPG_DB_UTC;
139
+ }
140
+ rtz = rb_funcall(spg_Sequel, spg_id_application_timezone, 0);
141
+ if (rtz == spg_sym_local) {
142
+ tz += SPG_APP_LOCAL;
143
+ } else if (rtz == spg_sym_utc) {
144
+ tz += SPG_APP_UTC;
145
+ }
146
+
147
+ if (dtc == rb_cTime) {
148
+ if (check_offset) {
149
+ /* Offset given, convert to local time if not already in local time.
150
+ * While PostgreSQL generally returns timestamps in local time, it's unwise to rely on this.
151
+ */
152
+ dt = rb_funcall(rb_cTime, spg_id_local, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(usec));
153
+ utc_offset = NUM2INT(rb_funcall(dt, spg_id_utc_offset, 0));
154
+ offset_seconds = offset_hour * 3600 + offset_minute * 60;
155
+ if (utc_offset != offset_seconds) {
156
+ dt = rb_funcall(dt, spg_id_op_plus, 1, INT2NUM(utc_offset - offset_seconds));
157
+ }
158
+
159
+ if (tz & SPG_APP_UTC) {
160
+ dt = rb_funcall(dt, spg_id_utc, 0);
161
+ }
162
+ return dt;
163
+ } else if (tz == SPG_NO_TZ) {
164
+ return rb_funcall(rb_cTime, spg_id_local, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(usec));
165
+ }
166
+
167
+ /* No offset given, and some timezone combination given */
168
+ if (tz & SPG_DB_UTC) {
169
+ dt = rb_funcall(rb_cTime, spg_id_utc, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(usec));
170
+ if (tz & SPG_APP_LOCAL) {
171
+ return rb_funcall(dt, spg_id_localtime, 0);
172
+ } else {
173
+ return dt;
174
+ }
175
+ } else {
176
+ dt = rb_funcall(rb_cTime, spg_id_local, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(usec));
177
+ if (tz & SPG_APP_UTC) {
178
+ return rb_funcall(dt, spg_id_utc, 0);
179
+ } else {
180
+ return dt;
181
+ }
182
+ }
183
+ } else {
184
+ /* datetime.class == DateTime */
185
+ if (check_offset) {
186
+ /* Offset given, handle correct local time.
187
+ * While PostgreSQL generally returns timestamps in local time, it's unwise to rely on this.
188
+ */
189
+ offset_fraction = offset_hour/24.0 + offset_minute/SPG_MINUTES_PER_DAY;
190
+ dt = rb_funcall(dtc, spg_id_new, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), rb_float_new(offset_fraction));
191
+ SPG_DT_ADD_USEC
192
+
193
+ if (tz & SPG_APP_LOCAL) {
194
+ utc_offset = NUM2INT(rb_funcall(rb_funcall(rb_cTime, spg_id_new, 0), spg_id_utc_offset, 0))/SPG_SECONDS_PER_DAY;
195
+ dt = rb_funcall(dt, spg_id_new_offset, 1, rb_float_new(utc_offset));
196
+ } else if (tz & SPG_APP_UTC) {
197
+ dt = rb_funcall(dt, spg_id_new_offset, 1, INT2NUM(0));
198
+ }
199
+ return dt;
200
+ } else if (tz == SPG_NO_TZ) {
201
+ dt = rb_funcall(dtc, spg_id_new, 6, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
202
+ SPG_DT_ADD_USEC
203
+ return dt;
204
+ }
205
+
206
+ /* No offset given, and some timezone combination given */
207
+ if (tz & SPG_DB_LOCAL) {
208
+ offset_fraction = NUM2INT(rb_funcall(rb_funcall(rb_cTime, spg_id_local, 6, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec)), spg_id_utc_offset, 0))/SPG_SECONDS_PER_DAY;
209
+ dt = rb_funcall(dtc, spg_id_new, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), rb_float_new(offset_fraction));
210
+ SPG_DT_ADD_USEC
211
+ if (tz & SPG_APP_UTC) {
212
+ return rb_funcall(dt, spg_id_new_offset, 1, INT2NUM(0));
213
+ } else {
214
+ return dt;
215
+ }
216
+ } else {
217
+ dt = rb_funcall(dtc, spg_id_new, 6, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
218
+ SPG_DT_ADD_USEC
219
+ if (tz & SPG_APP_LOCAL) {
220
+ offset_fraction = NUM2INT(rb_funcall(rb_funcall(rb_cTime, spg_id_local, 6, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec)), spg_id_utc_offset, 0))/SPG_SECONDS_PER_DAY;
221
+ return rb_funcall(dt, spg_id_new_offset, 1, rb_float_new(offset_fraction));
222
+ } else {
223
+ return dt;
224
+ }
225
+ }
226
+ }
227
+ }
228
+
229
+ static VALUE spg_fetch_rows_set_cols(VALUE self, VALUE ignore) {
230
+ return self;
231
+ }
232
+
233
+ static VALUE spg_yield_hash_rows(VALUE self, VALUE rres, VALUE ignore) {
234
+ PGresult *res;
235
+ VALUE colsyms[SPG_MAX_FIELDS];
236
+ long ntuples;
237
+ long nfields;
238
+ long i;
239
+ long j;
240
+ VALUE h, rv;
241
+ size_t l;
242
+ char * v;
243
+
244
+ #ifdef SPG_ENCODING
245
+ int enc_index;
246
+ enc_index = enc_get_index(rres);
247
+ #endif
248
+
249
+ Data_Get_Struct(rres, PGresult, res);
250
+ ntuples = PQntuples(res);
251
+ nfields = PQnfields(res);
252
+ if (nfields > SPG_MAX_FIELDS) {
253
+ rb_raise(rb_eRangeError, "more than %d columns in query", SPG_MAX_FIELDS);
254
+ }
255
+
256
+ for(j=0; j<nfields; j++) {
257
+ colsyms[j] = rb_funcall(self, spg_id_output_identifier, 1, rb_str_new2(PQfname(res, j)));
258
+ }
259
+ rb_ivar_set(self, spg_id_columns, rb_ary_new4(nfields, colsyms));
260
+
261
+ for(i=0; i<ntuples; i++) {
262
+ h = rb_hash_new();
263
+ for(j=0; j<nfields; j++) {
264
+ if(PQgetisnull(res, i, j)) {
265
+ rv = Qnil;
266
+ } else {
267
+ v = PQgetvalue(res, i, j);
268
+
269
+ switch(PQftype(res, j)) {
270
+ case 16: /* boolean */
271
+ rv = *v == 't' ? Qtrue : Qfalse;
272
+ break;
273
+ case 17: /* bytea */
274
+ v = (char *)PQunescapeBytea((unsigned char*)v, &l);
275
+ rv = rb_funcall(spg_Blob, spg_id_new, 1, rb_str_new(v, l));
276
+ PQfreemem(v);
277
+ break;
278
+ case 20: /* integer */
279
+ case 21:
280
+ case 22:
281
+ case 23:
282
+ case 26:
283
+ rv = rb_cstr2inum(v, 10);
284
+ break;
285
+ case 700: /* float */
286
+ case 701:
287
+ rv = rb_float_new(rb_cstr_to_dbl(v, Qfalse));
288
+ break;
289
+ case 790: /* numeric */
290
+ case 1700:
291
+ rv = rb_funcall(spg_BigDecimal, spg_id_new, 1, rb_str_new(v, PQgetlength(res, i, j)));
292
+ break;
293
+ case 1082: /* date */
294
+ rv = spg_date(v);
295
+ break;
296
+ case 1083: /* time */
297
+ case 1266:
298
+ rv = spg_time(v);
299
+ break;
300
+ case 1114: /* timestamp */
301
+ case 1184:
302
+ rv = spg_timestamp(v);
303
+ break;
304
+ default:
305
+ rv = rb_tainted_str_new(v, PQgetlength(res, i, j));
306
+ #ifdef SPG_ENCODING
307
+ rb_enc_associate_index(rv, enc_index);
308
+ #endif
309
+ }
310
+ }
311
+ rb_hash_aset(h, colsyms[j], rv);
312
+ }
313
+ rb_yield(h);
314
+ }
315
+
316
+ return self;
317
+ }
318
+
319
+ void Init_sequel_pg(void) {
320
+ VALUE c;
321
+ ID cg;
322
+ cg = rb_intern("const_get");
323
+ spg_id_new = rb_intern("new");
324
+ spg_id_local = rb_intern("local");
325
+ spg_id_year = rb_intern("year");
326
+ spg_id_month = rb_intern("month");
327
+ spg_id_day = rb_intern("day");
328
+ spg_id_output_identifier = rb_intern("output_identifier");
329
+ spg_id_datetime_class = rb_intern("datetime_class");
330
+ spg_id_application_timezone = rb_intern("application_timezone");
331
+ spg_id_database_timezone = rb_intern("database_timezone");
332
+ spg_id_op_plus = rb_intern("+");
333
+ spg_id_utc = rb_intern("utc");
334
+ spg_id_utc_offset = rb_intern("utc_offset");
335
+ spg_id_localtime = rb_intern("localtime");
336
+ spg_id_new_offset = rb_intern("new_offset");
337
+
338
+ spg_id_columns = rb_intern("@columns");
339
+ spg_id_encoding = rb_intern("@encoding");
340
+
341
+ spg_sym_utc = ID2SYM(rb_intern("utc"));
342
+ spg_sym_local = ID2SYM(rb_intern("local"));
343
+
344
+ spg_Sequel = rb_funcall(rb_cObject, cg, 1, rb_str_new2("Sequel"));
345
+ spg_Blob = rb_funcall(rb_funcall(spg_Sequel, cg, 1, rb_str_new2("SQL")), cg, 1, rb_str_new2("Blob"));
346
+ spg_BigDecimal = rb_funcall(rb_cObject, cg, 1, rb_str_new2("BigDecimal"));
347
+ spg_Date = rb_funcall(rb_cObject, cg, 1, rb_str_new2("Date"));
348
+
349
+ rb_global_variable(&spg_Sequel);
350
+ rb_global_variable(&spg_Blob);
351
+ rb_global_variable(&spg_BigDecimal);
352
+ rb_global_variable(&spg_Date);
353
+
354
+ c = rb_funcall(rb_funcall(spg_Sequel, cg, 1, rb_str_new2("Postgres")), cg, 1, rb_str_new2("Dataset"));
355
+ rb_define_private_method(c, "yield_hash_rows", spg_yield_hash_rows, 2);
356
+ rb_define_private_method(c, "fetch_rows_set_cols", spg_fetch_rows_set_cols, 1);
357
+ }
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sequel_pg
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Jeremy Evans
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-31 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: pg
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 63
30
+ segments:
31
+ - 0
32
+ - 8
33
+ - 0
34
+ version: 0.8.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: sequel
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 31
46
+ segments:
47
+ - 3
48
+ - 6
49
+ - 0
50
+ version: 3.6.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: |
54
+ sequel_pg overwrites the inner loop of the Sequel postgres
55
+ adapter row fetching code with a C version. The C version
56
+ is significantly faster (2-6x) than the pure ruby version
57
+ that Sequel uses by default.
58
+
59
+ email: code@jeremyevans.net
60
+ executables: []
61
+
62
+ extensions:
63
+ - ext/sequel_pg/extconf.rb
64
+ extra_rdoc_files:
65
+ - README.rdoc
66
+ - CHANGELOG
67
+ - LICENSE
68
+ files:
69
+ - LICENSE
70
+ - CHANGELOG
71
+ - README.rdoc
72
+ - Rakefile
73
+ - ext/sequel_pg/extconf.rb
74
+ - ext/sequel_pg/sequel_pg.c
75
+ has_rdoc: true
76
+ homepage: http://github.com/jeremyevans/sequel_pg
77
+ licenses: []
78
+
79
+ post_install_message:
80
+ rdoc_options:
81
+ - --quiet
82
+ - --line-numbers
83
+ - --inline-source
84
+ - --title
85
+ - "sequel_pg: Faster SELECTs when using Sequel with pg"
86
+ - --main
87
+ - README.rdoc
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: 59
96
+ segments:
97
+ - 1
98
+ - 8
99
+ - 6
100
+ version: 1.8.6
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 3
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ requirements: []
111
+
112
+ rubyforge_project:
113
+ rubygems_version: 1.3.7
114
+ signing_key:
115
+ specification_version: 3
116
+ summary: Faster SELECTs when using Sequel with pg
117
+ test_files: []
118
+