Skip to content

SQL placeholders

Introduction

go-pg recognizes ? in queries as a placeholder and replaces it with a param. Before replacing go-pg escapes param values according to PostgreSQL rules:

  • All params are properly quoted against SQL injections.
  • Null byte '0' is removed.
  • JSON/JSONB gets \u0000 escaped as \\u0000.

Basic placeholders

To use basic placeholders:

// SELECT 'foo', 'bar'
db.ColumnExpr("?, ?", 'foo', 'bar')

To use positional placeholders:

// SELECT 'foo', 'bar', 'foo'
db.ColumnExpr("?0, ?1, ?0", 'foo', 'bar')

Named placeholders

To name your placeholders, define a struct with required fields:

type Params struct {
    X int
    Y int
}

params := &Params{
    X: 1,
    Y: 2,
}
// SELECT 1 + 2
db.ColumnExpr("?x + ?y", params)

You can even use methods that return a singe value as a placeholder:

func (p *Params) Sum() int {
    return p.X + p.Y
}

// SELECT 1 + 2 = 3
db.ColumnExpr("?x + ?y = ?Sum", params)

PostgreSQL identifiers and disabling quotation

To quote PostgreSQL identifiers (column or table names), use pg.Ident:

// "foo" = 'bar'
db.ColumnExpr("? = ?", pg.Ident("foo"), "bar")

To disable quotation altogether, use pg.Safe:

// FROM (generate_series(0, 10)) AS foo
db.TableExpr("(?) AS foo", pg.Safe("generate_series(0, 10)"))

PostgreSQL IN

To use IN with multiple values, use pg.In:

// WHERE foo IN ('hello', 'world')
db.Where("foo IN (?)", pg.In([]string{"hello", "world"}))

To use IN with composite (multiple) keys:

// WHERE (foo, bar) IN (('hello', 'world'), ('hell', 'yeah'))
db.Where("(foo, bar) IN (?)", pg.InMulti(
    []string{"hello", "world"},
    []string{"hell", "yeah"},
))

PostgreSQL Arrays

To work with PostgreSQL arrays, use pg.Array:

// WHERE foo @> '{"foo","bar"}'
db.Where("foo @> ?", pg.Array([]string{"foo", "bar"}))

Global DB placeholders

go-pg also supports global DB placeholders:

// db1 and db2 share the same connection pool.
db1 := db.WithParam("SCHEMA", "foo")
db2 := db.WithParam("SCHEMA", "bar")

// FROM foo.table
db1.TableExpr("?SCHEMA.table")

// FROM bar.table
db2.TableExpr("?SCHEMA.table")

go-pg/sharding uses this feature to implement sharding using PostgreSQL schemas.