diff --git a/Cargo.lock b/Cargo.lock index a2eb9bd2..1fefa422 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -428,6 +428,14 @@ name = "fallible-iterator" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fdw" +version = "0.1.0" +dependencies = [ + "pg-extend 0.2.1", + "pg-extern-attr 0.2.2", +] + [[package]] name = "filetime" version = "0.2.10" diff --git a/Cargo.toml b/Cargo.toml index 6739749c..da12ed17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ "examples/adding", # Examples disabled because FDW support broken with PostgreSQL 11+. # See https://github.com/bluejekyll/pg-extend-rs/issues/49 -# "examples/fdw", + "examples/fdw", # "examples/fdw-rw", "examples/logging", "examples/memory_context", diff --git a/examples/fdw/src/lib.rs b/examples/fdw/src/lib.rs index 421b6c62..d62d3fd2 100644 --- a/examples/fdw/src/lib.rs +++ b/examples/fdw/src/lib.rs @@ -8,7 +8,7 @@ extern crate pg_extend; extern crate pg_extern_attr; -use pg_extend::pg_fdw::{ForeignData, ForeignRow, OptionMap, ForeignTableMetadata}; +use pg_extend::pg_fdw::{ForeignData, ForeignRow, ForeignTableMetadata, OptionMap}; use pg_extend::{pg_datum, pg_magic, pg_type}; use pg_extern_attr::pg_foreignwrapper; diff --git a/integration-tests/tests/fdw.rs b/integration-tests/tests/fdw.rs index ad44c1fb..819d9331 100644 --- a/integration-tests/tests/fdw.rs +++ b/integration-tests/tests/fdw.rs @@ -11,7 +11,6 @@ use integration_tests::*; // FDW tests disabled because it's broken with PostgreSQL 11+. // See See https://github.com/bluejekyll/pg-extend-rs/issues/49 #[test] -#[ignore] // this test is currently broken fn test_fdw() { test_in_db("fdw", |mut conn| { conn.batch_execute( diff --git a/pg-extend/src/pg_fdw.rs b/pg-extend/src/pg_fdw.rs index 9af4c29d..bd70b55e 100644 --- a/pg-extend/src/pg_fdw.rs +++ b/pg-extend/src/pg_fdw.rs @@ -306,7 +306,7 @@ impl ForeignWrapper { let mut t = HashMap::new(); for i in 0..(attrs.len().min(data.len())) { - let name = Self::name_to_string(unsafe { (*attrs[i]).attname }); + let name = Self::name_to_string((attrs[i]).attname); let data = unsafe { pg_datum::PgDatum::from_raw(memory_context, data[i], isnull[i]) }; t.insert(name, data); } @@ -314,18 +314,22 @@ impl ForeignWrapper { t } - unsafe fn tupdesc_attrs(tupledesc: &pg_sys::tupleDesc) -> &[pg_sys::Form_pg_attribute] { + unsafe fn tupdesc_attrs(tupledesc: &pg_sys::tupleDesc) -> &[pg_sys::FormData_pg_attribute] { #[cfg(feature = "postgres-11")] #[allow(clippy::cast_ptr_alignment)] - let attrs = (*tupledesc).attrs.as_ptr() as *const _; + { + let attrs = (*tupledesc).attrs.as_ptr(); + std::slice::from_raw_parts(attrs, (*tupledesc).natts as usize) + } #[cfg(not(feature = "postgres-11"))] - let attrs = (*tupledesc).attrs; - - std::slice::from_raw_parts(attrs, (*tupledesc).natts as usize) + { + let attrs = (*tupledesc).attrs; + std::slice::from_raw_parts(*attrs, (*tupledesc).natts as usize) + } } /// Retrieve next row from the result set, or clear tuple slot to indicate - /// EOF. + /// EOF. /// Fetch one row from the foreign /// (the node's ScanTupleSlot should be used for this purpose). /// Return NULL if no more rows are available. @@ -351,7 +355,7 @@ impl ForeignWrapper { let mut isnull = vec![pgbool!(true); attrs.len()]; for (i, pattr) in attrs.iter().enumerate() { // TODO: There must be a better way to do this? - let result = Self::get_field(&memory_context, &(**pattr), &(*row)); + let result = Self::get_field(&memory_context, &(*pattr), &(*row)); match result { Err(err) => { warn!("{}", err); @@ -408,11 +412,11 @@ impl ForeignWrapper { if let Some(keys) = T::index_columns(&table_metadata) { // Build a map of column names to attributes and column index - let attrs: HashMap = + let attrs: HashMap = Self::tupdesc_attrs(&*(*target_relation).rd_att) .iter() .enumerate() - .map(|(idx, rel)| (Self::name_to_string((**rel).attname), (rel, idx))) + .map(|(idx, rel)| (Self::name_to_string((rel).attname), (rel, idx))) .collect(); for key in keys { @@ -428,8 +432,8 @@ impl ForeignWrapper { let var = pg_sys::makeVar( (*parsetree).resultRelation as u32, *idx as i16 + 1, // points to the position in the tuple, 1-indexed - (*attr).atttypid, - (*attr).atttypmod, + (attr).atttypid, + (attr).atttypmod, 0 as pg_sys::Oid, // InvalidOid 0, );