@@ -20,7 +20,11 @@ use common_ast::ast::CopyStmt;
2020use common_ast:: ast:: CopyUnit ;
2121use common_ast:: ast:: FileLocation ;
2222use common_ast:: ast:: Query ;
23+ use common_ast:: ast:: SelectTarget ;
24+ use common_ast:: ast:: SetExpr ;
2325use common_ast:: ast:: Statement ;
26+ use common_ast:: ast:: TableAlias ;
27+ use common_ast:: ast:: TableReference ;
2428use common_ast:: ast:: UriLocation ;
2529use common_ast:: parser:: parse_sql;
2630use 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