Skip to content

Commit

Permalink
feat: add EXECUTE IMMEDIATE statement (#15144)
Browse files Browse the repository at this point in the history
* feat: add EXECUTE IMMEDIATE statement

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* add test
  • Loading branch information
andylokandy authored Apr 11, 2024
1 parent bb4464b commit 41ba9d1
Show file tree
Hide file tree
Showing 52 changed files with 2,841 additions and 793 deletions.
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/common/exception/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ arrow-schema = { workspace = true }
backtrace = { git = "https://github.com/rust-lang/backtrace-rs.git", rev = "6145fe6bac65c38375f1216a565a6cc7deb89a2d" }
#backtrace = "0.3.69"
bincode = { workspace = true }
geos = { workspace = true }
geozero = { workspace = true }
http = "0.2"
opendal = { workspace = true }
Expand All @@ -34,3 +35,6 @@ serde_json = { workspace = true }
tantivy = "0.21.1"
thiserror = { workspace = true }
tonic = { workspace = true }

[package.metadata.cargo-machete]
ignored = ["geos"]
2 changes: 2 additions & 0 deletions src/common/exception/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub use exception::ErrorCode;
pub use exception::Result;
pub use exception::ToErrorCode;
pub use exception_into::SerializedError;
pub use span::merge_span;
pub use span::offset_span;
pub use span::pretty_print_error;
pub use span::Range;
pub use span::Span;
Expand Down
24 changes: 22 additions & 2 deletions src/common/exception/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Formatter;

pub type Span = Option<Range>;

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
pub struct Range {
pub start: u32,
Expand All @@ -26,13 +28,12 @@ impl Range {
pub fn start(&self) -> usize {
self.start as usize
}

pub fn end(&self) -> usize {
self.end as usize
}
}

pub type Span = Option<Range>;

impl Debug for Range {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}..{}", self.start, self.end)
Expand Down Expand Up @@ -60,6 +61,25 @@ impl From<std::ops::Range<usize>> for Range {
}
}

pub fn offset_span(span: Span, offset: usize) -> Span {
span.map(|range| Range {
start: range.start + offset as u32,
end: range.end + offset as u32,
})
}

pub fn merge_span(lhs: Span, rhs: Span) -> Span {
match (lhs, rhs) {
(Some(lhs), Some(rhs)) => Some(Range {
start: lhs.start.min(rhs.start),
end: lhs.end.max(rhs.end),
}),
(Some(lhs), None) => Some(lhs),
(None, Some(rhs)) => Some(rhs),
(None, None) => None,
}
}

pub fn pretty_print_error(source: &str, labels: Vec<(Range, String)>) -> String {
use codespan_reporting::diagnostic::Diagnostic;
use codespan_reporting::diagnostic::Label;
Expand Down
4 changes: 4 additions & 0 deletions src/common/io/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ chrono = { workspace = true }
chrono-tz = { workspace = true }
ethnum = { workspace = true }
geo = { workspace = true }
geos = { workspace = true }
geozero = { workspace = true }
lexical-core = "0.8.5"
micromarshal = "0.5.0"
Expand All @@ -36,3 +37,6 @@ wkt = "0.10.3"
aho-corasick = { version = "1.0.1" }
rand = { workspace = true }
rmp-serde = "1.1.1"

[package.metadata.cargo-machete]
ignored = ["geos"]
2 changes: 1 addition & 1 deletion src/query/ast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ serde_json = { workspace = true }
strsim = "0.10"
strum = "0.24"
strum_macros = "0.24"
unindent = "0.2.3"
url = "2.3.1"

[dev-dependencies]
Expand All @@ -42,7 +43,6 @@ databend-common-base = { path = "../../common/base" }
goldenfile = "1.4"
pretty_assertions = "1.3.0"
regex = { workspace = true }
unindent = "0.2.3"

[[bench]]
name = "bench"
Expand Down
134 changes: 134 additions & 0 deletions src/query/ast/src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use std::fmt::Display;
use std::fmt::Formatter;

use databend_common_exception::merge_span;
use databend_common_exception::ErrorCode;
use databend_common_exception::Result;
use databend_common_exception::Span;
Expand Down Expand Up @@ -305,6 +306,139 @@ impl Expr {
}
}

pub fn whole_span(&self) -> Span {
match self {
Expr::ColumnRef { span, .. } => *span,
Expr::IsNull { span, expr, .. } => merge_span(*span, expr.whole_span()),
Expr::IsDistinctFrom {
span, left, right, ..
} => merge_span(merge_span(*span, left.whole_span()), right.whole_span()),
Expr::InList {
span, expr, list, ..
} => {
let mut span = merge_span(*span, expr.whole_span());
for item in list {
span = merge_span(span, item.whole_span());
}
span
}
Expr::InSubquery {
span,
expr,
subquery,
..
} => merge_span(merge_span(*span, expr.whole_span()), subquery.span),
Expr::Between {
span,
expr,
low,
high,
..
} => merge_span(
merge_span(*span, expr.whole_span()),
merge_span(low.whole_span(), high.whole_span()),
),
Expr::BinaryOp {
span, left, right, ..
} => merge_span(merge_span(*span, left.whole_span()), right.whole_span()),
Expr::JsonOp {
span, left, right, ..
} => merge_span(merge_span(*span, left.whole_span()), right.whole_span()),
Expr::UnaryOp { span, expr, .. } => merge_span(*span, expr.whole_span()),
Expr::Cast { span, expr, .. } => merge_span(*span, expr.whole_span()),
Expr::TryCast { span, expr, .. } => merge_span(*span, expr.whole_span()),
Expr::Extract { span, expr, .. } => merge_span(*span, expr.whole_span()),
Expr::DatePart { span, expr, .. } => merge_span(*span, expr.whole_span()),
Expr::Position {
span,
substr_expr,
str_expr,
..
} => merge_span(
merge_span(*span, substr_expr.whole_span()),
str_expr.whole_span(),
),
Expr::Substring {
span,
expr,
substring_from,
substring_for,
..
} => {
let mut span = merge_span(
merge_span(*span, expr.whole_span()),
substring_from.whole_span(),
);
if let Some(substring_for) = substring_for {
span = merge_span(span, substring_for.whole_span());
}
span
}
Expr::Trim { span, expr, .. } => merge_span(*span, expr.whole_span()),
Expr::Literal { span, .. } => *span,
Expr::CountAll { span, .. } => *span,
Expr::Tuple { span, exprs } => {
let mut span = *span;
for expr in exprs {
span = merge_span(span, expr.whole_span());
}
span
}
Expr::FunctionCall { span, .. } => *span,
Expr::Case {
span,
operand,
conditions,
results,
else_result,
} => {
let mut span = *span;
if let Some(operand) = operand {
span = merge_span(span, operand.whole_span());
}
for (cond, res) in conditions.iter().zip(results) {
span = merge_span(merge_span(span, cond.whole_span()), res.whole_span());
}
if let Some(else_result) = else_result {
span = merge_span(span, else_result.whole_span());
}
span
}
Expr::Exists { span, subquery, .. } => merge_span(*span, subquery.span),
Expr::Subquery { span, subquery, .. } => merge_span(*span, subquery.span),
Expr::MapAccess { span, expr, .. } => merge_span(*span, expr.whole_span()),
Expr::Array { span, exprs } => {
let mut span = *span;
for expr in exprs {
span = merge_span(span, expr.whole_span());
}
span
}
Expr::Map { span, kvs } => {
let mut span = *span;
for (_, v) in kvs {
span = merge_span(span, v.whole_span());
}
span
}
Expr::Interval { span, expr, .. } => merge_span(*span, expr.whole_span()),
Expr::DateAdd {
span,
interval,
date,
..
} => merge_span(merge_span(*span, interval.whole_span()), date.whole_span()),
Expr::DateSub {
span,
interval,
date,
..
} => merge_span(merge_span(*span, interval.whole_span()), date.whole_span()),
Expr::DateTrunc { span, date, .. } => merge_span(*span, date.whole_span()),
Expr::Hole { span, .. } => *span,
}
}

pub fn all_function_like_syntaxes() -> &'static [&'static str] {
&[
"CAST",
Expand Down
2 changes: 2 additions & 0 deletions src/query/ast/src/ast/statements/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ mod notification;
mod password_policy;
mod pipe;
mod presign;
mod procedure;
mod replace;
mod script;
mod share;
Expand Down Expand Up @@ -70,6 +71,7 @@ pub use notification::*;
pub use password_policy::*;
pub use pipe::*;
pub use presign::*;
pub use procedure::*;
pub use replace::*;
pub use script::*;
pub use share::*;
Expand Down
32 changes: 32 additions & 0 deletions src/query/ast/src/ast/statements/procedure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2021 Datafuse Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt::Display;
use std::fmt::Formatter;

use derive_visitor::Drive;
use derive_visitor::DriveMut;

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub struct ExecuteImmediateStmt {
#[drive(skip)]
pub script: String,
}

impl Display for ExecuteImmediateStmt {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "EXECUTE IMMEDIATE $$\n{}\n$$", self.script)?;
Ok(())
}
}
Loading

0 comments on commit 41ba9d1

Please sign in to comment.