Skip to content

Commit f60cd89

Browse files
feat: support INSERT INTO FUNCTION
1 parent 0cd49fb commit f60cd89

File tree

8 files changed

+124
-45
lines changed

8 files changed

+124
-45
lines changed

src/ast/dml.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use super::{
3636
FileFormat, 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
@@ -503,9 +502,9 @@ pub struct Insert {
503502
impl Display for Insert {
504503
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
505504
let table_name = if let Some(alias) = &self.table_alias {
506-
format!("{0} AS {alias}", self.table_name)
505+
format!("{0} AS {alias}", self.table_object)
507506
} else {
508-
self.table_name.to_string()
507+
self.table_object.to_string()
509508
};
510509

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

src/ast/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7766,6 +7766,25 @@ impl fmt::Display for RenameTable {
77667766
}
77677767
}
77687768

7769+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7770+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7771+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7772+
pub enum TableObject {
7773+
TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
7774+
7775+
// Clickhouse: [Table functions](https://clickhouse.com/docs/en/sql-reference/table-functions)
7776+
TableFunction(Function),
7777+
}
7778+
7779+
impl fmt::Display for TableObject {
7780+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7781+
match self {
7782+
Self::TableName(table_name) => write!(f, "{}", display_separated(&table_name.0, ".")),
7783+
Self::TableFunction(func) => write!(f, "FUNCTION {}", func),
7784+
}
7785+
}
7786+
}
7787+
77697788
#[cfg(test)]
77707789
mod tests {
77717790
use super::*;

src/ast/spans.rs

Lines changed: 16 additions & 4 deletions
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.
@@ -1140,7 +1141,7 @@ impl Spanned for Insert {
11401141
or: _, // enum, sqlite specific
11411142
ignore: _, // bool
11421143
into: _, // bool
1143-
table_name,
1144+
table_object,
11441145
table_alias,
11451146
columns,
11461147
overwrite: _, // bool
@@ -1157,7 +1158,7 @@ impl Spanned for Insert {
11571158
} = self;
11581159

11591160
union_spans(
1160-
core::iter::once(table_name.span())
1161+
core::iter::once(table_object.span())
11611162
.chain(table_alias.as_ref().map(|i| i.span))
11621163
.chain(columns.iter().map(|i| i.span))
11631164
.chain(source.as_ref().map(|q| q.span()))
@@ -2120,6 +2121,17 @@ impl Spanned for UpdateTableFromKind {
21202121
}
21212122
}
21222123

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

src/parser/mod.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8858,6 +8858,23 @@ impl<'a> Parser<'a> {
88588858
}
88598859
}
88608860

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

1189311910
let table_alias =
1189411911
if dialect_of!(self is PostgreSqlDialect) && self.parse_keyword(Keyword::AS) {
@@ -11996,7 +12013,7 @@ impl<'a> Parser<'a> {
1199612013

1199712014
Ok(Statement::Insert(Insert {
1199812015
or,
11999-
table_name,
12016+
table_object,
1200012017
table_alias,
1200112018
ignore,
1200212019
into,

tests/sqlparser_clickhouse.rs

Lines changed: 5 additions & 0 deletions
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

Lines changed: 16 additions & 7 deletions
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
..
@@ -148,7 +148,7 @@ fn parse_insert_default_values() {
148148
partitioned,
149149
returning,
150150
source,
151-
table_name,
151+
table_object: table_name,
152152
..
153153
}) => {
154154
assert_eq!(columns, vec![]);
@@ -157,7 +157,10 @@ fn parse_insert_default_values() {
157157
assert_eq!(partitioned, None);
158158
assert_eq!(returning, None);
159159
assert_eq!(source, None);
160-
assert_eq!(table_name, ObjectName(vec!["test_table".into()]));
160+
assert_eq!(
161+
table_name,
162+
TableObject::TableName(ObjectName(vec!["test_table".into()]))
163+
);
161164
}
162165
_ => unreachable!(),
163166
}
@@ -173,7 +176,7 @@ fn parse_insert_default_values() {
173176
partitioned,
174177
returning,
175178
source,
176-
table_name,
179+
table_object: table_name,
177180
..
178181
}) => {
179182
assert_eq!(after_columns, vec![]);
@@ -182,7 +185,10 @@ fn parse_insert_default_values() {
182185
assert_eq!(partitioned, None);
183186
assert!(returning.is_some());
184187
assert_eq!(source, None);
185-
assert_eq!(table_name, ObjectName(vec!["test_table".into()]));
188+
assert_eq!(
189+
table_name,
190+
TableObject::TableName(ObjectName(vec!["test_table".into()]))
191+
);
186192
}
187193
_ => unreachable!(),
188194
}
@@ -198,7 +204,7 @@ fn parse_insert_default_values() {
198204
partitioned,
199205
returning,
200206
source,
201-
table_name,
207+
table_object: table_name,
202208
..
203209
}) => {
204210
assert_eq!(after_columns, vec![]);
@@ -207,7 +213,10 @@ fn parse_insert_default_values() {
207213
assert_eq!(partitioned, None);
208214
assert_eq!(returning, None);
209215
assert_eq!(source, None);
210-
assert_eq!(table_name, ObjectName(vec!["test_table".into()]));
216+
assert_eq!(
217+
table_name,
218+
TableObject::TableName(ObjectName(vec!["test_table".into()]))
219+
);
211220
}
212221
_ => unreachable!(),
213222
}

0 commit comments

Comments
 (0)