Skip to the content.

Prepared Statements

By default the goqu will interpolate all parameters, if you do not want to have values interpolated you can use the Prepared method to prevent this.

Note For the examples all placeholders are ? this will be dialect specific when using other examples (e.g. Postgres $1, $2...)


preparedDs := db.From("items").Prepared(true)

sql, args, _ := preparedDs.Where(goqu.Ex{
	"col1": "a",
	"col2": 1,
	"col3": true,
	"col4": false,
	"col5": []string{"a", "b", "c"},
}).ToSQL()
fmt.Println(sql, args)

sql, args, _ = preparedDs.Insert().Rows(
	goqu.Record{"name": "Test1", "address": "111 Test Addr"},
	goqu.Record{"name": "Test2", "address": "112 Test Addr"},
).ToSQL()
fmt.Println(sql, args)

sql, args, _ = preparedDs.Update().Set(
	goqu.Record{"name": "Test", "address": "111 Test Addr"},
).ToSQL()
fmt.Println(sql, args)

sql, args, _ = preparedDs.
	Delete().
	Where(goqu.Ex{"id": goqu.Op{"gt": 10}}).
	ToSQL()
fmt.Println(sql, args)

// Output:
// SELECT * FROM "items" WHERE (("col1" = ?) AND ("col2" = ?) AND ("col3" IS TRUE) AND ("col4" IS FALSE) AND ("col5" IN (?, ?, ?))) [a 1 a b c]
// INSERT INTO "items" ("address", "name") VALUES (?, ?), (?, ?) [111 Test Addr Test1 112 Test Addr Test2]
// UPDATE "items" SET "address"=?,"name"=? [111 Test Addr Test]
// DELETE FROM "items" WHERE ("id" > ?) [10]

When setting prepared to true executing the SQL using the different querying methods will also use the non-interpolated SQL also.

var items []Item
sql, args, _ := db.From("items").Prepared(true).Where(goqu.Ex{
	"col1": "a",
	"col2": 1,
}).ScanStructs(&items)

//Is the same as
db.ScanStructs(&items, `SELECT * FROM "items" WHERE (("col1" = ?) AND ("col2" = ?))`,  "a", 1)

Unsigned integers

Unsigned integer values (uint, uint8…uint64) are supported in both interpolated and prepared queries.

Whether the database accepts a value that large depends on the driver and the column type. Many databases (for example SQL Server BIGINT, PostgreSQL BIGINT) only store signed 64-bit integers, so such a value is typically rejected by the database or the driver rather than by goqu.

Other value types

Values of types goqu has no built-in mapping for (for example structs, maps, and arrays such as a uuid.UUID) behave differently depending on the mode:

Functions, channels and complex numbers can never be bound by a driver, so they result in an encode error in both modes.

Byte slices

Interpolated []byte values are written as a string literal when they are valid UTF-8, and as a binary (hex) literal otherwise, using the dialect’s BinaryLiteralPrefix and BinaryLiteralSuffix (X'28fa' by default, decode('28fa', 'hex') for postgres, 0x28fa for sqlserver). The postgres and sqlserver dialects also use a binary literal when the bytes contain a NUL byte, as it cannot be part of a text literal.

NOTE Binary data that is valid UTF-8 and has no NUL byte is still written as a string, so a value containing a backslash is read by PostgreSQL as a bytea escape sequence. When you store arbitrary binary data in a bytea column, use Prepared(true) or pass the value as a hex literal yourself.