From fbb44b299f2f49f854ae8a0c5d2939941da2041f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E8=8B=B1=E5=BC=BA?= Date: Thu, 17 Oct 2024 11:34:34 +0800 Subject: [PATCH] support values fn call --- ast.go | 15 +++++++++++++++ parser.go | 22 ++++++++++++++-------- parser_test.go | 6 +++++- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/ast.go b/ast.go index 1f892f4..5361d1a 100644 --- a/ast.go +++ b/ast.go @@ -44,6 +44,7 @@ func (*StringLit) node() {} func (*TableName) node() {} func (*Type) node() {} func (*UnaryExpr) node() {} +func (*FnCallExpr) node() {} func (*UpdateStatement) node() {} func (*UpsertClause) node() {} func (*UsingConstraint) node() {} @@ -93,6 +94,7 @@ func (*QualifiedRef) expr() {} func (*Range) expr() {} func (*StringLit) expr() {} func (*UnaryExpr) expr() {} +func (*FnCallExpr) expr() {} // ExprString returns the string representation of expr. // Returns a blank string if expr is nil. @@ -362,6 +364,19 @@ func (expr *UnaryExpr) String() string { } } +type FnCallExpr struct { + Fn Token // function + X Expr // param expression +} + +func (expr *FnCallExpr) String() string { + paran, ok := expr.X.(*ParenExpr) + if ok { + return expr.Fn.String() + "(" + paran.X.String() + ")" + } + return expr.Fn.String() + "(" + expr.X.String() + ")" +} + type BinaryExpr struct { X Expr // lhs Op Token // operator diff --git a/parser.go b/parser.go index cad7401..84be4b3 100644 --- a/parser.go +++ b/parser.go @@ -2,7 +2,6 @@ package sqlparser import ( "errors" - "fmt" "io" "strings" ) @@ -221,8 +220,6 @@ func (p *Parser) parseUpsertClause() (_ *UpsertClause, err error) { return &clause, p.errorExpected(p.pos, p.tok, "CONFLICT or DUPLICATE") } p.lex() - fmt.Printf("-------- on duplicate key: %v\n", clause.DuplicateKey) - // Parse optional indexed column list & WHERE conditional. if p.peek() == LP { p.lex() @@ -937,12 +934,21 @@ func (p *Parser) ParseExpr() (expr Expr, err error) { func (p *Parser) parseOperand() (expr Expr, err error) { _, tok, lit := p.lex() - ////////////////// - if tok == VALUES { - _, tok, lit = p.lex() - } - ////////////////// switch tok { + case VALUES: + // 左括号 + _, tok, lit = p.lex() + var expr Expr + if tok == LP { + p.unlex() + var err error + expr, err = p.parseParenExpr() + if err != nil { + return nil, err + } + } + return &FnCallExpr{Fn: VALUES, X: expr}, nil + case IDENT, QIDENT: ident := identByNameAndTok(lit, tok) if p.peek() == DOT { diff --git a/parser_test.go b/parser_test.go index 2e27c54..4a55cc1 100644 --- a/parser_test.go +++ b/parser_test.go @@ -1,6 +1,7 @@ package sqlparser_test import ( + "fmt" "strings" "testing" @@ -1018,8 +1019,11 @@ func AssertParseExprError(tb testing.TB, s string, want string) { func TestSql_1(t *testing.T) { sql := "INSERT INTO `daily_asset` (`trade_date`,`fund_account`,`client_id`,`day_income`,`hold_income`,`acc_income`,`day_income_ratio`,`acc_income_sw_ratio`,`acc_income_nav_ratio`,`market_value`,`fund_asset`,`total_asset`,`sw_total_net`,`bank_transfer_in`,`bank_transfer_out`,`acc_bank_transfer_in`,`acc_bank_transfer_out`,`net_in_balance`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE `fund_asset`=VALUES(`fund_asset`),`hold_income`=VALUES(`hold_income`),`market_value`=VALUES(`market_value`),`total_asset`=VALUES(`total_asset`),`bank_transfer_in`=VALUES(`bank_transfer_in`),`bank_transfer_out`=VALUES(`bank_transfer_out`),`net_in_balance`=VALUES(`net_in_balance`)" - _, err := sqlparser.NewParser(strings.NewReader(sql)).ParseStatement() + stmt, err := sqlparser.NewParser(strings.NewReader(sql)).ParseStatement() if err != nil { t.Fatal(err) } + insert := stmt.(*sqlparser.InsertStatement) + result := insert.String() + fmt.Println(result) }