github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/lib/pq/copy_test.go (about)

     1  package pq
     2  
     3  import (
     4  	"bytes"
     5  	"database/sql"
     6  	"database/sql/driver"
     7  	"strings"
     8  	"testing"
     9  )
    10  
    11  func TestCopyInStmt(t *testing.T) {
    12  	var stmt string
    13  	stmt = CopyIn("table name")
    14  	if stmt != `COPY "table name" () FROM STDIN` {
    15  		t.Fatal(stmt)
    16  	}
    17  
    18  	stmt = CopyIn("table name", "column 1", "column 2")
    19  	if stmt != `COPY "table name" ("column 1", "column 2") FROM STDIN` {
    20  		t.Fatal(stmt)
    21  	}
    22  
    23  	stmt = CopyIn(`table " name """`, `co"lumn""`)
    24  	if stmt != `COPY "table "" name """"""" ("co""lumn""""") FROM STDIN` {
    25  		t.Fatal(stmt)
    26  	}
    27  }
    28  
    29  func TestCopyInSchemaStmt(t *testing.T) {
    30  	var stmt string
    31  	stmt = CopyInSchema("schema name", "table name")
    32  	if stmt != `COPY "schema name"."table name" () FROM STDIN` {
    33  		t.Fatal(stmt)
    34  	}
    35  
    36  	stmt = CopyInSchema("schema name", "table name", "column 1", "column 2")
    37  	if stmt != `COPY "schema name"."table name" ("column 1", "column 2") FROM STDIN` {
    38  		t.Fatal(stmt)
    39  	}
    40  
    41  	stmt = CopyInSchema(`schema " name """`, `table " name """`, `co"lumn""`)
    42  	if stmt != `COPY "schema "" name """"""".`+
    43  		`"table "" name """"""" ("co""lumn""""") FROM STDIN` {
    44  		t.Fatal(stmt)
    45  	}
    46  }
    47  
    48  func TestCopyInMultipleValues(t *testing.T) {
    49  	db := openTestConn(t)
    50  	defer db.Close()
    51  
    52  	txn, err := db.Begin()
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  	defer txn.Rollback()
    57  
    58  	_, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)")
    59  	if err != nil {
    60  		t.Fatal(err)
    61  	}
    62  
    63  	stmt, err := txn.Prepare(CopyIn("temp", "a", "b"))
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  
    68  	longString := strings.Repeat("#", 500)
    69  
    70  	for i := 0; i < 500; i++ {
    71  		_, err = stmt.Exec(int64(i), longString)
    72  		if err != nil {
    73  			t.Fatal(err)
    74  		}
    75  	}
    76  
    77  	_, err = stmt.Exec()
    78  	if err != nil {
    79  		t.Fatal(err)
    80  	}
    81  
    82  	err = stmt.Close()
    83  	if err != nil {
    84  		t.Fatal(err)
    85  	}
    86  
    87  	var num int
    88  	err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num)
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  
    93  	if num != 500 {
    94  		t.Fatalf("expected 500 items, not %d", num)
    95  	}
    96  }
    97  
    98  func TestCopyInRaiseStmtTrigger(t *testing.T) {
    99  	db := openTestConn(t)
   100  	defer db.Close()
   101  
   102  	if getServerVersion(t, db) < 90000 {
   103  		var exists int
   104  		err := db.QueryRow("SELECT 1 FROM pg_language WHERE lanname = 'plpgsql'").Scan(&exists)
   105  		if err == sql.ErrNoRows {
   106  			t.Skip("language PL/PgSQL does not exist; skipping TestCopyInRaiseStmtTrigger")
   107  		} else if err != nil {
   108  			t.Fatal(err)
   109  		}
   110  	}
   111  
   112  	txn, err := db.Begin()
   113  	if err != nil {
   114  		t.Fatal(err)
   115  	}
   116  	defer txn.Rollback()
   117  
   118  	_, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)")
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  
   123  	_, err = txn.Exec(`
   124  			CREATE OR REPLACE FUNCTION pg_temp.temptest()
   125  			RETURNS trigger AS 
   126  			$BODY$ begin
   127  				raise notice 'Hello world';
   128  				return new;
   129  			end $BODY$
   130  			LANGUAGE plpgsql`)
   131  	if err != nil {
   132  		t.Fatal(err)
   133  	}
   134  
   135  	_, err = txn.Exec(`
   136  			CREATE TRIGGER temptest_trigger
   137  			BEFORE INSERT
   138  			ON temp 
   139  			FOR EACH ROW
   140  			EXECUTE PROCEDURE pg_temp.temptest()`)
   141  	if err != nil {
   142  		t.Fatal(err)
   143  	}
   144  
   145  	stmt, err := txn.Prepare(CopyIn("temp", "a", "b"))
   146  	if err != nil {
   147  		t.Fatal(err)
   148  	}
   149  
   150  	longString := strings.Repeat("#", 500)
   151  
   152  	_, err = stmt.Exec(int64(1), longString)
   153  	if err != nil {
   154  		t.Fatal(err)
   155  	}
   156  
   157  	_, err = stmt.Exec()
   158  	if err != nil {
   159  		t.Fatal(err)
   160  	}
   161  
   162  	err = stmt.Close()
   163  	if err != nil {
   164  		t.Fatal(err)
   165  	}
   166  
   167  	var num int
   168  	err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num)
   169  	if err != nil {
   170  		t.Fatal(err)
   171  	}
   172  
   173  	if num != 1 {
   174  		t.Fatalf("expected 1 items, not %d", num)
   175  	}
   176  }
   177  
   178  func TestCopyInTypes(t *testing.T) {
   179  	db := openTestConn(t)
   180  	defer db.Close()
   181  
   182  	txn, err := db.Begin()
   183  	if err != nil {
   184  		t.Fatal(err)
   185  	}
   186  	defer txn.Rollback()
   187  
   188  	_, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER, text VARCHAR, blob BYTEA, nothing VARCHAR)")
   189  	if err != nil {
   190  		t.Fatal(err)
   191  	}
   192  
   193  	stmt, err := txn.Prepare(CopyIn("temp", "num", "text", "blob", "nothing"))
   194  	if err != nil {
   195  		t.Fatal(err)
   196  	}
   197  
   198  	_, err = stmt.Exec(int64(1234567890), "Héllö\n ☃!\r\t\\", []byte{0, 255, 9, 10, 13}, nil)
   199  	if err != nil {
   200  		t.Fatal(err)
   201  	}
   202  
   203  	_, err = stmt.Exec()
   204  	if err != nil {
   205  		t.Fatal(err)
   206  	}
   207  
   208  	err = stmt.Close()
   209  	if err != nil {
   210  		t.Fatal(err)
   211  	}
   212  
   213  	var num int
   214  	var text string
   215  	var blob []byte
   216  	var nothing sql.NullString
   217  
   218  	err = txn.QueryRow("SELECT * FROM temp").Scan(&num, &text, &blob, &nothing)
   219  	if err != nil {
   220  		t.Fatal(err)
   221  	}
   222  
   223  	if num != 1234567890 {
   224  		t.Fatal("unexpected result", num)
   225  	}
   226  	if text != "Héllö\n ☃!\r\t\\" {
   227  		t.Fatal("unexpected result", text)
   228  	}
   229  	if bytes.Compare(blob, []byte{0, 255, 9, 10, 13}) != 0 {
   230  		t.Fatal("unexpected result", blob)
   231  	}
   232  	if nothing.Valid {
   233  		t.Fatal("unexpected result", nothing.String)
   234  	}
   235  }
   236  
   237  func TestCopyInWrongType(t *testing.T) {
   238  	db := openTestConn(t)
   239  	defer db.Close()
   240  
   241  	txn, err := db.Begin()
   242  	if err != nil {
   243  		t.Fatal(err)
   244  	}
   245  	defer txn.Rollback()
   246  
   247  	_, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)")
   248  	if err != nil {
   249  		t.Fatal(err)
   250  	}
   251  
   252  	stmt, err := txn.Prepare(CopyIn("temp", "num"))
   253  	if err != nil {
   254  		t.Fatal(err)
   255  	}
   256  	defer stmt.Close()
   257  
   258  	_, err = stmt.Exec("Héllö\n ☃!\r\t\\")
   259  	if err != nil {
   260  		t.Fatal(err)
   261  	}
   262  
   263  	_, err = stmt.Exec()
   264  	if err == nil {
   265  		t.Fatal("expected error")
   266  	}
   267  	if pge := err.(*Error); pge.Code.Name() != "invalid_text_representation" {
   268  		t.Fatalf("expected 'invalid input syntax for integer' error, got %s (%+v)", pge.Code.Name(), pge)
   269  	}
   270  }
   271  
   272  func TestCopyOutsideOfTxnError(t *testing.T) {
   273  	db := openTestConn(t)
   274  	defer db.Close()
   275  
   276  	_, err := db.Prepare(CopyIn("temp", "num"))
   277  	if err == nil {
   278  		t.Fatal("COPY outside of transaction did not return an error")
   279  	}
   280  	if err != errCopyNotSupportedOutsideTxn {
   281  		t.Fatalf("expected %s, got %s", err, err.Error())
   282  	}
   283  }
   284  
   285  func TestCopyInBinaryError(t *testing.T) {
   286  	db := openTestConn(t)
   287  	defer db.Close()
   288  
   289  	txn, err := db.Begin()
   290  	if err != nil {
   291  		t.Fatal(err)
   292  	}
   293  	defer txn.Rollback()
   294  
   295  	_, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)")
   296  	if err != nil {
   297  		t.Fatal(err)
   298  	}
   299  	_, err = txn.Prepare("COPY temp (num) FROM STDIN WITH binary")
   300  	if err != errBinaryCopyNotSupported {
   301  		t.Fatalf("expected %s, got %+v", errBinaryCopyNotSupported, err)
   302  	}
   303  	// check that the protocol is in a valid state
   304  	err = txn.Rollback()
   305  	if err != nil {
   306  		t.Fatal(err)
   307  	}
   308  }
   309  
   310  func TestCopyFromError(t *testing.T) {
   311  	db := openTestConn(t)
   312  	defer db.Close()
   313  
   314  	txn, err := db.Begin()
   315  	if err != nil {
   316  		t.Fatal(err)
   317  	}
   318  	defer txn.Rollback()
   319  
   320  	_, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)")
   321  	if err != nil {
   322  		t.Fatal(err)
   323  	}
   324  	_, err = txn.Prepare("COPY temp (num) TO STDOUT")
   325  	if err != errCopyToNotSupported {
   326  		t.Fatalf("expected %s, got %+v", errCopyToNotSupported, err)
   327  	}
   328  	// check that the protocol is in a valid state
   329  	err = txn.Rollback()
   330  	if err != nil {
   331  		t.Fatal(err)
   332  	}
   333  }
   334  
   335  func TestCopySyntaxError(t *testing.T) {
   336  	db := openTestConn(t)
   337  	defer db.Close()
   338  
   339  	txn, err := db.Begin()
   340  	if err != nil {
   341  		t.Fatal(err)
   342  	}
   343  	defer txn.Rollback()
   344  
   345  	_, err = txn.Prepare("COPY ")
   346  	if err == nil {
   347  		t.Fatal("expected error")
   348  	}
   349  	if pge := err.(*Error); pge.Code.Name() != "syntax_error" {
   350  		t.Fatalf("expected syntax error, got %s (%+v)", pge.Code.Name(), pge)
   351  	}
   352  	// check that the protocol is in a valid state
   353  	err = txn.Rollback()
   354  	if err != nil {
   355  		t.Fatal(err)
   356  	}
   357  }
   358  
   359  // Tests for connection errors in copyin.resploop()
   360  func TestCopyRespLoopConnectionError(t *testing.T) {
   361  	db := openTestConn(t)
   362  	defer db.Close()
   363  
   364  	txn, err := db.Begin()
   365  	if err != nil {
   366  		t.Fatal(err)
   367  	}
   368  	defer txn.Rollback()
   369  
   370  	var pid int
   371  	err = txn.QueryRow("SELECT pg_backend_pid()").Scan(&pid)
   372  	if err != nil {
   373  		t.Fatal(err)
   374  	}
   375  
   376  	_, err = txn.Exec("CREATE TEMP TABLE temp (a int)")
   377  	if err != nil {
   378  		t.Fatal(err)
   379  	}
   380  
   381  	stmt, err := txn.Prepare(CopyIn("temp", "a"))
   382  	if err != nil {
   383  		t.Fatal(err)
   384  	}
   385  	defer stmt.Close()
   386  
   387  	_, err = db.Exec("SELECT pg_terminate_backend($1)", pid)
   388  	if err != nil {
   389  		t.Fatal(err)
   390  	}
   391  
   392  	if getServerVersion(t, db) < 90500 {
   393  		// We have to try and send something over, since postgres before
   394  		// version 9.5 won't process SIGTERMs while it's waiting for
   395  		// CopyData/CopyEnd messages; see tcop/postgres.c.
   396  		_, err = stmt.Exec(1)
   397  		if err != nil {
   398  			t.Fatal(err)
   399  		}
   400  	}
   401  	_, err = stmt.Exec()
   402  	if err == nil {
   403  		t.Fatalf("expected error")
   404  	}
   405  	pge, ok := err.(*Error)
   406  	if !ok {
   407  		if err == driver.ErrBadConn {
   408  			// likely an EPIPE
   409  		} else {
   410  			t.Fatalf("expected *pq.Error or driver.ErrBadConn, got %+#v", err)
   411  		}
   412  	} else if pge.Code.Name() != "admin_shutdown" {
   413  		t.Fatalf("expected admin_shutdown, got %s", pge.Code.Name())
   414  	}
   415  
   416  	_ = stmt.Close()
   417  }
   418  
   419  func BenchmarkCopyIn(b *testing.B) {
   420  	db := openTestConn(b)
   421  	defer db.Close()
   422  
   423  	txn, err := db.Begin()
   424  	if err != nil {
   425  		b.Fatal(err)
   426  	}
   427  	defer txn.Rollback()
   428  
   429  	_, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)")
   430  	if err != nil {
   431  		b.Fatal(err)
   432  	}
   433  
   434  	stmt, err := txn.Prepare(CopyIn("temp", "a", "b"))
   435  	if err != nil {
   436  		b.Fatal(err)
   437  	}
   438  
   439  	for i := 0; i < b.N; i++ {
   440  		_, err = stmt.Exec(int64(i), "hello world!")
   441  		if err != nil {
   442  			b.Fatal(err)
   443  		}
   444  	}
   445  
   446  	_, err = stmt.Exec()
   447  	if err != nil {
   448  		b.Fatal(err)
   449  	}
   450  
   451  	err = stmt.Close()
   452  	if err != nil {
   453  		b.Fatal(err)
   454  	}
   455  
   456  	var num int
   457  	err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num)
   458  	if err != nil {
   459  		b.Fatal(err)
   460  	}
   461  
   462  	if num != b.N {
   463  		b.Fatalf("expected %d items, not %d", b.N, num)
   464  	}
   465  }