Path: blob/main/crates/polars-sql/src/table_functions.rs
8362 views
use std::str::FromStr;12#[cfg(any(3feature = "csv",4feature = "parquet",5feature = "ipc",6feature = "json"7))]8use polars_core::prelude::polars_ensure;9use polars_core::prelude::{PolarsError, PolarsResult, polars_bail};10#[cfg(feature = "csv")]11use polars_lazy::prelude::LazyCsvReader;12use polars_lazy::prelude::LazyFrame;13use polars_utils::pl_path::PlRefPath;14use sqlparser::ast::{15Expr as SQLExpr, FunctionArg as SQLFunctionArg, FunctionArgExpr as SQLFunctionArgExpr,16Value as SQLValue, ValueWithSpan as SQLValueWithSpan,17};1819/// Table functions that are supported by Polars20#[allow(clippy::enum_variant_names)]21pub(crate) enum PolarsTableFunctions {22/// SQL 'read_csv' function.23/// ```sql24/// SELECT * FROM read_csv('path/to/file.csv')25/// ```26#[cfg(feature = "csv")]27ReadCsv,28/// SQL 'read_parquet' function.29/// ```sql30/// SELECT * FROM read_parquet('path/to/file.parquet')31/// ```32#[cfg(feature = "parquet")]33ReadParquet,34/// SQL 'read_ipc' function.35/// ```sql36/// SELECT * FROM read_ipc('path/to/file.ipc')37/// ```38#[cfg(feature = "ipc")]39ReadIpc,40/// SQL 'read_json' function (*only ndjson is currently supported*).41/// ```sql42/// SELECT * FROM read_json('path/to/file.json')43/// ```44#[cfg(feature = "json")]45ReadJson,46}4748impl FromStr for PolarsTableFunctions {49type Err = PolarsError;5051#[allow(unreachable_code)]52fn from_str(s: &str) -> Result<Self, Self::Err> {53Ok(match s.to_lowercase().as_str() {54#[cfg(feature = "csv")]55"read_csv" => PolarsTableFunctions::ReadCsv,56#[cfg(feature = "parquet")]57"read_parquet" => PolarsTableFunctions::ReadParquet,58#[cfg(feature = "ipc")]59"read_ipc" => PolarsTableFunctions::ReadIpc,60#[cfg(feature = "json")]61"read_json" => PolarsTableFunctions::ReadJson,62_ => polars_bail!(SQLInterface: "'{}' is not a supported table function", s),63})64}65}6667impl PolarsTableFunctions {68#[allow(unused_variables, unreachable_patterns)]69pub(crate) fn execute(&self, args: &[SQLFunctionArg]) -> PolarsResult<(PlRefPath, LazyFrame)> {70match self {71#[cfg(feature = "csv")]72PolarsTableFunctions::ReadCsv => self.read_csv(args),73#[cfg(feature = "parquet")]74PolarsTableFunctions::ReadParquet => self.read_parquet(args),75#[cfg(feature = "ipc")]76PolarsTableFunctions::ReadIpc => self.read_ipc(args),77#[cfg(feature = "json")]78PolarsTableFunctions::ReadJson => self.read_ndjson(args),79_ => unreachable!(),80}81}8283#[cfg(feature = "csv")]84fn read_csv(&self, args: &[SQLFunctionArg]) -> PolarsResult<(PlRefPath, LazyFrame)> {85polars_ensure!(args.len() == 1, SQLSyntax: "`read_csv` expects a single file path; found {:?} arguments", args.len());8687use polars_lazy::frame::LazyFileListReader;88let path = self.get_file_path_from_arg(&args[0])?;89let lf = LazyCsvReader::new(path.clone())90.with_try_parse_dates(true)91.with_missing_is_null(true)92.finish()?;93Ok((path, lf))94}9596#[cfg(feature = "parquet")]97fn read_parquet(&self, args: &[SQLFunctionArg]) -> PolarsResult<(PlRefPath, LazyFrame)> {98polars_ensure!(args.len() == 1, SQLSyntax: "`read_parquet` expects a single file path; found {:?} arguments", args.len());99100let path = self.get_file_path_from_arg(&args[0])?;101let lf = LazyFrame::scan_parquet(path.clone(), Default::default())?;102Ok((path, lf))103}104105#[cfg(feature = "ipc")]106fn read_ipc(&self, args: &[SQLFunctionArg]) -> PolarsResult<(PlRefPath, LazyFrame)> {107polars_ensure!(args.len() == 1, SQLSyntax: "`read_ipc` expects a single file path; found {:?} arguments", args.len());108109let path = self.get_file_path_from_arg(&args[0])?;110let lf = LazyFrame::scan_ipc(path.clone(), Default::default(), Default::default())?;111Ok((path, lf))112}113#[cfg(feature = "json")]114fn read_ndjson(&self, args: &[SQLFunctionArg]) -> PolarsResult<(PlRefPath, LazyFrame)> {115polars_ensure!(args.len() == 1, SQLSyntax: "`read_ndjson` expects a single file path; found {:?} arguments", args.len());116117use polars_lazy::frame::LazyFileListReader;118use polars_lazy::prelude::LazyJsonLineReader;119120let path = self.get_file_path_from_arg(&args[0])?;121let lf = LazyJsonLineReader::new(path.clone()).finish()?;122Ok((path, lf))123}124125#[allow(dead_code)]126fn get_file_path_from_arg(&self, arg: &SQLFunctionArg) -> PolarsResult<PlRefPath> {127match arg {128SQLFunctionArg::Unnamed(SQLFunctionArgExpr::Expr(SQLExpr::Value(129SQLValueWithSpan {130value: SQLValue::SingleQuotedString(s),131..132},133))) => Ok(PlRefPath::new(s)),134_ => polars_bail!(135SQLSyntax:136"expected a valid file path as a single-quoted string; found: {}", arg,137),138}139}140}141142impl PolarsTableFunctions {143// list sql names of all table functions144pub(crate) fn keywords() -> &'static [&'static str] {145&[146#[cfg(feature = "csv")]147"read_csv",148#[cfg(feature = "parquet")]149"read_parquet",150#[cfg(feature = "ipc")]151"read_ipc",152#[cfg(feature = "json")]153"read_json",154]155}156}157158159