Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved "HeapTuple" support #532

Merged
merged 22 commits into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4b867ec
Remove FromDatum::NEEDS_TYPID const
eeeebbbbrrrr Mar 30, 2022
cd50460
Remove the `typid` argument from `FromDatum::from_datum()`.
eeeebbbbrrrr Mar 30, 2022
d313053
Eliminate this pattern during `FromDatum::from_datum()`:
eeeebbbbrrrr Mar 30, 2022
eed2c1a
`FromDatum` gets a new function, `try_from_datum()`
eeeebbbbrrrr Mar 30, 2022
71e6c90
Merge branch 'master' into issue-502
eeeebbbbrrrr Apr 1, 2022
195fcaa
Initial work on a new `PgHeapTuple` type.
eeeebbbbrrrr Apr 1, 2022
116b565
default impl of a new IntoDatum::is_pass_by_value() function
eeeebbbbrrrr Apr 1, 2022
c8c878d
Merge branch 'from-datum-overhaul' into issue-502
eeeebbbbrrrr Apr 1, 2022
5535f04
fix compilation issues after merging from-datum-overhaul
eeeebbbbrrrr Apr 1, 2022
45a1ada
a few more pass-by-value types
eeeebbbbrrrr Apr 1, 2022
89e412e
Merge branch 'from-datum-overhaul' into issue-502
eeeebbbbrrrr Apr 1, 2022
2812e5a
WIP: ability to set attribute values on a HeapTuple
eeeebbbbrrrr Apr 2, 2022
c84f80a
Finish up the `PgHeapTuple` API, plus docs. Update the trigger and c…
eeeebbbbrrrr Apr 6, 2022
ca19a6f
Merge branch 'develop' into issue-502
eeeebbbbrrrr Apr 6, 2022
7aa4c9b
try to cleanup diff
eeeebbbbrrrr Apr 6, 2022
750aeea
try to cleanup diff
eeeebbbbrrrr Apr 6, 2022
def448f
code review cleanup
eeeebbbbrrrr Apr 6, 2022
80a1567
code review cleanup
eeeebbbbrrrr Apr 6, 2022
76130be
code review cleanup
eeeebbbbrrrr Apr 6, 2022
8362336
code review cleanup
eeeebbbbrrrr Apr 6, 2022
c7bf6ce
code review cleanup
eeeebbbbrrrr Apr 6, 2022
4062483
Merge branch 'develop-v0.5.0' into issue-502
eeeebbbbrrrr Apr 20, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ members = [
"pgx-examples/bad_ideas",
"pgx-examples/bgworker",
"pgx-examples/bytea",
"pgx-examples/composite_types",
"pgx-examples/custom_types",
"pgx-examples/custom_sql",
"pgx-examples/errors",
Expand Down
2 changes: 1 addition & 1 deletion pgx-examples/bgworker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub extern "C" fn _PG_init() {
#[pg_guard]
#[no_mangle]
pub extern "C" fn background_worker_main(arg: pg_sys::Datum) {
let arg = unsafe { i32::from_datum(arg, false, pg_sys::INT4OID) };
let arg = unsafe { i32::from_datum(arg, false) };

// these are the signals we want to receive. If we don't attach the SIGTERM handler, then
// we'll never be able to exit via an external notification
Expand Down
6 changes: 6 additions & 0 deletions pgx-examples/composite_types/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.DS_Store
.idea/
/target
*.iml
**/*.rs.bk
Cargo.lock
34 changes: 34 additions & 0 deletions pgx-examples/composite_types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[package]
name = "composite_types"
version = "0.0.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[features]
default = ["pg13"]
pg10 = ["pgx/pg10", "pgx-tests/pg10" ]
pg11 = ["pgx/pg11", "pgx-tests/pg11" ]
pg12 = ["pgx/pg12", "pgx-tests/pg12" ]
pg13 = ["pgx/pg13", "pgx-tests/pg13" ]
pg14 = ["pgx/pg14", "pgx-tests/pg14" ]
pg_test = []

[dependencies]
pgx = { path = "../../pgx", default-features = false }
serde = "1.0.136"

[dev-dependencies]
pgx-tests = { path = "../../pgx-tests" }

# uncomment these if compiling outside of 'pgx'
# [profile.dev]
# panic = "unwind"
# lto = "thin"

# [profile.release]
# panic = "unwind"
# opt-level = 3
# lto = "fat"
# codegen-units = 1
5 changes: 5 additions & 0 deletions pgx-examples/composite_types/composite_types.control
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
comment = 'composite_types: Created by pgx'
default_version = '@CARGO_VERSION@'
module_pathname = '$libdir/composite_types'
relocatable = false
superuser = false
78 changes: 78 additions & 0 deletions pgx-examples/composite_types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use pgx::*;

pg_module_magic!();

#[allow(dead_code)]
#[derive(Debug)]
struct MyType {
name: Option<String>,
age: Option<i32>,
}

impl FromDatum for MyType {
unsafe fn from_datum(composite: pg_sys::Datum, is_null: bool) -> Option<Self>
where
Self: Sized,
{
if is_null {
None
} else {
let tuple = PgHeapTuple::from_composite_datum(composite);
Some(Self {
name: tuple
.get_by_name::<String>("name")
.expect("failed to get attribute: name"),
age: tuple
.get_by_name::<i32>("age")
.expect("failed to get attribute: age"),
})
}
}
}

#[pg_extern]
unsafe fn debug_my_type(
_my_type: AnyElement,
fcinfo: pg_sys::FunctionCallInfo,
) -> Option<AnyElement> {
let composite = pg_getarg_datum(fcinfo, 0).unwrap();
let mut composite = PgHeapTuple::from_composite_datum(composite);

composite
.set_by_name("age", 100)
.expect("no such attribute");
composite
.set_by_name("name", "Someone Else")
.expect("no such attribute");

let composite = composite.into_composite_datum().unwrap();
AnyElement::from_datum(composite, false)
}

#[pg_extern]
fn hello_composite_types() -> &'static str {
eeeebbbbrrrr marked this conversation as resolved.
Show resolved Hide resolved
"Hello, composite_types"
}

#[cfg(any(test, feature = "pg_test"))]
#[pg_schema]
mod tests {
use pgx::*;

#[pg_test]
fn test_hello_composite_types() {
assert_eq!("Hello, composite_types", crate::hello_composite_types());
eeeebbbbrrrr marked this conversation as resolved.
Show resolved Hide resolved
}
}

#[cfg(test)]
eeeebbbbrrrr marked this conversation as resolved.
Show resolved Hide resolved
pub mod pg_test {
pub fn setup(_options: Vec<&str>) {
// perform one-off initialization when the pg_test framework starts
}

pub fn postgresql_conf_options() -> Vec<&'static str> {
// return any postgresql.conf settings that are required for your tests
vec![]
}
}
43 changes: 32 additions & 11 deletions pgx-examples/triggers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,29 @@ unsafe fn trigger_example(fcinfo: pg_sys::FunctionCallInfo) -> pg_sys::Datum {
panic!("not called by trigger manager");
}

let trigdata: PgBox<pg_sys::TriggerData> = PgBox::from_pg(
fcinfo.as_ref().expect("fcinfo is NULL").context as *mut pg_sys::TriggerData,
);
let trigdata = (fcinfo.as_ref().expect("fcinfo is NULL").context as *mut pg_sys::TriggerData)
.as_ref()
.unwrap();

// and for this example, we're only going to operate as an ON BEFORE INSERT FOR EACH ROW trigger
if trigger_fired_before(trigdata.tg_event)
&& trigger_fired_by_insert(trigdata.tg_event)
&& trigger_fired_for_row(trigdata.tg_event)
{
let tupdesc = PgTupleDesc::from_pg_copy(trigdata.tg_relation.as_ref().unwrap().rd_att);
let tuple = PgBox::<pg_sys::HeapTupleData>::from_pg(trigdata.tg_trigtuple);
let id = heap_getattr::<i64, AllocatedByPostgres>(&tuple, 1, &tupdesc);
let title = heap_getattr::<&str, AllocatedByPostgres>(&tuple, 2, &tupdesc);
let description = heap_getattr::<&str, AllocatedByPostgres>(&tuple, 3, &tupdesc);
let payload = heap_getattr::<JsonB, AllocatedByPostgres>(&tuple, 4, &tupdesc);
let tuple =
PgHeapTuple::from_trigger_data(trigdata, TriggerTuple::Current).expect("tuple is NULL");
let id = tuple
.get_by_index::<i64>(1.try_into().unwrap())
.expect("could not get id");
let title = tuple
.get_by_index::<String>(2.try_into().unwrap())
.expect("could not get title");
let description = tuple
.get_by_index::<String>(3.try_into().unwrap())
.expect("could not get description");
let payload = tuple
.get_by_index::<JsonB>(4.try_into().unwrap())
.expect("could not get payload");

warning!(
"id={:?}, title={:?}, description={:?}, payload={:?}",
Expand All @@ -47,8 +55,21 @@ unsafe fn trigger_example(fcinfo: pg_sys::FunctionCallInfo) -> pg_sys::Datum {
payload
);

// return the inserting tuple, unchanged
trigdata.tg_trigtuple as pg_sys::Datum
// change the title
let mut tuple = tuple.into_owned();
tuple
.set_by_name("title", "a new title")
.expect("failed to change the title");
assert_eq!(
tuple.get_by_name::<&str>("title").unwrap().unwrap(),
"a new title"
);

// return the inserting tuple, which includes the changed title
match tuple.into_datum() {
Some(datum) => datum,
None => return pg_return_null(fcinfo),
}
} else {
panic!("not fired in the ON BEFORE INSERT context");
}
Expand Down
2 changes: 1 addition & 1 deletion pgx-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ fn impl_postgres_enum(ast: DeriveInput) -> proc_macro2::TokenStream {
stream.extend(quote! {
impl pgx::FromDatum for #enum_ident {
#[inline]
unsafe fn from_datum(datum: pgx::pg_sys::Datum, is_null: bool, typeoid: pgx::pg_sys::Oid) -> Option<#enum_ident> {
unsafe fn from_datum(datum: pgx::pg_sys::Datum, is_null: bool) -> Option<#enum_ident> {
if is_null {
None
} else {
Expand Down
Loading