// Top-level parsing API (port of sqlglot/__init__.py parse/parse_one and
// Dialect.parse / Dialect.tokenize).
///|
/// Tokenizes `sql` with this dialect's tokenizer (virtual: see `DialectHooks::tokenize`).
pub fn Dialect::tokenize(
self : Dialect,
sql : String,
) -> Array[Token] raise SqlglotError {
match self.hooks.tokenize {
Some(f) => f(self, sql)
None => self.tokenize_base(sql)
}
}
///|
/// Tokenizes `sql` with this dialect's tokenizer settings.
pub fn Dialect::tokenize_base(
self : Dialect,
sql : String,
) -> Array[Token] raise SqlglotError {
Tokenizer::new(
self.tokenizer,
numbers_can_be_underscore_separated=self.cfg.numbers_can_be_underscore_separated,
identifiers_can_start_with_digit=self.cfg.identifiers_can_start_with_digit,
unescaped_sequences=self.cfg.unescaped_sequences,
).tokenize(sql)
}
///|
/// Creates a parser for this dialect.
pub fn Dialect::parser(
self : Dialect,
error_level? : ErrorLevel = Immediate,
error_message_context? : Int = 100,
max_errors? : Int = 3,
max_nodes? : Int = -1,
) -> Parser {
Parser::new(
self,
error_level~,
error_message_context~,
max_errors~,
max_nodes~,
)
}
///|
/// Parses `sql` into a list of syntax trees, one per statement.
pub fn Dialect::parse(
self : Dialect,
sql : String,
error_level? : ErrorLevel = Immediate,
error_message_context? : Int = 100,
max_errors? : Int = 3,
max_nodes? : Int = -1,
) -> Array[Expr?] raise SqlglotError {
let p = self.parser(
error_level~,
error_message_context~,
max_errors~,
max_nodes~,
)
match self.parser_fns.hooks.parse {
Some(f) => f(p, self.tokenize(sql), sql)
None => p.parse(self.tokenize(sql), sql)
}
}
///|
/// Parses `sql` into the given expression type(s).
pub fn Dialect::parse_into(
self : Dialect,
into : Array[Kind],
sql : String,
error_level? : ErrorLevel = Immediate,
error_message_context? : Int = 100,
max_errors? : Int = 3,
max_nodes? : Int = -1,
into_is_list? : Bool = false,
) -> Array[Expr?] raise SqlglotError {
let p = self.parser(
error_level~,
error_message_context~,
max_errors~,
max_nodes~,
)
match self.parser_fns.hooks.parse_into {
Some(f) => f(p, into, self.tokenize(sql), sql)
None => p.parse_into(into, self.tokenize(sql), sql~, into_is_list~)
}
}
///|
/// Parses the given SQL string and returns a syntax tree.
pub fn parse_one(
sql : String,
dialect? : Dialect,
into? : Array[Kind],
error_level? : ErrorLevel = Immediate,
error_message_context? : Int = 100,
max_errors? : Int = 3,
max_nodes? : Int = -1,
into_is_list? : Bool = false,
) -> Expr raise SqlglotError {
let d = match dialect {
Some(d) => d
None => base_dialect()
}
let result = match into {
Some(i) =>
d.parse_into(
i,
sql,
error_level~,
error_message_context~,
max_errors~,
max_nodes~,
into_is_list~,
)
None =>
d.parse(sql, error_level~, error_message_context~, max_errors~, max_nodes~)
}
if result.is_empty() || result[0] is None {
raise ParseError("No expression was parsed from '\{sql}'", [])
}
if result.length() > 1 {
mk(Block, [("expressions", result.filter_map(x => x))])
} else {
result[0].unwrap()
}
}
///|
/// Parses with a dialect given by name (e.g. "duckdb").
pub fn parse_one_with(
sql : String,
read : String,
into? : Array[Kind],
) -> Expr raise SqlglotError {
parse_one(sql, dialect=Dialect::get_or_raise(read), into?)
}
///|
/// Parses all statements of `sql`.
pub fn parse(
sql : String,
dialect? : Dialect,
error_level? : ErrorLevel = Immediate,
error_message_context? : Int = 100,
max_errors? : Int = 3,
max_nodes? : Int = -1,
) -> Array[Expr?] raise SqlglotError {
let d = match dialect {
Some(d) => d
None => base_dialect()
}
d.parse(sql, error_level~, error_message_context~, max_errors~, max_nodes~)
}
///|
/// Python `DataType.from_str`.
pub fn datatype_from_str(
dtype : String,
dialect? : Dialect,
udt? : Bool = false,
) -> Expr raise SqlglotError {
if py_upper(dtype) == "UNKNOWN" {
return mk1(DataType, DType::UNKNOWN)
}
parse_one(dtype, dialect?, into=[DataType], error_level=Ignore) catch {
ParseError(_, _) as e =>
if udt {
mk(DataType, [("this", DType::USERDEFINED), ("kind", dtype)])
} else {
raise e
}
e => raise e
}
}
///|
/// Parses `sql` with `read` and generates it with `write` (Python `sqlglot.transpile`).
pub fn transpile(
sql : String,
read? : Dialect,
write? : Dialect,
pretty? : Bool,
identify? : String = "",
error_level? : ErrorLevel = Immediate,
unsupported_level? : ErrorLevel = Warn,
) -> Array[String] raise SqlglotError {
let r = match read {
Some(d) => d
None => base_dialect()
}
let w = match write {
Some(d) => d
None => r
}
let out = []
for e in r.parse(sql, error_level~) {
match e {
Some(expr) =>
out.push(
Generator::new(w, pretty?, identify~, unsupported_level~).generate(
expr,
copy=false,
),
)
None => out.push("")
}
}
out
}