diff --git a/case.go b/case.go index 299e14b..e3b099b 100644 --- a/case.go +++ b/case.go @@ -27,7 +27,7 @@ func (b *sqlizerBuffer) WriteSql(item Sqlizer) { var str string var args []interface{} - str, args, b.err = nestedToSql(item) + str, args, b.err = item.ToSql() if b.err != nil { return diff --git a/delete.go b/delete.go index f3f31e6..f0c3d94 100644 --- a/delete.go +++ b/delete.go @@ -79,7 +79,17 @@ func (d *deleteData) ToSql() (sqlStr string, args []interface{}, err error) { } } - sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sql.String()) + sqlStr = sql.String() + + return +} + +func (d *deleteData) FinalizeSql() (sqlStr string, args []interface{}, err error) { + sqlStr, args, err = d.ToSql() + if err != nil { + return + } + sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sqlStr) return } @@ -115,13 +125,19 @@ func (b DeleteBuilder) Exec() (sql.Result, error) { // SQL methods -// ToSql builds the query into a SQL string and bound args. +// ToSql builds the query into a SQL string. func (b DeleteBuilder) ToSql() (string, []interface{}, error) { data := builder.GetStruct(b).(deleteData) return data.ToSql() } -// MustSql builds the query into a SQL string and bound args. +// FinalizeSql builds the query into a SQL string and bound args. +func (b DeleteBuilder) FinalizeSql() (string, []interface{}, error) { + data := builder.GetStruct(b).(deleteData) + return data.FinalizeSql() +} + +// MustSql builds the query into a SQL string. // It panics if there are any errors. func (b DeleteBuilder) MustSql() (string, []interface{}) { sql, args, err := b.ToSql() @@ -131,6 +147,16 @@ func (b DeleteBuilder) MustSql() (string, []interface{}) { return sql, args } +// MustFinalizeSql builds the query into a SQL string and bound args. +// It panics if there are any errors. +func (b DeleteBuilder) MustFinalizeSql() (string, []interface{}) { + sql, args, err := b.FinalizeSql() + if err != nil { + panic(err) + } + return sql, args +} + // Prefix adds an expression to the beginning of the query func (b DeleteBuilder) Prefix(sql string, args ...interface{}) DeleteBuilder { return b.PrefixExpr(Expr(sql, args...)) diff --git a/delete_test.go b/delete_test.go index 62691f2..143236c 100644 --- a/delete_test.go +++ b/delete_test.go @@ -46,10 +46,10 @@ func TestDeleteBuilderMustSql(t *testing.T) { func TestDeleteBuilderPlaceholders(t *testing.T) { b := Delete("test").Where("x = ? AND y = ?", 1, 2) - sql, _, _ := b.PlaceholderFormat(Question).ToSql() + sql, _, _ := b.PlaceholderFormat(Question).FinalizeSql() assert.Equal(t, "DELETE FROM test WHERE x = ? AND y = ?", sql) - sql, _, _ = b.PlaceholderFormat(Dollar).ToSql() + sql, _, _ = b.PlaceholderFormat(Dollar).FinalizeSql() assert.Equal(t, "DELETE FROM test WHERE x = $1 AND y = $2", sql) } diff --git a/expr.go b/expr.go index eba1b45..6154df4 100644 --- a/expr.go +++ b/expr.go @@ -23,7 +23,8 @@ type expr struct { // Expr builds an expression from a SQL fragment and arguments. // // Ex: -// Expr("FROM_UNIXTIME(?)", t) +// +// Expr("FROM_UNIXTIME(?)", t) func Expr(sql string, args ...interface{}) Sqlizer { return expr{sql: sql, args: args} } @@ -105,8 +106,9 @@ func (ce concatExpr) ToSql() (sql string, args []interface{}, err error) { // ConcatExpr builds an expression by concatenating strings and other expressions. // // Ex: -// name_expr := Expr("CONCAT(?, ' ', ?)", firstName, lastName) -// ConcatExpr("COALESCE(full_name,", name_expr, ")") +// +// name_expr := Expr("CONCAT(?, ' ', ?)", firstName, lastName) +// ConcatExpr("COALESCE(full_name,", name_expr, ")") func ConcatExpr(parts ...interface{}) concatExpr { return concatExpr(parts) } @@ -120,7 +122,8 @@ type aliasExpr struct { // Alias allows to define alias for column in SelectBuilder. Useful when column is // defined as complex expression like IF or CASE // Ex: -// .Column(Alias(caseStmt, "case_column")) +// +// .Column(Alias(caseStmt, "case_column")) func Alias(expr Sqlizer, alias string) aliasExpr { return aliasExpr{expr, alias} } @@ -212,7 +215,8 @@ func (eq Eq) ToSql() (sql string, args []interface{}, err error) { // NotEq is syntactic sugar for use with Where/Having/Set methods. // Ex: -// .Where(NotEq{"id": 1}) == "id <> 1" +// +// .Where(NotEq{"id": 1}) == "id <> 1" type NotEq Eq func (neq NotEq) ToSql() (sql string, args []interface{}, err error) { @@ -221,7 +225,8 @@ func (neq NotEq) ToSql() (sql string, args []interface{}, err error) { // Like is syntactic sugar for use with LIKE conditions. // Ex: -// .Where(Like{"name": "%irrel"}) +// +// .Where(Like{"name": "%irrel"}) type Like map[string]interface{} func (lk Like) toSql(opr string) (sql string, args []interface{}, err error) { @@ -260,7 +265,8 @@ func (lk Like) ToSql() (sql string, args []interface{}, err error) { // NotLike is syntactic sugar for use with LIKE conditions. // Ex: -// .Where(NotLike{"name": "%irrel"}) +// +// .Where(NotLike{"name": "%irrel"}) type NotLike Like func (nlk NotLike) ToSql() (sql string, args []interface{}, err error) { @@ -269,7 +275,8 @@ func (nlk NotLike) ToSql() (sql string, args []interface{}, err error) { // ILike is syntactic sugar for use with ILIKE conditions. // Ex: -// .Where(ILike{"name": "sq%"}) +// +// .Where(ILike{"name": "sq%"}) type ILike Like func (ilk ILike) ToSql() (sql string, args []interface{}, err error) { @@ -278,7 +285,8 @@ func (ilk ILike) ToSql() (sql string, args []interface{}, err error) { // NotILike is syntactic sugar for use with ILIKE conditions. // Ex: -// .Where(NotILike{"name": "sq%"}) +// +// .Where(NotILike{"name": "sq%"}) type NotILike Like func (nilk NotILike) ToSql() (sql string, args []interface{}, err error) { @@ -287,7 +295,8 @@ func (nilk NotILike) ToSql() (sql string, args []interface{}, err error) { // Lt is syntactic sugar for use with Where/Having/Set methods. // Ex: -// .Where(Lt{"id": 1}) +// +// .Where(Lt{"id": 1}) type Lt map[string]interface{} func (lt Lt) toSql(opposite, orEq bool) (sql string, args []interface{}, err error) { @@ -339,7 +348,8 @@ func (lt Lt) ToSql() (sql string, args []interface{}, err error) { // LtOrEq is syntactic sugar for use with Where/Having/Set methods. // Ex: -// .Where(LtOrEq{"id": 1}) == "id <= 1" +// +// .Where(LtOrEq{"id": 1}) == "id <= 1" type LtOrEq Lt func (ltOrEq LtOrEq) ToSql() (sql string, args []interface{}, err error) { @@ -348,7 +358,8 @@ func (ltOrEq LtOrEq) ToSql() (sql string, args []interface{}, err error) { // Gt is syntactic sugar for use with Where/Having/Set methods. // Ex: -// .Where(Gt{"id": 1}) == "id > 1" +// +// .Where(Gt{"id": 1}) == "id > 1" type Gt Lt func (gt Gt) ToSql() (sql string, args []interface{}, err error) { @@ -357,7 +368,8 @@ func (gt Gt) ToSql() (sql string, args []interface{}, err error) { // GtOrEq is syntactic sugar for use with Where/Having/Set methods. // Ex: -// .Where(GtOrEq{"id": 1}) == "id >= 1" +// +// .Where(GtOrEq{"id": 1}) == "id >= 1" type GtOrEq Lt func (gtOrEq GtOrEq) ToSql() (sql string, args []interface{}, err error) { @@ -372,7 +384,7 @@ func (c conj) join(sep, defaultExpr string) (sql string, args []interface{}, err } var sqlParts []string for _, sqlizer := range c { - partSQL, partArgs, err := nestedToSql(sqlizer) + partSQL, partArgs, err := sqlizer.ToSql() if err != nil { return "", nil, err } diff --git a/insert.go b/insert.go index c23a579..87e4583 100644 --- a/insert.go +++ b/insert.go @@ -110,7 +110,17 @@ func (d *insertData) ToSql() (sqlStr string, args []interface{}, err error) { } } - sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sql.String()) + sqlStr = sql.String() + + return +} + +func (d *insertData) FinalizeSql() (sqlStr string, args []interface{}, err error) { + sqlStr, args, err = d.ToSql() + if err != nil { + return + } + sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sqlStr) return } @@ -210,13 +220,19 @@ func (b InsertBuilder) Scan(dest ...interface{}) error { // SQL methods -// ToSql builds the query into a SQL string and bound args. +// ToSql builds the query into a SQL string. func (b InsertBuilder) ToSql() (string, []interface{}, error) { data := builder.GetStruct(b).(insertData) return data.ToSql() } -// MustSql builds the query into a SQL string and bound args. +// FinalizeSql builds the query into a SQL string and bound args. +func (b InsertBuilder) FinalizeSql() (string, []interface{}, error) { + data := builder.GetStruct(b).(insertData) + return data.FinalizeSql() +} + +// MustSql builds the query into a SQL string. // It panics if there are any errors. func (b InsertBuilder) MustSql() (string, []interface{}) { sql, args, err := b.ToSql() @@ -226,6 +242,16 @@ func (b InsertBuilder) MustSql() (string, []interface{}) { return sql, args } +// MustFinalizeSql builds the query into a SQL string and bound args. +// It panics if there are any errors. +func (b InsertBuilder) MustFinalizeSql() (string, []interface{}) { + sql, args, err := b.FinalizeSql() + if err != nil { + panic(err) + } + return sql, args +} + // Prefix adds an expression to the beginning of the query func (b InsertBuilder) Prefix(sql string, args ...interface{}) InsertBuilder { return b.PrefixExpr(Expr(sql, args...)) diff --git a/insert_test.go b/insert_test.go index ced2313..4ae9e13 100644 --- a/insert_test.go +++ b/insert_test.go @@ -49,10 +49,10 @@ func TestInsertBuilderMustSql(t *testing.T) { func TestInsertBuilderPlaceholders(t *testing.T) { b := Insert("test").Values(1, 2) - sql, _, _ := b.PlaceholderFormat(Question).ToSql() + sql, _, _ := b.PlaceholderFormat(Question).FinalizeSql() assert.Equal(t, "INSERT INTO test VALUES (?,?)", sql) - sql, _, _ = b.PlaceholderFormat(Dollar).ToSql() + sql, _, _ = b.PlaceholderFormat(Dollar).FinalizeSql() assert.Equal(t, "INSERT INTO test VALUES ($1,$2)", sql) } diff --git a/part.go b/part.go index f3a7b15..2926d03 100644 --- a/part.go +++ b/part.go @@ -29,17 +29,9 @@ func (p part) ToSql() (sql string, args []interface{}, err error) { return } -func nestedToSql(s Sqlizer) (string, []interface{}, error) { - if raw, ok := s.(rawSqlizer); ok { - return raw.toSqlRaw() - } else { - return s.ToSql() - } -} - func appendToSql(parts []Sqlizer, w io.Writer, sep string, args []interface{}) ([]interface{}, error) { for i, p := range parts { - partSql, partArgs, err := nestedToSql(p) + partSql, partArgs, err := p.ToSql() if err != nil { return nil, err } else if len(partSql) == 0 { diff --git a/select.go b/select.go index d7e9a51..9c62ff8 100644 --- a/select.go +++ b/select.go @@ -55,13 +55,7 @@ func (d *selectData) QueryRow() RowScanner { } func (d *selectData) ToSql() (sqlStr string, args []interface{}, err error) { - sqlStr, args, err = d.toSqlRaw() - if err != nil { - return - } - - sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sqlStr) - return + return d.toSqlRaw() } func (d *selectData) toSqlRaw() (sqlStr string, args []interface{}, err error) { @@ -188,6 +182,16 @@ func (d *selectData) toSqlRaw() (sqlStr string, args []interface{}, err error) { return } +func (d *selectData) FinalizeSql() (sqlStr string, args []interface{}, err error) { + sqlStr, args, err = d.toSqlRaw() + if err != nil { + return + } + sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sqlStr) + return + +} + // Builder // SelectBuilder builds SQL SELECT statements. @@ -240,7 +244,7 @@ func (b SelectBuilder) Scan(dest ...interface{}) error { // SQL methods -// ToSql builds the query into a SQL string and bound args. +// ToSql builds the query into a SQL string. func (b SelectBuilder) ToSql() (string, []interface{}, error) { data := builder.GetStruct(b).(selectData) return data.ToSql() @@ -251,7 +255,13 @@ func (b SelectBuilder) toSqlRaw() (string, []interface{}, error) { return data.toSqlRaw() } -// MustSql builds the query into a SQL string and bound args. +// FinalizeSql builds the query into a SQL string and bound args. +func (b SelectBuilder) FinalizeSql() (string, []interface{}, error) { + data := builder.GetStruct(b).(selectData) + return data.FinalizeSql() +} + +// MustSql builds the query into a SQL string. // It panics if there are any errors. func (b SelectBuilder) MustSql() (string, []interface{}) { sql, args, err := b.ToSql() @@ -261,6 +271,16 @@ func (b SelectBuilder) MustSql() (string, []interface{}) { return sql, args } +// MustFinalizeSql builds the query into a SQL string and bound args. +// It panics if there are any errors. +func (b SelectBuilder) MustFinalizeSql() (string, []interface{}) { + sql, args, err := b.FinalizeSql() + if err != nil { + panic(err) + } + return sql, args +} + // Prefix adds an expression to the beginning of the query func (b SelectBuilder) Prefix(sql string, args ...interface{}) SelectBuilder { return b.PrefixExpr(Expr(sql, args...)) @@ -309,7 +329,8 @@ func (b SelectBuilder) Columns(columns ...string) SelectBuilder { // Column adds a result column to the query. // Unlike Columns, Column accepts args which will be bound to placeholders in // the columns string, for example: -// Column("IF(col IN ("+squirrel.Placeholders(3)+"), 1, 0) as col", 1, 2, 3) +// +// Column("IF(col IN ("+squirrel.Placeholders(3)+"), 1, 0) as col", 1, 2, 3) func (b SelectBuilder) Column(column interface{}, args ...interface{}) SelectBuilder { return builder.Append(b, "Columns", newPart(column, args...)).(SelectBuilder) } diff --git a/select_test.go b/select_test.go index 5868a43..728287c 100644 --- a/select_test.go +++ b/select_test.go @@ -81,7 +81,7 @@ func TestSelectBuilderFromSelectNestedDollarPlaceholders(t *testing.T) { FromSelect(subQ, "subq"). Where(Lt{"c": 2}). PlaceholderFormat(Dollar) - sql, args, err := b.ToSql() + sql, args, err := b.FinalizeSql() assert.NoError(t, err) expectedSql := "SELECT c FROM (SELECT c FROM t WHERE c > $1) AS subq WHERE c < $2" @@ -99,16 +99,16 @@ func TestSelectBuilderToSqlErr(t *testing.T) { func TestSelectBuilderPlaceholders(t *testing.T) { b := Select("test").Where("x = ? AND y = ?") - sql, _, _ := b.PlaceholderFormat(Question).ToSql() + sql, _, _ := b.PlaceholderFormat(Question).FinalizeSql() assert.Equal(t, "SELECT test WHERE x = ? AND y = ?", sql) - sql, _, _ = b.PlaceholderFormat(Dollar).ToSql() + sql, _, _ = b.PlaceholderFormat(Dollar).FinalizeSql() assert.Equal(t, "SELECT test WHERE x = $1 AND y = $2", sql) - sql, _, _ = b.PlaceholderFormat(Colon).ToSql() + sql, _, _ = b.PlaceholderFormat(Colon).FinalizeSql() assert.Equal(t, "SELECT test WHERE x = :1 AND y = :2", sql) - sql, _, _ = b.PlaceholderFormat(AtP).ToSql() + sql, _, _ = b.PlaceholderFormat(AtP).FinalizeSql() assert.Equal(t, "SELECT test WHERE x = @p1 AND y = @p2", sql) } @@ -213,7 +213,7 @@ func TestSelectBuilderNestedSelectDollar(t *testing.T) { nestedBuilder := StatementBuilder.PlaceholderFormat(Dollar).Select("*").Prefix("NOT EXISTS ("). From("bar").Where("y = ?", 42).Suffix(")") outerSql, _, err := StatementBuilder.PlaceholderFormat(Dollar).Select("*"). - From("foo").Where("x = ?").Where(nestedBuilder).ToSql() + From("foo").Where("x = ?").Where(nestedBuilder).FinalizeSql() assert.NoError(t, err) assert.Equal(t, "SELECT * FROM foo WHERE x = $1 AND NOT EXISTS ( SELECT * FROM bar WHERE y = $2 )", outerSql) @@ -256,7 +256,7 @@ func TestSelectSubqueryPlaceholderNumbering(t *testing.T) { FromSelect(subquery, "q"). Where("c = ?", 2). PlaceholderFormat(Dollar). - ToSql() + FinalizeSql() assert.NoError(t, err) expectedSql := "WITH a AS ( SELECT a WHERE b = $1 ) SELECT * FROM (SELECT a WHERE b = $2) AS q WHERE c = $3" @@ -271,7 +271,7 @@ func TestSelectSubqueryInConjunctionPlaceholderNumbering(t *testing.T) { Where(Or{subquery}). Where("c = ?", 2). PlaceholderFormat(Dollar). - ToSql() + FinalizeSql() assert.NoError(t, err) expectedSql := "SELECT * WHERE (EXISTS( SELECT a WHERE b = $1 )) AND c = $2" @@ -295,6 +295,15 @@ func TestTwoCTEs(t *testing.T) { assert.Equal(t, "WITH cte AS (SELECT abc FROM def), cte2 AS (SELECT ghi FROM jkl) SELECT * FROM cte", sql) } +func TestRenderingPlaceholderInCTEAndMainQuery(t *testing.T) { + cteBuilder := Select("*").From("users").Where("id = ?", 1).PlaceholderFormat(Dollar) + queryBuilder := Select("*").From("base").Where("name = ?", "John Doe").With("base", cteBuilder).PlaceholderFormat(Dollar) + sql, args, err := queryBuilder.FinalizeSql() + assert.NoError(t, err) + assert.Equal(t, "WITH base AS (SELECT * FROM users WHERE id = $1) SELECT * FROM base WHERE name = $2", sql) + assert.Equal(t, []interface{}{1, "John Doe"}, args) +} + func TestCTEErrorBubblesUp(t *testing.T) { // a SELECT with no columns raises an error diff --git a/squirrel.go b/squirrel.go index 46d456e..0b17234 100644 --- a/squirrel.go +++ b/squirrel.go @@ -14,16 +14,15 @@ import ( // Sqlizer is the interface that wraps the ToSql method. // -// ToSql returns a SQL representation of the Sqlizer, along with a slice of args -// as passed to e.g. database/sql.Exec. It can also return an error. +// ToSql returns a SQL representation of the Sqlizer without finalizing placeholders, along +// with a slice of args. It can also return an error. type Sqlizer interface { ToSql() (string, []interface{}, error) } -// rawSqlizer is expected to do what Sqlizer does, but without finalizing placeholders. -// This is useful for nested queries. -type rawSqlizer interface { - toSqlRaw() (string, []interface{}, error) +// SqlFinalizer is expected to do what Sqlizer does, but with finalizing placeholders. +type SqlFinalizer interface { + FinalizeSql() (string, []interface{}, error) } // Execer is the interface that wraps the Exec method. @@ -99,17 +98,17 @@ var RunnerNotSet = fmt.Errorf("cannot run; no Runner set (RunWith)") var RunnerNotQueryRunner = fmt.Errorf("cannot QueryRow; Runner is not a QueryRower") // ExecWith Execs the SQL returned by s with db. -func ExecWith(db Execer, s Sqlizer) (res sql.Result, err error) { - query, args, err := s.ToSql() +func ExecWith(db Execer, s SqlFinalizer) (res sql.Result, err error) { + query, args, err := s.FinalizeSql() if err != nil { return } return db.Exec(query, args...) } -// QueryWith Querys the SQL returned by s with db. -func QueryWith(db Queryer, s Sqlizer) (rows *sql.Rows, err error) { - query, args, err := s.ToSql() +// QueryWith Queries the SQL returned by s with db. +func QueryWith(db Queryer, s SqlFinalizer) (rows *sql.Rows, err error) { + query, args, err := s.FinalizeSql() if err != nil { return } @@ -117,8 +116,8 @@ func QueryWith(db Queryer, s Sqlizer) (rows *sql.Rows, err error) { } // QueryRowWith QueryRows the SQL returned by s with db. -func QueryRowWith(db QueryRower, s Sqlizer) RowScanner { - query, args, err := s.ToSql() +func QueryRowWith(db QueryRower, s SqlFinalizer) RowScanner { + query, args, err := s.FinalizeSql() return &Row{RowScanner: db.QueryRow(query, args...), err: err} } diff --git a/squirrel_ctx.go b/squirrel_ctx.go index c20148a..4c93a0f 100644 --- a/squirrel_ctx.go +++ b/squirrel_ctx.go @@ -1,3 +1,4 @@ +//go:build go1.8 // +build go1.8 package squirrel @@ -69,8 +70,8 @@ func (r *stdsqlCtxRunner) QueryRowContext(ctx context.Context, query string, arg } // ExecContextWith ExecContexts the SQL returned by s with db. -func ExecContextWith(ctx context.Context, db ExecerContext, s Sqlizer) (res sql.Result, err error) { - query, args, err := s.ToSql() +func ExecContextWith(ctx context.Context, db ExecerContext, s SqlFinalizer) (res sql.Result, err error) { + query, args, err := s.FinalizeSql() if err != nil { return } @@ -78,8 +79,8 @@ func ExecContextWith(ctx context.Context, db ExecerContext, s Sqlizer) (res sql. } // QueryContextWith QueryContexts the SQL returned by s with db. -func QueryContextWith(ctx context.Context, db QueryerContext, s Sqlizer) (rows *sql.Rows, err error) { - query, args, err := s.ToSql() +func QueryContextWith(ctx context.Context, db QueryerContext, s SqlFinalizer) (rows *sql.Rows, err error) { + query, args, err := s.FinalizeSql() if err != nil { return } @@ -87,7 +88,7 @@ func QueryContextWith(ctx context.Context, db QueryerContext, s Sqlizer) (rows * } // QueryRowContextWith QueryRowContexts the SQL returned by s with db. -func QueryRowContextWith(ctx context.Context, db QueryRowerContext, s Sqlizer) RowScanner { - query, args, err := s.ToSql() +func QueryRowContextWith(ctx context.Context, db QueryRowerContext, s SqlFinalizer) RowScanner { + query, args, err := s.FinalizeSql() return &Row{RowScanner: db.QueryRowContext(ctx, query, args...), err: err} } diff --git a/update.go b/update.go index 8d658d7..b89744b 100644 --- a/update.go +++ b/update.go @@ -131,7 +131,17 @@ func (d *updateData) ToSql() (sqlStr string, args []interface{}, err error) { } } - sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sql.String()) + sqlStr = sql.String() + + return +} + +func (d *updateData) FinalizeSql() (sqlStr string, args []interface{}, err error) { + sqlStr, args, err = d.ToSql() + if err != nil { + return + } + sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sqlStr) return } @@ -181,13 +191,19 @@ func (b UpdateBuilder) Scan(dest ...interface{}) error { // SQL methods -// ToSql builds the query into a SQL string and bound args. +// ToSql builds the query into a SQL string. func (b UpdateBuilder) ToSql() (string, []interface{}, error) { data := builder.GetStruct(b).(updateData) return data.ToSql() } -// MustSql builds the query into a SQL string and bound args. +// FinalizeSql builds the query into a SQL string and bound args. +func (b UpdateBuilder) FinalizeSql() (string, []interface{}, error) { + data := builder.GetStruct(b).(updateData) + return data.FinalizeSql() +} + +// MustSql builds the query into a SQL string. // It panics if there are any errors. func (b UpdateBuilder) MustSql() (string, []interface{}) { sql, args, err := b.ToSql() @@ -197,6 +213,16 @@ func (b UpdateBuilder) MustSql() (string, []interface{}) { return sql, args } +// MustFinalizeSql builds the query into a SQL string and bound args. +// It panics if there are any errors. +func (b UpdateBuilder) MustFinalizeSql() (string, []interface{}) { + sql, args, err := b.FinalizeSql() + if err != nil { + panic(err) + } + return sql, args +} + // Prefix adds an expression to the beginning of the query func (b UpdateBuilder) Prefix(sql string, args ...interface{}) UpdateBuilder { return b.PrefixExpr(Expr(sql, args...)) diff --git a/update_test.go b/update_test.go index 9951451..249b94f 100644 --- a/update_test.go +++ b/update_test.go @@ -59,10 +59,10 @@ func TestUpdateBuilderMustSql(t *testing.T) { func TestUpdateBuilderPlaceholders(t *testing.T) { b := Update("test").SetMap(Eq{"x": 1, "y": 2}) - sql, _, _ := b.PlaceholderFormat(Question).ToSql() + sql, _, _ := b.PlaceholderFormat(Question).FinalizeSql() assert.Equal(t, "UPDATE test SET x = ?, y = ?", sql) - sql, _, _ = b.PlaceholderFormat(Dollar).ToSql() + sql, _, _ = b.PlaceholderFormat(Dollar).FinalizeSql() assert.Equal(t, "UPDATE test SET x = $1, y = $2", sql) } diff --git a/where.go b/where.go index 976b63a..3a2d7b7 100644 --- a/where.go +++ b/where.go @@ -14,8 +14,6 @@ func (p wherePart) ToSql() (sql string, args []interface{}, err error) { switch pred := p.pred.(type) { case nil: // no-op - case rawSqlizer: - return pred.toSqlRaw() case Sqlizer: return pred.ToSql() case map[string]interface{}: