Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-sql/src/table_functions.rs
6940 views
1
use std::str::FromStr;
2
3
#[cfg(any(
4
feature = "csv",
5
feature = "parquet",
6
feature = "ipc",
7
feature = "json"
8
))]
9
use polars_core::prelude::polars_ensure;
10
use polars_core::prelude::{PolarsError, PolarsResult, polars_bail};
11
#[cfg(feature = "csv")]
12
use polars_lazy::prelude::LazyCsvReader;
13
use polars_lazy::prelude::LazyFrame;
14
use polars_utils::plpath::PlPath;
15
use sqlparser::ast::{FunctionArg, FunctionArgExpr};
16
17
/// Table functions that are supported by Polars
18
#[allow(clippy::enum_variant_names)]
19
pub(crate) enum PolarsTableFunctions {
20
/// SQL 'read_csv' function.
21
/// ```sql
22
/// SELECT * FROM read_csv('path/to/file.csv')
23
/// ```
24
#[cfg(feature = "csv")]
25
ReadCsv,
26
/// SQL 'read_parquet' function.
27
/// ```sql
28
/// SELECT * FROM read_parquet('path/to/file.parquet')
29
/// ```
30
#[cfg(feature = "parquet")]
31
ReadParquet,
32
/// SQL 'read_ipc' function.
33
/// ```sql
34
/// SELECT * FROM read_ipc('path/to/file.ipc')
35
/// ```
36
#[cfg(feature = "ipc")]
37
ReadIpc,
38
/// SQL 'read_json' function (*only ndjson is currently supported*).
39
/// ```sql
40
/// SELECT * FROM read_json('path/to/file.json')
41
/// ```
42
#[cfg(feature = "json")]
43
ReadJson,
44
}
45
46
impl FromStr for PolarsTableFunctions {
47
type Err = PolarsError;
48
49
#[allow(unreachable_code)]
50
fn from_str(s: &str) -> Result<Self, Self::Err> {
51
Ok(match s {
52
#[cfg(feature = "csv")]
53
"read_csv" => PolarsTableFunctions::ReadCsv,
54
#[cfg(feature = "parquet")]
55
"read_parquet" => PolarsTableFunctions::ReadParquet,
56
#[cfg(feature = "ipc")]
57
"read_ipc" => PolarsTableFunctions::ReadIpc,
58
#[cfg(feature = "json")]
59
"read_json" => PolarsTableFunctions::ReadJson,
60
_ => polars_bail!(SQLInterface: "'{}' is not a supported table function", s),
61
})
62
}
63
}
64
65
impl PolarsTableFunctions {
66
#[allow(unused_variables, unreachable_patterns)]
67
pub(crate) fn execute(&self, args: &[FunctionArg]) -> PolarsResult<(PlPath, LazyFrame)> {
68
match self {
69
#[cfg(feature = "csv")]
70
PolarsTableFunctions::ReadCsv => self.read_csv(args),
71
#[cfg(feature = "parquet")]
72
PolarsTableFunctions::ReadParquet => self.read_parquet(args),
73
#[cfg(feature = "ipc")]
74
PolarsTableFunctions::ReadIpc => self.read_ipc(args),
75
#[cfg(feature = "json")]
76
PolarsTableFunctions::ReadJson => self.read_ndjson(args),
77
_ => unreachable!(),
78
}
79
}
80
81
#[cfg(feature = "csv")]
82
fn read_csv(&self, args: &[FunctionArg]) -> PolarsResult<(PlPath, LazyFrame)> {
83
polars_ensure!(args.len() == 1, SQLSyntax: "`read_csv` expects a single file path; found {:?} arguments", args.len());
84
85
use polars_lazy::frame::LazyFileListReader;
86
let path = self.get_file_path_from_arg(&args[0])?;
87
let lf = LazyCsvReader::new(path.clone())
88
.with_try_parse_dates(true)
89
.with_missing_is_null(true)
90
.finish()?;
91
Ok((path, lf))
92
}
93
94
#[cfg(feature = "parquet")]
95
fn read_parquet(&self, args: &[FunctionArg]) -> PolarsResult<(PlPath, LazyFrame)> {
96
polars_ensure!(args.len() == 1, SQLSyntax: "`read_parquet` expects a single file path; found {:?} arguments", args.len());
97
98
let path = self.get_file_path_from_arg(&args[0])?;
99
let lf = LazyFrame::scan_parquet(path.clone(), Default::default())?;
100
Ok((path, lf))
101
}
102
103
#[cfg(feature = "ipc")]
104
fn read_ipc(&self, args: &[FunctionArg]) -> PolarsResult<(PlPath, LazyFrame)> {
105
polars_ensure!(args.len() == 1, SQLSyntax: "`read_ipc` expects a single file path; found {:?} arguments", args.len());
106
107
let path = self.get_file_path_from_arg(&args[0])?;
108
let lf = LazyFrame::scan_ipc(path.clone(), Default::default())?;
109
Ok((path, lf))
110
}
111
#[cfg(feature = "json")]
112
fn read_ndjson(&self, args: &[FunctionArg]) -> PolarsResult<(PlPath, LazyFrame)> {
113
polars_ensure!(args.len() == 1, SQLSyntax: "`read_ndjson` expects a single file path; found {:?} arguments", args.len());
114
115
use polars_lazy::frame::LazyFileListReader;
116
use polars_lazy::prelude::LazyJsonLineReader;
117
118
let path = self.get_file_path_from_arg(&args[0])?;
119
let lf = LazyJsonLineReader::new(path.clone()).finish()?;
120
Ok((path, lf))
121
}
122
123
#[allow(dead_code)]
124
fn get_file_path_from_arg(&self, arg: &FunctionArg) -> PolarsResult<PlPath> {
125
use sqlparser::ast::{Expr as SQLExpr, Value as SQLValue};
126
match arg {
127
FunctionArg::Unnamed(FunctionArgExpr::Expr(SQLExpr::Value(
128
SQLValue::SingleQuotedString(s),
129
))) => Ok(PlPath::from_str(s)),
130
_ => polars_bail!(
131
SQLSyntax:
132
"expected a valid file path as a single-quoted string; found: {}", arg,
133
),
134
}
135
}
136
}
137
138
impl PolarsTableFunctions {
139
// list sql names of all table functions
140
pub(crate) fn keywords() -> &'static [&'static str] {
141
&[
142
#[cfg(feature = "csv")]
143
"read_csv",
144
#[cfg(feature = "parquet")]
145
"read_parquet",
146
#[cfg(feature = "ipc")]
147
"read_ipc",
148
#[cfg(feature = "json")]
149
"read_json",
150
]
151
}
152
}
153
154