lovasoa commented on code in PR #1500:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1500#discussion_r1832982378


##########
tests/sqlparser_common.rs:
##########
@@ -11387,6 +11387,372 @@ fn test_try_convert() {
     dialects.verified_expr("TRY_CONVERT('foo', VARCHAR(MAX))");
 }
 
+#[test]
+fn parse_composite_function() {
+    let sql = all_dialects().verified_only_select("SELECT STUFF((SELECT ',' + 
name FROM sys.objects FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 
1, '') AS T");
+    assert_eq!(
+        vec![SelectItem::ExprWithAlias {
+            expr: Expr::Function(Function {
+                name: ObjectName(vec![Ident {
+                    value: "STUFF".into(),
+                    quote_style: None
+                }]),
+                parameters: FunctionArguments::None,
+                args: FunctionArguments::List(FunctionArgumentList {
+                    duplicate_treatment: None,
+                    args: vec![
+                        
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::CompositeFunction(
+                            CompositeFunction {
+                                left: Expr::Subquery(
+                                    Query {
+                                        with: None,
+                                        body: SetExpr::Select(
+                                            Select {
+                                                distinct: None,
+                                                top: None,
+                                                top_before_distinct: false,
+                                                projection: 
vec![SelectItem::UnnamedExpr(
+                                                    Expr::BinaryOp {
+                                                        left: Expr::Value(
+                                                            
Value::SingleQuotedString(",".into())
+                                                        )
+                                                        .into(),
+                                                        op: 
BinaryOperator::Plus,
+                                                        right: 
Expr::Identifier(Ident {
+                                                            value: 
"name".into(),
+                                                            quote_style: None
+                                                        })
+                                                        .into()
+                                                    }
+                                                )],
+                                                into: None,
+                                                from: vec![TableWithJoins {
+                                                    relation: 
TableFactor::Table {
+                                                        name: ObjectName(vec![
+                                                            Ident {
+                                                                value: 
"sys".into(),
+                                                                quote_style: 
None,
+                                                            },
+                                                            Ident {
+                                                                value: 
"objects".into(),
+                                                                quote_style: 
None,
+                                                            }
+                                                        ]),
+                                                        alias: None,
+                                                        args: None,
+                                                        with_hints: vec![],
+                                                        version: None,
+                                                        with_ordinality: false,
+                                                        partitions: vec![]
+                                                    },
+                                                    joins: vec![]
+                                                }],
+                                                lateral_views: vec![],
+                                                prewhere: None,
+                                                selection: None,
+                                                group_by: 
GroupByExpr::Expressions(vec![], vec![]),
+                                                cluster_by: vec![],
+                                                distribute_by: vec![],
+                                                sort_by: vec![],
+                                                having: None,
+                                                named_window: vec![],
+                                                qualify: None,
+                                                window_before_qualify: false,
+                                                value_table_mode: None,
+                                                connect_by: None,
+                                            }
+                                            .into()
+                                        )
+                                        .into(),
+                                        order_by: None,
+                                        limit: None,
+                                        limit_by: vec![],
+                                        offset: None,
+                                        fetch: None,
+                                        locks: vec![],
+                                        for_clause: Some(ForClause::Xml {
+                                            for_xml: 
ForXml::Path(Some("".into())),
+                                            elements: false,
+                                            binary_base64: false,
+                                            root: None,
+                                            r#type: true
+                                        }),
+                                        settings: None,
+                                        format_clause: None,
+                                    }
+                                    .into()
+                                )
+                                .into(),
+                                right: Function {
+                                    name: ObjectName(vec![Ident {
+                                        value: "value".into(),
+                                        quote_style: None
+                                    }]),
+                                    parameters: FunctionArguments::None,
+                                    args: 
FunctionArguments::List(FunctionArgumentList {
+                                        duplicate_treatment: None,
+                                        args: vec![
+                                            
FunctionArg::Unnamed(FunctionArgExpr::Expr(
+                                                
Expr::Value(Value::SingleQuotedString(".".into()))
+                                            )),
+                                            
FunctionArg::Unnamed(FunctionArgExpr::Expr(
+                                                
Expr::Value(Value::SingleQuotedString(
+                                                    "NVARCHAR(MAX)".into()
+                                                ))
+                                            ))
+                                        ],
+                                        clauses: vec![]
+                                    }),
+                                    filter: None,
+                                    null_treatment: None,
+                                    over: None,
+                                    within_group: vec![]
+                                }
+                            }
+                        ))),
+                        
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("1")))),
+                        
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("1")))),
+                        FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
+                            Value::SingleQuotedString("".into())
+                        )))
+                    ],
+                    clauses: vec![]
+                }),
+                filter: None,
+                null_treatment: None,
+                over: None,
+                within_group: vec![]
+            })
+            .into(),
+            alias: Ident {
+                value: "T".into(),
+                quote_style: None
+            }
+        }],
+        sql.projection
+    );
+    let sql = all_dialects()
+        .verified_only_select("SELECT CAST(column AS XML).value('.', 
'NVARCHAR(MAX)') AS T");
+    assert_eq!(
+        vec![SelectItem::ExprWithAlias {
+            expr: Expr::CompositeFunction(CompositeFunction {
+                left: Expr::Cast {
+                    kind: CastKind::Cast,
+                    expr: Expr::Identifier(Ident {
+                        value: "column".into(),
+                        quote_style: None
+                    })
+                    .into(),
+                    data_type: DataType::Custom(
+                        ObjectName(vec![Ident {
+                            value: "XML".into(),
+                            quote_style: None
+                        }]),
+                        vec![]
+                    ),
+                    format: None
+                }
+                .into(),
+                right: Function {
+                    name: ObjectName(vec![Ident {
+                        value: "value".into(),
+                        quote_style: None
+                    }]),
+                    parameters: FunctionArguments::None,
+                    args: FunctionArguments::List(FunctionArgumentList {
+                        duplicate_treatment: None,
+                        args: vec![
+                            
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
+                                Value::SingleQuotedString(".".into())
+                            ))),
+                            
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
+                                
Value::SingleQuotedString("NVARCHAR(MAX)".into())
+                            )))
+                        ],
+                        clauses: vec![]
+                    }),
+                    filter: None,
+                    null_treatment: None,
+                    over: None,
+                    within_group: vec![]
+                }
+            })
+            .into(),
+            alias: Ident {
+                value: "T".into(),
+                quote_style: None
+            }
+        }],
+        sql.projection
+    );
+    let dialects =
+        all_dialects_where(|d| d.supports_try_convert() && 
d.convert_type_before_value());
+    let sql = dialects.verified_only_select("SELECT CONVERT(XML, 
'<Book>abc</Book>').value('.', 'NVARCHAR(MAX)').value('.', 'NVARCHAR(MAX)') AS 
T");
+    assert_eq!(
+        vec![SelectItem::ExprWithAlias {
+            expr: Expr::CompositeFunction(CompositeFunction {
+                left: Expr::CompositeFunction(CompositeFunction {
+                    left: Expr::Convert {
+                        expr: 
Expr::Value(Value::SingleQuotedString("<Book>abc</Book>".into()))
+                            .into(),
+                        is_try: false,
+                        data_type: Some(DataType::Custom(
+                            ObjectName(vec![Ident {
+                                value: "XML".into(),
+                                quote_style: None
+                            }]),
+                            vec![]
+                        )),
+                        charset: None,
+                        target_before_value: true,
+                        styles: vec![]
+                    }
+                    .into(),
+                    right: Function {
+                        name: ObjectName(vec![Ident {
+                            value: "value".into(),
+                            quote_style: None
+                        }]),
+                        parameters: FunctionArguments::None,
+                        args: FunctionArguments::List(FunctionArgumentList {
+                            duplicate_treatment: None,
+                            args: vec![
+                                
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
+                                    Value::SingleQuotedString(".".into())
+                                ))),
+                                
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
+                                    
Value::SingleQuotedString("NVARCHAR(MAX)".into())
+                                )))
+                            ],
+                            clauses: vec![]
+                        }),
+                        filter: None,
+                        null_treatment: None,
+                        over: None,
+                        within_group: vec![]
+                    }
+                })
+                .into(),
+                right: Function {
+                    name: ObjectName(vec![Ident {
+                        value: "value".into(),
+                        quote_style: None
+                    }]),
+                    parameters: FunctionArguments::None,
+                    args: FunctionArguments::List(FunctionArgumentList {
+                        duplicate_treatment: None,
+                        args: vec![
+                            
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
+                                Value::SingleQuotedString(".".into())
+                            ))),
+                            
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
+                                
Value::SingleQuotedString("NVARCHAR(MAX)".into())
+                            )))
+                        ],
+                        clauses: vec![]
+                    }),
+                    filter: None,
+                    null_treatment: None,
+                    over: None,
+                    within_group: vec![]
+                }
+            }),
+            alias: Ident {
+                value: "T".into(),
+                quote_style: None
+            }
+        }],
+        sql.projection
+    );

Review Comment:
   I find these tests hard to follow. And they will need to be updated even 
when the ast changes in places completely unrelated to Expr::CompositeFunction.
   
   Maybe you could just test the new syntax introduced here with small precise 
asserts that test just a single thing ? Like:
   
   ```rs
   assert!eq!(verified_expr("convert(XML, '<x/>').query('x')", some_small_ast);
   ```
   
   If you want to ensure some more complex queries always parse, you could add 
some verified_only_select, without adding an assert on the result.
   
   This should make the tests easier to understand, this pr easier to review, 
and reduce the burden of maintaining these tests in the future.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to