Skip to content

Commit 128b0ef

Browse files
committed
feat: add check_transform_query.
1 parent 064b298 commit 128b0ef

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

src/query/ast/src/ast/statements/stage.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ pub struct SelectStageOptions {
9090
pub connection: BTreeMap<String, String>,
9191
}
9292

93+
impl SelectStageOptions {
94+
pub fn is_empty(&self) -> bool {
95+
self.files.is_none()
96+
&& self.pattern.is_none()
97+
&& self.file_format.is_none()
98+
&& self.connection.is_empty()
99+
}
100+
}
101+
93102
// SELECT <columns> FROM
94103
// {@<stage_name>[/<path>] | '<uri>'} [(
95104
// [ PARTTERN => '<regex_pattern>']

src/query/sql/src/planner/binder/copy.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ use common_ast::ast::CopyStmt;
2020
use common_ast::ast::CopyUnit;
2121
use common_ast::ast::FileLocation;
2222
use common_ast::ast::Query;
23+
use common_ast::ast::SelectTarget;
24+
use common_ast::ast::SetExpr;
2325
use common_ast::ast::Statement;
26+
use common_ast::ast::TableAlias;
27+
use common_ast::ast::TableReference;
2428
use common_ast::ast::UriLocation;
2529
use common_ast::parser::parse_sql;
2630
use common_ast::parser::tokenize_sql;
@@ -495,6 +499,46 @@ impl<'a> Binder {
495499
}
496500
}
497501

502+
// we can avoid this by specializing the parser.
503+
// make parse a little more complex, now it is COPY ~ INTO ~ #copy_unit ~ FROM ~ #copy_unit
504+
// also check_query here may give a more friendly error msg.
505+
fn check_transform_query(
506+
query: &Query,
507+
) -> Result<(&Vec<SelectTarget>, &FileLocation, &Option<TableAlias>)> {
508+
if query.offset.is_none()
509+
&& query.limit.is_empty()
510+
&& query.order_by.is_empty()
511+
&& query.with.is_none()
512+
{
513+
if let SetExpr::Select(select) = &query.body {
514+
if select.group_by.is_empty()
515+
&& !select.distinct
516+
&& select.having.is_none()
517+
&& select.from.len() == 1
518+
{
519+
if let TableReference::Stage {
520+
span: _,
521+
location,
522+
options,
523+
alias,
524+
} = &select.from[0]
525+
{
526+
if options.is_empty() {
527+
return Ok((&select.select_list, location, alias));
528+
} else {
529+
return Err(ErrorCode::SyntaxException(
530+
"stage table function inside copy not allow options, apply them in the outer copy stmt instead.",
531+
));
532+
}
533+
}
534+
}
535+
}
536+
}
537+
Err(ErrorCode::SyntaxException(
538+
"query as source of copy only allow projection on one stage table",
539+
))
540+
}
541+
498542
/// Named stage(start with `@`):
499543
///
500544
/// ```sql

0 commit comments

Comments
 (0)