Skip to content

Commit 164ad14

Browse files
committed
Add pg{13,14,15} to support matrix
1 parent c602f6b commit 164ad14

File tree

13 files changed

+357
-143
lines changed

13 files changed

+357
-143
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
runs-on: ubuntu-latest
2121
strategy:
2222
matrix:
23-
postgres: [ 16, 17 ]
23+
postgres: [ 13, 14, 15, 16, 17 ]
2424
env:
2525
PG_MAJOR: ${{ matrix.postgres }}
2626

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ path = "./src/bin/pgrx_embed.rs"
1313

1414
[features]
1515
default = ["pg17"]
16-
pg16 = ["pgrx/pg16", "pgrx-tests/pg16" ]
17-
pg17 = ["pgrx/pg17", "pgrx-tests/pg17" ]
16+
pg17 = ["pgrx/pg17", "pgrx-tests/pg17"]
17+
pg16 = ["pgrx/pg16", "pgrx-tests/pg16"]
18+
pg15 = ["pgrx/pg15", "pgrx-tests/pg15"]
19+
pg14 = ["pgrx/pg14", "pgrx-tests/pg14"]
20+
pg13 = ["pgrx/pg13", "pgrx-tests/pg13"]
1821
pg_test = []
1922

2023
[dependencies]

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,11 @@ There is currently only one GUC parameter to enable/disable the `pg_parquet`:
235235
> Any type that does not have a corresponding Parquet type will be represented, as a fallback mechanism, as `BYTE_ARRAY` with `STRING` logical type. e.g. `enum`
236236
237237
## Postgres Support Matrix
238-
`pg_parquet` is tested with the following PostgreSQL versions:
238+
`pg_parquet` supports the following PostgreSQL versions:
239239
| PostgreSQL Major Version | Supported |
240240
|--------------------------|-----------|
241-
| 17 ||
241+
| 13 ||
242+
| 14 ||
243+
| 15 ||
242244
| 16 ||
245+
| 17 ||

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use parquet_copy_hook::hook::{init_parquet_copy_hook, ENABLE_PARQUET_COPY_HOOK};
2-
use pg_sys::{AsPgCStr, MarkGUCPrefixReserved};
2+
use parquet_copy_hook::pg_compat::MarkGUCPrefixReserved;
33
use pgrx::{prelude::*, GucContext, GucFlags, GucRegistry};
44

55
mod arrow_parquet;
@@ -29,7 +29,7 @@ pub extern "C" fn _PG_init() {
2929
GucFlags::default(),
3030
);
3131

32-
unsafe { MarkGUCPrefixReserved("pg_parquet".as_pg_cstr()) };
32+
MarkGUCPrefixReserved("pg_parquet");
3333

3434
init_parquet_copy_hook();
3535
}

src/parquet_copy_hook.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ pub(crate) mod copy_to;
33
pub(crate) mod copy_to_dest_receiver;
44
pub(crate) mod copy_utils;
55
pub(crate) mod hook;
6+
pub(crate) mod pg_compat;

src/parquet_copy_hook/copy_from.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use pgrx::{
55
pg_sys::{
66
addNSItemToQuery, assign_expr_collations, canonicalize_qual, check_enable_rls,
77
coerce_to_boolean, eval_const_expressions, make_ands_implicit, transformExpr, AsPgCStr,
8-
BeginCopyFrom, CheckEnableRlsResult, CopyFrom, CopyStmt, EndCopyFrom, InvalidOid, Node,
9-
Oid, ParseExprKind, ParseNamespaceItem, ParseState, PlannedStmt, QueryEnvironment,
8+
CheckEnableRlsResult, CopyFrom, CopyStmt, EndCopyFrom, InvalidOid, Node, Oid,
9+
ParseExprKind, ParseNamespaceItem, ParseState, PlannedStmt, QueryEnvironment,
1010
},
1111
void_mut_ptr, PgBox, PgLogLevel, PgRelation, PgSqlErrorCode,
1212
};
@@ -19,9 +19,12 @@ use crate::{
1919
},
2020
};
2121

22-
use super::copy_utils::{
23-
copy_stmt_attribute_list, copy_stmt_create_namespace_item, copy_stmt_create_parse_state,
24-
create_filtered_tupledesc_for_relation,
22+
use super::{
23+
copy_utils::{
24+
copy_stmt_attribute_list, copy_stmt_create_namespace_item, copy_stmt_create_parse_state,
25+
create_filtered_tupledesc_for_relation,
26+
},
27+
pg_compat::BeginCopyFrom,
2528
};
2629

2730
// stack to store parquet reader contexts for COPY FROM.
@@ -104,47 +107,45 @@ extern "C" fn copy_parquet_data_to_buffer(
104107
// 3. Calls the executor's CopyFrom function to read data from the parquet file and write
105108
// it to the copy buffer.
106109
pub(crate) fn execute_copy_from(
107-
p_stmt: PgBox<PlannedStmt>,
110+
p_stmt: &PgBox<PlannedStmt>,
108111
query_string: &CStr,
109-
query_env: PgBox<QueryEnvironment>,
112+
query_env: &PgBox<QueryEnvironment>,
110113
uri: Url,
111114
) -> u64 {
112-
let rel_oid = copy_stmt_relation_oid(&p_stmt);
115+
let rel_oid = copy_stmt_relation_oid(p_stmt);
113116

114117
copy_from_stmt_ensure_row_level_security(rel_oid);
115118

116-
let lock_mode = copy_stmt_lock_mode(&p_stmt);
119+
let lock_mode = copy_stmt_lock_mode(p_stmt);
117120

118121
let relation = unsafe { PgRelation::with_lock(rel_oid, lock_mode) };
119122

120-
let p_state = copy_stmt_create_parse_state(query_string, &query_env);
123+
let p_state = copy_stmt_create_parse_state(query_string, query_env);
121124

122-
let ns_item = copy_stmt_create_namespace_item(&p_stmt, &p_state, &relation);
125+
let ns_item = copy_stmt_create_namespace_item(p_stmt, &p_state, &relation);
123126

124-
let mut where_clause = copy_from_stmt_where_clause(&p_stmt);
127+
let mut where_clause = copy_from_stmt_where_clause(p_stmt);
125128

126129
if !where_clause.is_null() {
127130
where_clause = copy_from_stmt_transform_where_clause(&p_state, &ns_item, where_clause);
128131
}
129132

130-
let attribute_list = copy_stmt_attribute_list(&p_stmt);
133+
let attribute_list = copy_stmt_attribute_list(p_stmt);
131134

132-
let tupledesc = create_filtered_tupledesc_for_relation(&p_stmt, &relation);
135+
let tupledesc = create_filtered_tupledesc_for_relation(p_stmt, &relation);
133136

134137
unsafe {
135138
// parquet reader context is used throughout the COPY FROM operation.
136139
let parquet_reader_context = ParquetReaderContext::new(uri, &tupledesc);
137140
push_parquet_reader_context(parquet_reader_context);
138141

139142
// makes sure to set binary format
140-
let copy_options = copy_from_stmt_create_option_list(&p_stmt);
143+
let copy_options = copy_from_stmt_create_option_list(p_stmt);
141144

142145
let copy_from_state = BeginCopyFrom(
143146
p_state.as_ptr(),
144147
relation.as_ptr(),
145148
where_clause,
146-
std::ptr::null(),
147-
false,
148149
Some(copy_parquet_data_to_buffer),
149150
attribute_list,
150151
copy_options.as_ptr(),

src/parquet_copy_hook/copy_to.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use std::ffi::{c_char, CStr};
33
use pgrx::{
44
ereport, is_a,
55
pg_sys::{
6-
makeRangeVar, pg_analyze_and_rewrite_fixedparams, pg_plan_query, A_Star, ColumnRef,
7-
CommandTag, CopyStmt, CreateNewPortal, DestReceiver, GetActiveSnapshot,
6+
makeRangeVar, pg_plan_query, A_Star, ColumnRef, CommandTag, CopyStmt, CreateNewPortal,
7+
DestReceiver, GetActiveSnapshot, Node,
88
NodeTag::{self, T_CopyStmt},
99
ParamListInfoData, PlannedStmt, PortalDefineQuery, PortalDrop, PortalRun, PortalStart,
1010
QueryCompletion, QueryEnvironment, RawStmt, ResTarget, SelectStmt, CURSOR_OPT_PARALLEL_OK,
@@ -14,8 +14,9 @@ use pgrx::{
1414
AllocatedByRust, PgBox, PgList, PgLogLevel, PgRelation, PgSqlErrorCode,
1515
};
1616

17-
use crate::parquet_copy_hook::copy_utils::{
18-
copy_stmt_has_relation, copy_stmt_lock_mode, copy_stmt_relation_oid,
17+
use crate::parquet_copy_hook::{
18+
copy_utils::{copy_stmt_has_relation, copy_stmt_lock_mode, copy_stmt_relation_oid},
19+
pg_compat::pg_analyze_and_rewrite,
1920
};
2021

2122
// execute_copy_to_with_dest_receiver executes a COPY TO statement with our custom DestReceiver
@@ -28,8 +29,8 @@ use crate::parquet_copy_hook::copy_utils::{
2829
pub(crate) fn execute_copy_to_with_dest_receiver(
2930
p_stmt: &PgBox<PlannedStmt>,
3031
query_string: &CStr,
31-
params: PgBox<ParamListInfoData>,
32-
query_env: PgBox<QueryEnvironment>,
32+
params: &PgBox<ParamListInfoData>,
33+
query_env: &PgBox<QueryEnvironment>,
3334
parquet_dest: PgBox<DestReceiver>,
3435
) -> u64 {
3536
unsafe {
@@ -51,11 +52,9 @@ pub(crate) fn execute_copy_to_with_dest_receiver(
5152

5253
let raw_query = prepare_copy_to_raw_stmt(p_stmt, &copy_stmt, &relation);
5354

54-
let rewritten_queries = pg_analyze_and_rewrite_fixedparams(
55+
let rewritten_queries = pg_analyze_and_rewrite(
5556
raw_query.as_ptr(),
5657
query_string.as_ptr(),
57-
std::ptr::null_mut(),
58-
0,
5958
query_env.as_ptr(),
6059
);
6160

@@ -156,8 +155,7 @@ fn convert_copy_to_relation_to_select_stmt(
156155
target_list.push(target.into_pg());
157156
} else {
158157
// SELECT a,b,... FROM relation
159-
let attribute_name_list =
160-
unsafe { PgList::<pgrx::pg_sys::String>::from_pg(copy_stmt.attlist) };
158+
let attribute_name_list = unsafe { PgList::<Node>::from_pg(copy_stmt.attlist) };
161159
for attribute_name in attribute_name_list.iter_ptr() {
162160
let mut col_ref = unsafe { PgBox::<ColumnRef>::alloc_node(NodeTag::T_ColumnRef) };
163161

src/parquet_copy_hook/copy_to_dest_receiver.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
use std::ffi::{c_char, CStr};
1+
use std::ffi::{c_char, CStr, CString};
22

33
use pg_sys::{
44
get_typlenbyval, slot_getallattrs, toast_raw_datum_size, AllocSetContextCreateExtended,
5-
AsPgCStr, BlessTupleDesc, CommandDest, CurrentMemoryContext, Datum, DatumGetCString,
6-
DestReceiver, HeapTupleData, List, MemoryContext, MemoryContextAllocZero, MemoryContextDelete,
5+
AsPgCStr, BlessTupleDesc, CommandDest, CurrentMemoryContext, Datum, DestReceiver,
6+
HeapTupleData, List, MemoryContext, MemoryContextAllocZero, MemoryContextDelete,
77
MemoryContextReset, TupleDesc, TupleTableSlot, ALLOCSET_DEFAULT_INITSIZE,
88
ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, VARHDRSZ,
99
};
10-
use pgrx::{prelude::*, PgList, PgMemoryContexts, PgTupleDesc};
10+
use pgrx::{prelude::*, FromDatum, PgList, PgMemoryContexts, PgTupleDesc};
1111

1212
use crate::{
1313
arrow_parquet::{
@@ -373,15 +373,11 @@ fn tuple_column_sizes(tuple_datums: &[Option<Datum>], tupledesc: &PgTupleDesc) -
373373
(unsafe { toast_raw_datum_size(*column_datum) }) as i32 - VARHDRSZ as i32
374374
} else if typlen == -2 {
375375
// cstring
376-
let cstring = unsafe { DatumGetCString(*column_datum) };
377-
378376
let cstring = unsafe {
379-
CStr::from_ptr(cstring)
380-
.to_str()
381-
.expect("cstring is not a valid CString")
377+
CString::from_datum(*column_datum, false)
378+
.expect("cannot get cstring from datum")
382379
};
383-
384-
cstring.len() as i32 + 1
380+
cstring.as_bytes().len() as i32 + 1
385381
} else {
386382
// fixed size type
387383
typlen as i32

src/parquet_copy_hook/copy_utils.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use pgrx::{
55
pg_sys::{
66
addRangeTableEntryForRelation, defGetInt32, defGetInt64, defGetString, get_namespace_name,
77
get_rel_namespace, makeDefElem, makeString, make_parsestate, quote_qualified_identifier,
8-
AccessShareLock, AsPgCStr, CopyStmt, CreateTemplateTupleDesc, DefElem, List, NoLock,
8+
AccessShareLock, AsPgCStr, CopyStmt, CreateTemplateTupleDesc, DefElem, List, NoLock, Node,
99
NodeTag::T_CopyStmt, Oid, ParseNamespaceItem, ParseState, PlannedStmt, QueryEnvironment,
1010
RangeVar, RangeVarGetRelidExtended, RowExclusiveLock, TupleDescInitEntry,
1111
},
@@ -19,6 +19,8 @@ use crate::arrow_parquet::{
1919
uri_utils::parse_uri,
2020
};
2121

22+
use super::pg_compat::strVal;
23+
2224
pub(crate) fn validate_copy_to_options(p_stmt: &PgBox<PlannedStmt>, uri: &Url) {
2325
validate_copy_option_names(
2426
p_stmt,
@@ -444,13 +446,7 @@ fn copy_stmt_attribute_names(p_stmt: &PgBox<PlannedStmt>) -> Vec<String> {
444446
unsafe {
445447
PgList::from_pg(attribute_name_list)
446448
.iter_ptr()
447-
.map(|attribute_name: *mut pgrx::pg_sys::String| {
448-
let attribute_name = PgBox::from_pg(attribute_name);
449-
CStr::from_ptr(attribute_name.sval)
450-
.to_str()
451-
.expect("cannot get attribute name for copy from statement")
452-
.to_string()
453-
})
449+
.map(|attribute_name: *mut Node| strVal(attribute_name))
454450
.collect::<Vec<_>>()
455451
}
456452
}

0 commit comments

Comments
 (0)