sequel_pg 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/README.rdoc +25 -0
- data/Rakefile +1 -1
- data/ext/sequel_pg/sequel_pg.c +303 -71
- data/lib/sequel_pg/sequel_pg.rb +76 -0
- metadata +11 -12
data/CHANGELOG
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
=== 1.2.0 (2011-11-01)
|
2
|
+
|
3
|
+
* Add optimize_model_load setting to speedup loading of model objects, off by default (jeremyevans)
|
4
|
+
|
5
|
+
* Add major speedup to Dataset#map, #to_hash, #select_map, #select_order_map, and #select_hash (jeremyevans)
|
6
|
+
|
7
|
+
* Work with the new Database#timezone setting in Sequel 3.29.0 (jeremyevans)
|
8
|
+
|
9
|
+
=== 1.1.1 (2011-09-01)
|
10
|
+
|
11
|
+
* Work with new Sequel::SQLTime for time columns in Sequel 3.27.0 (jeremyevans)
|
12
|
+
|
1
13
|
=== 1.1.0 (2011-06-01)
|
2
14
|
|
3
15
|
* Work with new Database#conversion_procs method in Sequel 3.24.0 (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -38,6 +38,31 @@ Here's an example that uses a modified version of swift's benchmarks
|
|
38
38
|
sequel #select 0.090000 2.020000 2.110000 2.246688 46.54m
|
39
39
|
sequel_pg #select 0.000000 0.250000 0.250000 0.361999 7.33m
|
40
40
|
|
41
|
+
sequel_pg also has code to speed up the map, to_hash, select_hash,
|
42
|
+
select_map, and select_order_map Dataset methods, which is on by
|
43
|
+
default. It also has code to speed up the loading of model objects,
|
44
|
+
which is off by default as it isn't fully compatible. It doesn't
|
45
|
+
handle overriding Model.call, Model#set_values, or
|
46
|
+
Model#after_initialize, which may cause problems with the
|
47
|
+
following plugins that ship with Sequel:
|
48
|
+
|
49
|
+
* class_table_inheritance
|
50
|
+
* force_encoding
|
51
|
+
* serializiation
|
52
|
+
* single_table_interitance
|
53
|
+
* typecast_on_load
|
54
|
+
* update_primary_key
|
55
|
+
|
56
|
+
If you want to extract that last ounce of performance when loading
|
57
|
+
model objects and you can live with the limitations, you can
|
58
|
+
enable the model optimization via:
|
59
|
+
|
60
|
+
# All datasets
|
61
|
+
DB.optimize_model_load = true
|
62
|
+
|
63
|
+
# Specific dataset
|
64
|
+
Artist.dataset.optimize_model_load = true
|
65
|
+
|
41
66
|
== Installing the gem
|
42
67
|
|
43
68
|
gem install sequel_pg
|
data/Rakefile
CHANGED
data/ext/sequel_pg/sequel_pg.c
CHANGED
@@ -7,6 +7,9 @@
|
|
7
7
|
#if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
|
8
8
|
#define SPG_ENCODING 1
|
9
9
|
#include <ruby/encoding.h>
|
10
|
+
#define ENC_INDEX ,enc_index
|
11
|
+
#else
|
12
|
+
#define ENC_INDEX
|
10
13
|
#endif
|
11
14
|
|
12
15
|
#define SPG_MAX_FIELDS 256
|
@@ -22,6 +25,17 @@
|
|
22
25
|
#define SPG_APP_LOCAL 4
|
23
26
|
#define SPG_APP_UTC 8
|
24
27
|
|
28
|
+
#define SPG_YIELD_NORMAL 0
|
29
|
+
#define SPG_YIELD_COLUMN 1
|
30
|
+
#define SPG_YIELD_COLUMNS 2
|
31
|
+
#define SPG_YIELD_FIRST 3
|
32
|
+
#define SPG_YIELD_ARRAY 4
|
33
|
+
#define SPG_YIELD_KV_HASH 5
|
34
|
+
#define SPG_YIELD_MKV_HASH 6
|
35
|
+
#define SPG_YIELD_KMV_HASH 7
|
36
|
+
#define SPG_YIELD_MKMV_HASH 8
|
37
|
+
#define SPG_YIELD_MODEL 9
|
38
|
+
|
25
39
|
static VALUE spg_Sequel;
|
26
40
|
static VALUE spg_Blob;
|
27
41
|
static VALUE spg_BigDecimal;
|
@@ -30,6 +44,13 @@ static VALUE spg_SQLTime;
|
|
30
44
|
|
31
45
|
static VALUE spg_sym_utc;
|
32
46
|
static VALUE spg_sym_local;
|
47
|
+
static VALUE spg_sym_map;
|
48
|
+
static VALUE spg_sym_first;
|
49
|
+
static VALUE spg_sym_array;
|
50
|
+
static VALUE spg_sym_hash;
|
51
|
+
static VALUE spg_sym_model;
|
52
|
+
static VALUE spg_sym__sequel_pg_type;
|
53
|
+
static VALUE spg_sym__sequel_pg_value;
|
33
54
|
|
34
55
|
static ID spg_id_new;
|
35
56
|
static ID spg_id_local;
|
@@ -39,7 +60,7 @@ static ID spg_id_day;
|
|
39
60
|
static ID spg_id_output_identifier;
|
40
61
|
static ID spg_id_datetime_class;
|
41
62
|
static ID spg_id_application_timezone;
|
42
|
-
static ID
|
63
|
+
static ID spg_id_timezone;
|
43
64
|
static ID spg_id_op_plus;
|
44
65
|
static ID spg_id_utc;
|
45
66
|
static ID spg_id_utc_offset;
|
@@ -48,12 +69,14 @@ static ID spg_id_new_offset;
|
|
48
69
|
|
49
70
|
static ID spg_id_call;
|
50
71
|
static ID spg_id_get;
|
72
|
+
static ID spg_id_opts;
|
51
73
|
|
52
74
|
static ID spg_id_db;
|
53
75
|
static ID spg_id_conversion_procs;
|
54
76
|
|
55
77
|
static ID spg_id_columns;
|
56
78
|
static ID spg_id_encoding;
|
79
|
+
static ID spg_id_values;
|
57
80
|
|
58
81
|
#if SPG_ENCODING
|
59
82
|
static int enc_get_index(VALUE val)
|
@@ -94,7 +117,7 @@ static VALUE spg_date(const char *s) {
|
|
94
117
|
return rb_funcall(spg_Date, spg_id_new, 3, INT2NUM(year), INT2NUM(month), INT2NUM(day));
|
95
118
|
}
|
96
119
|
|
97
|
-
static VALUE spg_timestamp(const char *s) {
|
120
|
+
static VALUE spg_timestamp(const char *s, VALUE self) {
|
98
121
|
VALUE dtc, dt, rtz;
|
99
122
|
int tz = SPG_NO_TZ;
|
100
123
|
int year, month, day, hour, min, sec, usec, tokens, utc_offset;
|
@@ -135,7 +158,7 @@ static VALUE spg_timestamp(const char *s) {
|
|
135
158
|
|
136
159
|
/* Get values of datetime_class, database_timezone, and application_timezone */
|
137
160
|
dtc = rb_funcall(spg_Sequel, spg_id_datetime_class, 0);
|
138
|
-
rtz = rb_funcall(
|
161
|
+
rtz = rb_funcall(rb_funcall(self, spg_id_db, 0), spg_id_timezone, 0);
|
139
162
|
if (rtz == spg_sym_local) {
|
140
163
|
tz += SPG_DB_LOCAL;
|
141
164
|
} else if (rtz == spg_sym_utc) {
|
@@ -234,6 +257,116 @@ static VALUE spg_fetch_rows_set_cols(VALUE self, VALUE ignore) {
|
|
234
257
|
return self;
|
235
258
|
}
|
236
259
|
|
260
|
+
static VALUE spg__col_value(VALUE self, PGresult *res, long i, long j, VALUE* colconvert
|
261
|
+
#ifdef SPG_ENCODING
|
262
|
+
, int enc_index
|
263
|
+
#endif
|
264
|
+
) {
|
265
|
+
char *v;
|
266
|
+
VALUE rv;
|
267
|
+
size_t l;
|
268
|
+
|
269
|
+
if(PQgetisnull(res, i, j)) {
|
270
|
+
rv = Qnil;
|
271
|
+
} else {
|
272
|
+
v = PQgetvalue(res, i, j);
|
273
|
+
|
274
|
+
switch(PQftype(res, j)) {
|
275
|
+
case 16: /* boolean */
|
276
|
+
rv = *v == 't' ? Qtrue : Qfalse;
|
277
|
+
break;
|
278
|
+
case 17: /* bytea */
|
279
|
+
v = (char *)PQunescapeBytea((unsigned char*)v, &l);
|
280
|
+
rv = rb_funcall(spg_Blob, spg_id_new, 1, rb_str_new(v, l));
|
281
|
+
PQfreemem(v);
|
282
|
+
break;
|
283
|
+
case 20: /* integer */
|
284
|
+
case 21:
|
285
|
+
case 22:
|
286
|
+
case 23:
|
287
|
+
case 26:
|
288
|
+
rv = rb_cstr2inum(v, 10);
|
289
|
+
break;
|
290
|
+
case 700: /* float */
|
291
|
+
case 701:
|
292
|
+
rv = rb_float_new(rb_cstr_to_dbl(v, Qfalse));
|
293
|
+
break;
|
294
|
+
case 790: /* numeric */
|
295
|
+
case 1700:
|
296
|
+
rv = rb_funcall(spg_BigDecimal, spg_id_new, 1, rb_str_new(v, PQgetlength(res, i, j)));
|
297
|
+
break;
|
298
|
+
case 1082: /* date */
|
299
|
+
rv = spg_date(v);
|
300
|
+
break;
|
301
|
+
case 1083: /* time */
|
302
|
+
case 1266:
|
303
|
+
rv = spg_time(v);
|
304
|
+
break;
|
305
|
+
case 1114: /* timestamp */
|
306
|
+
case 1184:
|
307
|
+
rv = spg_timestamp(v, self);
|
308
|
+
break;
|
309
|
+
case 18: /* char */
|
310
|
+
case 25: /* text */
|
311
|
+
case 1043: /* varchar*/
|
312
|
+
rv = rb_tainted_str_new(v, PQgetlength(res, i, j));
|
313
|
+
#ifdef SPG_ENCODING
|
314
|
+
rb_enc_associate_index(rv, enc_index);
|
315
|
+
#endif
|
316
|
+
break;
|
317
|
+
default:
|
318
|
+
rv = rb_tainted_str_new(v, PQgetlength(res, i, j));
|
319
|
+
#ifdef SPG_ENCODING
|
320
|
+
rb_enc_associate_index(rv, enc_index);
|
321
|
+
#endif
|
322
|
+
if (colconvert[j] != Qnil) {
|
323
|
+
rv = rb_funcall(colconvert[j], spg_id_call, 1, rv);
|
324
|
+
}
|
325
|
+
}
|
326
|
+
}
|
327
|
+
return rv;
|
328
|
+
}
|
329
|
+
|
330
|
+
static VALUE spg__col_values(VALUE self, VALUE v, VALUE *colsyms, long nfields, PGresult *res, long i, VALUE *colconvert
|
331
|
+
#ifdef SPG_ENCODING
|
332
|
+
, int enc_index
|
333
|
+
#endif
|
334
|
+
) {
|
335
|
+
long j;
|
336
|
+
VALUE cur;
|
337
|
+
long len = RARRAY_LEN(v);
|
338
|
+
VALUE a = rb_ary_new2(len);
|
339
|
+
for (j=0; j<len; j++) {
|
340
|
+
cur = rb_ary_entry(v, j);
|
341
|
+
rb_ary_store(a, j, cur == Qnil ? Qnil : spg__col_value(self, res, i, NUM2LONG(cur), colconvert ENC_INDEX));
|
342
|
+
}
|
343
|
+
return a;
|
344
|
+
}
|
345
|
+
|
346
|
+
static long spg__field_id(VALUE v, VALUE *colsyms, long nfields) {
|
347
|
+
long j;
|
348
|
+
for (j=0; j<nfields; j++) {
|
349
|
+
if (colsyms[j] == v) {
|
350
|
+
return j;
|
351
|
+
}
|
352
|
+
}
|
353
|
+
return -1;
|
354
|
+
}
|
355
|
+
|
356
|
+
static VALUE spg__field_ids(VALUE v, VALUE *colsyms, long nfields) {
|
357
|
+
long i;
|
358
|
+
long j;
|
359
|
+
VALUE cur;
|
360
|
+
long len = RARRAY_LEN(v);
|
361
|
+
VALUE pg_columns = rb_ary_new2(len);
|
362
|
+
for (i=0; i<len; i++) {
|
363
|
+
cur = rb_ary_entry(v, i);
|
364
|
+
j = spg__field_id(cur, colsyms, nfields);
|
365
|
+
rb_ary_store(pg_columns, i, j == -1 ? Qnil : LONG2NUM(j));
|
366
|
+
}
|
367
|
+
return pg_columns;
|
368
|
+
}
|
369
|
+
|
237
370
|
static VALUE spg_yield_hash_rows(VALUE self, VALUE rres, VALUE ignore) {
|
238
371
|
PGresult *res;
|
239
372
|
VALUE colsyms[SPG_MAX_FIELDS];
|
@@ -242,10 +375,12 @@ static VALUE spg_yield_hash_rows(VALUE self, VALUE rres, VALUE ignore) {
|
|
242
375
|
long nfields;
|
243
376
|
long i;
|
244
377
|
long j;
|
245
|
-
VALUE h
|
246
|
-
|
247
|
-
|
248
|
-
VALUE
|
378
|
+
VALUE h;
|
379
|
+
VALUE conv_procs = 0;
|
380
|
+
VALUE opts;
|
381
|
+
VALUE pg_type;
|
382
|
+
VALUE pg_value;
|
383
|
+
char type = SPG_YIELD_NORMAL;
|
249
384
|
|
250
385
|
#ifdef SPG_ENCODING
|
251
386
|
int enc_index;
|
@@ -285,7 +420,7 @@ static VALUE spg_yield_hash_rows(VALUE self, VALUE rres, VALUE ignore) {
|
|
285
420
|
colconvert[j] = Qnil;
|
286
421
|
break;
|
287
422
|
default:
|
288
|
-
if (conv_procs ==
|
423
|
+
if (conv_procs == 0) {
|
289
424
|
conv_procs = rb_funcall(rb_funcall(self, spg_id_db, 0), spg_id_conversion_procs, 0);
|
290
425
|
}
|
291
426
|
colconvert[j] = rb_funcall(conv_procs, spg_id_get, 1, INT2NUM(i));
|
@@ -294,72 +429,157 @@ static VALUE spg_yield_hash_rows(VALUE self, VALUE rres, VALUE ignore) {
|
|
294
429
|
}
|
295
430
|
rb_ivar_set(self, spg_id_columns, rb_ary_new4(nfields, colsyms));
|
296
431
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
break;
|
329
|
-
case 1082: /* date */
|
330
|
-
rv = spg_date(v);
|
331
|
-
break;
|
332
|
-
case 1083: /* time */
|
333
|
-
case 1266:
|
334
|
-
rv = spg_time(v);
|
335
|
-
break;
|
336
|
-
case 1114: /* timestamp */
|
337
|
-
case 1184:
|
338
|
-
rv = spg_timestamp(v);
|
339
|
-
break;
|
340
|
-
case 18: /* char */
|
341
|
-
case 25: /* text */
|
342
|
-
case 1043: /* varchar*/
|
343
|
-
rv = rb_tainted_str_new(v, PQgetlength(res, i, j));
|
344
|
-
#ifdef SPG_ENCODING
|
345
|
-
rb_enc_associate_index(rv, enc_index);
|
346
|
-
#endif
|
347
|
-
break;
|
348
|
-
default:
|
349
|
-
rv = rb_tainted_str_new(v, PQgetlength(res, i, j));
|
350
|
-
#ifdef SPG_ENCODING
|
351
|
-
rb_enc_associate_index(rv, enc_index);
|
352
|
-
#endif
|
353
|
-
if (colconvert[j] != Qnil) {
|
354
|
-
rv = rb_funcall(colconvert[j], spg_id_call, 1, rv);
|
355
|
-
}
|
432
|
+
opts = rb_funcall(self, spg_id_opts, 0);
|
433
|
+
if (rb_type(opts) == T_HASH) {
|
434
|
+
pg_type = rb_hash_aref(opts, spg_sym__sequel_pg_type);
|
435
|
+
pg_value = rb_hash_aref(opts, spg_sym__sequel_pg_value);
|
436
|
+
if (SYMBOL_P(pg_type)) {
|
437
|
+
if (pg_type == spg_sym_map) {
|
438
|
+
if (SYMBOL_P(pg_value)) {
|
439
|
+
type = SPG_YIELD_COLUMN;
|
440
|
+
} else if (rb_type(pg_value) == T_ARRAY) {
|
441
|
+
type = SPG_YIELD_COLUMNS;
|
442
|
+
}
|
443
|
+
} else if (pg_type == spg_sym_first) {
|
444
|
+
type = SPG_YIELD_FIRST;
|
445
|
+
} else if (pg_type == spg_sym_array) {
|
446
|
+
type = SPG_YIELD_ARRAY;
|
447
|
+
} else if (pg_type == spg_sym_hash && rb_type(pg_value) == T_ARRAY) {
|
448
|
+
VALUE pg_value_key, pg_value_value;
|
449
|
+
pg_value_key = rb_ary_entry(pg_value, 0);
|
450
|
+
pg_value_value = rb_ary_entry(pg_value, 1);
|
451
|
+
if (SYMBOL_P(pg_value_key)) {
|
452
|
+
if (SYMBOL_P(pg_value_value)) {
|
453
|
+
type = SPG_YIELD_KV_HASH;
|
454
|
+
} else if (rb_type(pg_value_value) == T_ARRAY) {
|
455
|
+
type = SPG_YIELD_KMV_HASH;
|
456
|
+
}
|
457
|
+
} else if (rb_type(pg_value_key) == T_ARRAY) {
|
458
|
+
if (SYMBOL_P(pg_value_value)) {
|
459
|
+
type = SPG_YIELD_MKV_HASH;
|
460
|
+
} else if (rb_type(pg_value_value) == T_ARRAY) {
|
461
|
+
type = SPG_YIELD_MKMV_HASH;
|
462
|
+
}
|
356
463
|
}
|
464
|
+
} else if (pg_type == spg_sym_model && rb_type(pg_value) == T_CLASS) {
|
465
|
+
type = SPG_YIELD_MODEL;
|
357
466
|
}
|
358
|
-
rb_hash_aset(h, colsyms[j], rv);
|
359
467
|
}
|
360
|
-
rb_yield(h);
|
361
468
|
}
|
362
|
-
|
469
|
+
|
470
|
+
switch(type) {
|
471
|
+
case SPG_YIELD_NORMAL:
|
472
|
+
/* Normal, hash for entire row */
|
473
|
+
for(i=0; i<ntuples; i++) {
|
474
|
+
h = rb_hash_new();
|
475
|
+
for(j=0; j<nfields; j++) {
|
476
|
+
rb_hash_aset(h, colsyms[j], spg__col_value(self, res, i, j, colconvert ENC_INDEX));
|
477
|
+
}
|
478
|
+
rb_yield(h);
|
479
|
+
}
|
480
|
+
break;
|
481
|
+
case SPG_YIELD_COLUMN:
|
482
|
+
/* Single column */
|
483
|
+
j = spg__field_id(pg_value, colsyms, nfields);
|
484
|
+
if (j == -1) {
|
485
|
+
for(i=0; i<ntuples; i++) {
|
486
|
+
rb_yield(Qnil);
|
487
|
+
}
|
488
|
+
} else {
|
489
|
+
for(i=0; i<ntuples; i++) {
|
490
|
+
rb_yield(spg__col_value(self, res, i, j, colconvert ENC_INDEX));
|
491
|
+
}
|
492
|
+
}
|
493
|
+
break;
|
494
|
+
case SPG_YIELD_COLUMNS:
|
495
|
+
/* Multiple columns as an array */
|
496
|
+
h = spg__field_ids(pg_value, colsyms, nfields);
|
497
|
+
for(i=0; i<ntuples; i++) {
|
498
|
+
rb_yield(spg__col_values(self, h, colsyms, nfields, res, i, colconvert ENC_INDEX));
|
499
|
+
}
|
500
|
+
break;
|
501
|
+
case SPG_YIELD_FIRST:
|
502
|
+
/* First column */
|
503
|
+
for(i=0; i<ntuples; i++) {
|
504
|
+
rb_yield(spg__col_value(self, res, i, 0, colconvert ENC_INDEX));
|
505
|
+
}
|
506
|
+
break;
|
507
|
+
case SPG_YIELD_ARRAY:
|
508
|
+
/* Array of all columns */
|
509
|
+
for(i=0; i<ntuples; i++) {
|
510
|
+
h = rb_ary_new2(nfields);
|
511
|
+
for(j=0; j<nfields; j++) {
|
512
|
+
rb_ary_store(h, j, spg__col_value(self, res, i, j, colconvert ENC_INDEX));
|
513
|
+
}
|
514
|
+
rb_yield(h);
|
515
|
+
}
|
516
|
+
break;
|
517
|
+
case SPG_YIELD_KV_HASH:
|
518
|
+
/* Hash with single key and single value */
|
519
|
+
{
|
520
|
+
VALUE k, v;
|
521
|
+
h = rb_hash_new();
|
522
|
+
k = spg__field_id(rb_ary_entry(pg_value, 0), colsyms, nfields);
|
523
|
+
v = spg__field_id(rb_ary_entry(pg_value, 1), colsyms, nfields);
|
524
|
+
for(i=0; i<ntuples; i++) {
|
525
|
+
rb_hash_aset(h, spg__col_value(self, res, i, k, colconvert ENC_INDEX), spg__col_value(self, res, i, v, colconvert ENC_INDEX));
|
526
|
+
}
|
527
|
+
rb_yield(h);
|
528
|
+
}
|
529
|
+
break;
|
530
|
+
case SPG_YIELD_MKV_HASH:
|
531
|
+
/* Hash with array of keys and single value */
|
532
|
+
{
|
533
|
+
VALUE k, v;
|
534
|
+
h = rb_hash_new();
|
535
|
+
k = spg__field_ids(rb_ary_entry(pg_value, 0), colsyms, nfields);
|
536
|
+
v = spg__field_id(rb_ary_entry(pg_value, 1), colsyms, nfields);
|
537
|
+
for(i=0; i<ntuples; i++) {
|
538
|
+
rb_hash_aset(h, spg__col_values(self, k, colsyms, nfields, res, i, colconvert ENC_INDEX), spg__col_value(self, res, i, v, colconvert ENC_INDEX));
|
539
|
+
}
|
540
|
+
rb_yield(h);
|
541
|
+
}
|
542
|
+
break;
|
543
|
+
case SPG_YIELD_KMV_HASH:
|
544
|
+
/* Hash with single keys and array of values */
|
545
|
+
{
|
546
|
+
VALUE k, v;
|
547
|
+
h = rb_hash_new();
|
548
|
+
k = spg__field_id(rb_ary_entry(pg_value, 0), colsyms, nfields);
|
549
|
+
v = spg__field_ids(rb_ary_entry(pg_value, 1), colsyms, nfields);
|
550
|
+
for(i=0; i<ntuples; i++) {
|
551
|
+
rb_hash_aset(h, spg__col_value(self, res, i, k, colconvert ENC_INDEX), spg__col_values(self, v, colsyms, nfields, res, i, colconvert ENC_INDEX));
|
552
|
+
}
|
553
|
+
rb_yield(h);
|
554
|
+
}
|
555
|
+
break;
|
556
|
+
case SPG_YIELD_MKMV_HASH:
|
557
|
+
/* Hash with array of keys and array of values */
|
558
|
+
{
|
559
|
+
VALUE k, v;
|
560
|
+
h = rb_hash_new();
|
561
|
+
k = spg__field_ids(rb_ary_entry(pg_value, 0), colsyms, nfields);
|
562
|
+
v = spg__field_ids(rb_ary_entry(pg_value, 1), colsyms, nfields);
|
563
|
+
for(i=0; i<ntuples; i++) {
|
564
|
+
rb_hash_aset(h, spg__col_values(self, k, colsyms, nfields, res, i, colconvert ENC_INDEX), spg__col_values(self, v, colsyms, nfields, res, i, colconvert ENC_INDEX));
|
565
|
+
}
|
566
|
+
rb_yield(h);
|
567
|
+
}
|
568
|
+
break;
|
569
|
+
case SPG_YIELD_MODEL:
|
570
|
+
/* Model object for entire row */
|
571
|
+
for(i=0; i<ntuples; i++) {
|
572
|
+
h = rb_hash_new();
|
573
|
+
for(j=0; j<nfields; j++) {
|
574
|
+
rb_hash_aset(h, colsyms[j], spg__col_value(self, res, i, j, colconvert ENC_INDEX));
|
575
|
+
}
|
576
|
+
/* Abuse local variable */
|
577
|
+
pg_type = rb_obj_alloc(pg_value);
|
578
|
+
rb_ivar_set(pg_type, spg_id_values, h);
|
579
|
+
rb_yield(pg_type);
|
580
|
+
}
|
581
|
+
break;
|
582
|
+
}
|
363
583
|
return self;
|
364
584
|
}
|
365
585
|
|
@@ -375,7 +595,7 @@ void Init_sequel_pg(void) {
|
|
375
595
|
spg_id_output_identifier = rb_intern("output_identifier");
|
376
596
|
spg_id_datetime_class = rb_intern("datetime_class");
|
377
597
|
spg_id_application_timezone = rb_intern("application_timezone");
|
378
|
-
|
598
|
+
spg_id_timezone = rb_intern("timezone");
|
379
599
|
spg_id_op_plus = rb_intern("+");
|
380
600
|
spg_id_utc = rb_intern("utc");
|
381
601
|
spg_id_utc_offset = rb_intern("utc_offset");
|
@@ -385,14 +605,24 @@ void Init_sequel_pg(void) {
|
|
385
605
|
spg_id_call = rb_intern("call");
|
386
606
|
spg_id_get = rb_intern("[]");
|
387
607
|
|
608
|
+
spg_id_opts = rb_intern("opts");
|
609
|
+
|
388
610
|
spg_id_db = rb_intern("db");
|
389
611
|
spg_id_conversion_procs = rb_intern("conversion_procs");
|
390
612
|
|
391
613
|
spg_id_columns = rb_intern("@columns");
|
392
614
|
spg_id_encoding = rb_intern("@encoding");
|
615
|
+
spg_id_values = rb_intern("@values");
|
393
616
|
|
394
617
|
spg_sym_utc = ID2SYM(rb_intern("utc"));
|
395
618
|
spg_sym_local = ID2SYM(rb_intern("local"));
|
619
|
+
spg_sym_map = ID2SYM(rb_intern("map"));
|
620
|
+
spg_sym_first = ID2SYM(rb_intern("first"));
|
621
|
+
spg_sym_array = ID2SYM(rb_intern("array"));
|
622
|
+
spg_sym_hash = ID2SYM(rb_intern("hash"));
|
623
|
+
spg_sym_model = ID2SYM(rb_intern("model"));
|
624
|
+
spg_sym__sequel_pg_type = ID2SYM(rb_intern("_sequel_pg_type"));
|
625
|
+
spg_sym__sequel_pg_value = ID2SYM(rb_intern("_sequel_pg_value"));
|
396
626
|
|
397
627
|
spg_Sequel = rb_funcall(rb_cObject, cg, 1, rb_str_new2("Sequel"));
|
398
628
|
spg_Blob = rb_funcall(rb_funcall(spg_Sequel, cg, 1, rb_str_new2("SQL")), cg, 1, rb_str_new2("Blob"));
|
@@ -409,4 +639,6 @@ void Init_sequel_pg(void) {
|
|
409
639
|
c = rb_funcall(spg_Postgres, cg, 1, rb_str_new2("Dataset"));
|
410
640
|
rb_define_private_method(c, "yield_hash_rows", spg_yield_hash_rows, 2);
|
411
641
|
rb_define_private_method(c, "fetch_rows_set_cols", spg_fetch_rows_set_cols, 1);
|
642
|
+
|
643
|
+
rb_require("sequel_pg/sequel_pg");
|
412
644
|
}
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Add speedup for model class creation from dataset
|
2
|
+
class Sequel::Postgres::Database
|
3
|
+
# Whether to optimize loads for all model datasets created from this dataset.
|
4
|
+
# Has certain limitations, see the README for details.
|
5
|
+
attr_accessor :optimize_model_load
|
6
|
+
end
|
7
|
+
|
8
|
+
# Add faster versions of Dataset#map, #to_hash, #select_map, #select_order_map, and #select_hash
|
9
|
+
class Sequel::Postgres::Dataset
|
10
|
+
# Set whether to enable optimized model loading for this dataset.
|
11
|
+
attr_writer :optimize_model_load
|
12
|
+
|
13
|
+
# In the case where an argument is given, use an optimized version.
|
14
|
+
def map(sym=nil)
|
15
|
+
if sym
|
16
|
+
if block_given?
|
17
|
+
super
|
18
|
+
else
|
19
|
+
rows = []
|
20
|
+
clone(:_sequel_pg_type=>:map, :_sequel_pg_value=>sym).fetch_rows(sql){|s| rows << s}
|
21
|
+
rows
|
22
|
+
end
|
23
|
+
else
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# If this dataset has turned model loading on or off, use the default value from
|
29
|
+
# the Database object.
|
30
|
+
def optimize_model_load
|
31
|
+
defined?(@optimize_model_load) ? @optimize_model_load : db.optimize_model_load
|
32
|
+
end
|
33
|
+
|
34
|
+
# In the case where both arguments given, use an optimized version.
|
35
|
+
def to_hash(key_column, value_column = nil)
|
36
|
+
if value_column
|
37
|
+
clone(:_sequel_pg_type=>:hash, :_sequel_pg_value=>[key_column, value_column]).fetch_rows(sql){|s| return s}
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# If model loads are being optimized and this is a model load, use the optimized
|
44
|
+
# version.
|
45
|
+
def each
|
46
|
+
if (rp = row_proc) && optimize_model_load?
|
47
|
+
clone(:_sequel_pg_type=>:model, :_sequel_pg_value=>rp).fetch_rows(sql, &Proc.new)
|
48
|
+
else
|
49
|
+
super
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
# Always use optimized version
|
56
|
+
def _select_map_multiple(ret_cols)
|
57
|
+
rows = []
|
58
|
+
clone(:_sequel_pg_type=>:array).fetch_rows(sql){|s| rows << s}
|
59
|
+
rows
|
60
|
+
end
|
61
|
+
|
62
|
+
# Always use optimized version
|
63
|
+
def _select_map_single
|
64
|
+
rows = []
|
65
|
+
clone(:_sequel_pg_type=>:first).fetch_rows(sql){|s| rows << s}
|
66
|
+
rows
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# The model load can only be optimized if it's for a model and it's not a graphed dataset
|
72
|
+
# or using a cursor.
|
73
|
+
def optimize_model_load?
|
74
|
+
(rp = row_proc).is_a?(Class) && (rp < Sequel::Model) && optimize_model_load && !opts[:use_cursor] && !opts[:graph]
|
75
|
+
end
|
76
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel_pg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 31
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 1.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 1.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeremy Evans
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
19
|
-
default_executable:
|
18
|
+
date: 2011-11-01 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: pg
|
@@ -42,12 +41,12 @@ dependencies:
|
|
42
41
|
requirements:
|
43
42
|
- - ">="
|
44
43
|
- !ruby/object:Gem::Version
|
45
|
-
hash:
|
44
|
+
hash: 115
|
46
45
|
segments:
|
47
46
|
- 3
|
48
|
-
-
|
47
|
+
- 29
|
49
48
|
- 0
|
50
|
-
version: 3.
|
49
|
+
version: 3.29.0
|
51
50
|
type: :runtime
|
52
51
|
version_requirements: *id002
|
53
52
|
description: |
|
@@ -72,7 +71,7 @@ files:
|
|
72
71
|
- Rakefile
|
73
72
|
- ext/sequel_pg/extconf.rb
|
74
73
|
- ext/sequel_pg/sequel_pg.c
|
75
|
-
|
74
|
+
- lib/sequel_pg/sequel_pg.rb
|
76
75
|
homepage: http://github.com/jeremyevans/sequel_pg
|
77
76
|
licenses: []
|
78
77
|
|
@@ -110,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
109
|
requirements: []
|
111
110
|
|
112
111
|
rubyforge_project:
|
113
|
-
rubygems_version: 1.
|
112
|
+
rubygems_version: 1.8.10
|
114
113
|
signing_key:
|
115
114
|
specification_version: 3
|
116
115
|
summary: Faster SELECTs when using Sequel with pg
|