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, ¬hing) 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 }