github.com/snowflakedb/gosnowflake@v1.9.0/htap_test.go (about) 1 package gosnowflake 2 3 import ( 4 "context" 5 "database/sql/driver" 6 "fmt" 7 "reflect" 8 "strconv" 9 "strings" 10 "testing" 11 "time" 12 ) 13 14 func TestSortingByPriority(t *testing.T) { 15 qcc := (&queryContextCache{}).init() 16 sc := htapTestSnowflakeConn() 17 18 qceA := queryContextEntry{ID: 12, Timestamp: 123, Priority: 7, Context: "a"} 19 qceB := queryContextEntry{ID: 13, Timestamp: 124, Priority: 9, Context: "b"} 20 qceC := queryContextEntry{ID: 14, Timestamp: 125, Priority: 6, Context: "c"} 21 qceD := queryContextEntry{ID: 15, Timestamp: 126, Priority: 8, Context: "d"} 22 23 t.Run("Add to empty cache", func(t *testing.T) { 24 qcc.add(sc, qceA) 25 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceA}) { 26 t.Fatalf("no entries added to cache. %v", qcc.entries) 27 } 28 }) 29 t.Run("Add another entry with different id, timestamp and priority - greater priority", func(t *testing.T) { 30 qcc.add(sc, qceB) 31 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceA, qceB}) { 32 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 33 } 34 }) 35 t.Run("Add another entry with different id, timestamp and priority - lesser priority", func(t *testing.T) { 36 qcc.add(sc, qceC) 37 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceC, qceA, qceB}) { 38 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 39 } 40 }) 41 t.Run("Add another entry with different id, timestamp and priority - priority in the middle", func(t *testing.T) { 42 qcc.add(sc, qceD) 43 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceC, qceA, qceD, qceB}) { 44 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 45 } 46 }) 47 } 48 49 func TestAddingQcesWithTheSameIdAndLaterTimestamp(t *testing.T) { 50 qcc := (&queryContextCache{}).init() 51 sc := htapTestSnowflakeConn() 52 53 qceA := queryContextEntry{ID: 12, Timestamp: 123, Priority: 7, Context: "a"} 54 qceB := queryContextEntry{ID: 13, Timestamp: 124, Priority: 9, Context: "b"} 55 qceC := queryContextEntry{ID: 12, Timestamp: 125, Priority: 6, Context: "c"} 56 qceD := queryContextEntry{ID: 12, Timestamp: 126, Priority: 6, Context: "d"} 57 58 t.Run("Add to empty cache", func(t *testing.T) { 59 qcc.add(sc, qceA) 60 qcc.add(sc, qceB) 61 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceA, qceB}) { 62 t.Fatalf("no entries added to cache. %v", qcc.entries) 63 } 64 }) 65 t.Run("Add another entry with different priority", func(t *testing.T) { 66 qcc.add(sc, qceC) 67 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceC, qceB}) { 68 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 69 } 70 }) 71 t.Run("Add another entry with same priority", func(t *testing.T) { 72 qcc.add(sc, qceD) 73 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceD, qceB}) { 74 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 75 } 76 }) 77 } 78 79 func TestAddingQcesWithTheSameIdAndSameTimestamp(t *testing.T) { 80 qcc := (&queryContextCache{}).init() 81 sc := htapTestSnowflakeConn() 82 83 qceA := queryContextEntry{ID: 12, Timestamp: 123, Priority: 7, Context: "a"} 84 qceB := queryContextEntry{ID: 13, Timestamp: 124, Priority: 9, Context: "b"} 85 qceC := queryContextEntry{ID: 12, Timestamp: 123, Priority: 6, Context: "c"} 86 qceD := queryContextEntry{ID: 12, Timestamp: 123, Priority: 6, Context: "d"} 87 88 t.Run("Add to empty cache", func(t *testing.T) { 89 qcc.add(sc, qceA) 90 qcc.add(sc, qceB) 91 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceA, qceB}) { 92 t.Fatalf("no entries added to cache. %v", qcc.entries) 93 } 94 }) 95 t.Run("Add another entry with different priority", func(t *testing.T) { 96 qcc.add(sc, qceC) 97 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceC, qceB}) { 98 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 99 } 100 }) 101 t.Run("Add another entry with same priority", func(t *testing.T) { 102 qcc.add(sc, qceD) 103 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceC, qceB}) { 104 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 105 } 106 }) 107 } 108 109 func TestAddingQcesWithTheSameIdAndEarlierTimestamp(t *testing.T) { 110 qcc := (&queryContextCache{}).init() 111 sc := htapTestSnowflakeConn() 112 113 qceA := queryContextEntry{ID: 12, Timestamp: 123, Priority: 7, Context: "a"} 114 qceB := queryContextEntry{ID: 13, Timestamp: 124, Priority: 9, Context: "b"} 115 qceC := queryContextEntry{ID: 12, Timestamp: 122, Priority: 6, Context: "c"} 116 qceD := queryContextEntry{ID: 12, Timestamp: 122, Priority: 7, Context: "d"} 117 118 t.Run("Add to empty cache", func(t *testing.T) { 119 qcc.add(sc, qceA) 120 qcc.add(sc, qceB) 121 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceA, qceB}) { 122 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 123 } 124 }) 125 t.Run("Add another entry with different priority", func(t *testing.T) { 126 qcc.add(sc, qceC) 127 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceA, qceB}) { 128 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 129 } 130 }) 131 t.Run("Add another entry with same priority", func(t *testing.T) { 132 qcc.add(sc, qceD) 133 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceA, qceB}) { 134 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 135 } 136 }) 137 } 138 139 func TestAddingQcesWithDifferentId(t *testing.T) { 140 qcc := (&queryContextCache{}).init() 141 sc := htapTestSnowflakeConn() 142 143 qceA := queryContextEntry{ID: 12, Timestamp: 123, Priority: 7, Context: "a"} 144 qceB := queryContextEntry{ID: 13, Timestamp: 124, Priority: 9, Context: "b"} 145 qceC := queryContextEntry{ID: 14, Timestamp: 122, Priority: 7, Context: "c"} 146 qceD := queryContextEntry{ID: 15, Timestamp: 122, Priority: 6, Context: "d"} 147 148 t.Run("Add to empty cache", func(t *testing.T) { 149 qcc.add(sc, qceA) 150 qcc.add(sc, qceB) 151 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceA, qceB}) { 152 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 153 } 154 }) 155 t.Run("Add another entry with same priority", func(t *testing.T) { 156 qcc.add(sc, qceC) 157 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceC, qceB}) { 158 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 159 } 160 }) 161 t.Run("Add another entry with different priority", func(t *testing.T) { 162 qcc.add(sc, qceD) 163 if !reflect.DeepEqual(qcc.entries, []queryContextEntry{qceD, qceC, qceB}) { 164 t.Fatalf("unexpected qcc entries. %v", qcc.entries) 165 } 166 }) 167 } 168 169 func TestAddingQueryContextCacheEntry(t *testing.T) { 170 runSnowflakeConnTest(t, func(sct *SCTest) { 171 t.Run("First query (may be on empty cache)", func(t *testing.T) { 172 entriesBefore := make([]queryContextEntry, len(sct.sc.queryContextCache.entries)) 173 copy(entriesBefore, sct.sc.queryContextCache.entries) 174 sct.mustQuery("SELECT 1", nil) 175 entriesAfter := sct.sc.queryContextCache.entries 176 177 if !containsNewEntries(entriesAfter, entriesBefore) { 178 t.Error("no new entries added to the query context cache") 179 } 180 }) 181 182 t.Run("Second query (cache should not be empty)", func(t *testing.T) { 183 entriesBefore := make([]queryContextEntry, len(sct.sc.queryContextCache.entries)) 184 copy(entriesBefore, sct.sc.queryContextCache.entries) 185 if len(entriesBefore) == 0 { 186 t.Fatalf("cache should not be empty after first query") 187 } 188 sct.mustQuery("SELECT 2", nil) 189 entriesAfter := sct.sc.queryContextCache.entries 190 191 if !containsNewEntries(entriesAfter, entriesBefore) { 192 t.Error("no new entries added to the query context cache") 193 } 194 }) 195 }) 196 } 197 198 func containsNewEntries(entriesAfter []queryContextEntry, entriesBefore []queryContextEntry) bool { 199 if len(entriesAfter) > len(entriesBefore) { 200 return true 201 } 202 203 for _, entryAfter := range entriesAfter { 204 for _, entryBefore := range entriesBefore { 205 if !reflect.DeepEqual(entryBefore, entryAfter) { 206 return true 207 } 208 } 209 } 210 211 return false 212 } 213 214 func TestPruneBySessionValue(t *testing.T) { 215 qce1 := queryContextEntry{1, 1, 1, ""} 216 qce2 := queryContextEntry{2, 2, 2, ""} 217 qce3 := queryContextEntry{3, 3, 3, ""} 218 219 testcases := []struct { 220 size string 221 expected []queryContextEntry 222 }{ 223 { 224 size: "1", 225 expected: []queryContextEntry{qce1}, 226 }, 227 { 228 size: "2", 229 expected: []queryContextEntry{qce1, qce2}, 230 }, 231 { 232 size: "3", 233 expected: []queryContextEntry{qce1, qce2, qce3}, 234 }, 235 { 236 size: "4", 237 expected: []queryContextEntry{qce1, qce2, qce3}, 238 }, 239 } 240 241 for _, tc := range testcases { 242 t.Run(tc.size, func(t *testing.T) { 243 sc := &snowflakeConn{ 244 cfg: &Config{ 245 Params: map[string]*string{ 246 queryContextCacheSizeParamName: &tc.size, 247 }, 248 }, 249 } 250 251 qcc := (&queryContextCache{}).init() 252 253 qcc.add(sc, qce1) 254 qcc.add(sc, qce2) 255 qcc.add(sc, qce3) 256 257 if !reflect.DeepEqual(qcc.entries, tc.expected) { 258 t.Errorf("unexpected cache entries. expected: %v, got: %v", tc.expected, qcc.entries) 259 } 260 }) 261 } 262 } 263 264 func TestPruneByDefaultValue(t *testing.T) { 265 qce1 := queryContextEntry{1, 1, 1, ""} 266 qce2 := queryContextEntry{2, 2, 2, ""} 267 qce3 := queryContextEntry{3, 3, 3, ""} 268 qce4 := queryContextEntry{4, 4, 4, ""} 269 qce5 := queryContextEntry{5, 5, 5, ""} 270 qce6 := queryContextEntry{6, 6, 6, ""} 271 272 sc := &snowflakeConn{ 273 cfg: &Config{ 274 Params: map[string]*string{}, 275 }, 276 } 277 278 qcc := (&queryContextCache{}).init() 279 qcc.add(sc, qce1) 280 qcc.add(sc, qce2) 281 qcc.add(sc, qce3) 282 qcc.add(sc, qce4) 283 qcc.add(sc, qce5) 284 285 if len(qcc.entries) != 5 { 286 t.Fatalf("Expected 5 elements, got: %v", len(qcc.entries)) 287 } 288 289 qcc.add(sc, qce6) 290 if len(qcc.entries) != 5 { 291 t.Fatalf("Expected 5 elements, got: %v", len(qcc.entries)) 292 } 293 } 294 295 func TestNoQcesClearsCache(t *testing.T) { 296 qce1 := queryContextEntry{1, 1, 1, ""} 297 298 sc := &snowflakeConn{ 299 cfg: &Config{ 300 Params: map[string]*string{}, 301 }, 302 } 303 304 qcc := (&queryContextCache{}).init() 305 qcc.add(sc, qce1) 306 307 if len(qcc.entries) != 1 { 308 t.Fatalf("improperly inited cache") 309 } 310 311 qcc.add(sc) 312 313 if len(qcc.entries) != 0 { 314 t.Errorf("after adding empty context list cache should be cleared") 315 } 316 } 317 318 func htapTestSnowflakeConn() *snowflakeConn { 319 return &snowflakeConn{ 320 cfg: &Config{ 321 Params: map[string]*string{}, 322 }, 323 } 324 } 325 326 func TestQueryContextCacheDisabled(t *testing.T) { 327 origDsn := dsn 328 defer func() { 329 dsn = origDsn 330 }() 331 dsn += "&disableQueryContextCache=true" 332 runSnowflakeConnTest(t, func(sct *SCTest) { 333 sct.mustExec("SELECT 1", nil) 334 if len(sct.sc.queryContextCache.entries) > 0 { 335 t.Error("should not contain any entries") 336 } 337 }) 338 } 339 340 func TestHybridTablesE2E(t *testing.T) { 341 skipOnJenkins(t, "HTAP is not enabled on environment") 342 if runningOnGithubAction() && !runningOnAWS() { 343 t.Skip("HTAP is enabled only on AWS") 344 } 345 runID := time.Now().UnixMilli() 346 testDb1 := fmt.Sprintf("hybrid_db_test_%v", runID) 347 testDb2 := fmt.Sprintf("hybrid_db_test_%v_2", runID) 348 runSnowflakeConnTest(t, func(sct *SCTest) { 349 dbQuery := sct.mustQuery("SELECT CURRENT_DATABASE()", nil) 350 defer dbQuery.Close() 351 currentDb := make([]driver.Value, 1) 352 dbQuery.Next(currentDb) 353 defer func() { 354 sct.mustExec(fmt.Sprintf("USE DATABASE %v", currentDb[0]), nil) 355 sct.mustExec(fmt.Sprintf("DROP DATABASE IF EXISTS %v", testDb1), nil) 356 sct.mustExec(fmt.Sprintf("DROP DATABASE IF EXISTS %v", testDb2), nil) 357 }() 358 359 t.Run("Run tests on first database", func(t *testing.T) { 360 sct.mustExec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %v", testDb1), nil) 361 sct.mustExec("CREATE HYBRID TABLE test_hybrid_table (id INT PRIMARY KEY, text VARCHAR)", nil) 362 363 sct.mustExec("INSERT INTO test_hybrid_table VALUES (1, 'a')", nil) 364 rows := sct.mustQuery("SELECT * FROM test_hybrid_table", nil) 365 defer rows.Close() 366 row := make([]driver.Value, 2) 367 rows.Next(row) 368 if row[0] != "1" || row[1] != "a" { 369 t.Errorf("expected 1, got %v and expected a, got %v", row[0], row[1]) 370 } 371 372 sct.mustExec("INSERT INTO test_hybrid_table VALUES (2, 'b')", nil) 373 rows2 := sct.mustQuery("SELECT * FROM test_hybrid_table", nil) 374 defer rows2.Close() 375 rows2.Next(row) 376 if row[0] != "1" || row[1] != "a" { 377 t.Errorf("expected 1, got %v and expected a, got %v", row[0], row[1]) 378 } 379 rows2.Next(row) 380 if row[0] != "2" || row[1] != "b" { 381 t.Errorf("expected 2, got %v and expected b, got %v", row[0], row[1]) 382 } 383 if len(sct.sc.queryContextCache.entries) != 2 { 384 t.Errorf("expected two entries in query context cache, got: %v", sct.sc.queryContextCache.entries) 385 } 386 }) 387 t.Run("Run tests on second database", func(t *testing.T) { 388 sct.mustExec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %v", testDb2), nil) 389 sct.mustExec("CREATE HYBRID TABLE test_hybrid_table_2 (id INT PRIMARY KEY, text VARCHAR)", nil) 390 sct.mustExec("INSERT INTO test_hybrid_table_2 VALUES (3, 'c')", nil) 391 392 rows := sct.mustQuery("SELECT * FROM test_hybrid_table_2", nil) 393 defer rows.Close() 394 row := make([]driver.Value, 2) 395 rows.Next(row) 396 if row[0] != "3" || row[1] != "c" { 397 t.Errorf("expected 3, got %v and expected c, got %v", row[0], row[1]) 398 } 399 if len(sct.sc.queryContextCache.entries) != 3 { 400 t.Errorf("expected three entries in query context cache, got: %v", sct.sc.queryContextCache.entries) 401 } 402 }) 403 t.Run("Run tests on first database again", func(t *testing.T) { 404 sct.mustExec(fmt.Sprintf("USE DATABASE %v", testDb1), nil) 405 406 sct.mustExec("INSERT INTO test_hybrid_table VALUES (4, 'd')", nil) 407 408 rows := sct.mustQuery("SELECT * FROM test_hybrid_table", nil) 409 defer rows.Close() 410 if len(sct.sc.queryContextCache.entries) != 3 { 411 t.Errorf("expected three entries in query context cache, got: %v", sct.sc.queryContextCache.entries) 412 } 413 }) 414 }) 415 } 416 417 func TestHTAPOptimizations(t *testing.T) { 418 if runningOnGithubAction() { 419 t.Skip("insufficient permissions") 420 } 421 for _, useHtapOptimizations := range []bool{true, false} { 422 runSnowflakeConnTest(t, func(sct *SCTest) { 423 t.Run("useHtapOptimizations="+strconv.FormatBool(useHtapOptimizations), func(t *testing.T) { 424 if useHtapOptimizations { 425 sct.mustExec("ALTER SESSION SET ENABLE_SNOW_654741_FOR_TESTING = true", nil) 426 } 427 runID := time.Now().UnixMilli() 428 t.Run("Schema", func(t *testing.T) { 429 newSchema := fmt.Sprintf("test_schema_%v", runID) 430 if strings.EqualFold(sct.sc.cfg.Schema, newSchema) { 431 t.Errorf("schema should not be switched") 432 } 433 434 sct.mustExec(fmt.Sprintf("CREATE SCHEMA %v", newSchema), nil) 435 defer sct.mustExec(fmt.Sprintf("DROP SCHEMA %v", newSchema), nil) 436 437 if !strings.EqualFold(sct.sc.cfg.Schema, newSchema) { 438 t.Errorf("schema should be switched, expected %v, got %v", newSchema, sct.sc.cfg.Schema) 439 } 440 441 query := sct.mustQuery("SELECT 1", nil) 442 query.Close() 443 444 if !strings.EqualFold(sct.sc.cfg.Schema, newSchema) { 445 t.Errorf("schema should be switched, expected %v, got %v", newSchema, sct.sc.cfg.Schema) 446 } 447 }) 448 t.Run("Database", func(t *testing.T) { 449 newDatabase := fmt.Sprintf("test_database_%v", runID) 450 if strings.EqualFold(sct.sc.cfg.Database, newDatabase) { 451 t.Errorf("database should not be switched") 452 } 453 454 sct.mustExec(fmt.Sprintf("CREATE DATABASE %v", newDatabase), nil) 455 defer sct.mustExec(fmt.Sprintf("DROP DATABASE %v", newDatabase), nil) 456 457 if !strings.EqualFold(sct.sc.cfg.Database, newDatabase) { 458 t.Errorf("database should be switched, expected %v, got %v", newDatabase, sct.sc.cfg.Database) 459 } 460 461 query := sct.mustQuery("SELECT 1", nil) 462 query.Close() 463 464 if !strings.EqualFold(sct.sc.cfg.Database, newDatabase) { 465 t.Errorf("database should be switched, expected %v, got %v", newDatabase, sct.sc.cfg.Database) 466 } 467 }) 468 t.Run("Warehouse", func(t *testing.T) { 469 newWarehouse := fmt.Sprintf("test_warehouse_%v", runID) 470 if strings.EqualFold(sct.sc.cfg.Warehouse, newWarehouse) { 471 t.Errorf("warehouse should not be switched") 472 } 473 474 sct.mustExec(fmt.Sprintf("CREATE WAREHOUSE %v", newWarehouse), nil) 475 defer sct.mustExec(fmt.Sprintf("DROP WAREHOUSE %v", newWarehouse), nil) 476 477 if !strings.EqualFold(sct.sc.cfg.Warehouse, newWarehouse) { 478 t.Errorf("warehouse should be switched, expected %v, got %v", newWarehouse, sct.sc.cfg.Warehouse) 479 } 480 481 query := sct.mustQuery("SELECT 1", nil) 482 query.Close() 483 484 if !strings.EqualFold(sct.sc.cfg.Warehouse, newWarehouse) { 485 t.Errorf("warehouse should be switched, expected %v, got %v", newWarehouse, sct.sc.cfg.Warehouse) 486 } 487 }) 488 t.Run("Role", func(t *testing.T) { 489 if strings.EqualFold(sct.sc.cfg.Role, "PUBLIC") { 490 t.Errorf("role should not be public for this test") 491 } 492 493 sct.mustExec("USE ROLE public", nil) 494 495 if !strings.EqualFold(sct.sc.cfg.Role, "PUBLIC") { 496 t.Errorf("role should be switched, expected public, got %v", sct.sc.cfg.Role) 497 } 498 499 query := sct.mustQuery("SELECT 1", nil) 500 query.Close() 501 502 if !strings.EqualFold(sct.sc.cfg.Role, "PUBLIC") { 503 t.Errorf("role should be switched, expected public, got %v", sct.sc.cfg.Role) 504 } 505 }) 506 t.Run("Session param - DATE_OUTPUT_FORMAT", func(t *testing.T) { 507 if !strings.EqualFold(*sct.sc.cfg.Params["date_output_format"], "YYYY-MM-DD") { 508 t.Errorf("should use default date_output_format, but got: %v", *sct.sc.cfg.Params["date_output_format"]) 509 } 510 511 sct.mustExec("ALTER SESSION SET DATE_OUTPUT_FORMAT = 'DD-MM-YYYY'", nil) 512 defer sct.mustExec("ALTER SESSION SET DATE_OUTPUT_FORMAT = 'YYYY-MM-DD'", nil) 513 514 if !strings.EqualFold(*sct.sc.cfg.Params["date_output_format"], "DD-MM-YYYY") { 515 t.Errorf("date output format should be switched, expected DD-MM-YYYY, got %v", sct.sc.cfg.Params["date_output_format"]) 516 } 517 518 query := sct.mustQuery("SELECT 1", nil) 519 query.Close() 520 521 if !strings.EqualFold(*sct.sc.cfg.Params["date_output_format"], "DD-MM-YYYY") { 522 t.Errorf("date output format should be switched, expected DD-MM-YYYY, got %v", sct.sc.cfg.Params["date_output_format"]) 523 } 524 }) 525 }) 526 }) 527 } 528 } 529 530 func TestConnIsCleanAfterClose(t *testing.T) { 531 // We create a new db here to not use the default pool as we can leave it in dirty state. 532 t.Skip("Fails, because connection is returned to a pool dirty") 533 ctx := context.Background() 534 runID := time.Now().UnixMilli() 535 536 db := openDB(t) 537 defer db.Close() 538 db.SetMaxOpenConns(1) 539 540 conn, err := db.Conn(ctx) 541 if err != nil { 542 t.Fatal(err) 543 } 544 defer conn.Close() 545 546 dbt := DBTest{t, conn} 547 548 dbt.mustExec(forceJSON) 549 550 var dbName string 551 rows1 := dbt.mustQuery("SELECT CURRENT_DATABASE()") 552 rows1.Next() 553 rows1.Scan(&dbName) 554 555 newDbName := fmt.Sprintf("test_database_%v", runID) 556 dbt.mustExec("CREATE DATABASE " + newDbName) 557 558 rows1.Close() 559 conn.Close() 560 561 conn2, err := db.Conn(ctx) 562 if err != nil { 563 t.Fatal(err) 564 } 565 566 dbt2 := DBTest{t, conn2} 567 568 var dbName2 string 569 rows2 := dbt2.mustQuery("SELECT CURRENT_DATABASE()") 570 defer rows2.Close() 571 rows2.Next() 572 rows2.Scan(&dbName2) 573 574 if !strings.EqualFold(dbName, dbName2) { 575 t.Errorf("fresh connection from pool should have original database") 576 } 577 }