diff --git a/Cargo.toml b/Cargo.toml
index 54750274..769e554d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,7 +30,7 @@ serde = "1.0.201"
serde_json = "1.0.120"
signal-hook = "0.3.17"
strum = { version = "0.26.3", features = ["derive"] }
-supabase-wrappers = { git = "https://github.com/paradedb/wrappers.git", default-features = false, rev = "c6f5e79" }
+supabase-wrappers = { git = "https://github.com/paradedb/wrappers.git", default-features = false, rev = "719628f" }
thiserror = "1.0.59"
uuid = "1.9.1"
diff --git a/src/duckdb/csv.rs b/src/duckdb/csv.rs
index 0e5414fb..fe82de31 100644
--- a/src/duckdb/csv.rs
+++ b/src/duckdb/csv.rs
@@ -19,6 +19,8 @@ use anyhow::{anyhow, Result};
use std::collections::HashMap;
use strum::{AsRefStr, EnumIter};
+use crate::fdw::base::OptionValidator;
+
use super::utils;
#[derive(EnumIter, AsRefStr, PartialEq, Debug)]
@@ -93,8 +95,8 @@ pub enum CsvOption {
UnionByName,
}
-impl CsvOption {
- pub fn is_required(&self) -> bool {
+impl OptionValidator for CsvOption {
+ fn is_required(&self) -> bool {
match self {
Self::AllVarchar => false,
Self::AllowQuotedNulls => false,
diff --git a/src/duckdb/delta.rs b/src/duckdb/delta.rs
index 412f1d2b..0d95e65a 100644
--- a/src/duckdb/delta.rs
+++ b/src/duckdb/delta.rs
@@ -15,6 +15,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+use crate::fdw::base::OptionValidator;
use anyhow::{anyhow, Result};
use std::collections::HashMap;
use strum::{AsRefStr, EnumIter};
@@ -29,8 +30,8 @@ pub enum DeltaOption {
Select,
}
-impl DeltaOption {
- pub fn is_required(&self) -> bool {
+impl OptionValidator for DeltaOption {
+ fn is_required(&self) -> bool {
match self {
Self::Files => true,
Self::PreserveCasing => false,
diff --git a/src/duckdb/iceberg.rs b/src/duckdb/iceberg.rs
index 851e9fb4..689afc52 100644
--- a/src/duckdb/iceberg.rs
+++ b/src/duckdb/iceberg.rs
@@ -19,6 +19,8 @@ use anyhow::{anyhow, Result};
use std::collections::HashMap;
use strum::{AsRefStr, EnumIter};
+use crate::fdw::base::OptionValidator;
+
#[derive(EnumIter, AsRefStr, PartialEq, Debug)]
pub enum IcebergOption {
#[strum(serialize = "allow_moved_paths")]
@@ -31,8 +33,8 @@ pub enum IcebergOption {
Select,
}
-impl IcebergOption {
- pub fn is_required(&self) -> bool {
+impl OptionValidator for IcebergOption {
+ fn is_required(&self) -> bool {
match self {
Self::AllowMovedPaths => false,
Self::Files => true,
diff --git a/src/duckdb/parquet.rs b/src/duckdb/parquet.rs
index c79c39aa..96e45ea2 100644
--- a/src/duckdb/parquet.rs
+++ b/src/duckdb/parquet.rs
@@ -19,6 +19,8 @@ use anyhow::{anyhow, Result};
use std::collections::HashMap;
use strum::{AsRefStr, EnumIter};
+use crate::fdw::base::OptionValidator;
+
use super::utils;
#[derive(EnumIter, AsRefStr, PartialEq, Debug)]
@@ -46,8 +48,8 @@ pub enum ParquetOption {
// TODO: EncryptionConfig
}
-impl ParquetOption {
- pub fn is_required(&self) -> bool {
+impl OptionValidator for ParquetOption {
+ fn is_required(&self) -> bool {
match self {
Self::BinaryAsString => false,
Self::FileName => false,
diff --git a/src/duckdb/secret.rs b/src/duckdb/secret.rs
index cce3c561..81104152 100644
--- a/src/duckdb/secret.rs
+++ b/src/duckdb/secret.rs
@@ -19,6 +19,8 @@ use anyhow::{anyhow, bail, Result};
use std::collections::HashMap;
use strum::{AsRefStr, EnumIter};
+use crate::fdw::base::OptionValidator;
+
#[derive(EnumIter, AsRefStr, PartialEq, Debug)]
pub enum UserMappingOptions {
// Universal
@@ -70,9 +72,8 @@ pub enum UserMappingOptions {
ProxyPassword,
}
-impl UserMappingOptions {
- #[allow(unused)]
- pub fn is_required(&self) -> bool {
+impl OptionValidator for UserMappingOptions {
+ fn is_required(&self) -> bool {
match self {
Self::Type => true,
Self::Provider => false,
diff --git a/src/duckdb/spatial.rs b/src/duckdb/spatial.rs
index db330f6a..b0d54e24 100644
--- a/src/duckdb/spatial.rs
+++ b/src/duckdb/spatial.rs
@@ -20,6 +20,8 @@ use std::collections::HashMap;
use strum::IntoEnumIterator;
use strum::{AsRefStr, EnumIter};
+use crate::fdw::base::OptionValidator;
+
/// SpatialOption is an enum that represents the options that can be passed to the st_read function.
/// Reference https://github.com/duckdb/duckdb_spatial/blob/main/docs/functions.md#st_read
#[derive(EnumIter, AsRefStr, PartialEq, Debug)]
@@ -44,8 +46,8 @@ pub enum SpatialOption {
KeepWkb,
}
-impl SpatialOption {
- pub fn is_required(&self) -> bool {
+impl OptionValidator for SpatialOption {
+ fn is_required(&self) -> bool {
match self {
Self::Files => true,
Self::SequentialLayerScan => false,
diff --git a/src/fdw/base.rs b/src/fdw/base.rs
index 3f7e64fa..01d10365 100644
--- a/src/fdw/base.rs
+++ b/src/fdw/base.rs
@@ -19,6 +19,7 @@ use anyhow::{anyhow, bail, Result};
use duckdb::arrow::array::RecordBatch;
use pgrx::*;
use std::collections::HashMap;
+use strum::IntoEnumIterator;
use supabase_wrappers::prelude::*;
use thiserror::Error;
@@ -288,3 +289,22 @@ impl DuckDbFormatter {
Self {}
}
}
+
+pub(crate) trait OptionValidator {
+ fn is_required(&self) -> bool;
+}
+
+pub fn validate_mapping_option>(
+ opt_list: Vec