Skip to content

Commit 9944ca8

Browse files
committed
add support for FOR ORDINALITY in JSON_TABLE
fixes apache#1492
1 parent ee90373 commit 9944ca8

File tree

4 files changed

+73
-14
lines changed

4 files changed

+73
-14
lines changed

src/ast/mod.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,14 @@ pub use self::query::{
5454
ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, Fetch, ForClause, ForJson, ForXml,
5555
FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias, IlikeSelectItem, Interpolate,
5656
InterpolateExpr, Join, JoinConstraint, JoinOperator, JsonTableColumn,
57-
JsonTableColumnErrorHandling, LateralView, LockClause, LockType, MatchRecognizePattern,
58-
MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
59-
OffsetRows, OrderBy, OrderByExpr, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
60-
RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
61-
SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table,
62-
TableAlias, TableFactor, TableFunctionArgs, TableVersion, TableWithJoins, Top, TopQuantity,
63-
ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
57+
JsonTableColumnErrorHandling, JsonTableNamedColumn, JsonTableNestedColumn, LateralView,
58+
LockClause, LockType, MatchRecognizePattern, MatchRecognizeSymbol, Measure,
59+
NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset, OffsetRows, OrderBy, OrderByExpr,
60+
PivotValueSource, ProjectionSelect, Query, RenameSelectItem, RepetitionQuantifier,
61+
ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select, SelectInto, SelectItem, SetExpr,
62+
SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, TableFactor,
63+
TableFunctionArgs, TableVersion, TableWithJoins, Top, TopQuantity, ValueTableMode, Values,
64+
WildcardAdditionalOptions, With, WithFill,
6465
};
6566

6667
pub use self::trigger::{

src/ast/query.rs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,14 +2281,65 @@ impl fmt::Display for ForJson {
22812281
/// FROM JSON_TABLE(
22822282
/// '["a", "b"]',
22832283
/// '$[*]' COLUMNS (
2284-
/// value VARCHAR(20) PATH '$'
2284+
/// name FOR ORDINALITY,
2285+
/// value VARCHAR(20) PATH '$',
2286+
/// NESTED PATH '$[*]' COLUMNS (
2287+
/// value VARCHAR(20) PATH '$'
2288+
/// )
22852289
/// )
22862290
/// ) AS jt;
22872291
/// ```
22882292
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
22892293
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
22902294
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2291-
pub struct JsonTableColumn {
2295+
pub enum JsonTableColumn {
2296+
Named(JsonTableNamedColumn),
2297+
ForOrdinality(Ident),
2298+
Nested(JsonTableNestedColumn),
2299+
}
2300+
2301+
impl fmt::Display for JsonTableColumn {
2302+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2303+
match self {
2304+
JsonTableColumn::Named(json_table_named_column) => {
2305+
write!(f, "{json_table_named_column}")
2306+
}
2307+
JsonTableColumn::ForOrdinality(ident) => write!(f, "{} FOR ORDINALITY", ident),
2308+
JsonTableColumn::Nested(json_table_nested_column) => {
2309+
write!(f, "{json_table_nested_column}")
2310+
}
2311+
}
2312+
}
2313+
}
2314+
2315+
/// A nested column in a JSON_TABLE column list
2316+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2317+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2318+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2319+
pub struct JsonTableNestedColumn {
2320+
pub path: Value,
2321+
pub columns: Vec<JsonTableColumn>,
2322+
}
2323+
2324+
impl fmt::Display for JsonTableNestedColumn {
2325+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2326+
write!(
2327+
f,
2328+
"NESTED PATH {} COLUMNS ({})",
2329+
self.path,
2330+
display_comma_separated(&self.columns)
2331+
)
2332+
}
2333+
}
2334+
2335+
/// A single column definition in MySQL's `JSON_TABLE` table valued function.
2336+
/// ```sql
2337+
/// value VARCHAR(20) PATH '$'
2338+
/// ```
2339+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2340+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2341+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2342+
pub struct JsonTableNamedColumn {
22922343
/// The name of the column to be extracted.
22932344
pub name: Ident,
22942345
/// The type of the column to be extracted.
@@ -2303,7 +2354,7 @@ pub struct JsonTableColumn {
23032354
pub on_error: Option<JsonTableColumnErrorHandling>,
23042355
}
23052356

2306-
impl fmt::Display for JsonTableColumn {
2357+
impl fmt::Display for JsonTableNamedColumn {
23072358
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23082359
write!(
23092360
f,

src/parser/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10402,6 +10402,10 @@ impl<'a> Parser<'a> {
1040210402
/// For example: `id INT EXISTS PATH '$' DEFAULT '0' ON EMPTY ERROR ON ERROR`
1040310403
pub fn parse_json_table_column_def(&mut self) -> Result<JsonTableColumn, ParserError> {
1040410404
let name = self.parse_identifier(false)?;
10405+
if self.parse_keyword(Keyword::FOR) {
10406+
self.expect_keyword(Keyword::ORDINALITY)?;
10407+
return Ok(JsonTableColumn::ForOrdinality(name));
10408+
}
1040510409
let r#type = self.parse_data_type()?;
1040610410
let exists = self.parse_keyword(Keyword::EXISTS);
1040710411
self.expect_keyword(Keyword::PATH)?;
@@ -10416,14 +10420,14 @@ impl<'a> Parser<'a> {
1041610420
on_error = Some(error_handling);
1041710421
}
1041810422
}
10419-
Ok(JsonTableColumn {
10423+
Ok(JsonTableColumn::Named(JsonTableNamedColumn {
1042010424
name,
1042110425
r#type,
1042210426
path,
1042310427
exists,
1042410428
on_empty,
1042510429
on_error,
10426-
})
10430+
}))
1042710431
}
1042810432

1042910433
fn parse_json_table_column_error_handling(

tests/sqlparser_mysql.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2758,6 +2758,9 @@ fn parse_json_table() {
27582758
r#"SELECT * FROM JSON_TABLE('[1,2]', '$[*]' COLUMNS(x INT PATH '$' ERROR ON EMPTY)) AS t"#,
27592759
);
27602760
mysql().verified_only_select(r#"SELECT * FROM JSON_TABLE('[1,2]', '$[*]' COLUMNS(x INT PATH '$' ERROR ON EMPTY DEFAULT '0' ON ERROR)) AS t"#);
2761+
mysql().verified_only_select(
2762+
r#"SELECT jt.* FROM JSON_TABLE('["Alice", "Bob", "Charlie"]', '$[*]' COLUMNS(row_num FOR ORDINALITY, name VARCHAR(50) PATH '$')) AS jt"#,
2763+
);
27612764
assert_eq!(
27622765
mysql()
27632766
.verified_only_select(
@@ -2769,14 +2772,14 @@ fn parse_json_table() {
27692772
json_expr: Expr::Value(Value::SingleQuotedString("[1,2]".to_string())),
27702773
json_path: Value::SingleQuotedString("$[*]".to_string()),
27712774
columns: vec![
2772-
JsonTableColumn {
2775+
JsonTableColumn::Named(JsonTableNamedColumn {
27732776
name: Ident::new("x"),
27742777
r#type: DataType::Int(None),
27752778
path: Value::SingleQuotedString("$".to_string()),
27762779
exists: false,
27772780
on_empty: Some(JsonTableColumnErrorHandling::Default(Value::SingleQuotedString("0".to_string()))),
27782781
on_error: Some(JsonTableColumnErrorHandling::Null),
2779-
},
2782+
}),
27802783
],
27812784
alias: Some(TableAlias {
27822785
name: Ident::new("t"),

0 commit comments

Comments
 (0)