Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TRIM functionality #88

Merged
merged 18 commits into from
Nov 4, 2021
Merged
37 changes: 37 additions & 0 deletions go/vt/sqlparser/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -3529,6 +3529,7 @@ func (*CaseExpr) iExpr() {}
func (*ValuesFuncExpr) iExpr() {}
func (*ConvertExpr) iExpr() {}
func (*SubstrExpr) iExpr() {}
func (*TrimExpr) iExpr() {}
func (*ConvertUsingExpr) iExpr() {}
func (*MatchExpr) iExpr() {}
func (*GroupConcatExpr) iExpr() {}
Expand Down Expand Up @@ -4531,6 +4532,42 @@ func (node *SubstrExpr) walkSubtree(visit Visit) error {
)
}

// Options for Trim
const (
Leading string = "l"
Trailing string = "r"
Both string = "b"
)

type TrimExpr struct {
Str Expr
Pattern Expr
Dir string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declare some exported constants for this value

}

// Format formats the node
func (node *TrimExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("trim(%v, %v, %s)", node.Str, node.Pattern, node.Dir)
}

func (node *TrimExpr) replace(from, to Expr) bool {
if replaceExprs(from, to, &node.Pattern) {
return true
}
if replaceExprs(from, to, &node.Str) {
return true
}

return false
}

func (node *TrimExpr) walkSubtree(visit Visit) error {
if node == nil || node.Str == nil {
return nil
}
return Walk(visit, node.Str, node.Pattern)
}

// ConvertExpr represents a call to CONVERT(expr, type)
// or it's equivalent CAST(expr AS type). Both are rewritten to the former.
type ConvertExpr struct {
Expand Down
42 changes: 40 additions & 2 deletions go/vt/sqlparser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2643,8 +2643,8 @@ func TestKeywords(t *testing.T) {
input: "select /* share and mode as cols */ share, mode from t where share = 'foo'",
output: "select /* share and mode as cols */ `share`, `mode` from t where `share` = 'foo'",
}, {
input: "select /* unused keywords as cols */ write, virtual from t where trailing = 'foo'",
output: "select /* unused keywords as cols */ `write`, `virtual` from t where `trailing` = 'foo'",
input: "select /* unused keywords as cols */ write, virtual from t where varcharacter = 'foo'",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to this test case?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment still applies, you changed this test case and should put it back

output: "select /* unused keywords as cols */ `write`, `virtual` from t where `varcharacter` = 'foo'",
}, {
input: "insert into x (status) values (42)",
output: "insert into x(`status`) values (42)",
Expand Down Expand Up @@ -3489,6 +3489,44 @@ func TestLoadData(t *testing.T) {
}
}

func TestTrim(t *testing.T) {
testCases := []parseTest{
{
input: `SELECT TRIM("foo")`,
output: `select trim('foo', ' ', b) from dual`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So generally speaking, the Format function should produce output which is itself parseable, and this won't

Unless you have a good reason not to do it this way instead, you should change the Format function to return something similar to the input

serializeSelectExprs: true,
},
{
input: `SELECT TRIM("bar" FROM "foo")`,
output: `select trim('foo', 'bar', b) from dual`,
serializeSelectExprs: true,
},
{
input: `SELECT TRIM(LEADING "bar" FROM "foo")`,
output: `select trim('foo', 'bar', l) from dual`,
serializeSelectExprs: true,
},
{
input: `SELECT TRIM(TRAILING "bar" FROM "foo")`,
output: `select trim('foo', 'bar', r) from dual`,
serializeSelectExprs: true,
},
{
input: `SELECT TRIM(BOTH "bar" FROM "foo")`,
output: `select trim('foo', 'bar', b) from dual`,
serializeSelectExprs: true,
},
{
input: `SELECT TRIM(TRIM("foobar"))`,
output: `select trim(trim('foobar', ' ', b), ' ', b) from dual`,
serializeSelectExprs: true,
},
}
for _, tcase := range testCases {
runParseTestCase(t, tcase)
}
}

func TestCreateTableLike(t *testing.T) {
normal := "create table a like b"
testCases := []struct {
Expand Down
Loading