From 6da7e284f16d6a02aef3d16100160f61bc945f9c Mon Sep 17 00:00:00 2001 From: Vivek Menezes Date: Tue, 4 Apr 2017 18:09:57 -0400 Subject: [PATCH] sql: ensure a Prepare referencing a table created in the same txn works fixes #14548 --- pkg/sql/executor.go | 12 ++++++------ pkg/sql/pgwire/pgwire_test.go | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/pkg/sql/executor.go b/pkg/sql/executor.go index e364be2a6caa..9a1d345cfff6 100644 --- a/pkg/sql/executor.go +++ b/pkg/sql/executor.go @@ -446,12 +446,12 @@ func (e *Executor) Prepare( // Prepare needs a transaction because it needs to retrieve db/table // descriptors for type checking. - // TODO(andrei): is this OK? If we're preparing as part of a SQL txn, how do - // we check that they're reading descriptors consistent with the txn in which - // they'll be used? - txn := client.NewTxn(e.cfg.DB) - if err := txn.SetIsolation(session.DefaultIsolationLevel); err != nil { - panic(err) + txn := session.TxnState.txn + if txn == nil { + txn = client.NewTxn(e.cfg.DB) + if err := txn.SetIsolation(session.DefaultIsolationLevel); err != nil { + panic(err) + } } txn.Proto().OrigTimestamp = e.cfg.Clock.Now() diff --git a/pkg/sql/pgwire/pgwire_test.go b/pkg/sql/pgwire/pgwire_test.go index 6299ff6aa949..a94879cd13a0 100644 --- a/pkg/sql/pgwire/pgwire_test.go +++ b/pkg/sql/pgwire/pgwire_test.go @@ -434,6 +434,42 @@ func TestPGPrepareFail(t *testing.T) { } } +// Run a Prepare referencing a table created in the same transaction. +func TestPGPrepareAfterCreateInTxn(t *testing.T) { + defer leaktest.AfterTest(t)() + s, _, _ := serverutils.StartServer(t, base.TestServerArgs{}) + defer s.Stopper().Stop() + + pgURL, cleanupFn := sqlutils.PGUrl(t, s.ServingAddr(), "TestPGPrepareAfterCreateInTxn", url.User(security.RootUser)) + defer cleanupFn() + + db, err := gosql.Open("postgres", pgURL.String()) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + tx, err := db.Begin() + if err != nil { + t.Fatal(err) + } + + if _, err := tx.Exec(` + CREATE DATABASE d; + CREATE TABLE d.kv (k CHAR PRIMARY KEY, v CHAR); +`); err != nil { + t.Fatal(err) + } + + if _, err := tx.Prepare(`INSERT INTO d.kv (k,v) VALUES ($1, $2);`); err != nil { + t.Fatal(err) + } + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } +} + type preparedQueryTest struct { qargs []interface{} results [][]interface{}