package main
import (
"log"
"github.com/jackc/pgtype"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/stdlib"
"github.com/jmoiron/sqlx"
func main() {
dns := "user=tester host=localhost dbname=tester sslmode=disable"
connConfig, _ := pgx.ParseConfig(dns)
connConfig.PreferSimpleProtocol = true
conn, err := sqlx.Open("pgx", stdlib.RegisterConnConfig(connConfig))
//conn, err := pgx.ConnectConfig(ctx, connConfig)
if err != nil {
log.Fatal(err)
_, err = conn.Exec(`drop table if exists pgx514;`)
if err != nil {
log.Fatal(err)
_, err = conn.Exec(`create table pgx514 (id serial primary key, data jsonb not null);`)
if err != nil {
log.Fatal(err)
dataJSON := &pgtype.JSON{Bytes: []byte(`{"foo": "bar"}`), Status: pgtype.Present}
commandTag, err := conn.Exec("insert into pgx514(data) values($1)", dataJSON)
if err == nil {
log.Println("pgtype.JSON", commandTag)
} else {
log.Println("pgtype.JSON", err)
dataBytes := []byte(`{"foo": "bar"}`)
commandTag, err = conn.Exec("insert into pgx514(data) values($1)", dataBytes)
if err == nil {
log.Println("[]byte", commandTag)
} else {
log.Println("[]byte", err)
This is an edge case with the simple protocol and database/sql
.
One problem is that when using the simple protocol is the destination PostgreSQL type is unknown. The type has to be determined by completely by the Go side. What is a []byte
encoded as? pgx considers it bytea
which means it is hex encoded. Use a string
for raw JSON data instead of []byte
.
The pgtype.JSON
case is more complicated. (As an aside, use pgtype.JSONB
for PostgreSQL jsonb
.) When using the pgx native interface there is a special case to handle pgtype.JSON
.
https://github.com/jackc/pgx/blob/eeda0368e66fafed0a3db500108bdb87b657a88a/values.go#L40
However, when using database/sql
, pgx can't see that it is a pgtype.JSON
, database/sql
has already called Value()
and converted it to a []byte
. And Value()
returns []byte
for compatibility with lib/pq
and json.RawMessage
(jackc/pgx#409).
So I'm not sure if this exact case can be solved without breaking something else. But you can use string
, sql.NullString
, or pgtype.Text
instead.
@aethanol It's still an issue with v5. Same fundamental problem though the internal implementation details differ.
One problem is that when using the simple protocol is the destination PostgreSQL type is unknown. The type has to be determined by completely by the Go side. What is a []byte encoded as? pgx considers it bytea which means it is hex encoded. Use a string for raw JSON data instead of []byte.
JSONB query support with pgx/v4 and prefer_simple_protocol results in ERROR: invalid input syntax for type json (SQLSTATE 22P02)
sqlc-dev/sqlc#2085
So I'm not sure if this exact case can be solved without breaking something else. But you can use string
, sql.NullString
, or pgtype.Text
instead.
Thanks for the explanation @jackc.
I solved my issue by doing something like this:
-- schema.sql
CREATE TABLE IF NOT EXISTS my_table(
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
my_data jsonb
-- query.sql
-- name: InsertMyTable :exec
INSERT INTO my_table (data)
VALUES ((@my_data::text)::jsonb);
Please let me know if I missed something.