Skip to content

Commit 6d6cc30

Browse files
authored
Merge pull request #675 from larskanis/each_tuple
Add PG::Result#each_tuple
2 parents c2d824b + 41c2bc9 commit 6d6cc30

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

ext/pg_result.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ static void pgresult_init_fnames(VALUE self)
531531
* res.column_values(1) # ["2"]
532532
* res.each.first # {"a" => "1", "b" => "2", "c" => nil}
533533
* res.each_row.first # ["1", "2", nil]
534+
* res.each_tuple.first # #<PG::Tuple a: "1", b: "2", c: nil>
534535
*
535536
* Whenever a value is accessed it is casted to a Ruby object by the assigned #type_map which is PG::TypeMapAllStrings by default.
536537
* Similarly field names can be retrieved either as strings (default) or as symbols which can be switched per #field_name_type= .
@@ -549,6 +550,7 @@ static void pgresult_init_fnames(VALUE self)
549550
* res.column_values(1) # [2]
550551
* res.each.first # {a: 1, b: 2, c: nil}
551552
* res.each_row.first # [1, 2, nil]
553+
* res.each_tuple.first # #<PG::Tuple a: 1, b: 2, c: nil>
552554
*
553555
* Since pg-1.1 the amount of memory in use by a PG::Result object is estimated and passed to ruby's garbage collector.
554556
* You can invoke the #clear method to force deallocation of memory of the instance when finished with the result for better memory performance.
@@ -1430,6 +1432,32 @@ pgresult_each(VALUE self)
14301432
return self;
14311433
}
14321434

1435+
/*
1436+
* call-seq:
1437+
* res.each_tuple{ |tuple| ... }
1438+
*
1439+
* Yields a PG::Tuple object for each row in the result.
1440+
*
1441+
* res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
1442+
* res.each_tuple.first # #<PG::Tuple a: "1", b: "2", c: nil>
1443+
*/
1444+
static VALUE
1445+
pgresult_each_tuple(VALUE self)
1446+
{
1447+
PGresult *result;
1448+
int tuple_num;
1449+
1450+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, pgresult_ntuples_for_enum);
1451+
1452+
result = pgresult_get(self);
1453+
1454+
for(tuple_num = 0; tuple_num < PQntuples(result); tuple_num++) {
1455+
VALUE tuple = pgresult_tuple(self, INT2FIX(tuple_num));
1456+
rb_yield( tuple );
1457+
}
1458+
return self;
1459+
}
1460+
14331461
/*
14341462
* call-seq:
14351463
* res.fields() -> Array
@@ -1797,6 +1825,7 @@ init_pg_result(void)
17971825
rb_define_method(rb_cPGresult, "each", pgresult_each, 0);
17981826
rb_define_method(rb_cPGresult, "fields", pgresult_fields, 0);
17991827
rb_define_method(rb_cPGresult, "each_row", pgresult_each_row, 0);
1828+
rb_define_method(rb_cPGresult, "each_tuple", pgresult_each_tuple, 0);
18001829
rb_define_method(rb_cPGresult, "values", pgresult_values, 0);
18011830
rb_define_method(rb_cPGresult, "column_values", pgresult_column_values, 1);
18021831
rb_define_method(rb_cPGresult, "field_values", pgresult_field_values, 1);

spec/pg/result_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@
122122
expect( list ).to eq [['1', '2']]
123123
end
124124

125+
it "yields a row as a PG::Tuple" do
126+
res = @conn.exec("SELECT 2 AS a, NULL AS b")
127+
list = []
128+
res.each_tuple { |r| list << r }
129+
expect( list.map(&:class) ).to eq [PG::Tuple]
130+
expect( list.map(&:to_h) ).to eq([{"a" => "2", "b" => nil}])
131+
end
132+
125133
it "yields a row as an Enumerator" do
126134
res = @conn.exec("SELECT 1 AS a, 2 AS b")
127135
e = res.each_row

0 commit comments

Comments
 (0)