Skip to content

Commit 123d574

Browse files
feat: support INSERT INTO FUNCTION
1 parent 94ea206 commit 123d574

File tree

8 files changed

+124
-45
lines changed

8 files changed

+124
-45
lines changed

src/ast/dml.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use super::{
3636
FromTable, HiveDistributionStyle, HiveFormat, HiveIOFormat, HiveRowFormat, Ident,
3737
InsertAliases, MysqlInsertPriority, ObjectName, OnCommit, OnInsert, OneOrManyWithParens,
3838
OrderByExpr, Query, RowAccessPolicy, SelectItem, SqlOption, SqliteOnConflict, TableEngine,
39-
TableWithJoins, Tag, WrappedCollection,
39+
TableObject, TableWithJoins, Tag, WrappedCollection,
4040
};
4141

4242
/// CREATE INDEX statement.
@@ -470,8 +470,7 @@ pub struct Insert {
470470
/// INTO - optional keyword
471471
pub into: bool,
472472
/// TABLE
473-
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
474-
pub table_name: ObjectName,
473+
pub table_object: TableObject,
475474
/// table_name as foo (for PostgreSQL)
476475
pub table_alias: Option<Ident>,
477476
/// COLUMNS
@@ -500,9 +499,9 @@ pub struct Insert {
500499
impl Display for Insert {
501500
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502501
let table_name = if let Some(alias) = &self.table_alias {
503-
format!("{0} AS {alias}", self.table_name)
502+
format!("{0} AS {alias}", self.table_object)
504503
} else {
505-
self.table_name.to_string()
504+
self.table_object.to_string()
506505
};
507506

508507
if let Some(on_conflict) = self.or {

src/ast/mod.rs

+19
Original file line numberDiff line numberDiff line change
@@ -7698,6 +7698,25 @@ impl fmt::Display for RenameTable {
76987698
}
76997699
}
77007700

7701+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7702+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7703+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7704+
pub enum TableObject {
7705+
TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
7706+
7707+
// Clickhouse: [Table functions](https://clickhouse.com/docs/en/sql-reference/table-functions)
7708+
TableFunction(Function),
7709+
}
7710+
7711+
impl fmt::Display for TableObject {
7712+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7713+
match self {
7714+
Self::TableName(table_name) => write!(f, "{}", display_separated(&table_name.0, ".")),
7715+
Self::TableFunction(func) => write!(f, "FUNCTION {}", func),
7716+
}
7717+
}
7718+
}
7719+
77017720
#[cfg(test)]
77027721
mod tests {
77037722
use super::*;

src/ast/spans.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ use super::{
3232
OrderBy, OrderByExpr, Partition, PivotValueSource, ProjectionSelect, Query, ReferentialAction,
3333
RenameSelectItem, ReplaceSelectElement, ReplaceSelectItem, Select, SelectInto, SelectItem,
3434
SetExpr, SqlOption, Statement, Subscript, SymbolDefinition, TableAlias, TableAliasColumnDef,
35-
TableConstraint, TableFactor, TableOptionsClustered, TableWithJoins, UpdateTableFromKind, Use,
36-
Value, Values, ViewColumnDef, WildcardAdditionalOptions, With, WithFill,
35+
TableConstraint, TableFactor, TableObject, TableOptionsClustered, TableWithJoins,
36+
UpdateTableFromKind, Use, Value, Values, ViewColumnDef, WildcardAdditionalOptions, With,
37+
WithFill,
3738
};
3839

3940
/// Given an iterator of spans, return the [Span::union] of all spans.
@@ -1139,7 +1140,7 @@ impl Spanned for Insert {
11391140
or: _, // enum, sqlite specific
11401141
ignore: _, // bool
11411142
into: _, // bool
1142-
table_name,
1143+
table_object,
11431144
table_alias,
11441145
columns,
11451146
overwrite: _, // bool
@@ -1155,7 +1156,7 @@ impl Spanned for Insert {
11551156
} = self;
11561157

11571158
union_spans(
1158-
core::iter::once(table_name.span())
1159+
core::iter::once(table_object.span())
11591160
.chain(table_alias.as_ref().map(|i| i.span))
11601161
.chain(columns.iter().map(|i| i.span))
11611162
.chain(source.as_ref().map(|q| q.span()))
@@ -2117,6 +2118,17 @@ impl Spanned for UpdateTableFromKind {
21172118
}
21182119
}
21192120

2121+
impl Spanned for TableObject {
2122+
fn span(&self) -> Span {
2123+
match self {
2124+
TableObject::TableName(ObjectName(segments)) => {
2125+
union_spans(segments.iter().map(|i| i.span))
2126+
}
2127+
TableObject::TableFunction(func) => func.span(),
2128+
}
2129+
}
2130+
}
2131+
21202132
#[cfg(test)]
21212133
pub mod tests {
21222134
use crate::dialect::{Dialect, GenericDialect, SnowflakeDialect};

src/parser/mod.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -8857,6 +8857,23 @@ impl<'a> Parser<'a> {
88578857
}
88588858
}
88598859

8860+
pub fn parse_table_object(
8861+
&mut self,
8862+
in_table_clause: bool,
8863+
) -> Result<TableObject, ParserError> {
8864+
if dialect_of!(self is ClickHouseDialect) && self.parse_keyword(Keyword::FUNCTION) {
8865+
self.parse_table_function().map(TableObject::TableFunction)
8866+
} else {
8867+
self.parse_object_name(in_table_clause)
8868+
.map(TableObject::TableName)
8869+
}
8870+
}
8871+
8872+
pub fn parse_table_function(&mut self) -> Result<Function, ParserError> {
8873+
let fn_name = self.parse_object_name(false)?;
8874+
self.parse_function_call(fn_name)
8875+
}
8876+
88608877
/// Parse a possibly qualified, possibly quoted identifier, e.g.
88618878
/// `foo` or `myschema."table"
88628879
///
@@ -11831,7 +11848,7 @@ impl<'a> Parser<'a> {
1183111848
} else {
1183211849
// Hive lets you put table here regardless
1183311850
let table = self.parse_keyword(Keyword::TABLE);
11834-
let table_name = self.parse_object_name(false)?;
11851+
let table_object = self.parse_table_object(false)?;
1183511852

1183611853
let table_alias =
1183711854
if dialect_of!(self is PostgreSqlDialect) && self.parse_keyword(Keyword::AS) {
@@ -11934,7 +11951,7 @@ impl<'a> Parser<'a> {
1193411951

1193511952
Ok(Statement::Insert(Insert {
1193611953
or,
11937-
table_name,
11954+
table_object,
1193811955
table_alias,
1193911956
ignore,
1194011957
into,

tests/sqlparser_clickhouse.rs

+5
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ fn parse_create_table() {
222222
);
223223
}
224224

225+
#[test]
226+
fn parse_insert_into_function() {
227+
clickhouse().verified_stmt(r#"INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table) VALUES (100, 'inserted via remote()')"#);
228+
}
229+
225230
#[test]
226231
fn parse_alter_table_attach_and_detach_partition() {
227232
for operation in &["ATTACH", "DETACH"] {

tests/sqlparser_common.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ fn parse_insert_values() {
9595
) {
9696
match verified_stmt(sql) {
9797
Statement::Insert(Insert {
98-
table_name,
98+
table_object: table_name,
9999
columns,
100100
source: Some(source),
101101
..
@@ -142,7 +142,7 @@ fn parse_insert_default_values() {
142142
partitioned,
143143
returning,
144144
source,
145-
table_name,
145+
table_object: table_name,
146146
..
147147
}) => {
148148
assert_eq!(columns, vec![]);
@@ -151,7 +151,10 @@ fn parse_insert_default_values() {
151151
assert_eq!(partitioned, None);
152152
assert_eq!(returning, None);
153153
assert_eq!(source, None);
154-
assert_eq!(table_name, ObjectName(vec!["test_table".into()]));
154+
assert_eq!(
155+
table_name,
156+
TableObject::TableName(ObjectName(vec!["test_table".into()]))
157+
);
155158
}
156159
_ => unreachable!(),
157160
}
@@ -167,7 +170,7 @@ fn parse_insert_default_values() {
167170
partitioned,
168171
returning,
169172
source,
170-
table_name,
173+
table_object: table_name,
171174
..
172175
}) => {
173176
assert_eq!(after_columns, vec![]);
@@ -176,7 +179,10 @@ fn parse_insert_default_values() {
176179
assert_eq!(partitioned, None);
177180
assert!(returning.is_some());
178181
assert_eq!(source, None);
179-
assert_eq!(table_name, ObjectName(vec!["test_table".into()]));
182+
assert_eq!(
183+
table_name,
184+
TableObject::TableName(ObjectName(vec!["test_table".into()]))
185+
);
180186
}
181187
_ => unreachable!(),
182188
}
@@ -192,7 +198,7 @@ fn parse_insert_default_values() {
192198
partitioned,
193199
returning,
194200
source,
195-
table_name,
201+
table_object: table_name,
196202
..
197203
}) => {
198204
assert_eq!(after_columns, vec![]);
@@ -201,7 +207,10 @@ fn parse_insert_default_values() {
201207
assert_eq!(partitioned, None);
202208
assert_eq!(returning, None);
203209
assert_eq!(source, None);
204-
assert_eq!(table_name, ObjectName(vec!["test_table".into()]));
210+
assert_eq!(
211+
table_name,
212+
TableObject::TableName(ObjectName(vec!["test_table".into()]))
213+
);
205214
}
206215
_ => unreachable!(),
207216
}

0 commit comments

Comments
 (0)