Skip to content

Commit

Permalink
refactor: pattern use type LiteralStringOrVariable.
Browse files Browse the repository at this point in the history
  • Loading branch information
youngsofun committed Oct 9, 2024
1 parent 7092ac9 commit a25756a
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 64 deletions.
30 changes: 27 additions & 3 deletions src/query/ast/src/ast/statements/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use crate::ast::quote::QuotedString;
use crate::ast::write_comma_separated_map;
use crate::ast::write_comma_separated_string_list;
use crate::ast::write_comma_separated_string_map;
use crate::ast::Expr;
use crate::ast::Hint;
use crate::ast::Identifier;
use crate::ast::Query;
Expand Down Expand Up @@ -55,7 +54,7 @@ pub struct CopyIntoTableStmt {

// files to load
pub files: Option<Vec<String>>,
pub pattern: Option<Expr>,
pub pattern: Option<LiteralStringOrVariable>,
pub force: bool,

// copy options
Expand Down Expand Up @@ -439,9 +438,34 @@ impl Display for FileLocation {
}
}

/// Used when we want to allow use variable for options etc.
/// Other expr is not necessary, because
/// 1. we can allways create a variable that can be used directly.
/// 2. columns can not be referred.
///
/// Can extend to all type of Literals if needed later.
#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
pub enum LiteralStringOrVariable {
Literal(String),
Variable(String),
}

impl Display for LiteralStringOrVariable {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
LiteralStringOrVariable::Literal(s) => {
write!(f, "'{s}'")
}
LiteralStringOrVariable::Variable(s) => {
write!(f, "${s}")
}
}
}
}

pub enum CopyIntoTableOption {
Files(Vec<String>),
Pattern(Expr),
Pattern(LiteralStringOrVariable),
FileFormat(FileFormatOptions),
ValidationMode(String),
SizeLimit(usize),
Expand Down
6 changes: 3 additions & 3 deletions src/query/ast/src/ast/statements/stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use derive_visitor::DriveMut;
use crate::ast::write_comma_separated_string_list;
use crate::ast::write_comma_separated_string_map;
use crate::ast::CreateOption;
use crate::ast::Expr;
use crate::ast::FileFormatOptions;
use crate::ast::LiteralStringOrVariable;
use crate::ast::UriLocation;

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
Expand Down Expand Up @@ -84,7 +84,7 @@ impl Display for CreateStageStmt {
#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
pub enum SelectStageOption {
Files(Vec<String>),
Pattern(Expr),
Pattern(LiteralStringOrVariable),
FileFormat(String),
Connection(BTreeMap<String, String>),
}
Expand All @@ -107,7 +107,7 @@ impl SelectStageOptions {
#[derive(Debug, Clone, PartialEq, Default, Drive, DriveMut)]
pub struct SelectStageOptions {
pub files: Option<Vec<String>>,
pub pattern: Option<Expr>,
pub pattern: Option<LiteralStringOrVariable>,
pub file_format: Option<String>,
pub connection: BTreeMap<String, String>,
}
Expand Down
16 changes: 12 additions & 4 deletions src/query/ast/src/parser/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::ast::CopyIntoLocationStmt;
use crate::ast::CopyIntoTableOption;
use crate::ast::CopyIntoTableSource;
use crate::ast::CopyIntoTableStmt;
use crate::ast::LiteralStringOrVariable;
use crate::ast::Statement;
use crate::ast::Statement::CopyIntoLocation;
use crate::parser::common::comma_separated_list0;
Expand All @@ -31,7 +32,6 @@ use crate::parser::common::ident;
use crate::parser::common::table_ref;
use crate::parser::common::IResult;
use crate::parser::common::*;
use crate::parser::expr::expr;
use crate::parser::expr::literal_bool;
use crate::parser::expr::literal_string;
use crate::parser::expr::literal_u64;
Expand Down Expand Up @@ -139,15 +139,23 @@ pub fn copy_into(i: Input) -> IResult<Statement> {
)(i)
}

pub fn literal_string_or_variable(i: Input) -> IResult<LiteralStringOrVariable> {
alt((
map(literal_string, LiteralStringOrVariable::Literal),
map(variable_ident, LiteralStringOrVariable::Variable),
))(i)
}

fn copy_into_table_option(i: Input) -> IResult<CopyIntoTableOption> {
alt((
map(
rule! { FILES ~ "=" ~ "(" ~ #comma_separated_list0(literal_string) ~ ")" },
|(_, _, _, files, _)| CopyIntoTableOption::Files(files),
),
map(rule! { PATTERN ~ "=" ~ #expr }, |(_, _, pattern)| {
CopyIntoTableOption::Pattern(pattern)
}),
map(
rule! { PATTERN ~ ^"=" ~ ^#literal_string_or_variable },
|(_, _, pattern)| CopyIntoTableOption::Pattern(pattern),
),
map(rule! { #file_format_clause }, |options| {
CopyIntoTableOption::FileFormat(options)
}),
Expand Down
36 changes: 22 additions & 14 deletions src/query/ast/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use crate::parser::query::*;
use crate::parser::token::*;
use crate::parser::Error;
use crate::parser::ErrorKind;
use crate::Span;

pub fn expr(i: Input) -> IResult<Expr> {
context("expression", subexpr(0))(i)
Expand Down Expand Up @@ -643,20 +644,10 @@ impl<'a, I: Iterator<Item = WithSpan<'a, ExprElement>>> PrattParser<I> for ExprP
span: transform_span(elem.span.tokens),
name,
},
ExprElement::VariableAccess(name) => Expr::FunctionCall {
span: transform_span(elem.span.tokens),
func: FunctionCall {
distinct: false,
name: Identifier::from_name(transform_span(elem.span.tokens), "getvariable"),
args: vec![Expr::Literal {
span: transform_span(elem.span.tokens),
value: Literal::String(name),
}],
params: vec![],
window: None,
lambda: None,
},
},
ExprElement::VariableAccess(name) => {
let span = transform_span(elem.span.tokens);
make_func_get_variable(span, name)
}
_ => unreachable!(),
};
Ok(expr)
Expand Down Expand Up @@ -1843,3 +1834,20 @@ pub fn parse_uint(text: &str, radix: u32) -> Result<Literal, ErrorKind> {
})
}
}

pub(crate) fn make_func_get_variable(span: Span, name: String) -> Expr {
Expr::FunctionCall {
span,
func: FunctionCall {
distinct: false,
name: Identifier::from_name(span, "getvariable"),
args: vec![Expr::Literal {
span,
value: Literal::String(name),
}],
params: vec![],
window: None,
lambda: None,
},
}
}
8 changes: 5 additions & 3 deletions src/query/ast/src/parser/stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::ast::FileLocation;
use crate::ast::SelectStageOption;
use crate::ast::UriLocation;
use crate::parser::common::*;
use crate::parser::copy::literal_string_or_variable;
use crate::parser::expr::*;
use crate::parser::input::Input;
use crate::parser::token::*;
Expand Down Expand Up @@ -255,9 +256,10 @@ pub fn select_stage_option(i: Input) -> IResult<SelectStageOption> {
rule! { FILES ~ ^"=>" ~ ^"(" ~ ^#comma_separated_list0(literal_string) ~ ^")" },
|(_, _, _, files, _)| SelectStageOption::Files(files),
),
map(rule! { PATTERN ~ ^"=>" ~ ^#expr }, |(_, _, pattern)| {
SelectStageOption::Pattern(pattern)
}),
map(
rule! { PATTERN ~ ^"=>" ~ ^#literal_string_or_variable },
|(_, _, pattern)| SelectStageOption::Pattern(pattern),
),
map(
rule! { FILE_FORMAT ~ ^"=>" ~ ^#literal_string },
|(_, _, file_format)| SelectStageOption::FileFormat(file_format),
Expand Down
52 changes: 16 additions & 36 deletions src/query/sql/src/planner/binder/copy_into_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use databend_common_ast::ast::Hint;
use databend_common_ast::ast::HintItem;
use databend_common_ast::ast::Identifier;
use databend_common_ast::ast::Literal;
use databend_common_ast::ast::LiteralStringOrVariable;
use databend_common_ast::ast::Query;
use databend_common_ast::ast::SelectTarget;
use databend_common_ast::ast::SetExpr;
Expand All @@ -42,6 +43,7 @@ use databend_common_config::GlobalConfig;
use databend_common_exception::ErrorCode;
use databend_common_exception::Result;
use databend_common_expression::infer_table_schema;
use databend_common_expression::shrink_scalar;
use databend_common_expression::types::DataType;
use databend_common_expression::DataSchema;
use databend_common_expression::DataSchemaRef;
Expand All @@ -54,8 +56,6 @@ use databend_common_meta_app::principal::NullAs;
use databend_common_meta_app::principal::OnErrorMode;
use databend_common_meta_app::principal::StageInfo;
use databend_common_meta_app::principal::COPY_MAX_FILES_PER_COMMIT;
use databend_common_meta_app::tenant::Tenant;
use databend_common_settings::Settings;
use databend_common_storage::StageFilesInfo;
use databend_common_users::UserApiProvider;
use derive_visitor::Drive;
Expand All @@ -67,7 +67,6 @@ use parking_lot::RwLock;
use crate::binder::bind_query::MaxColumnPosition;
use crate::binder::location::parse_uri_location;
use crate::binder::Binder;
use crate::plans::ConstantExpr;
use crate::plans::CopyIntoTableMode;
use crate::plans::CopyIntoTablePlan;
use crate::plans::Plan;
Expand All @@ -76,7 +75,6 @@ use crate::BindContext;
use crate::Metadata;
use crate::NameResolutionContext;
use crate::ScalarBinder;
use crate::TypeChecker;

impl<'a> Binder {
#[async_backtrace::framed]
Expand Down Expand Up @@ -115,41 +113,23 @@ impl<'a> Binder {
}
}

fn resolve_const_expr(ctx: Arc<dyn TableContext>, expr: &Expr) -> Result<Scalar> {
let settings = Settings::create(Tenant::new_literal("dummy"));
let mut bind_context = BindContext::new();
let metadata = Metadata::default();

let name_resolution_ctx = NameResolutionContext::try_from(settings.as_ref())?;
let mut type_checker = TypeChecker::try_create(
&mut bind_context,
ctx.clone(),
&name_resolution_ctx,
Arc::new(RwLock::new(metadata)),
&[],
false,
)?;
let (scalar, _) = *type_checker.resolve(expr)?;
if let Ok(arg) = ConstantExpr::try_from(scalar) {
Ok(arg.value)
} else {
Err(ErrorCode::BadArguments(format!(
"except const expr, got {expr}"
)))
}
}

pub(crate) fn resolve_copy_pattern(
ctx: Arc<dyn TableContext>,
pattern: &Expr,
pattern: &LiteralStringOrVariable,
) -> Result<String> {
let c = Self::resolve_const_expr(ctx.clone(), pattern)?;
if let Scalar::String(s) = c {
Ok(s)
} else {
Err(ErrorCode::BadArguments(format!(
"invalid pattern expr: {c}"
)))
match pattern {
LiteralStringOrVariable::Literal(s) => Ok(s.clone()),
LiteralStringOrVariable::Variable(var_name) => {
let var_value = ctx.get_variable(&var_name).unwrap_or(Scalar::Null);
let var_value = shrink_scalar(var_value);
if let Scalar::String(s) = var_value {
Ok(s)
} else {
Err(ErrorCode::BadArguments(format!(
"invalid pattern expr: {var_value}"
)))
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ unset variable pt;
query error 1006
copy into t1 from @data/csv/ pattern= $p file_format=(type=csv)

query error 1065
query error 1005
copy into t1 from @data/csv/ pattern=x file_format=(type=csv)

0 comments on commit a25756a

Please sign in to comment.