Skip to main content

partiql_extension_ion_functions/
lib.rs

1#![deny(rust_2018_idioms)]
2#![deny(clippy::all)]
3
4use crate::scan_ion::ScanIonFunction;
5use partiql_catalog::catalog::Catalog;
6use partiql_catalog::extension::{ExtensionError, ExtensionResultError};
7use partiql_catalog::table_fn::{BaseTableFunctionInfo, TableFunction};
8use partiql_extension_ion::decode::IonDecodeError;
9use partiql_value::Value;
10use read_ion::ReadIonFunction;
11use std::error::Error;
12use std::fmt::Debug;
13use thiserror::Error;
14
15mod buffer;
16mod read_ion;
17mod scan_ion;
18
19/// Errors in ion extension.
20///
21/// ### Notes
22/// This is marked `#[non_exhaustive]`, to reserve the right to add more variants in the future.
23#[derive(Error, Debug)]
24#[non_exhaustive]
25pub enum IonExtensionError {
26    /// Function error.
27    #[error("`read_ion` function error: `{}`", .0)]
28    FunctionError(String),
29
30    /// Ion Stream Error
31    #[error("Ion Stream Error: `{}`", .0)]
32    IonStreamError(IonDecodeError),
33
34    /// Ion Read Error
35    #[error("Ion Read Error: `{}`", .0)]
36    IonReadError(Box<dyn Error>),
37
38    /// Io error.
39    #[error("`read_ion` io error: `{}`", .0)]
40    IoError(std::io::Error),
41
42    /// Data error. Generally this will result in a `MISSING` in place of this data item.
43    #[error("Data error: `{}`", .0)]
44    DataError(ExtensionError),
45
46    /// Any other reading error.
47    #[error("Ion read error: unknown error")]
48    Unknown,
49}
50
51pub type IonTableExprResult<'a> = Result<IonTableExprResultValueIter<'a>, IonExtensionError>;
52
53pub type IonTableExprResultValueIter<'a> =
54    Box<dyn 'a + Iterator<Item = Result<Value, IonExtensionError>>>;
55
56impl From<std::io::Error> for IonExtensionError {
57    fn from(e: std::io::Error) -> Self {
58        IonExtensionError::IoError(e)
59    }
60}
61
62impl From<IonExtensionError> for ExtensionResultError {
63    fn from(value: IonExtensionError) -> Self {
64        match value {
65            IonExtensionError::FunctionError(_) => ExtensionResultError::ReadError(Box::new(value)),
66            IonExtensionError::IoError(_) => ExtensionResultError::ReadError(Box::new(value)),
67            IonExtensionError::DataError(_) => ExtensionResultError::DataError(Box::new(value)),
68            IonExtensionError::Unknown => ExtensionResultError::ReadError(Box::new(value)),
69            IonExtensionError::IonStreamError(_) => {
70                ExtensionResultError::ReadError(Box::new(value))
71            }
72            IonExtensionError::IonReadError(_) => ExtensionResultError::ReadError(Box::new(value)),
73        }
74    }
75}
76
77#[derive(Debug)]
78pub struct IonExtension {}
79
80impl partiql_catalog::extension::Extension for IonExtension {
81    fn name(&self) -> String {
82        "ion".into()
83    }
84
85    fn load(&self, catalog: &mut dyn Catalog) -> Result<(), ExtensionResultError> {
86        load_table_fn(catalog, Box::new(ReadIonFunction::new()))?;
87        load_table_fn(catalog, Box::new(ScanIonFunction::new()))?;
88        Ok(())
89    }
90}
91
92fn load_table_fn(
93    catalog: &mut dyn Catalog,
94    fn_info: Box<dyn BaseTableFunctionInfo>,
95) -> Result<(), ExtensionResultError> {
96    match catalog.add_table_function(TableFunction::new(fn_info)) {
97        Ok(_) => Ok(()),
98        Err(e) => Err(ExtensionResultError::LoadError(e.into())),
99    }
100}