Skip to content

Commit 0375432

Browse files
authored
feat: add some types from pg_catalog (#216)
* feat: add some types from pg_catalog * fix: pin arrow-odbc version
1 parent f392b09 commit 0375432

4 files changed

Lines changed: 78 additions & 3 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ arrow-flight = { version = "53", optional = true, features = [
1212
"flight-sql-experimental",
1313
"tls",
1414
] }
15-
arrow-odbc = { version = "14.0", optional = true }
15+
arrow-odbc = { version = "=14.0.1", optional = true }
1616
async-stream = { version = "0.3.6", optional = true }
1717
async-trait = "0.1"
1818
bb8 = { version = "0.8", optional = true }

src/sql/arrow_sql_gen/arrow.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ pub fn map_data_type_to_array_builder(data_type: &DataType) -> Box<dyn ArrayBuil
8686
DataType::Int16 => Box::new(ListBuilder::new(Int16Builder::new())),
8787
DataType::Int32 => Box::new(ListBuilder::new(Int32Builder::new())),
8888
DataType::Int64 => Box::new(ListBuilder::new(Int64Builder::new())),
89+
DataType::UInt32 => Box::new(ListBuilder::new(UInt32Builder::new())),
8990
DataType::Float32 => Box::new(ListBuilder::new(Float32Builder::new())),
9091
DataType::Float64 => Box::new(ListBuilder::new(Float64Builder::new())),
9192
DataType::Utf8 => Box::new(ListBuilder::new(StringBuilder::new())),
@@ -111,6 +112,10 @@ pub fn map_data_type_to_array_builder(data_type: &DataType) -> Box<dyn ArrayBuil
111112
Int64Builder::new(),
112113
size.to_owned(),
113114
)),
115+
DataType::UInt32 => Box::new(FixedSizeListBuilder::new(
116+
UInt32Builder::new(),
117+
size.to_owned(),
118+
)),
114119
DataType::Float32 => Box::new(FixedSizeListBuilder::new(
115120
Float32Builder::new(),
116121
size.to_owned(),

src/sql/arrow_sql_gen/postgres.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,12 +258,36 @@ pub fn rows_to_arrow(rows: &[Row], projected_schema: &Option<SchemaRef>) -> Resu
258258
Type::OID => {
259259
handle_primitive_type!(builder, Type::OID, UInt32Builder, u32, row, i);
260260
}
261+
Type::XID => {
262+
let Some(builder) = builder else {
263+
return NoBuilderForIndexSnafu { index: i }.fail();
264+
};
265+
let Some(builder) = builder.as_any_mut().downcast_mut::<UInt32Builder>() else {
266+
return FailedToDowncastBuilderSnafu {
267+
postgres_type: format!("{postgres_type}"),
268+
}
269+
.fail();
270+
};
271+
let v = row
272+
.try_get::<usize, Option<XidFromSql>>(i)
273+
.with_context(|_| FailedToGetRowValueSnafu { pg_type: Type::XID })?;
274+
275+
match v {
276+
Some(v) => {
277+
builder.append_value(v.xid);
278+
}
279+
None => builder.append_null(),
280+
}
281+
}
261282
Type::FLOAT4 => {
262283
handle_primitive_type!(builder, Type::FLOAT4, Float32Builder, f32, row, i);
263284
}
264285
Type::FLOAT8 => {
265286
handle_primitive_type!(builder, Type::FLOAT8, Float64Builder, f64, row, i);
266287
}
288+
Type::CHAR => {
289+
handle_primitive_type!(builder, Type::CHAR, Int8Builder, i8, row, i);
290+
}
267291
Type::TEXT => {
268292
handle_primitive_type!(builder, Type::TEXT, StringBuilder, &str, row, i);
269293
}
@@ -645,6 +669,14 @@ pub fn rows_to_arrow(rows: &[Row], projected_schema: &Option<SchemaRef>) -> Resu
645669
ListBuilder<Int64Builder>,
646670
i64
647671
),
672+
Type::OID_ARRAY => handle_primitive_array_type!(
673+
Type::OID_ARRAY,
674+
builder,
675+
row,
676+
i,
677+
ListBuilder<UInt32Builder>,
678+
u32
679+
),
648680
Type::FLOAT4_ARRAY => handle_primitive_array_type!(
649681
Type::FLOAT4_ARRAY,
650682
builder,
@@ -841,9 +873,10 @@ fn map_column_type_to_data_type(column_type: &Type) -> Option<DataType> {
841873
Type::INT2 => Some(DataType::Int16),
842874
Type::INT4 => Some(DataType::Int32),
843875
Type::INT8 | Type::MONEY => Some(DataType::Int64),
844-
Type::OID => Some(DataType::UInt32),
876+
Type::OID | Type::XID => Some(DataType::UInt32),
845877
Type::FLOAT4 => Some(DataType::Float32),
846878
Type::FLOAT8 => Some(DataType::Float64),
879+
Type::CHAR => Some(DataType::Int8),
847880
Type::TEXT | Type::VARCHAR | Type::BPCHAR | Type::UUID | Type::NAME => Some(DataType::Utf8),
848881
Type::BYTEA => Some(DataType::Binary),
849882
Type::BOOL => Some(DataType::Boolean),
@@ -859,6 +892,7 @@ fn map_column_type_to_data_type(column_type: &Type) -> Option<DataType> {
859892
Arc::new(Field::new("item", DataType::Float64, true)),
860893
2,
861894
)),
895+
Type::PG_NODE_TREE => Some(DataType::Utf8),
862896
Type::INT2_ARRAY => Some(DataType::List(Arc::new(Field::new(
863897
"item",
864898
DataType::Int16,
@@ -874,6 +908,11 @@ fn map_column_type_to_data_type(column_type: &Type) -> Option<DataType> {
874908
DataType::Int64,
875909
true,
876910
)))),
911+
Type::OID_ARRAY => Some(DataType::List(Arc::new(Field::new(
912+
"item",
913+
DataType::UInt32,
914+
true,
915+
)))),
877916
Type::FLOAT4_ARRAY => Some(DataType::List(Arc::new(Field::new(
878917
"item",
879918
DataType::Float32,
@@ -1126,6 +1165,25 @@ impl<'a> FromSql<'a> for GeometryFromSql<'a> {
11261165
}
11271166
}
11281167

1168+
struct XidFromSql {
1169+
xid: u32,
1170+
}
1171+
1172+
impl<'a> FromSql<'a> for XidFromSql {
1173+
fn from_sql(
1174+
_ty: &Type,
1175+
raw: &'a [u8],
1176+
) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
1177+
let mut cursor = std::io::Cursor::new(raw);
1178+
let xid = cursor.read_u32::<BigEndian>()?;
1179+
Ok(XidFromSql { xid })
1180+
}
1181+
1182+
fn accepts(ty: &Type) -> bool {
1183+
matches!(*ty, Type::XID)
1184+
}
1185+
}
1186+
11291187
fn get_decimal_column_precision_and_scale(
11301188
column_name: &str,
11311189
projected_schema: &SchemaRef,

src/sql/arrow_sql_gen/postgres/schema.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ pub(crate) fn pg_data_type_to_arrow_type(
1414
"smallint" => Ok(DataType::Int16),
1515
"integer" | "int" | "int4" => Ok(DataType::Int32),
1616
"bigint" | "int8" | "money" => Ok(DataType::Int64),
17-
"oid" => Ok(DataType::UInt32),
17+
"oid" | "xid" | "regproc" => Ok(DataType::UInt32),
1818
"numeric" | "decimal" => {
1919
let (precision, scale) = parse_numeric_type(pg_type)?;
2020
Ok(DataType::Decimal128(precision, scale))
2121
}
2222
"real" | "float4" => Ok(DataType::Float32),
2323
"double precision" | "float8" => Ok(DataType::Float64),
24+
"\"char\"" => Ok(DataType::Int8),
2425
"character" | "char" | "character varying" | "varchar" | "text" | "bpchar" | "uuid"
2526
| "name" => Ok(DataType::Utf8),
2627
"bytea" => Ok(DataType::Binary),
@@ -48,7 +49,13 @@ pub(crate) fn pg_data_type_to_arrow_type(
4849
"bit" | "bit varying" => Ok(DataType::Binary),
4950
"tsvector" | "tsquery" => Ok(DataType::LargeUtf8),
5051
"xml" | "json" | "jsonb" => Ok(DataType::LargeUtf8),
52+
"aclitem" | "pg_node_tree" => Ok(DataType::Utf8),
5153
"array" => parse_array_type(type_details),
54+
"anyarray" => Ok(DataType::List(Arc::new(Field::new(
55+
"item",
56+
DataType::Binary,
57+
true,
58+
)))),
5259
"int4range" => Ok(DataType::Struct(Fields::from(vec![
5360
Field::new("lower", DataType::Int32, true),
5461
Field::new("upper", DataType::Int32, true),
@@ -213,6 +220,11 @@ mod tests {
213220
pg_data_type_to_arrow_type("boolean", None).expect("Failed to convert boolean"),
214221
DataType::Boolean
215222
);
223+
assert_eq!(
224+
pg_data_type_to_arrow_type("\"char\"", None)
225+
.expect("Failed to convert single character"),
226+
DataType::Int8
227+
);
216228

217229
// Test string types
218230
assert_eq!(

0 commit comments

Comments
 (0)