Skip to content

Commit e1e20e3

Browse files
committed
add new catalog and cache APIs
Signed-off-by: usamoi <[email protected]>
1 parent 12842b6 commit e1e20e3

File tree

12 files changed

+908
-430
lines changed

12 files changed

+908
-430
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pgrx-pg-sys/include/pg12.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "catalog/pg_foreign_data_wrapper.h"
5151
#include "catalog/pg_foreign_server.h"
5252
#include "catalog/pg_foreign_table.h"
53+
#include "catalog/pg_index.h"
5354
#include "catalog/pg_operator.h"
5455
#include "catalog/pg_opclass.h"
5556
#include "catalog/pg_opfamily.h"

pgrx-pg-sys/include/pg13.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "catalog/pg_foreign_data_wrapper.h"
5151
#include "catalog/pg_foreign_server.h"
5252
#include "catalog/pg_foreign_table.h"
53+
#include "catalog/pg_index.h"
5354
#include "catalog/pg_operator.h"
5455
#include "catalog/pg_opclass.h"
5556
#include "catalog/pg_opfamily.h"

pgrx-pg-sys/include/pg14.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "catalog/pg_foreign_data_wrapper.h"
5151
#include "catalog/pg_foreign_server.h"
5252
#include "catalog/pg_foreign_table.h"
53+
#include "catalog/pg_index.h"
5354
#include "catalog/pg_operator.h"
5455
#include "catalog/pg_opclass.h"
5556
#include "catalog/pg_opfamily.h"

pgrx-pg-sys/include/pg15.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "catalog/pg_foreign_data_wrapper.h"
5252
#include "catalog/pg_foreign_server.h"
5353
#include "catalog/pg_foreign_table.h"
54+
#include "catalog/pg_index.h"
5455
#include "catalog/pg_operator.h"
5556
#include "catalog/pg_opclass.h"
5657
#include "catalog/pg_opfamily.h"

pgrx-pg-sys/include/pg16.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include "catalog/pg_foreign_data_wrapper.h"
5353
#include "catalog/pg_foreign_server.h"
5454
#include "catalog/pg_foreign_table.h"
55+
#include "catalog/pg_index.h"
5556
#include "catalog/pg_operator.h"
5657
#include "catalog/pg_opclass.h"
5758
#include "catalog/pg_opfamily.h"

pgrx/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,4 @@ seahash = "4.1.0" # derive(PostgresHash)
6565
serde = { version = "1.0", features = [ "derive" ] } # impls on pub types
6666
serde_cbor = "0.11.2" # derive(PostgresType)
6767
serde_json = "1.0" # everything JSON
68+
paste = "1.0.14"

pgrx/src/enum_helper.rs

Lines changed: 17 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,45 +9,26 @@
99
//LICENSE Use of this source code is governed by the MIT license that can be found in the LICENSE file.
1010
//! Helper functions for working with Postgres `enum` types
1111
12-
use crate::pg_sys::GETSTRUCT;
12+
use crate::pg_catalog::PgEnum;
1313
use crate::{ereport, pg_sys, PgLogLevel, PgSqlErrorCode};
1414

1515
pub fn lookup_enum_by_oid(enumval: pg_sys::Oid) -> (String, pg_sys::Oid, f32) {
16-
let tup = unsafe {
17-
pg_sys::SearchSysCache(
18-
pg_sys::SysCacheIdentifier_ENUMOID as i32,
19-
pg_sys::Datum::from(enumval),
20-
pg_sys::Datum::from(0),
21-
pg_sys::Datum::from(0),
22-
pg_sys::Datum::from(0),
23-
)
24-
};
25-
if tup.is_null() {
16+
let pg_enum = PgEnum::search_enumoid(enumval).unwrap();
17+
18+
let Some(pg_enum) = pg_enum.get() else {
2619
ereport!(
2720
PgLogLevel::ERROR,
2821
PgSqlErrorCode::ERRCODE_INVALID_BINARY_REPRESENTATION,
2922
format!("invalid internal value for enum: {enumval:?}")
3023
);
31-
}
32-
33-
let en = unsafe { GETSTRUCT(tup) } as pg_sys::Form_pg_enum;
34-
let en = unsafe { en.as_ref() }.unwrap();
35-
let result = (
36-
unsafe {
37-
core::ffi::CStr::from_ptr(en.enumlabel.data.as_ptr() as *const std::os::raw::c_char)
38-
}
39-
.to_str()
40-
.unwrap()
41-
.to_string(),
42-
en.enumtypid,
43-
en.enumsortorder as f32,
44-
);
45-
46-
unsafe {
47-
pg_sys::ReleaseSysCache(tup);
48-
}
24+
unreachable!()
25+
};
4926

50-
result
27+
(
28+
pg_enum.enumlabel().to_str().unwrap().to_string(),
29+
pg_enum.enumtypid(),
30+
pg_enum.enumsortorder() as f32,
31+
)
5132
}
5233

5334
pub fn lookup_enum_by_label(typname: &str, label: &str) -> pg_sys::Datum {
@@ -57,35 +38,13 @@ pub fn lookup_enum_by_label(typname: &str, label: &str) -> pg_sys::Datum {
5738
panic!("could not locate type oid for type: {typname}");
5839
}
5940

60-
let tup = unsafe {
61-
let label =
62-
alloc::ffi::CString::new(label).expect("failed to convert enum typname to a CString");
63-
pg_sys::SearchSysCache(
64-
pg_sys::SysCacheIdentifier_ENUMTYPOIDNAME as i32,
65-
pg_sys::Datum::from(enumtypoid),
66-
pg_sys::Datum::from(label.as_ptr()),
67-
pg_sys::Datum::from(0usize),
68-
pg_sys::Datum::from(0usize),
69-
)
70-
};
71-
72-
if tup.is_null() {
73-
panic!("could not find heap tuple for enum: {typname}.{label}, typoid={enumtypoid:?}");
74-
}
41+
let label = std::ffi::CString::new(label).expect("failed to convert enum typname to a CString");
7542

76-
// SAFETY: we know that `tup` is valid because we just got it from Postgres above
77-
unsafe {
78-
let oid = extract_enum_oid(tup);
79-
pg_sys::ReleaseSysCache(tup);
80-
pg_sys::Datum::from(oid)
81-
}
82-
}
43+
let pg_enum = PgEnum::search_enumtypoidname(enumtypoid, &label).unwrap();
8344

84-
unsafe fn extract_enum_oid(tup: *mut pg_sys::HeapTupleData) -> pg_sys::Oid {
85-
let en = {
86-
// SAFETY: the caller has assured us that `tup` is a valid HeapTupleData pointer
87-
GETSTRUCT(tup) as pg_sys::Form_pg_enum
45+
let Some(pg_enum) = pg_enum.get() else {
46+
panic!("could not find heap tuple for enum: {typname}.{label:?}, typoid={enumtypoid:?}");
8847
};
89-
let en = en.as_ref().unwrap();
90-
en.oid
48+
49+
pg_sys::Datum::from(pg_enum.oid())
9150
}

pgrx/src/fn_call.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use pgrx_pg_sys::PgTryBuilder;
1414
use std::panic::AssertUnwindSafe;
1515

1616
use crate::memcx;
17-
use crate::pg_catalog::pg_proc::{PgProc, ProArgMode, ProKind};
17+
use crate::pg_catalog::PgProc;
18+
use crate::pg_catalog::{PgProcProargmodes, PgProcProkind};
1819
use crate::seal::Sealed;
1920
use crate::{
2021
direct_function_call, is_a, list::List, pg_sys, pg_sys::AsPgCStr, Array, FromDatum, IntoDatum,
@@ -205,18 +206,22 @@ pub fn fn_call_with_collation<R: FromDatum + IntoDatum>(
205206
let func_oid = lookup_fn(fname, args)?;
206207

207208
// lookup the function's pg_proc entry and do some validation
208-
let pg_proc = PgProc::new(func_oid).ok_or(FnCallError::UndefinedFunction)?;
209+
let pg_proc = PgProc::search_procoid(func_oid).ok_or(FnCallError::UndefinedFunction)?;
210+
let pg_proc = pg_proc.get().ok_or(FnCallError::UndefinedFunction)?;
209211
let retoid = pg_proc.prorettype();
210212

211213
//
212214
// do some validation to catch the cases we don't/can't directly call
213215
//
214216

215-
if !matches!(pg_proc.prokind(), ProKind::Function) {
217+
if !matches!(pg_proc.prokind(), PgProcProkind::Function) {
216218
// It only makes sense to directly call regular functions. Calling aggregate or window
217219
// functions is nonsensical
218220
return Err(FnCallError::UnsupportedFunctionType);
219-
} else if pg_proc.proargmodes().iter().any(|mode| *mode != ProArgMode::In) {
221+
} else if pg_proc
222+
.proargmodes()
223+
.map_or(false, |x| x.iter_deny_null().any(|mode| mode != PgProcProargmodes::In))
224+
{
220225
// Right now we only know how to support arguments with the IN mode. Perhaps in the
221226
// future we can support IN_OUT and TABLE return types
222227
return Err(FnCallError::UnsupportedArgumentModes);
@@ -240,7 +245,7 @@ pub fn fn_call_with_collation<R: FromDatum + IntoDatum>(
240245
.iter()
241246
.enumerate()
242247
.map(|(i, a)| a.as_datum(&pg_proc, i))
243-
.chain((args.len()..pg_proc.pronargs()).map(|i| create_default_value(&pg_proc, i)))
248+
.chain((args.len()..pg_proc.pronargs() as usize).map(|i| create_default_value(&pg_proc, i)))
244249
.map(|datum| {
245250
null |= matches!(datum, Ok(None));
246251
datum
@@ -276,7 +281,7 @@ pub fn fn_call_with_collation<R: FromDatum + IntoDatum>(
276281
//
277282
// SAFETY: we allocate enough zeroed space for the base FunctionCallInfoBaseData *plus* the number of arguments
278283
// we have, and we've asserted that we have the correct number of arguments
279-
assert_eq!(nargs, pg_proc.pronargs());
284+
assert_eq!(nargs, pg_proc.pronargs() as usize);
280285
let fcinfo = pg_sys::palloc0(
281286
std::mem::size_of::<pg_sys::FunctionCallInfoBaseData>()
282287
+ std::mem::size_of::<pg_sys::NullableDatum>() * nargs,
@@ -433,7 +438,7 @@ fn parse_sql_ident(ident: &str) -> Result<Array<&str>> {
433438
/// - [`FnCallError::NotDefaultArgument`] if the specified `argnum` does not have a `DEFAULT` clause
434439
/// - [`FnCallError::DefaultNotConstantExpression`] if the `DEFAULT` clause is one we cannot evaluate
435440
fn create_default_value(pg_proc: &PgProc, argnum: usize) -> Result<Option<pg_sys::Datum>> {
436-
let non_default_args_cnt = pg_proc.pronargs() - pg_proc.pronargdefaults();
441+
let non_default_args_cnt = (pg_proc.pronargs() - pg_proc.pronargdefaults()) as usize;
437442
if argnum < non_default_args_cnt {
438443
return Err(FnCallError::NotDefaultArgument(argnum));
439444
}

0 commit comments

Comments
 (0)