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 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
@@ -5,7 +5,7 @@ CLEAN.include %w'**.rbc rdoc'
5
5
 
6
6
  desc "Do a full cleaning"
7
7
  task :distclean do
8
- CLEAN.include %w'tmp pkg sequel_pg*.gem lib'
8
+ CLEAN.include %w'tmp pkg sequel_pg*.gem lib/*.so'
9
9
  Rake::Task[:clean].invoke
10
10
  end
11
11
 
@@ -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 spg_id_database_timezone;
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(spg_Sequel, spg_id_database_timezone, 0);
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, rv;
246
- size_t l;
247
- char * v;
248
- VALUE conv_procs = NULL;
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 == NULL) {
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
- for(i=0; i<ntuples; i++) {
298
- h = rb_hash_new();
299
- for(j=0; j<nfields; j++) {
300
- if(PQgetisnull(res, i, j)) {
301
- rv = Qnil;
302
- } else {
303
- v = PQgetvalue(res, i, j);
304
-
305
- switch(PQftype(res, j)) {
306
- case 16: /* boolean */
307
- rv = *v == 't' ? Qtrue : Qfalse;
308
- break;
309
- case 17: /* bytea */
310
- v = (char *)PQunescapeBytea((unsigned char*)v, &l);
311
- rv = rb_funcall(spg_Blob, spg_id_new, 1, rb_str_new(v, l));
312
- PQfreemem(v);
313
- break;
314
- case 20: /* integer */
315
- case 21:
316
- case 22:
317
- case 23:
318
- case 26:
319
- rv = rb_cstr2inum(v, 10);
320
- break;
321
- case 700: /* float */
322
- case 701:
323
- rv = rb_float_new(rb_cstr_to_dbl(v, Qfalse));
324
- break;
325
- case 790: /* numeric */
326
- case 1700:
327
- rv = rb_funcall(spg_BigDecimal, spg_id_new, 1, rb_str_new(v, PQgetlength(res, i, j)));
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
- spg_id_database_timezone = rb_intern("database_timezone");
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: 17
5
- prerelease: false
4
+ hash: 31
5
+ prerelease:
6
6
  segments:
7
7
  - 1
8
- - 1
9
- - 1
10
- version: 1.1.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-09-01 00:00:00 -07:00
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: 107
44
+ hash: 115
46
45
  segments:
47
46
  - 3
48
- - 27
47
+ - 29
49
48
  - 0
50
- version: 3.27.0
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
- has_rdoc: true
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.3.7
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