Support CONVERT expressions#1048
Conversation
Pull Request Test Coverage Report for Build 6915102482
💛 - Coveralls |
b222845 to
e5399b3
Compare
fixes apache#1047 adds support for the following CONVERT syntaxes: - `CONVERT('héhé' USING utf8mb4)` (MySQL, Postgres) - `CONVERT('héhé', CHAR CHARACTER SET utf8mb4)` (MySQL) - `CONVERT(DECIMAL(10, 5), 42)` (MSSQL) - the type comes first
e5399b3 to
bbd99a4
Compare
|
The "simple" function syntax already works (eg You can possibly make the code simpler by keep this behaviour and adding the more complex CONVERT statement parsing if it is detected. Adding something like the following in the parser. This approach would remove the need for the check for function order and mean CONVERT struct would not need so many Optional types as you only ever use it for the "complex" CONVERT statements. |
|
@tobyhede , we cannot do a |
Does it ? I think |
I agree this is what it seems to do: $ echo "select CONVERT(DECIMAL(10, 5), 42)" > /tmp/foo.sql
$ cargo run --example cli -- /tmp/foo.sql
Finished dev [unoptimized + debuginfo] target(s) in 0.07s
Running `target/debug/examples/cli /tmp/foo.sql`
Parsing from file '/tmp/foo.sql' using GenericDialect
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] Parsing sql 'select CONVERT(DECIMAL(10, 5), 42)
'...
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] parsing expr
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] parsing expr
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] parsing expr
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] prefix: Value(Number("10", false))
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] get_next_precedence() TokenWithLocation { token: Comma, location: Location { line: 1, column: 26 } }
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] 0: , 1: 5 2: )
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] next precedence: 0
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] parsing expr
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] prefix: Value(Number("5", false))
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] get_next_precedence() TokenWithLocation { token: RParen, location: Location { line: 1, column: 29 } }
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] 0: ) 1: , 2: 42
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] next precedence: 0
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] prefix: Function(Function { name: ObjectName([Ident { value: "DECIMAL", quote_style: None }]), args: [Unnamed(Expr(Value(Number("10", false)))), Unnamed(Expr(Value(Number("5", false))))], filter: None, null_treatment: None, over: None, distinct: false, special: false, order_by: [] })
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] get_next_precedence() TokenWithLocation { token: Comma, location: Location { line: 1, column: 30 } }
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] 0: , 1: 42 2: )
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] next precedence: 0
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] parsing expr
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] prefix: Value(Number("42", false))
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] get_next_precedence() TokenWithLocation { token: RParen, location: Location { line: 1, column: 34 } }
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] 0: ) 1: EOF 2: EOF
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] next precedence: 0
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] prefix: Function(Function { name: ObjectName([Ident { value: "CONVERT", quote_style: None }]), args: [Unnamed(Expr(Function(Function { name: ObjectName([Ident { value: "DECIMAL", quote_style: None }]), args: [Unnamed(Expr(Value(Number("10", false)))), Unnamed(Expr(Value(Number("5", false))))], filter: None, null_treatment: None, over: None, distinct: false, special: false, order_by: [] }))), Unnamed(Expr(Value(Number("42", false))))], filter: None, null_treatment: None, over: None, distinct: false, special: false, order_by: [] })
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] get_next_precedence() TokenWithLocation { token: EOF, location: Location { line: 0, column: 0 } }
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] 0: EOF 1: EOF 2: EOF
2023-11-20T19:50:50.259Z DEBUG [sqlparser::parser] next precedence: 0
Round-trip:
'SELECT CONVERT(DECIMAL(10, 5), 42)'
Parse results:
[
Query(
Query {
with: None,
body: Select(
Select {
distinct: None,
top: None,
projection: [
UnnamedExpr(
Function(
Function {
name: ObjectName(
[
Ident {
value: "CONVERT",
quote_style: None,
},
],
),
args: [
Unnamed(
Expr(
Function(
Function {
name: ObjectName(
[
Ident {
value: "DECIMAL",
quote_style: None,
},
],
),
args: [
Unnamed(
Expr(
Value(
Number(
"10",
false,
),
),
),
),
Unnamed(
Expr(
Value(
Number(
"5",
false,
),
),
),
),
],
filter: None,
null_treatment: None,
over: None,
distinct: false,
special: false,
order_by: [],
},
),
),
),
Unnamed(
Expr(
Value(
Number(
"42",
false,
),
),
),
),
],
filter: None,
null_treatment: None,
over: None,
distinct: false,
special: false,
order_by: [],
},
),
),
],
into: None,
from: [],
lateral_views: [],
selection: None,
group_by: Expressions(
[],
),
cluster_by: [],
distribute_by: [],
sort_by: [],
having: None,
named_window: [],
qualify: None,
},
),
order_by: [],
limit: None,
limit_by: [],
offset: None,
fetch: None,
locks: [],
for_clause: None,
},
),
] |
| /// The target data type | ||
| data_type: Option<DataType>, | ||
| /// The target character encoding | ||
| charset: Option<ObjectName>, |
There was a problem hiding this comment.
FWIW Postgres calls this "conversion name" but that appears to be an ObjectName so 👍
| || ch == '_' | ||
| } | ||
|
|
||
| /// SQL Server has `CONVERT(type, value)` instead of `CONVERT(value, type)` |
CONVERT expressions
fixes #1047
adds support for the following CONVERT syntaxes:
CONVERT('héhé' USING utf8mb4)(MySQL, Postgres)CONVERT('héhé', CHAR CHARACTER SET utf8mb4)(MySQL)CONVERT(DECIMAL(10, 5), 42)(MSSQL) - the type comes first