TestWriteWithSimpleProtocol is a regression test for a bug where Write operations failed with "invalid input syntax for type integer: TUPLE_OPERATION_WRITE" (SQLSTATE 22P02) when the connection uses PostgreSQL's simple query protocol (e.g. behind PgBouncer in transaction pooling mode). Setting Defau
(t *testing.T)
| 119 | // the same encoding path, reproducing the failure without a real PgBouncer instance. |
| 120 | // See: https://github.com/openfga/openfga/issues/3011 |
| 121 | func TestWriteWithSimpleProtocol(t *testing.T) { |
| 122 | testDatastore := storagefixtures.RunDatastoreTestContainer(t, "postgres") |
| 123 | |
| 124 | uri := testDatastore.GetConnectionURI(true) |
| 125 | cfg := sqlcommon.NewConfig() |
| 126 | |
| 127 | // Build the pool config the same way New() does, then override the query |
| 128 | // execution mode to SimpleProtocol to mimic PgBouncer transaction-pooling mode. |
| 129 | poolCfg, err := parseConfig(uri, false, cfg) |
| 130 | require.NoError(t, err) |
| 131 | poolCfg.ConnConfig.DefaultQueryExecMode = pgx.QueryExecModeSimpleProtocol |
| 132 | |
| 133 | primaryDB, err := pgxpool.NewWithConfig(context.Background(), poolCfg) |
| 134 | require.NoError(t, err) |
| 135 | |
| 136 | ds, err := NewWithDB(primaryDB, nil, cfg) |
| 137 | require.NoError(t, err) |
| 138 | defer ds.Close() |
| 139 | |
| 140 | ctx := context.Background() |
| 141 | storeID := ulid.Make().String() |
| 142 | |
| 143 | writes := []*openfgav1.TupleKey{ |
| 144 | {Object: "document:1", Relation: "viewer", User: "user:alice"}, |
| 145 | {Object: "document:2", Relation: "editor", User: "user:bob"}, |
| 146 | } |
| 147 | |
| 148 | err = ds.Write(ctx, storeID, nil, writes) |
| 149 | require.NoError(t, err, "Write must succeed with SimpleProtocol (PgBouncer regression)") |
| 150 | |
| 151 | deletes := []*openfgav1.TupleKeyWithoutCondition{ |
| 152 | {Object: "document:1", Relation: "viewer", User: "user:alice"}, |
| 153 | } |
| 154 | err = ds.Write(ctx, storeID, deletes, nil) |
| 155 | require.NoError(t, err, "Delete must succeed with SimpleProtocol (PgBouncer regression)") |
| 156 | |
| 157 | tk, err := ds.ReadUserTuple(ctx, storeID, storage.ReadUserTupleFilter{ |
| 158 | Object: "document:2", |
| 159 | Relation: "editor", |
| 160 | User: "user:bob", |
| 161 | }, storage.ReadUserTupleOptions{}) |
| 162 | require.NoError(t, err) |
| 163 | require.Equal(t, "document:2", tk.GetKey().GetObject()) |
| 164 | } |
| 165 | |
| 166 | func TestPostgresDatastoreStartup(t *testing.T) { |
| 167 | primaryDatastore := storagefixtures.RunDatastoreTestContainer(t, "postgres") |
nothing calls this directly
no test coverage detected
searching dependent graphs…