Skip to content

Commit

Permalink
Merge pull request #695 from upper/fix-funcexpr-expansion
Browse files Browse the repository at this point in the history
fix FuncExpr expansion
  • Loading branch information
xiam authored Sep 2, 2023
2 parents fe91b0b + 241dcdb commit 8e61801
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 11 deletions.
2 changes: 1 addition & 1 deletion internal/sqlbuilder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ func columnFragments(columns []interface{}) ([]exql.Fragment, []interface{}, err
if len(fnArgs) == 0 {
fnName = fnName + "()"
} else {
fnName = fnName + "(?" + strings.Repeat("?, ", len(fnArgs)-1) + ")"
fnName = fnName + "(?" + strings.Repeat(", ?", len(fnArgs)-1) + ")"
}
fnName, fnArgs = Preprocess(fnName, fnArgs)
f[i] = &exql.Raw{Value: fnName}
Expand Down
26 changes: 26 additions & 0 deletions internal/sqlbuilder/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,32 @@ func TestSelect(t *testing.T) {
sel.Arguments(),
)

{
sel := b.Select(db.Func("FOO", "A", "B", 1)).From("accounts").Where(db.Cond{"time": db.Func("FUNCTION", "20170103", "YYYYMMDD", 1, "E")})

assert.Equal(
`SELECT FOO($1, $2, $3) FROM "accounts" WHERE ("time" = FUNCTION($4, $5, $6, $7))`,
sel.String(),
)
assert.Equal(
[]interface{}{"A", "B", 1, "20170103", "YYYYMMDD", 1, "E"},
sel.Arguments(),
)
}

{

sel := b.Select(db.Func("FOO", "A", "B", 1)).From("accounts").Where(db.Cond{db.Func("FUNCTION", "20170103", "YYYYMMDD", 1, "E"): db.Func("FOO", 1)})

assert.Equal(
`SELECT FOO($1, $2, $3) FROM "accounts" WHERE (FUNCTION($4, $5, $6, $7) = FOO($8))`,
sel.String(),
)
assert.Equal(
[]interface{}{"A", "B", 1, "20170103", "YYYYMMDD", 1, "E", 1},
sel.Arguments(),
)
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/sqlbuilder/select.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ func (sel *selector) OrderBy(columns ...interface{}) db.Selector {
if len(fnArgs) == 0 {
fnName = fnName + "()"
} else {
fnName = fnName + "(?" + strings.Repeat("?, ", len(fnArgs)-1) + ")"
fnName = fnName + "(?" + strings.Repeat(", ?", len(fnArgs)-1) + ")"
}
fnName, fnArgs = Preprocess(fnName, fnArgs)
sort = &exql.SortColumn{
Expand Down
29 changes: 20 additions & 9 deletions internal/sqlbuilder/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,20 +161,31 @@ func (tu *templateWithUtils) toColumnValues(term interface{}) (cv exql.ColumnVal
case adapter.Constraint:
columnValue := exql.ColumnValue{}

// Getting column and operator.
if column, ok := t.Key().(string); ok {
chunks := strings.SplitN(strings.TrimSpace(column), " ", 2)
// TODO: Key and Value are similar. Can we refactor this? Maybe think about
// Left/Right rather than Key/Value.

switch key := t.Key().(type) {
case string:
chunks := strings.SplitN(strings.TrimSpace(key), " ", 2)
columnValue.Column = exql.ColumnWithName(chunks[0])
if len(chunks) > 1 {
columnValue.Operator = chunks[1]
}
} else {
if rawValue, ok := t.Key().(*adapter.RawExpr); ok {
columnValue.Column = &exql.Raw{Value: rawValue.Raw()}
args = append(args, rawValue.Arguments()...)
case *adapter.RawExpr:
columnValue.Column = &exql.Raw{Value: key.Raw()}
args = append(args, key.Arguments()...)
case *db.FuncExpr:
fnName, fnArgs := key.Name(), key.Arguments()
if len(fnArgs) == 0 {
fnName = fnName + "()"
} else {
columnValue.Column = &exql.Raw{Value: fmt.Sprintf("%v", t.Key())}
fnName = fnName + "(?" + strings.Repeat(", ?", len(fnArgs)-1) + ")"
}
fnName, fnArgs = Preprocess(fnName, fnArgs)
columnValue.Column = &exql.Raw{Value: fnName}
args = append(args, fnArgs...)
default:
columnValue.Column = &exql.Raw{Value: fmt.Sprintf("%v", key)}
}

switch value := t.Value().(type) {
Expand All @@ -185,7 +196,7 @@ func (tu *templateWithUtils) toColumnValues(term interface{}) (cv exql.ColumnVal
fnName = fnName + "()"
} else {
// A function with one or more arguments.
fnName = fnName + "(?" + strings.Repeat("?, ", len(fnArgs)-1) + ")"
fnName = fnName + "(?" + strings.Repeat(", ?", len(fnArgs)-1) + ")"
}
fnName, fnArgs = Preprocess(fnName, fnArgs)
columnValue.Value = &exql.Raw{Value: fnName}
Expand Down

0 comments on commit 8e61801

Please sign in to comment.