sequel_pg 1.17.2 → 1.18.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61a49fada0595f92d8452ff231ff0d44ffadf59a887671c9d86178d957f95f44
4
- data.tar.gz: 8969b6f0b9492e2f9edb087b57ef7b13993d61eeaabb9a0291478c1a227448ff
3
+ metadata.gz: 2662871f93e6779540dacacdcee37d0942f65c456ddd7d6d5c2587936a0f5903
4
+ data.tar.gz: 9b364ee075aabd1af37cd0980b5eb256c4cbefd8a473b4aead23203709896e12
5
5
  SHA512:
6
- metadata.gz: 7d5f69fd6e5f2a7dd3b067ca423c85ed2d9fc2f3af9ae191a19507ac3635e654699e5dac6c90ba1f910d5619cf8242a039e07752bfccbfed8c2a57a280fe0bb3
7
- data.tar.gz: 899259457171fafd01c689f234da55255a06a4408ab7e58bcbdf8df94a409884a46ce3e613a2faabe9fbec350b65188d3d8a3e1821832b74d7ff9d145bbb16ef
6
+ metadata.gz: 935750c355575ef4f7b5ccdfb87aa098e46c110bac13699175b7dbbd7eb292dfd4664f88f9cca3c795c0ba35a89fc5a44d57120fd1d9a4ad6ed13046c5c75bd6
7
+ data.tar.gz: b7b3eca0d8b4f938ed8678efec72c057e3208d9656964a44dbb4e9f68f28aeff1b5d3c2dfe7c94f9b5d63d5ccb852ef9016515c146c70457ec228291a3d0feb1
data/CHANGELOG CHANGED
@@ -1,3 +1,25 @@
1
+ === 1.18.1 (2025-12-16)
2
+
3
+ * Fix truncated results for map/select_map/select_order_map/as_hash/to_hash_groups/select_hash/select_hash_groups/as_set/select_set for datasets using use_cursor (jeremyevans) (#62)
4
+
5
+ * Avoid compilation warnings checking for HAVE_* definitions (jeremyevans)
6
+
7
+ === 1.18.0 (2025-12-01)
8
+
9
+ * Optimize Dataset#all and #with_sql_all (jeremyevans)
10
+
11
+ * Fix runtime warnings when using Dataset#as_hash and #to_hash_groups with invalid columns (jeremyevans)
12
+
13
+ * Fix Dataset#map return value when the null_dataset extension is used (jeremyevans)
14
+
15
+ * Further optimize Dataset#as_set and #select_set on Ruby 4+ using core Set C-API (jeremyevans)
16
+
17
+ * Use rb_hash_new_capa if available to avoid unnecessary hash resizing (jeremyevans)
18
+
19
+ * Further optimize Dataset#map and #select_map by populating array in C instead of yielding to Ruby (jeremyevans)
20
+
21
+ * Optimize Dataset#as_set and #select_set in Sequel 5.99+ (jeremyevans)
22
+
1
23
  === 1.17.2 (2025-03-14)
2
24
 
3
25
  * Add explicit arguments to PQfreemem casts to avoid compilation issues when using the C23 standard (jeremyevans) (#59)
data/README.rdoc CHANGED
@@ -127,13 +127,26 @@ requirements:
127
127
  PostgreSQL defaulting to ISO, Sequel also manually sets the
128
128
  date format to ISO by default, so unless you are overriding that
129
129
  setting (via DB.use_iso_date_format = false), you should be OK.
130
+
130
131
  * Adding your own type conversion procs only has an effect if those
131
132
  types are not handled by default.
133
+
132
134
  * You do not need to require the library, the sequel postgres adapter
133
135
  will require it automatically. If you are using bundler, you
134
136
  should add it to your Gemfile like so:
135
137
 
136
- gem 'sequel_pg', :require=>'sequel'
138
+ gem 'sequel_pg', require: 'sequel'
139
+
140
+ * Using a precompiled pg gem can cause issues in certain cases,
141
+ since it statically links a libpq that could differ from the system
142
+ libpq dynamically linked to the sequel_pg gem. You can work around
143
+ the issue by forcing the ruby platform for the pg gem:
144
+
145
+ # Manual install
146
+ gem install pg --platform ruby
147
+
148
+ # Gemfile
149
+ gem 'pg', force_ruby_platform: true
137
150
 
138
151
  * sequel_pg currently calls functions defined in the pg gem, which
139
152
  does not work on Windows and does not work in some unix-like
@@ -7,6 +7,8 @@ dir_config('pg', ENV["POSTGRES_INCLUDE"] || (IO.popen("pg_config --includedir").
7
7
  ENV["POSTGRES_LIB"] || (IO.popen("pg_config --libdir").readline.chomp rescue nil))
8
8
 
9
9
  if (have_library('pq') || have_library('libpq') || have_library('ms/libpq')) && have_header('libpq-fe.h')
10
+ have_func 'rb_hash_new_capa'
11
+ have_func 'rb_set_new_capa'
10
12
  have_func 'PQsetSingleRowMode'
11
13
  have_func 'timegm'
12
14
  create_makefile("sequel_pg")
@@ -1,4 +1,4 @@
1
- #define SEQUEL_PG_VERSION_INTEGER 11702
1
+ #define SEQUEL_PG_VERSION_INTEGER 11801
2
2
 
3
3
  #include <string.h>
4
4
  #include <stdio.h>
@@ -24,6 +24,10 @@
24
24
  #define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
25
25
  #endif
26
26
 
27
+ #ifndef HAVE_RB_HASH_NEW_CAPA
28
+ #define rb_hash_new_capa(_) rb_hash_new()
29
+ #endif
30
+
27
31
  #define ntohll(c) ((uint64_t)( \
28
32
  (((uint64_t)(*((unsigned char*)(c)+0)))<<56LL) | \
29
33
  (((uint64_t)(*((unsigned char*)(c)+1)))<<48LL) | \
@@ -65,6 +69,16 @@
65
69
  #define SPG_YIELD_MKV_HASH_GROUPS 11
66
70
  #define SPG_YIELD_KMV_HASH_GROUPS 12
67
71
  #define SPG_YIELD_MKMV_HASH_GROUPS 13
72
+ #define SPG_YIELD_COLUMN_ARRAY 14
73
+ #define SPG_YIELD_COLUMNS_ARRAY 15
74
+ #define SPG_YIELD_FIRST_ARRAY 16
75
+ #define SPG_YIELD_ARRAY_ARRAY 17
76
+ #define SPG_YIELD_COLUMN_SET 18
77
+ #define SPG_YIELD_COLUMNS_SET 19
78
+ #define SPG_YIELD_FIRST_SET 20
79
+ #define SPG_YIELD_ARRAY_SET 21
80
+ #define SPG_YIELD_ALL 22
81
+ #define SPG_YIELD_ALL_MODEL 23
68
82
 
69
83
  /* External functions defined by ruby-pg */
70
84
  PGconn* pg_get_pgconn(VALUE);
@@ -91,11 +105,19 @@ static VALUE spg_vmasks6;
91
105
  static VALUE spg_sym_utc;
92
106
  static VALUE spg_sym_local;
93
107
  static VALUE spg_sym_map;
108
+ static VALUE spg_sym_map_array;
109
+ static VALUE spg_sym_map_set;
94
110
  static VALUE spg_sym_first;
111
+ static VALUE spg_sym_first_array;
112
+ static VALUE spg_sym_first_set;
95
113
  static VALUE spg_sym_array;
114
+ static VALUE spg_sym_array_array;
115
+ static VALUE spg_sym_array_set;
96
116
  static VALUE spg_sym_hash;
97
117
  static VALUE spg_sym_hash_groups;
98
118
  static VALUE spg_sym_model;
119
+ static VALUE spg_sym_all;
120
+ static VALUE spg_sym_all_model;
99
121
  static VALUE spg_sym__sequel_pg_type;
100
122
  static VALUE spg_sym__sequel_pg_value;
101
123
 
@@ -171,7 +193,7 @@ static ID spg_id_family;
171
193
  static ID spg_id_addr;
172
194
  static ID spg_id_mask_addr;
173
195
 
174
- #if HAVE_PQSETSINGLEROWMODE
196
+ #ifdef HAVE_PQSETSINGLEROWMODE
175
197
  static ID spg_id_get_result;
176
198
  static ID spg_id_clear;
177
199
  static ID spg_id_check;
@@ -1405,10 +1427,34 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
1405
1427
  } else if (rb_type(pg_value) == T_ARRAY) {
1406
1428
  type = SPG_YIELD_COLUMNS;
1407
1429
  }
1430
+ } else if (pg_type == spg_sym_map_array) {
1431
+ if (SYMBOL_P(pg_value)) {
1432
+ type = SPG_YIELD_COLUMN_ARRAY;
1433
+ } else if (rb_type(pg_value) == T_ARRAY) {
1434
+ type = SPG_YIELD_COLUMNS_ARRAY;
1435
+ }
1436
+ #ifdef HAVE_RB_SET_NEW_CAPA
1437
+ } else if (pg_type == spg_sym_map_set) {
1438
+ if (SYMBOL_P(pg_value)) {
1439
+ type = SPG_YIELD_COLUMN_SET;
1440
+ } else if (rb_type(pg_value) == T_ARRAY) {
1441
+ type = SPG_YIELD_COLUMNS_SET;
1442
+ }
1443
+ #endif
1408
1444
  } else if (pg_type == spg_sym_first) {
1409
1445
  type = SPG_YIELD_FIRST;
1410
1446
  } else if (pg_type == spg_sym_array) {
1411
1447
  type = SPG_YIELD_ARRAY;
1448
+ } else if (pg_type == spg_sym_first_array) {
1449
+ type = SPG_YIELD_FIRST_ARRAY;
1450
+ } else if (pg_type == spg_sym_array_array) {
1451
+ type = SPG_YIELD_ARRAY_ARRAY;
1452
+ #ifdef HAVE_RB_SET_NEW_CAPA
1453
+ } else if (pg_type == spg_sym_first_set) {
1454
+ type = SPG_YIELD_FIRST_SET;
1455
+ } else if (pg_type == spg_sym_array_set) {
1456
+ type = SPG_YIELD_ARRAY_SET;
1457
+ #endif
1412
1458
  } else if ((pg_type == spg_sym_hash || pg_type == spg_sym_hash_groups) && rb_type(pg_value) == T_ARRAY) {
1413
1459
  VALUE pg_value_key, pg_value_value;
1414
1460
  pg_value_key = rb_ary_entry(pg_value, 0);
@@ -1428,6 +1474,10 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
1428
1474
  }
1429
1475
  } else if (pg_type == spg_sym_model && rb_type(pg_value) == T_CLASS) {
1430
1476
  type = SPG_YIELD_MODEL;
1477
+ } else if (pg_type == spg_sym_all_model && rb_type(pg_value) == T_CLASS) {
1478
+ type = SPG_YIELD_ALL_MODEL;
1479
+ } else if (pg_type == spg_sym_all) {
1480
+ type = SPG_YIELD_ALL;
1431
1481
  }
1432
1482
  }
1433
1483
  }
@@ -1436,7 +1486,7 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
1436
1486
  case SPG_YIELD_NORMAL:
1437
1487
  /* Normal, hash for entire row */
1438
1488
  for(i=0; i<ntuples; i++) {
1439
- h = rb_hash_new();
1489
+ h = rb_hash_new_capa(nfields);
1440
1490
  for(j=0; j<nfields; j++) {
1441
1491
  rb_hash_aset(h, colsyms[j], spg__col_value(self, res, i, j, colconvert, enc_index));
1442
1492
  }
@@ -1463,6 +1513,63 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
1463
1513
  rb_yield(spg__col_values(self, h, colsyms, nfields, res, i, colconvert, enc_index));
1464
1514
  }
1465
1515
  break;
1516
+ case SPG_YIELD_COLUMN_ARRAY:
1517
+ /* Array containing single column */
1518
+ {
1519
+ VALUE ary = rb_ary_new2(ntuples);
1520
+ j = spg__field_id(pg_value, colsyms, nfields);
1521
+ if (j == -1) {
1522
+ for(i=0; i<ntuples; i++) {
1523
+ rb_ary_store(ary, i, Qnil);
1524
+ }
1525
+ }
1526
+ else {
1527
+ for(i=0; i<ntuples; i++) {
1528
+ rb_ary_store(ary, i, spg__col_value(self, res, i, j, colconvert, enc_index));
1529
+ }
1530
+ }
1531
+ rb_yield(ary);
1532
+ }
1533
+ break;
1534
+ case SPG_YIELD_COLUMNS_ARRAY:
1535
+ /* Array containing arrays of columns */
1536
+ {
1537
+ VALUE ary = rb_ary_new2(ntuples);
1538
+ h = spg__field_ids(pg_value, colsyms, nfields);
1539
+ for(i=0; i<ntuples; i++) {
1540
+ rb_ary_store(ary, i, spg__col_values(self, h, colsyms, nfields, res, i, colconvert, enc_index));
1541
+ }
1542
+ rb_yield(ary);
1543
+ }
1544
+ break;
1545
+ #ifdef HAVE_RB_SET_NEW_CAPA
1546
+ case SPG_YIELD_COLUMN_SET:
1547
+ /* Set containing single column */
1548
+ {
1549
+ VALUE set = rb_set_new_capa(ntuples);
1550
+ j = spg__field_id(pg_value, colsyms, nfields);
1551
+ if (j == -1) {
1552
+ rb_set_add(set, Qnil);
1553
+ } else {
1554
+ for(i=0; i<ntuples; i++) {
1555
+ rb_set_add(set, spg__col_value(self, res, i, j, colconvert, enc_index));
1556
+ }
1557
+ }
1558
+ rb_yield(set);
1559
+ }
1560
+ break;
1561
+ case SPG_YIELD_COLUMNS_SET:
1562
+ /* Set containing arrays of columns */
1563
+ {
1564
+ VALUE set = rb_set_new_capa(ntuples);
1565
+ h = spg__field_ids(pg_value, colsyms, nfields);
1566
+ for(i=0; i<ntuples; i++) {
1567
+ rb_set_add(set, spg__col_values(self, h, colsyms, nfields, res, i, colconvert, enc_index));
1568
+ }
1569
+ rb_yield(set);
1570
+ }
1571
+ break;
1572
+ #endif
1466
1573
  case SPG_YIELD_FIRST:
1467
1574
  /* First column */
1468
1575
  for(i=0; i<ntuples; i++) {
@@ -1479,23 +1586,73 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
1479
1586
  rb_yield(h);
1480
1587
  }
1481
1588
  break;
1589
+ case SPG_YIELD_FIRST_ARRAY:
1590
+ /* Array of first column */
1591
+ h = rb_ary_new2(ntuples);
1592
+ for(i=0; i<ntuples; i++) {
1593
+ rb_ary_store(h, i, spg__col_value(self, res, i, 0, colconvert, enc_index));
1594
+ }
1595
+ rb_yield(h);
1596
+ break;
1597
+ case SPG_YIELD_ARRAY_ARRAY:
1598
+ /* Array of arrays of all columns */
1599
+ {
1600
+ VALUE ary = rb_ary_new2(ntuples);
1601
+ for(i=0; i<ntuples; i++) {
1602
+ h = rb_ary_new2(nfields);
1603
+ for(j=0; j<nfields; j++) {
1604
+ rb_ary_store(h, j, spg__col_value(self, res, i, j, colconvert, enc_index));
1605
+ }
1606
+ rb_ary_store(ary, i, h);
1607
+ }
1608
+ rb_yield(ary);
1609
+ }
1610
+ break;
1611
+ #ifdef HAVE_RB_SET_NEW_CAPA
1612
+ case SPG_YIELD_FIRST_SET:
1613
+ /* Array of first column */
1614
+ h = rb_set_new_capa(ntuples);
1615
+ for(i=0; i<ntuples; i++) {
1616
+ rb_set_add(h, spg__col_value(self, res, i, 0, colconvert, enc_index));
1617
+ }
1618
+ rb_yield(h);
1619
+ break;
1620
+ case SPG_YIELD_ARRAY_SET:
1621
+ /* Array of arrays of all columns */
1622
+ {
1623
+ VALUE set = rb_set_new_capa(ntuples);
1624
+ for(i=0; i<ntuples; i++) {
1625
+ h = rb_ary_new2(nfields);
1626
+ for(j=0; j<nfields; j++) {
1627
+ rb_ary_store(h, j, spg__col_value(self, res, i, j, colconvert, enc_index));
1628
+ }
1629
+ rb_set_add(set, h);
1630
+ }
1631
+ rb_yield(set);
1632
+ }
1633
+ break;
1634
+ #endif
1482
1635
  case SPG_YIELD_KV_HASH:
1483
1636
  case SPG_YIELD_KV_HASH_GROUPS:
1484
1637
  /* Hash with single key and single value */
1485
1638
  {
1486
1639
  int k, v;
1487
- h = rb_hash_new();
1640
+ VALUE kv, vv;
1488
1641
  k = spg__field_id(rb_ary_entry(pg_value, 0), colsyms, nfields);
1489
1642
  v = spg__field_id(rb_ary_entry(pg_value, 1), colsyms, nfields);
1490
1643
  if(type == SPG_YIELD_KV_HASH) {
1644
+ h = rb_hash_new_capa(ntuples);
1491
1645
  for(i=0; i<ntuples; i++) {
1492
- rb_hash_aset(h, spg__col_value(self, res, i, k, colconvert, enc_index), spg__col_value(self, res, i, v, colconvert, enc_index));
1646
+ kv = k == -1 ? Qnil : spg__col_value(self, res, i, k, colconvert, enc_index);
1647
+ vv = v == -1 ? Qnil : spg__col_value(self, res, i, v, colconvert, enc_index);
1648
+ rb_hash_aset(h, kv, vv);
1493
1649
  }
1494
1650
  } else {
1495
- VALUE kv, vv, a;
1651
+ VALUE a;
1652
+ h = rb_hash_new();
1496
1653
  for(i=0; i<ntuples; i++) {
1497
- kv = spg__col_value(self, res, i, k, colconvert, enc_index);
1498
- vv = spg__col_value(self, res, i, v, colconvert, enc_index);
1654
+ kv = k == -1 ? Qnil : spg__col_value(self, res, i, k, colconvert, enc_index);
1655
+ vv = v == -1 ? Qnil : spg__col_value(self, res, i, v, colconvert, enc_index);
1499
1656
  a = rb_hash_lookup(h, kv);
1500
1657
  if(!RTEST(a)) {
1501
1658
  rb_hash_aset(h, kv, rb_ary_new3(1, vv));
@@ -1511,20 +1668,22 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
1511
1668
  case SPG_YIELD_MKV_HASH_GROUPS:
1512
1669
  /* Hash with array of keys and single value */
1513
1670
  {
1514
- VALUE k;
1671
+ VALUE k, vv;
1515
1672
  int v;
1516
- h = rb_hash_new();
1517
1673
  k = spg__field_ids(rb_ary_entry(pg_value, 0), colsyms, nfields);
1518
1674
  v = spg__field_id(rb_ary_entry(pg_value, 1), colsyms, nfields);
1519
1675
  if(type == SPG_YIELD_MKV_HASH) {
1676
+ h = rb_hash_new_capa(ntuples);
1520
1677
  for(i=0; i<ntuples; i++) {
1521
- 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));
1678
+ vv = v == -1 ? Qnil : spg__col_value(self, res, i, v, colconvert, enc_index);
1679
+ rb_hash_aset(h, spg__col_values(self, k, colsyms, nfields, res, i, colconvert, enc_index), vv);
1522
1680
  }
1523
1681
  } else {
1524
- VALUE kv, vv, a;
1682
+ VALUE kv, a;
1683
+ h = rb_hash_new();
1525
1684
  for(i=0; i<ntuples; i++) {
1526
1685
  kv = spg__col_values(self, k, colsyms, nfields, res, i, colconvert, enc_index);
1527
- vv = spg__col_value(self, res, i, v, colconvert, enc_index);
1686
+ vv = v == -1 ? Qnil : spg__col_value(self, res, i, v, colconvert, enc_index);
1528
1687
  a = rb_hash_lookup(h, kv);
1529
1688
  if(!RTEST(a)) {
1530
1689
  rb_hash_aset(h, kv, rb_ary_new3(1, vv));
@@ -1540,19 +1699,21 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
1540
1699
  case SPG_YIELD_KMV_HASH_GROUPS:
1541
1700
  /* Hash with single keys and array of values */
1542
1701
  {
1543
- VALUE v;
1702
+ VALUE v, kv;
1544
1703
  int k;
1545
- h = rb_hash_new();
1546
1704
  k = spg__field_id(rb_ary_entry(pg_value, 0), colsyms, nfields);
1547
1705
  v = spg__field_ids(rb_ary_entry(pg_value, 1), colsyms, nfields);
1548
1706
  if(type == SPG_YIELD_KMV_HASH) {
1707
+ h = rb_hash_new_capa(ntuples);
1549
1708
  for(i=0; i<ntuples; i++) {
1550
- 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));
1709
+ kv = k == -1 ? Qnil : spg__col_value(self, res, i, k, colconvert, enc_index);
1710
+ rb_hash_aset(h, kv, spg__col_values(self, v, colsyms, nfields, res, i, colconvert, enc_index));
1551
1711
  }
1552
1712
  } else {
1553
- VALUE kv, vv, a;
1713
+ VALUE vv, a;
1714
+ h = rb_hash_new();
1554
1715
  for(i=0; i<ntuples; i++) {
1555
- kv = spg__col_value(self, res, i, k, colconvert, enc_index);
1716
+ kv = k == -1 ? Qnil : spg__col_value(self, res, i, k, colconvert, enc_index);
1556
1717
  vv = spg__col_values(self, v, colsyms, nfields, res, i, colconvert, enc_index);
1557
1718
  a = rb_hash_lookup(h, kv);
1558
1719
  if(!RTEST(a)) {
@@ -1570,15 +1731,16 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
1570
1731
  /* Hash with array of keys and array of values */
1571
1732
  {
1572
1733
  VALUE k, v;
1573
- h = rb_hash_new();
1574
1734
  k = spg__field_ids(rb_ary_entry(pg_value, 0), colsyms, nfields);
1575
1735
  v = spg__field_ids(rb_ary_entry(pg_value, 1), colsyms, nfields);
1576
1736
  if(type == SPG_YIELD_MKMV_HASH) {
1737
+ h = rb_hash_new_capa(ntuples);
1577
1738
  for(i=0; i<ntuples; i++) {
1578
1739
  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));
1579
1740
  }
1580
1741
  } else {
1581
1742
  VALUE kv, vv, a;
1743
+ h = rb_hash_new();
1582
1744
  for(i=0; i<ntuples; i++) {
1583
1745
  kv = spg__col_values(self, k, colsyms, nfields, res, i, colconvert, enc_index);
1584
1746
  vv = spg__col_values(self, v, colsyms, nfields, res, i, colconvert, enc_index);
@@ -1596,7 +1758,7 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
1596
1758
  case SPG_YIELD_MODEL:
1597
1759
  /* Model object for entire row */
1598
1760
  for(i=0; i<ntuples; i++) {
1599
- h = rb_hash_new();
1761
+ h = rb_hash_new_capa(nfields);
1600
1762
  for(j=0; j<nfields; j++) {
1601
1763
  rb_hash_aset(h, colsyms[j], spg__col_value(self, res, i, j, colconvert, enc_index));
1602
1764
  }
@@ -1606,6 +1768,35 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
1606
1768
  rb_yield(pg_type);
1607
1769
  }
1608
1770
  break;
1771
+ case SPG_YIELD_ALL_MODEL:
1772
+ {
1773
+ VALUE ary = rb_ary_new2(ntuples);
1774
+ VALUE obj;
1775
+ for(i=0; i<ntuples; i++) {
1776
+ h = rb_hash_new_capa(nfields);
1777
+ for(j=0; j<nfields; j++) {
1778
+ rb_hash_aset(h, colsyms[j], spg__col_value(self, res, i, j, colconvert, enc_index));
1779
+ }
1780
+ obj = rb_obj_alloc(pg_value);
1781
+ rb_ivar_set(obj, spg_id_values, h);
1782
+ rb_ary_store(ary, i, obj);
1783
+ }
1784
+ rb_yield(ary);
1785
+ }
1786
+ break;
1787
+ case SPG_YIELD_ALL:
1788
+ {
1789
+ VALUE ary = rb_ary_new2(ntuples);
1790
+ for(i=0; i<ntuples; i++) {
1791
+ h = rb_hash_new_capa(nfields);
1792
+ for(j=0; j<nfields; j++) {
1793
+ rb_hash_aset(h, colsyms[j], spg__col_value(self, res, i, j, colconvert, enc_index));
1794
+ }
1795
+ rb_ary_store(ary, i, h);
1796
+ }
1797
+ rb_yield(ary);
1798
+ }
1799
+ break;
1609
1800
  }
1610
1801
  return self;
1611
1802
  }
@@ -1646,14 +1837,14 @@ static VALUE spg_yield_hash_rows(VALUE self, VALUE rres, VALUE ignore) {
1646
1837
 
1647
1838
  static VALUE spg_supports_streaming_p(VALUE self) {
1648
1839
  return
1649
- #if HAVE_PQSETSINGLEROWMODE
1840
+ #ifdef HAVE_PQSETSINGLEROWMODE
1650
1841
  Qtrue;
1651
1842
  #else
1652
1843
  Qfalse;
1653
1844
  #endif
1654
1845
  }
1655
1846
 
1656
- #if HAVE_PQSETSINGLEROWMODE
1847
+ #ifdef HAVE_PQSETSINGLEROWMODE
1657
1848
  static VALUE spg_set_single_row_mode(VALUE self) {
1658
1849
  PGconn *conn;
1659
1850
  conn = pg_get_pgconn(self);
@@ -1674,7 +1865,7 @@ struct spg__yield_each_row_stream_data {
1674
1865
 
1675
1866
  static int spg__yield_each_row_stream(VALUE rres, int ntuples, int nfields, void *rdata) {
1676
1867
  struct spg__yield_each_row_stream_data* data = (struct spg__yield_each_row_stream_data *)rdata;
1677
- VALUE h = rb_hash_new();
1868
+ VALUE h = rb_hash_new_capa(nfields);
1678
1869
  VALUE self = data->self;
1679
1870
  VALUE *colsyms = data->colsyms;
1680
1871
  VALUE *colconvert= data->colconvert;
@@ -1735,7 +1926,7 @@ static VALUE spg__yield_each_row_internal(VALUE self, VALUE rconn, VALUE rres, P
1735
1926
  }
1736
1927
 
1737
1928
  while (PQntuples(res) != 0) {
1738
- h = rb_hash_new();
1929
+ h = rb_hash_new_capa(nfields);
1739
1930
  for(j=0; j<nfields; j++) {
1740
1931
  rb_hash_aset(h, colsyms[j], spg__col_value(self, res, 0, j, colconvert , enc_index));
1741
1932
  }
@@ -1918,11 +2109,19 @@ void Init_sequel_pg(void) {
1918
2109
  spg_sym_utc = ID2SYM(rb_intern("utc"));
1919
2110
  spg_sym_local = ID2SYM(rb_intern("local"));
1920
2111
  spg_sym_map = ID2SYM(rb_intern("map"));
2112
+ spg_sym_map_array = ID2SYM(rb_intern("map_array"));
2113
+ spg_sym_map_set = ID2SYM(rb_intern("map_set"));
1921
2114
  spg_sym_first = ID2SYM(rb_intern("first"));
1922
2115
  spg_sym_array = ID2SYM(rb_intern("array"));
2116
+ spg_sym_first_array = ID2SYM(rb_intern("first_array"));
2117
+ spg_sym_array_array = ID2SYM(rb_intern("array_array"));
2118
+ spg_sym_first_set = ID2SYM(rb_intern("first_set"));
2119
+ spg_sym_array_set = ID2SYM(rb_intern("array_set"));
1923
2120
  spg_sym_hash = ID2SYM(rb_intern("hash"));
1924
2121
  spg_sym_hash_groups = ID2SYM(rb_intern("hash_groups"));
1925
2122
  spg_sym_model = ID2SYM(rb_intern("model"));
2123
+ spg_sym_all = ID2SYM(rb_intern("all"));
2124
+ spg_sym_all_model = ID2SYM(rb_intern("all_model"));
1926
2125
  spg_sym__sequel_pg_type = ID2SYM(rb_intern("_sequel_pg_type"));
1927
2126
  spg_sym__sequel_pg_value = ID2SYM(rb_intern("_sequel_pg_value"));
1928
2127
 
@@ -1994,7 +2193,7 @@ void Init_sequel_pg(void) {
1994
2193
 
1995
2194
  rb_define_singleton_method(spg_Postgres, "supports_streaming?", spg_supports_streaming_p, 0);
1996
2195
 
1997
- #if HAVE_PQSETSINGLEROWMODE
2196
+ #ifdef HAVE_PQSETSINGLEROWMODE
1998
2197
  spg_id_get_result = rb_intern("get_result");
1999
2198
  spg_id_clear = rb_intern("clear");
2000
2199
  spg_id_check = rb_intern("check");
@@ -0,0 +1,48 @@
1
+ class Sequel::Postgres::Dataset
2
+ # If model loads are being optimized and this is a model load, use the optimized
3
+ # version.
4
+ def each(&block)
5
+ rp = row_proc
6
+ return super unless allow_sequel_pg_optimization? && optimize_model_load?(rp)
7
+ clone(:_sequel_pg_type=>:model, :_sequel_pg_value=>rp).fetch_rows(sql, &block)
8
+ end
9
+
10
+ # Avoid duplicate method warning
11
+ alias with_sql_all with_sql_all
12
+
13
+ # Always use optimized version
14
+ def with_sql_all(sql, &block)
15
+ rp = row_proc
16
+ return super unless allow_sequel_pg_optimization?
17
+
18
+ if optimize_model_load?(rp)
19
+ clone(:_sequel_pg_type=>:all_model, :_sequel_pg_value=>row_proc).fetch_rows(sql) do |array|
20
+ post_load(array)
21
+ array.each(&block) if block
22
+ return array
23
+ end
24
+ []
25
+ else
26
+ clone(:_sequel_pg_type=>:all).fetch_rows(sql) do |array|
27
+ if rp = row_proc
28
+ array.map!{|h| rp.call(h)}
29
+ end
30
+ post_load(array)
31
+ array.each(&block) if block
32
+ return array
33
+ end
34
+ []
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ # The model load can only be optimized if it's for a model and it's not a graphed dataset
41
+ # or using a cursor.
42
+ def optimize_model_load?(rp)
43
+ rp.is_a?(Class) &&
44
+ rp < Sequel::Model &&
45
+ rp.method(:call).owner == Sequel::Model::ClassMethods &&
46
+ opts[:optimize_model_load] != false
47
+ end
48
+ end
@@ -21,15 +21,36 @@ class Sequel::Postgres::Dataset
21
21
  opts.has_key?(:optimize_model_load) ? opts[:optimize_model_load] : true
22
22
  end
23
23
 
24
+ # :nocov:
25
+ if method_defined?(:as_set)
26
+ # :nocov:
27
+ if RUBY_VERSION > '4'
28
+ def as_set(column)
29
+ return super unless allow_sequel_pg_optimization?
30
+ clone(:_sequel_pg_type=>:map_set, :_sequel_pg_value=>column).fetch_rows(sql){return it}
31
+ Set.new
32
+ end
33
+ # :nocov:
34
+ else
35
+ def as_set(column)
36
+ return super unless allow_sequel_pg_optimization?
37
+ rows = Set.new
38
+ clone(:_sequel_pg_type=>:map, :_sequel_pg_value=>column).fetch_rows(sql){|s| rows.add(s)}
39
+ rows
40
+ end
41
+ end
42
+ # :nocov:
43
+ end
44
+
24
45
  # In the case where an argument is given, use an optimized version.
25
46
  def map(sym=nil)
26
47
  if sym
27
48
  if block_given?
28
49
  super
29
50
  else
30
- rows = []
31
- clone(:_sequel_pg_type=>:map, :_sequel_pg_value=>sym).fetch_rows(sql){|s| rows << s}
32
- rows
51
+ return super unless allow_sequel_pg_optimization?
52
+ clone(:_sequel_pg_type=>:map_array, :_sequel_pg_value=>sym).fetch_rows(sql){|a| return a}
53
+ []
33
54
  end
34
55
  else
35
56
  super
@@ -44,6 +65,7 @@ class Sequel::Postgres::Dataset
44
65
  # In the case where both arguments given, use an optimized version.
45
66
  def as_hash(key_column, value_column = nil, opts = Sequel::OPTS)
46
67
  if value_column && !opts[:hash]
68
+ return super unless allow_sequel_pg_optimization?
47
69
  clone(:_sequel_pg_type=>:hash, :_sequel_pg_value=>[key_column, value_column]).fetch_rows(sql){|s| return s}
48
70
  {}
49
71
  elsif opts.empty?
@@ -64,6 +86,7 @@ class Sequel::Postgres::Dataset
64
86
  # In the case where both arguments given, use an optimized version.
65
87
  def to_hash_groups(key_column, value_column = nil, opts = Sequel::OPTS)
66
88
  if value_column && !opts[:hash]
89
+ return super unless allow_sequel_pg_optimization?
67
90
  clone(:_sequel_pg_type=>:hash_groups, :_sequel_pg_value=>[key_column, value_column]).fetch_rows(sql){|s| return s}
68
91
  {}
69
92
  elsif opts.empty?
@@ -73,48 +96,92 @@ class Sequel::Postgres::Dataset
73
96
  end
74
97
  end
75
98
 
76
- if defined?(Sequel::Model::ClassMethods)
77
- # If model loads are being optimized and this is a model load, use the optimized
78
- # version.
79
- def each(&block)
80
- if optimize_model_load?
81
- clone(:_sequel_pg_type=>:model, :_sequel_pg_value=>row_proc).fetch_rows(sql, &block)
82
- else
83
- super
99
+ # Delegate to with_sql_all using the default SQL
100
+ def all(&block)
101
+ with_sql_all(sql, &block)
102
+ end
103
+
104
+ # :nocov:
105
+ # Generally overridden by the model support, only used if the model
106
+ # support is not used.
107
+ def with_sql_all(sql, &block)
108
+ return super unless allow_sequel_pg_optimization?
109
+
110
+ clone(:_sequel_pg_type=>:all).fetch_rows(sql) do |array|
111
+ if rp = row_proc
112
+ array.map!{|h| rp.call(h)}
84
113
  end
114
+ post_load(array)
115
+ array.each(&block) if block
116
+ return array
85
117
  end
118
+ []
86
119
  end
120
+ # :nocov:
87
121
 
88
122
  protected
89
123
 
90
124
  # Always use optimized version
91
125
  def _select_map_multiple(ret_cols)
92
- rows = []
93
- clone(:_sequel_pg_type=>:array).fetch_rows(sql){|s| rows << s}
94
- rows
126
+ return super unless allow_sequel_pg_optimization?
127
+ clone(:_sequel_pg_type=>:array_array).fetch_rows(sql){|a| return a}
128
+ []
95
129
  end
96
130
 
97
131
  # Always use optimized version
98
132
  def _select_map_single
99
- rows = []
100
- clone(:_sequel_pg_type=>:first).fetch_rows(sql){|s| rows << s}
101
- rows
133
+ return super unless allow_sequel_pg_optimization?
134
+ clone(:_sequel_pg_type=>:first_array).fetch_rows(sql){|a| return a}
135
+ []
102
136
  end
103
137
 
104
- private
138
+ # :nocov:
139
+ if method_defined?(:_select_set_multiple)
140
+ # :nocov:
141
+ if RUBY_VERSION > '4'
142
+ # Always use optimized version
143
+ def _select_set_multiple(ret_cols)
144
+ return super unless allow_sequel_pg_optimization?
145
+ clone(:_sequel_pg_type=>:array_set).fetch_rows(sql){return it}
146
+ Set.new
147
+ end
105
148
 
106
- if defined?(Sequel::Model::ClassMethods)
107
- # The model load can only be optimized if it's for a model and it's not a graphed dataset
108
- # or using a cursor.
109
- def optimize_model_load?
110
- (rp = row_proc) &&
111
- rp.is_a?(Class) &&
112
- rp < Sequel::Model &&
113
- rp.method(:call).owner == Sequel::Model::ClassMethods &&
114
- opts[:optimize_model_load] != false &&
115
- !opts[:use_cursor] &&
116
- !opts[:graph]
149
+ # Always use optimized version
150
+ def _select_set_single
151
+ return super unless allow_sequel_pg_optimization?
152
+ clone(:_sequel_pg_type=>:first_set).fetch_rows(sql){return it}
153
+ Set.new
154
+ end
155
+ # :nocov:
156
+ else
157
+ # Always use optimized version
158
+ def _select_set_multiple(ret_cols)
159
+ return super unless allow_sequel_pg_optimization?
160
+ set = Set.new
161
+ clone(:_sequel_pg_type=>:array).fetch_rows(sql){|s| set.add s}
162
+ set
163
+ end
164
+
165
+ # Always use optimized version
166
+ def _select_set_single
167
+ return super unless allow_sequel_pg_optimization?
168
+ set = Set.new
169
+ clone(:_sequel_pg_type=>:first).fetch_rows(sql){|s| set.add s}
170
+ set
171
+ end
117
172
  end
173
+ # :nocov:
174
+ end
175
+
176
+ if defined?(Sequel::Model::ClassMethods)
177
+ require_relative 'model'
178
+ end
179
+
180
+ private
181
+
182
+ # Whether to allow sequel_pg to optimize the each/all/with_sql_all call.
183
+ def allow_sequel_pg_optimization?
184
+ (!opts[:graph] || opts[:eager_graph]) && !opts[:cursor]
118
185
  end
119
186
  end
120
187
 
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
- version: 1.17.2
4
+ version: 1.18.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-14 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: pg
@@ -57,9 +57,9 @@ executables: []
57
57
  extensions:
58
58
  - ext/sequel_pg/extconf.rb
59
59
  extra_rdoc_files:
60
- - README.rdoc
61
60
  - CHANGELOG
62
61
  - MIT-LICENSE
62
+ - README.rdoc
63
63
  files:
64
64
  - CHANGELOG
65
65
  - MIT-LICENSE
@@ -68,6 +68,7 @@ files:
68
68
  - ext/sequel_pg/extconf.rb
69
69
  - ext/sequel_pg/sequel_pg.c
70
70
  - lib/sequel/extensions/pg_streaming.rb
71
+ - lib/sequel_pg/model.rb
71
72
  - lib/sequel_pg/sequel_pg.rb
72
73
  homepage: http://github.com/jeremyevans/sequel_pg
73
74
  licenses:
@@ -99,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
100
  - !ruby/object:Gem::Version
100
101
  version: '0'
101
102
  requirements: []
102
- rubygems_version: 3.6.2
103
+ rubygems_version: 3.6.9
103
104
  specification_version: 4
104
105
  summary: Faster SELECTs when using Sequel with pg
105
106
  test_files: []