Description
It would be useful to be able to treat the value of a composite-value column as a Row
. Presently, to read composite values you need to use postgres-derive
or handle the raw bytes returned by Row::get_bytes(...)
. In certain situations neither option is attractive. Using postgres-derive
requires one to define a struct matching the fields of the composite value and results in parsing based on name matching, which could be a performance issue. Manually handling the raw bytes returned by Row::get_bytes(...)
could avoid the performance issue, but that would mean duplicating a fair amount of code that is already in postgres-protocol
in the form of message::DataRowBody
and message::DataRowRanges
.
I'm not entirely certain of the best approach within the library (a simple hack is to make DataRowBody
and DataRowRanges
externally constructible and feed the field's raw bytes into them).
An example use case would be in working with class-table inheritance, where you might want to query the concrete type variants as composites:
let sql = "\
SELECT widget.type, widget.name, machine, toy \
FROM widget LEFT JOIN machine USING (id) LEFT JOIN toy USING (id) \
";
for row in &conn.query(sql, &[]).unwrap() {
let ty = str::from_utf8(row.get_bytes(0).unwrap()).unwrap();
let name = row.get(1);
let kind = match ty {
"machine" => {
let row: Composite = row.get(2);
WidgetKind::Machine {
gears: row.get(0),
operator: row.get(1),
}
},
"toy" => {
let row: Composite = row.get(3);
WidgetKind::Toy {
minimum_age: row.get(0),
}
},
};
let widget = Widget { name, kind };
println!("{:?}", widget);
}