github.com/nakagami/firebirdsql@v0.9.10/driver_test.go (about) 1 /******************************************************************************* 2 The MIT License (MIT) 3 4 Copyright (c) 2013-2019 Hajime Nakagami 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy of 7 this software and associated documentation files (the "Software"), to deal in 8 the Software without restriction, including without limitation the rights to 9 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 the Software, and to permit persons to whom the Software is furnished to do so, 11 subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in all 14 copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 *******************************************************************************/ 23 24 package firebirdsql 25 26 import ( 27 "context" 28 "crypto/rand" 29 "database/sql" 30 "encoding/hex" 31 "fmt" 32 "github.com/stretchr/testify/assert" 33 "github.com/stretchr/testify/require" 34 "math/big" 35 "os" 36 "path/filepath" 37 "reflect" 38 "runtime" 39 "strconv" 40 "strings" 41 "testing" 42 "time" 43 ) 44 45 var ( 46 longQueryNonSelectable = ` 47 execute block 48 as 49 declare c integer = 0; 50 begin 51 while (c < 9000000000 ) do 52 begin 53 c = c + 1; 54 end 55 end` 56 57 longQuerySelectable = ` 58 execute block returns (i integer) as declare c integer = 0; 59 begin 60 i = 0; 61 while (c < 9000000000 ) do 62 begin 63 c = c + 1; 64 i = c; 65 suspend; 66 end 67 end` 68 ) 69 70 func get_firebird_major_version(conn *sql.DB) int { 71 var s string 72 conn.QueryRow("SELECT rdb$get_context('SYSTEM', 'ENGINE_VERSION') from rdb$database").Scan(&s) 73 major_version, _ := strconv.Atoi(s[:strings.Index(s, ".")]) 74 return major_version 75 } 76 77 func GetTestDSN(prefix string) string { 78 var tmppath string 79 randBytes := make([]byte, 16) 80 rand.Read(randBytes) 81 82 tmppath = filepath.Join(os.TempDir(), prefix+hex.EncodeToString(randBytes)+".fdb") 83 if runtime.GOOS == "windows" { 84 tmppath = "/" + tmppath 85 } 86 87 test_user := "sysdba" 88 if isc_user := os.Getenv("ISC_USER"); isc_user != "" { 89 test_user = isc_user 90 } 91 92 test_password := "masterkey" 93 if isc_password := os.Getenv("ISC_PASSWORD"); isc_password != "" { 94 test_password = isc_password 95 } 96 97 retorno := test_user + ":" + test_password + "@localhost:3050" 98 return retorno + tmppath 99 } 100 101 func TestBasic(t *testing.T) { 102 test_dsn := GetTestDSN("test_basic_") 103 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 104 105 if err != nil { 106 t.Fatalf("Error connecting: %v", err) 107 } 108 var n int 109 110 query := "SELECT Count(*) FROM rdb$relations where rdb$relation_name='FOO'" 111 err = conn.QueryRow(query).Scan(&n) 112 if err != nil { 113 t.Fatalf("Error QueryRow: %v", err) 114 } 115 if n > 0 { 116 conn.Exec("DROP TABLE foo") 117 } 118 119 query = ` 120 CREATE TABLE foo ( 121 a INTEGER NOT NULL, 122 b VARCHAR(30) NOT NULL UNIQUE, 123 c VARCHAR(1024), 124 d DECIMAL(16,3) DEFAULT -0.123, 125 e DATE DEFAULT '1967-08-11', 126 f TIMESTAMP DEFAULT '1967-08-11 23:45:01', 127 g TIME DEFAULT '23:45:01', 128 h BLOB SUB_TYPE 1, 129 i DOUBLE PRECISION DEFAULT 0.0, 130 j FLOAT DEFAULT 0.0, 131 PRIMARY KEY (a), 132 CONSTRAINT CHECK_A CHECK (a <> 0) 133 ) 134 ` 135 conn.Exec(query) 136 conn.Close() 137 138 time.Sleep(1 * time.Second) 139 140 conn, err = sql.Open("firebirdsql", test_dsn) 141 _, err = conn.Exec("CREATE TABLE foo (a INTEGER)") 142 if err == nil { 143 t.Fatalf("Need metadata update error") 144 } 145 if !strings.Contains(err.Error(), "unsuccessful metadata update\n") { 146 t.Fatalf("Bad message:%v", err.Error()) 147 } 148 149 // 3 records insert 150 conn.Exec("insert into foo(a, b, c, h) values (1, 'a', 'b','This is a memo')") 151 conn.Exec("insert into foo(a, b, c, e, g, i, j) values (2, 'A', 'B', '1999-01-25', '00:00:01', 0.1, 0.1)") 152 conn.Exec("insert into foo(a, b, c, e, g, i, j) values (3, 'X', 'Y', '2001-07-05', '00:01:02', 0.2, 0.2)") 153 154 err = conn.QueryRow("select count(*) cnt from foo").Scan(&n) 155 if err != nil { 156 t.Fatalf("Error QueryRow: %v", err) 157 } 158 if n != 3 { 159 t.Fatalf("Error bad record count: %v", n) 160 } 161 162 rows, err := conn.Query("select a, b, c, d, e, f, g, h, i, j from foo") 163 columns, err := rows.Columns() 164 if !reflect.DeepEqual(columns, []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"}) { 165 t.Fatalf("Columns() mismatch: %v", columns) 166 } 167 168 var a int 169 var b, c string 170 var d float64 171 var e time.Time 172 var f time.Time 173 var g time.Time 174 var h []byte 175 var i float64 176 var j float32 177 178 for rows.Next() { 179 rows.Scan(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j) 180 // fmt.Println(a, b, c, d, e, f, g, h, i, j) 181 } 182 183 stmt, _ := conn.Prepare("select count(*) from foo where a=? and b=? and d=? and e=? and f=? and g=?") 184 ep := time.Date(1967, 8, 11, 0, 0, 0, 0, time.Local) 185 fp := time.Date(1967, 8, 11, 23, 45, 1, 0, time.Local) 186 gp, err := time.Parse("15:04:05", "23:45:01") 187 err = stmt.QueryRow(1, "a", -0.123, ep, fp, gp).Scan(&n) 188 if err != nil { 189 t.Fatalf("Error QueryRow: %v", err) 190 } 191 if n != 1 { 192 t.Fatalf("Error bad record count: %v", n) 193 } 194 195 // Issue #169 196 stmt, _ = conn.Prepare("select * from foo where a=?") 197 for k := 1; k < 5; k++ { 198 rows, err := stmt.Query(k) 199 require.NoError(t, err) 200 rows.Next() 201 err = rows.Close() 202 require.NoError(t, err) 203 } 204 205 // Issue #174 206 // https://github.com/nakagami/firebirdsql/issues/174#issue-2312621571 207 stmt1, err := conn.Prepare("select * from foo where a=?") 208 require.NoError(t, err) 209 210 stmt2, err := conn.Prepare("select * from foo where a=?") 211 require.NoError(t, err) 212 for k := 0; k < 3; k++ { 213 rows1, err := stmt1.Query(k) 214 require.NoError(t, err) 215 216 rows2, err := stmt2.Query(1) 217 require.NoError(t, err) 218 219 err = rows1.Close() 220 require.NoError(t, err) 221 222 err = rows2.Close() 223 require.NoError(t, err) 224 } 225 226 err = stmt1.Close() 227 require.NoError(t, err) 228 229 err = stmt2.Close() 230 require.NoError(t, err) 231 232 // https://github.com/nakagami/firebirdsql/issues/174#issuecomment-2134693366 233 stmt, err = conn.Prepare("select * from foo where a=?") 234 require.NoError(t, err) 235 236 tx, err := conn.Begin() 237 require.NoError(t, err) 238 err = tx.Commit() 239 require.NoError(t, err) 240 241 rows, err = stmt.Query(1) 242 require.NoError(t, err) 243 244 rows.Close() 245 require.NoError(t, err) 246 247 // https://github.com/nakagami/firebirdsql/issues/174#issuecomment-2139296394 248 // START TX1 249 tx, err = conn.Begin() 250 require.NoError(t, err) 251 252 stmt1, err = conn.Prepare(`select * from foo where a=?`) 253 require.NoError(t, err) 254 rows1, err := tx.Stmt(stmt1).Query(1) 255 require.NoError(t, err) 256 err = rows1.Close() 257 require.NoError(t, err) 258 err = stmt1.Close() 259 require.NoError(t, err) 260 261 stmt2, err = conn.Prepare(`select * from foo where a=?`) 262 require.NoError(t, err) 263 _, err = tx.Stmt(stmt2).Exec(333) 264 require.NoError(t, err) 265 266 err = tx.Commit() 267 require.NoError(t, err) 268 // END TX1 269 270 // START TX2 271 tx, err = conn.Begin() 272 require.NoError(t, err) 273 _, err = tx.Stmt(stmt2).Exec(333) 274 require.NoError(t, err) 275 err = tx.Rollback() 276 require.NoError(t, err) 277 // END TX2 278 279 err = conn.Close() 280 require.NoError(t, err) 281 // Issue #174 end 282 283 conn.Close() 284 } 285 286 func TestReturning(t *testing.T) { 287 test_dsn := GetTestDSN("test_returning_") 288 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 289 if err != nil { 290 t.Fatalf("Error sql.Open() : %v", err) 291 } 292 293 conn.Exec(` 294 CREATE TABLE test_returning ( 295 f1 integer NOT NULL, 296 f2 integer default 2, 297 f3 varchar(20) default 'abc')`) 298 299 conn.Close() 300 301 time.Sleep(1 * time.Second) 302 303 conn, err = sql.Open("firebirdsql", test_dsn) 304 if err != nil { 305 t.Fatalf("Error sql.Open() : %v", err) 306 } 307 308 for i := 0; i < 2; i++ { 309 rows, err := conn.Query("INSERT INTO test_returning (f1) values (1) returning f2, f3") 310 if err != nil { 311 t.Fatalf("Error Insert returning : %v", err) 312 } 313 var f2 int 314 var f3 string 315 rows.Next() 316 rows.Scan(&f2, &f3) 317 if f2 != 2 || f3 != "abc" { 318 t.Fatalf("Bad value insert returning: %v,%v", f2, f3) 319 } 320 } 321 322 conn.Close() 323 } 324 325 func TestInsertBlobsWithParams(t *testing.T) { 326 test_dsn := GetTestDSN("test_insert_blobs_with_params") 327 conn, _ := sql.Open("firebirdsql_createdb", test_dsn) 328 conn.Exec("CREATE TABLE test_blobs (f1 BLOB SUB_TYPE 0, f2 BLOB SUB_TYPE 1)") 329 conn.Close() 330 331 time.Sleep(1 * time.Second) 332 333 conn, _ = sql.Open("firebirdsql", test_dsn) 334 335 s0 := "Test Text" 336 b0 := []byte{0, 1, 2, 3, 4, 13, 10, 5, 6, 7} 337 if _, err := conn.Exec("INSERT INTO test_blobs (f1, f2) values (?, ?)", b0, s0); err != nil { 338 t.Fatalf("Error inserting blobs with params: %v", err) 339 } 340 341 var s string 342 var b []byte 343 err := conn.QueryRow("SELECT f1, f2 from test_blobs").Scan(&b, &s) 344 if err != nil { 345 t.Fatalf("Error in query: %v", err) 346 } 347 if s != s0 { 348 t.Fatalf("Text blob: expected <%s>, got <%s>", s0, s) 349 } 350 if !reflect.DeepEqual(b, b0) { 351 t.Fatalf("Binary blob: expected <%v>, got <%v> (%s)", b0, b, string(b)) 352 } 353 354 conn.Close() 355 } 356 357 func TestError(t *testing.T) { 358 conn, err := sql.Open("firebirdsql_createdb", GetTestDSN("test_error_")) 359 if err != nil { 360 t.Fatalf("Error connecting: %v", err) 361 } 362 _, err = conn.Exec("incorrect sql statement") 363 if err == nil { 364 t.Fatalf("Incorrect error") 365 } else if err.Error() != "Dynamic SQL Error\nSQL error code = -104\nToken unknown - line 1, column 1\nincorrect\n" { 366 t.Fatalf("Incorrect error: %v", err.Error()) 367 } 368 conn.Close() 369 } 370 371 func TestRole(t *testing.T) { 372 test_dsn := GetTestDSN("test_role_") 373 conn1, err := sql.Open("firebirdsql_createdb", test_dsn) 374 if err != nil { 375 t.Fatalf("Error creating: %v", err) 376 } 377 conn1.Exec("CREATE TABLE test_role (f1 integer)") 378 conn1.Exec("INSERT INTO test_role (f1) values (1)") 379 _, err = conn1.Exec("CREATE ROLE DRIVERROLE") 380 if err != nil { 381 t.Fatalf("Error creating role: %v", err) 382 } 383 conn1.Exec("GRANT DRIVERROLE TO SYSDBA") 384 if err != nil { 385 t.Fatalf("Error creating role: %v", err) 386 } 387 conn1.Exec("GRANT SELECT ON test_role TO DRIVERROLE") 388 if err != nil { 389 t.Fatalf("Error granting right to role: %v", err) 390 } 391 conn1.Close() 392 393 time.Sleep(1 * time.Second) 394 395 conn2, err := sql.Open("firebirdsql", test_dsn+"?role=driverrole") 396 if err != nil { 397 t.Fatalf("Error connecting: %v", err) 398 } 399 400 rows, err := conn2.Query("SELECT f1 FROM test_role") 401 if err != nil { 402 t.Fatalf("Error Query: %v", err) 403 } 404 405 for rows.Next() { 406 } 407 conn2.Close() 408 } 409 410 func TestInsertTimestamp(t *testing.T) { 411 conn, err := sql.Open("firebirdsql_createdb", GetTestDSN("test_timestamp_")) 412 if err != nil { 413 t.Fatalf("Error creating: %v", err) 414 } 415 416 _, err = conn.Exec("CREATE TABLE TEST (VAL1 TIMESTAMP, VAL2 TIMESTAMP, VAL3 TIMESTAMP, VAL4 TIMESTAMP)") 417 if err != nil { 418 t.Fatalf("Error creating table: %v", err) 419 } 420 421 dt1 := time.Date(2015, 2, 9, 19, 25, 50, 740500000, time.Local) 422 dt2 := "2015/2/9 19:25:50.7405" 423 dt3 := "2015-2-9 19:25:50.7405" 424 425 if _, err = conn.Exec("INSERT INTO TEST (VAL1, VAL2, VAL3, VAL4) VALUES (?, ?, ?, '2015/2/9 19:25:50.7405')", dt1, dt2, dt3); err != nil { 426 t.Fatalf("Error executing insert: %s", err) 427 } 428 429 var rt1, rt2, rt3, rt4 time.Time 430 431 err = conn.QueryRow("SELECT * FROM TEST").Scan(&rt1, &rt2, &rt3, &rt4) 432 if err != nil { 433 t.Fatalf("Unexpected error in select: %s", err) 434 } 435 436 if rt1 != dt1 { 437 t.Errorf("Expected <%v>, got <%v>", dt1, rt1) 438 } 439 if rt2 != dt1 { 440 t.Errorf("Expected <%v>, got <%v>", dt1, rt2) 441 } 442 if rt3 != dt1 { 443 t.Errorf("Expected <%v>, got <%v>", dt1, rt3) 444 } 445 if rt4 != dt1 { 446 t.Errorf("Expected <%v>, got <%v>", dt1, rt4) 447 } 448 conn.Close() 449 } 450 451 func TestBoolean(t *testing.T) { 452 conn, err := sql.Open("firebirdsql_createdb", GetTestDSN("test_boolean_")) 453 if err != nil { 454 t.Fatalf("Error connecting: %v", err) 455 } 456 457 firebird_major_version := get_firebird_major_version(conn) 458 if firebird_major_version < 3 { 459 return 460 } 461 462 var sql string 463 var n int 464 465 sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='TEST_FB3'" 466 err = conn.QueryRow(sql).Scan(&n) 467 if err != nil { 468 t.Fatalf("Error QueryRow: %v", err) 469 } 470 if n > 0 { 471 conn.Exec("DROP TABLE test_fb3") 472 } 473 474 sql = ` 475 CREATE TABLE test_fb3 ( 476 b BOOLEAN 477 ) 478 ` 479 conn.Exec(sql) 480 conn.Exec("insert into test_fb3(b) values (true)") 481 conn.Exec("insert into test_fb3(b) values (false)") 482 var b bool 483 err = conn.QueryRow("select * from test_fb3 where b is true").Scan(&b) 484 if err != nil { 485 t.Fatalf("Error QueryRow: %v", err) 486 } 487 if b != true { 488 conn.Exec("Invalid boolean value") 489 } 490 err = conn.QueryRow("select * from test_fb3 where b is false").Scan(&b) 491 if err != nil { 492 t.Fatalf("Error QueryRow: %v", err) 493 } 494 if b != false { 495 conn.Exec("Invalid boolean value") 496 } 497 498 stmt, _ := conn.Prepare("select * from test_fb3 where b=?") 499 err = stmt.QueryRow(true).Scan(&b) 500 if err != nil { 501 t.Fatalf("Error QueryRow: %v", err) 502 } 503 if b != false { 504 conn.Exec("Invalid boolean value") 505 } 506 507 conn.Close() 508 } 509 510 func TestDecFloat(t *testing.T) { 511 conn, err := sql.Open("firebirdsql_createdb", GetTestDSN("test_decfloat_")) 512 if err != nil { 513 t.Fatalf("Error connecting: %v", err) 514 } 515 516 firebird_major_version := get_firebird_major_version(conn) 517 if firebird_major_version < 4 { 518 return 519 } 520 521 query := ` 522 CREATE TABLE test_decfloat ( 523 i integer, 524 d DECIMAL(20, 2), 525 df16 DECFLOAT(16), 526 df34 DECFLOAT(34), 527 s varchar(32) 528 ) 529 ` 530 conn.Exec(query) 531 conn.Exec("insert into test_decfloat(i, d, df16, df34, s) values (1, 0.0, 0.0, 0.0, '0.0')") 532 conn.Exec("insert into test_decfloat(i, d, df16, df34, s) values (2, 1.1, 1.1, 1.1, '1.1')") 533 conn.Exec("insert into test_decfloat(i, d, df16, df34, s) values (3, 120.2, 120.2, 120.2, '120.2')") 534 conn.Exec("insert into test_decfloat(i, d, df16, df34, s) values (4, -1.1, -1.1, -1.1, '-1.1')") 535 conn.Exec("insert into test_decfloat(i, d, df16, df34, s) values (5, -120.2, -120.2, -120.2, '-120.2')") 536 537 var n int 538 err = conn.QueryRow("select count(*) cnt from test_decfloat").Scan(&n) 539 if err != nil { 540 t.Fatalf("Error QueryRow: %v", err) 541 } 542 if n != 5 { 543 t.Fatalf("Error bad record count: %v", n) 544 } 545 546 rows, err := conn.Query("select df16, df34, s from test_decfloat order by i") 547 548 var df16, df34 sql.NullFloat64 549 var s string 550 for rows.Next() { 551 rows.Scan(&df16, &df34, &s) 552 f, _ := strconv.ParseFloat(s, 64) 553 df16v, _ := df16.Value() 554 df34v, _ := df34.Value() 555 556 if df16v != f || df34v != f { 557 fmt.Printf("Error decfloat value : %v,%v,%v\n", df16v, df34v, f) 558 } 559 } 560 561 conn.Close() 562 } 563 564 func TestTimeZone(t *testing.T) { 565 conn, err := sql.Open("firebirdsql_createdb", GetTestDSN("test_timezone_")+"?timezone=Asia/Tokyo") 566 if err != nil { 567 t.Fatalf("Error connecting: %v", err) 568 } 569 570 firebird_major_version := get_firebird_major_version(conn) 571 if firebird_major_version < 4 { 572 return 573 } 574 575 sql := ` 576 CREATE TABLE test_timezone ( 577 id INTEGER NOT NULL, 578 a TIME WITH TIME ZONE DEFAULT '12:34:56', 579 b TIMESTAMP WITH TIME ZONE DEFAULT '1967-08-11 23:45:01', 580 PRIMARY KEY (id) 581 ) 582 ` 583 conn.Exec(sql) 584 conn.Exec("insert into test_timezone (id) values (0)") 585 conn.Exec("insert into test_timezone (id, a, b) values (1, '12:34:56 Asia/Seoul', '1967-08-11 23:45:01.0000 Asia/Seoul')") 586 conn.Exec("insert into test_timezone (id, a, b) values (2, '03:34:56 UTC', '1967-08-11 14:45:01.0000 UTC')") 587 588 var id int 589 var a time.Time 590 var b time.Time 591 rows, _ := conn.Query("select * from test_timezone") 592 expected := []string{ 593 "0000-01-01 12:34:56 +0900 JST, 1967-08-11 23:45:01 +0900 JST", 594 "0000-01-01 12:34:56 +0900 KST, 1967-08-11 23:45:01 +0900 KST", 595 "0000-01-01 03:34:56 +0000 UTC, 1967-08-11 14:45:01 +0000 UTC"} 596 597 for rows.Next() { 598 rows.Scan(&id, &a, &b) 599 s := fmt.Sprintf("%v, %v", a, b) 600 if s != expected[id] { 601 t.Fatalf("Incorrect result: %v", s) 602 } 603 } 604 605 conn.Close() 606 } 607 608 func TestInt128(t *testing.T) { 609 // https://github.com/nakagami/firebirdsql/issues/129 610 conn, err := sql.Open("firebirdsql_createdb", GetTestDSN("test_int128_")) 611 if err != nil { 612 t.Fatalf("Error connecting: %v", err) 613 } 614 615 firebird_major_version := get_firebird_major_version(conn) 616 if firebird_major_version < 4 { 617 return 618 } 619 620 sql := ` 621 CREATE TABLE test_int128 ( 622 i int128 623 ) 624 ` 625 conn.Exec(sql) 626 conn.Exec("insert into test_int128(i) values (170141183460469231731687303715884105727)") 627 628 var i128 *big.Int 629 err = conn.QueryRow("SELECT i FROM test_int128").Scan(&i128) 630 if err != nil { 631 t.Fatalf("Error SELECT: %v", err) 632 } 633 634 var toCmp = new(big.Int) 635 toCmp, _ = toCmp.SetString("170141183460469231731687303715884105727", 10) 636 637 if i128.Cmp(toCmp) != 0 { 638 t.Fatalf("INT128 Error: %v", i128) 639 } 640 641 conn.Close() 642 } 643 644 func TestNegativeInt128(t *testing.T) { 645 conn, err := sql.Open("firebirdsql_createdb", GetTestDSN("test_negative_int128_")) 646 if err != nil { 647 t.Fatalf("Error connecting: %v", err) 648 } 649 650 firebird_major_version := get_firebird_major_version(conn) 651 if firebird_major_version < 4 { 652 return 653 } 654 655 sql := ` 656 CREATE TABLE test_negative_int128 ( 657 i int128 658 ) 659 ` 660 conn.Exec(sql) 661 conn.Exec("insert into test_negative_int128(i) values (-170141183460469231731687303715884105727)") 662 663 var i128 *big.Int 664 err = conn.QueryRow("SELECT i FROM test_negative_int128").Scan(&i128) 665 if err != nil { 666 t.Fatalf("Error SELECT: %v", err) 667 } 668 669 var toCmp = new(big.Int) 670 toCmp, _ = toCmp.SetString("-170141183460469231731687303715884105727", 10) 671 672 if i128.Cmp(toCmp) != 0 { 673 t.Fatalf("Negative INT128 Error: %v", i128) 674 } 675 676 conn.Close() 677 } 678 679 func TestLegacyAuthWireCrypt(t *testing.T) { 680 test_dsn := GetTestDSN("test_legacy_auth_") 681 var n int 682 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 683 if err != nil { 684 t.Fatalf("Error connecting: %v", err) 685 } 686 err = conn.Ping() 687 if err != nil { 688 t.Fatalf("Error ping: %v", err) 689 } 690 conn.Close() 691 692 time.Sleep(1 * time.Second) 693 694 conn, err = sql.Open("firebirdsql", test_dsn+"?auth_plugin_anme=Legacy_Auth") 695 if err != nil { 696 t.Fatalf("Error connecting: %v", err) 697 } 698 err = conn.QueryRow("SELECT Count(*) FROM rdb$relations").Scan(&n) 699 if err != nil { 700 t.Fatalf("Error SELECT: %v", err) 701 } 702 conn.Close() 703 704 conn, err = sql.Open("firebirdsql", test_dsn+"?wire_crypt=false") 705 if err != nil { 706 t.Fatalf("Error connecting: %v", err) 707 } 708 err = conn.QueryRow("SELECT Count(*) FROM rdb$relations").Scan(&n) 709 if err != nil { 710 t.Fatalf("Error SELECT: %v", err) 711 } 712 conn.Close() 713 714 conn, err = sql.Open("firebirdsql", test_dsn+"?auth_plugin_name=Legacy_Auth&wire_auth=true") 715 if err != nil { 716 t.Fatalf("Error connecting: %v", err) 717 } 718 err = conn.QueryRow("SELECT Count(*) FROM rdb$relations").Scan(&n) 719 if err != nil { 720 t.Fatalf("Error SELECT: %v", err) 721 } 722 conn.Close() 723 724 conn, err = sql.Open("firebirdsql", test_dsn+"?auth_plugin_name=Legacy_Auth&wire_auth=false") 725 if err != nil { 726 t.Fatalf("Error connecting: %v", err) 727 } 728 err = conn.QueryRow("SELECT Count(*) FROM rdb$relations").Scan(&n) 729 if err != nil { 730 t.Fatalf("Error SELECT: %v", err) 731 } 732 conn.Close() 733 } 734 735 func TestErrorConnect(t *testing.T) { 736 var n int 737 conn, err := sql.Open("firebirdsql", "foo:bar@something_wrong_hostname:3050/dbname") 738 if err != nil { 739 t.Fatalf("Error occured at sql.Open()") 740 } 741 err = conn.QueryRow("SELECT Count(*) FROM rdb$relations").Scan(&n) 742 if err == nil { 743 t.Fatalf("Error not occured") 744 } 745 746 conn.Close() 747 } 748 749 func TestGoIssue44(t *testing.T) { 750 conn, err := sql.Open("firebirdsql", "SomethingWrongConnectionString") 751 err = conn.Ping() 752 if err == nil { 753 t.Fatalf("Error not occured") 754 } 755 conn.Close() 756 } 757 758 func TestGoIssue45(t *testing.T) { 759 test_dsn := GetTestDSN("test_issue45_") 760 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 761 if err != nil { 762 t.Fatalf("Error occured at sql.Open()") 763 } 764 765 conn.Exec(` 766 CREATE TABLE person ( 767 name VARCHAR(60) NOT NULL, 768 created TIMESTAMP 769 ) 770 `) 771 conn.Exec(` 772 insert into person (name, created) 773 values ('Giovanni', null) 774 `) 775 776 conn.Close() 777 778 time.Sleep(1 * time.Second) 779 780 conn, err = sql.Open("firebirdsql", test_dsn) 781 782 // select null value 783 type response struct { 784 name string 785 created *time.Time 786 } 787 r := response{} 788 789 err = conn.QueryRow(` 790 select name, created from person 791 `).Scan(&r.name, &r.created) 792 if err != nil { 793 t.Fatalf("Error: %v", err) 794 } 795 if r.created != nil { 796 t.Fatalf("created is not nil") 797 } 798 799 // insert returning not null value 800 err = conn.QueryRow(` 801 insert into person (name, created) 802 values ('Giovanni Gaspar', current_timestamp) 803 returning name, created 804 `).Scan(&r.name, &r.created) 805 if err != nil { 806 t.Fatalf("Error: %v", err) 807 } 808 if r.created == nil { 809 t.Fatalf("created is nil") 810 } 811 812 // insert returning null value 813 err = conn.QueryRow(` 814 insert into person (name, created) 815 values ('Nakagami', null) 816 returning name, created 817 `).Scan( 818 &r.name, &r.created) 819 if err != nil { 820 t.Fatalf("Error: %v", err) 821 } 822 if r.created != nil { 823 t.Fatalf("created is not nil") 824 } 825 826 conn.Close() 827 } 828 829 func TestGoIssue49(t *testing.T) { 830 test_dsn := GetTestDSN("test_issue49_") 831 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 832 if err != nil { 833 t.Fatalf("Error occured at sql.Open()") 834 } 835 defer conn.Close() 836 837 sqlCreate := ` 838 CREATE TABLE NullTest ( 839 name VARCHAR(60) NOT NULL, 840 nullname VARCHAR(10), 841 nullDate DATE, 842 bug1 SMALLINT, 843 bug2 INTEGER 844 ) 845 ` 846 conn.Exec(sqlCreate) 847 848 //Worked 849 sqlTest1 := `insert into NullTest (name, nullDate)values ('value', null)` 850 _, err = conn.Exec(sqlTest1) 851 if err != nil { 852 t.Error(err) 853 } 854 //Worked 855 sqlTest1 = `insert into NullTest (name, nullDate)values (?, ?)` 856 _, err = conn.Exec(sqlTest1, "value", nil) 857 if err != nil { 858 t.Error(err) 859 } 860 861 //Failed 862 sqlTest1 = `insert into NullTest (name, nullDate)values (?, ?)` 863 _, err = conn.Exec(sqlTest1, "value", nil) 864 if err != nil { 865 t.Error(err) 866 } 867 868 // Failed 869 sqlTest1 = `insert into NullTest (name, bug1) values ('value', ?)` 870 _, err = conn.Exec(sqlTest1, nil) 871 if err != nil { 872 t.Error(err) 873 } 874 // Failed 875 sqlTest1 = `insert into NullTest (name, bug1,bug2) values ('value', ?,?)` 876 _, err = conn.Exec(sqlTest1, nil, nil) 877 if err != nil { 878 t.Error(err) 879 } 880 881 // must be failed! 882 sqlTest1 = `insert into NullTest (name, bug1) values ('value', ?)` 883 _, err = conn.Exec(sqlTest1) 884 if err == nil { 885 t.Error("Expected error!") 886 } 887 } 888 889 func TestGoIssue53(t *testing.T) { 890 timeout := time.Second * 40 891 test_dsn := GetTestDSN("test_issue53_") 892 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 893 if err != nil { 894 t.Fatalf("Error occured at sql.Open()") 895 } 896 defer conn.Close() 897 898 tests := []int{ 899 31, 900 BLOB_SEGMENT_SIZE, 901 BLOB_SEGMENT_SIZE + 1, 902 22*BLOB_SEGMENT_SIZE + 21, 903 97*BLOB_SEGMENT_SIZE + 21, 904 } 905 906 conn.Exec(`CREATE TABLE BlobTest (bugField blob sub_type binary )`) 907 908 for _, test := range tests { 909 t.Run(fmt.Sprintf("%d", test), func(t *testing.T) { 910 sqlDelete := `delete from BlobTest` 911 _, err = conn.Exec(sqlDelete) 912 if err != nil { 913 t.Error(err) 914 } 915 916 sqlTest1 := `insert into BlobTest(bugField) values(?)` 917 918 str := strings.Repeat("F", test) 919 920 done := make(chan bool) 921 go func(ch chan bool) { 922 _, err = conn.Exec(sqlTest1, str) 923 if err != nil { 924 t.Error(err) 925 } 926 close(done) 927 }(done) 928 929 select { 930 case <-done: 931 case <-time.After(timeout): 932 t.Fatal("Test timed out after ", timeout) 933 } 934 935 sqlget := `select bugField from BlobTest` 936 rows, err := conn.Query(sqlget) 937 if err != nil { 938 t.Error(err) 939 return 940 } 941 942 for rows.Next() { 943 var buf []byte 944 err = rows.Scan(&buf) 945 if err != nil { 946 t.Error(err) 947 } 948 if len(buf) != test { 949 t.Errorf("Expected size blob %d, got %d", test, len(buf)) 950 } 951 } 952 953 rows.Close() 954 955 }) 956 } 957 } 958 func TestGoIssue65(t *testing.T) { 959 test_dsn := GetTestDSN("test_issue65_") 960 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 961 if err != nil { 962 t.Fatalf("Error occured at sql.Open()") 963 } 964 defer conn.Close() 965 966 conn.Exec(`CREATE TABLE FPI_MOVTO_MOVIMIENTOS 967 ( 968 RFCEMPRESA varchar(20) NOT NULL, 969 NOSUCURSAL integer NOT NULL, 970 TIPO integer NOT NULL, 971 SERIE varchar(5) NOT NULL, 972 NODOCTO integer NOT NULL, 973 LINEA integer NOT NULL, 974 CODART varchar(20), 975 NOMART varchar(80), 976 CLAVEPRODSERV varchar(10), 977 UNIDADCLAVE varchar(10), 978 UNIDADNOMBRE varchar(80), 979 CANT1 double precision, 980 CATN2 double precision, 981 PUNIT double precision, 982 MONTO double precision, 983 IMPTO1 double precision, 984 IMPTO2 double precision, 985 PIMPTO1 double precision, 986 PIMPTO2 double precision, 987 TIMPTO1 varchar(10), 988 TIMPTO2 varchar(10), 989 TFIMPTO1 varchar(10), 990 TFIMPTO2 varchar(10), 991 PDESCTO double precision, 992 IDESCTO double precision, 993 CONSTRAINT PXFPI_MOVTO_MOVIMIENTOS PRIMARY KEY (RFCEMPRESA,NOSUCURSAL,TIPO,SERIE,NODOCTO,LINEA) 994 );`) 995 996 //Worked 997 sqlTest1 := `INSERT INTO FPI_MOVTO_MOVIMIENTOS (RFCEMPRESA, NOSUCURSAL, TIPO, SERIE, NODOCTO, LINEA, CODART, NOMART, CLAVEPRODSERV, UNIDADCLAVE, UNIDADNOMBRE, CANT1, CATN2, PUNIT, MONTO, IMPTO1, IMPTO2, PIMPTO1, PIMPTO2, TIMPTO1, TIMPTO2, TFIMPTO1, TFIMPTO2, PDESCTO, IDESCTO) VALUES ('p2', '0', '700', 'X', '1', '1', 'ART-001', 'PRUEBA DE ARTICULO', '01010101', 'ACT', 'Actividad', '10.000000', '0.000000', '2.500000', '25.000000', '4.000000', '0.000000', '16.000000', '0.000000', '002', '', 'Tasa', '', '0.000000', '0.000000');` 998 _, err = conn.Exec(sqlTest1) 999 if err != nil { 1000 t.Error(err) 1001 } 1002 1003 sqlTest2 := "select doc.RFCEMPRESA, doc.NOSUCURSAL, doc.TIPO, doc.SERIE, doc.NODOCTO, doc.LINEA,\n" + 1004 " doc.CODART, doc.NOMART, doc.CLAVEPRODSERV, doc.UNIDADCLAVE, doc.UNIDADNOMBRE, doc.CANT1,\n" + 1005 " doc.CATN2, doc.PUNIT, doc.MONTO, doc.IMPTO1, doc.IMPTO2, doc.PIMPTO1, doc.PIMPTO2,\n" + 1006 " doc.TIMPTO1, doc.TIMPTO2, doc.TFIMPTO1, doc.TFIMPTO2, doc.PDESCTO, doc.IDESCTO\n" + 1007 "from FPI_MOVTO_MOVIMIENTOS doc\n" + 1008 "where doc.RFCEMPRESA = 'p2' and doc.NOSUCURSAL = 0 and doc.TIPO = 700 and doc.SERIE = 'X' and doc.NODOCTO = 1 \n" 1009 movtos, err := conn.Query(sqlTest2) 1010 if err != nil { 1011 t.Error(err) 1012 return 1013 } 1014 1015 existData := movtos.Next() 1016 if existData == false { 1017 t.Fatalf("Expecting Data") 1018 } 1019 } 1020 1021 func TestGoIssue80(t *testing.T) { 1022 test_dsn := GetTestDSN("test_issue80_") 1023 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 1024 if err != nil { 1025 t.Fatalf("Error occured at sql.Open()") 1026 } 1027 defer conn.Close() 1028 1029 query := ` 1030 CREATE TABLE foo ( 1031 a VARCHAR(10), 1032 b VARCHAR(10), 1033 c BIGINT, 1034 d INT, 1035 e INT, 1036 f INT, 1037 g INT, 1038 h INT, 1039 i INT, 1040 j INT, 1041 k INT, 1042 l INT, 1043 m INT, 1044 n INT 1045 ) 1046 ` 1047 1048 _, err = conn.Exec(query) 1049 if err != nil { 1050 t.Error(err) 1051 } 1052 1053 _, err = conn.Exec( 1054 "insert into foo(a, b, c, d, e, f, g, h, i, j, k, l, m, n) values (?, ?, ? ,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1055 " ", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) 1056 1057 if err != nil { 1058 t.Error(err) 1059 } 1060 1061 } 1062 1063 func TestIssue96(t *testing.T) { 1064 test_dsn := GetTestDSN("test_issue96_") 1065 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 1066 if err != nil { 1067 t.Fatalf("Error connecting: %v", err) 1068 } 1069 1070 conn.Exec(`CREATE EXCEPTION EX_DATA_ERROR ''`) 1071 conn.Exec(`CREATE PROCEDURE EXCEPTION_PROC(in1 INTEGER) 1072 RETURNS (out1 INTEGER) 1073 AS 1074 BEGIN 1075 IF (IN1=1) THEN 1076 BEGIN 1077 EXCEPTION EX_DATA_ERROR 'data error'; 1078 END 1079 out1 = in1; 1080 SUSPEND; 1081 END`) 1082 1083 query := "SELECT * FROM exception_proc(1)" 1084 rows, err := conn.Query(query) 1085 if err != nil { 1086 t.Fatalf("Error Query: %v", err) 1087 } 1088 rows.Next() 1089 var n int 1090 err = rows.Scan(&n) 1091 if err == nil { 1092 t.Error("Error not occured") 1093 } 1094 1095 conn.Close() 1096 } 1097 1098 func TestGoIssue112(t *testing.T) { 1099 test_dsn := GetTestDSN("test_issue112_") 1100 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 1101 if err != nil { 1102 t.Fatalf("Error occured at sql.Open()") 1103 } 1104 defer conn.Close() 1105 1106 query := ` 1107 CREATE TABLE foo ( 1108 i BIGINT 1109 ) 1110 ` 1111 1112 _, err = conn.Exec(query) 1113 if err != nil { 1114 t.Error(err) 1115 } 1116 1117 var input_val, output_val int64 1118 input_val = 2147483648 1119 err = conn.QueryRow(` 1120 insert into foo (i) 1121 values (?) 1122 returning i 1123 `, input_val).Scan( 1124 &output_val) 1125 if err != nil { 1126 t.Error(err) 1127 } 1128 if input_val != output_val { 1129 t.Fatalf("%v != %v", input_val, output_val) 1130 } 1131 1132 } 1133 1134 func TestGoIssue134(t *testing.T) { 1135 test_dsn := GetTestDSN("test_issue134_") 1136 conn, err := sql.Open("firebirdsql_createdb", test_dsn) 1137 if err != nil { 1138 t.Fatalf("Error occured at sql.Open()") 1139 } 1140 1141 query := ` 1142 CREATE TABLE t ( 1143 text VARCHAR(4) 1144 ) 1145 ` 1146 _, err = conn.Exec(query) 1147 if err != nil { 1148 t.Error(err) 1149 } 1150 1151 conn.Exec("INSERT INTO t(text) VALUES ('café')") 1152 if err != nil { 1153 t.Fatalf("Error Insert : %v", err) 1154 } 1155 1156 rows, err := conn.Query("select text from t") 1157 if err != nil { 1158 t.Error(err) 1159 } 1160 rows.Next() 1161 var text string 1162 err = rows.Scan(&text) 1163 if err != nil { 1164 t.Error(err) 1165 } 1166 1167 if text != "café" { 1168 t.Fatalf("Error bad record : %v", text) 1169 } 1170 1171 } 1172 1173 func TestGoIssue117(t *testing.T) { 1174 testDsn := GetTestDSN("test_issue117_") 1175 conn, err := sql.Open("firebirdsql_createdb", testDsn) 1176 require.NoError(t, err) 1177 1178 query := `CREATE TABLE t (text CHAR(16))` 1179 _, err = conn.Exec(query) 1180 require.NoError(t, err) 1181 1182 _, err = conn.Exec("INSERT INTO t VALUES ('test')") 1183 require.NoError(t, err) 1184 1185 rows, err := conn.Query("select text from t") 1186 require.NoError(t, err) 1187 1188 var text string 1189 require.True(t, rows.Next()) 1190 require.NoError(t, rows.Scan(&text)) 1191 assert.Equal(t, "test", text) 1192 require.NoError(t, rows.Close()) 1193 1194 rows, err = conn.Query("select 'test' from rdb$database") 1195 require.NoError(t, err) 1196 1197 require.True(t, rows.Next()) 1198 require.NoError(t, rows.Scan(&text)) 1199 assert.Equal(t, "test", text) 1200 require.NoError(t, rows.Close()) 1201 } 1202 1203 func TestGoIssue164(t *testing.T) { 1204 testDsn := GetTestDSN("test_issue164_") + "?charset=WIN1251" 1205 conn, err := sql.Open("firebirdsql_createdb", testDsn) 1206 require.NoError(t, err) 1207 1208 query := `CREATE TABLE t (text CHAR(2))` 1209 _, err = conn.Exec(query) 1210 require.NoError(t, err) 1211 1212 _, err = conn.Exec("INSERT INTO t VALUES ('Б')") 1213 require.NoError(t, err) 1214 1215 rows, err := conn.Query("select text from t") 1216 require.NoError(t, err) 1217 1218 var text string 1219 require.True(t, rows.Next()) 1220 require.NoError(t, rows.Scan(&text)) 1221 assert.Equal(t, "Б", text) 1222 require.NoError(t, rows.Close()) 1223 1224 var text2 string 1225 stmt, err := conn.Prepare("select text from t where text=?") 1226 require.NoError(t, err) 1227 err = stmt.QueryRow(text).Scan(&text2) 1228 require.NoError(t, err) 1229 assert.Equal(t, "Б", text2) 1230 } 1231 1232 func TestGoIssue170(t *testing.T) { 1233 testDsn := GetTestDSN("test_issue170") + "?charset=None" 1234 conn, err := sql.Open("firebirdsql_createdb", testDsn) 1235 require.NoError(t, err) 1236 1237 query := ` 1238 CREATE TABLE T2 ( 1239 ENTERO_NN INTEGER NOT NULL, 1240 ENTERO INTEGER, 1241 TEXTO_NN VARCHAR(30) NOT NULL, 1242 TEXTO VARCHAR(3000), 1243 FECHA_NN DATE NOT NULL, 1244 FECHA DATE, 1245 HORA_NN TIME NOT NULL, 1246 HORA TIME, 1247 MOMENTO_NN TIMESTAMP NOT NULL, 1248 MOMENTO TIMESTAMP, 1249 MEMO BLOB SUB_TYPE TEXT, 1250 BINARIO BLOB SUB_TYPE BINARY, 1251 SIMPLE_NN FLOAT NOT NULL, 1252 SIMPLE FLOAT, 1253 DOBLE_NN DOUBLE PRECISION NOT NULL, 1254 DOBLE DOUBLE PRECISION, 1255 LETRAS_NN CHAR(30) NOT NULL, 1256 LETRAS CHAR(30), 1257 CONSTRAINT PK_T2 PRIMARY KEY (ENTERO_NN) 1258 ) 1259 ` 1260 _, err = conn.Exec(query) 1261 require.NoError(t, err) 1262 1263 _, err = conn.Exec(` 1264 INSERT INTO T2 1265 (ENTERO_NN, ENTERO, TEXTO_NN, TEXTO, FECHA_NN, FECHA, HORA_NN, HORA, MOMENTO_NN, MOMENTO, MEMO, BINARIO, SIMPLE_NN, SIMPLE, DOBLE_NN, DOBLE, LETRAS_NN, LETRAS) 1266 VALUES(1, 1, 'uno', 'uno', '2024-06-04', '2024-06-04', '12:50:00', '12:50:00', '2024-06-04 12:50:00', '2024-06-04 12:50:00', 'memo', NULL, 1234.0, 1234.0, 12345678, 12345678, 'HOLA', 'ESCAROLA') 1267 `) 1268 require.NoError(t, err) 1269 _, err = conn.Exec(` 1270 INSERT INTO T2 1271 (ENTERO_NN, ENTERO, TEXTO_NN, TEXTO, FECHA_NN, FECHA, HORA_NN, HORA, MOMENTO_NN, MOMENTO, MEMO, BINARIO, SIMPLE_NN, SIMPLE, DOBLE_NN, DOBLE, LETRAS_NN, LETRAS) 1272 VALUES(2, NULL, 'dos', NULL, '2024-06-04', NULL, '12:50:00', NULL, '2024-06-04 12:50:00', NULL, NULL, NULL, 1234.0, NULL, 12345678, NULL, 'HOLA', NULL); 1273 `) 1274 require.NoError(t, err) 1275 1276 rows, err := conn.Query("select * from T2") 1277 require.NoError(t, err) 1278 1279 rows.Next() 1280 1281 rows.Close() 1282 conn.Close() 1283 } 1284 1285 func TestGoIssue172(t *testing.T) { 1286 testDsn := GetTestDSN("test_constraint_type_") 1287 conn, err := sql.Open("firebirdsql_createdb", testDsn) 1288 require.NoError(t, err) 1289 firebird_major_version := get_firebird_major_version(conn) 1290 if firebird_major_version < 3 { 1291 return 1292 } 1293 1294 rows, err := conn.Query("select RDB$CONSTRAINT_TYPE from RDB$RELATION_CONSTRAINTS") 1295 require.NoError(t, err) 1296 1297 var text string 1298 require.True(t, rows.Next()) 1299 require.NoError(t, rows.Scan(&text)) 1300 require.NoError(t, rows.Close()) 1301 } 1302 1303 func TestKSC_5601(t *testing.T) { 1304 testDsn := GetTestDSN("test_KSC_5601_") + "?charset=KSC_5601" 1305 conn, err := sql.Open("firebirdsql_createdb", testDsn) 1306 require.NoError(t, err) 1307 1308 query := `CREATE TABLE t (text CHAR(6))` 1309 _, err = conn.Exec(query) 1310 require.NoError(t, err) 1311 1312 _, err = conn.Exec("INSERT INTO t VALUES ('안녕하세요.')") 1313 require.NoError(t, err) 1314 1315 rows, err := conn.Query("SELECT text FROM t") 1316 require.NoError(t, err) 1317 1318 var text string 1319 require.True(t, rows.Next()) 1320 require.NoError(t, rows.Scan(&text)) 1321 assert.Equal(t, "안녕하세요.", text) 1322 require.NoError(t, rows.Close()) 1323 1324 _, err = conn.Exec("INSERT INTO t VALUES (?)", "안녕하세요.") 1325 require.NoError(t, err) 1326 1327 rows, err = conn.Query("SELECT text FROM t") 1328 require.NoError(t, err) 1329 1330 require.True(t, rows.Next()) 1331 require.NoError(t, rows.Scan(&text)) 1332 assert.Equal(t, "안녕하세요.", text) 1333 require.NoError(t, rows.Close()) 1334 } 1335 1336 func TestTimeoutQueryContextDuringScan(t *testing.T) { 1337 testDsn := GetTestDSN("test_timeout_query_context_scan_") 1338 conn, err := sql.Open("firebirdsql_createdb", testDsn) 1339 require.NoError(t, err) 1340 1341 ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 1342 defer cancel() 1343 1344 rows, err := conn.QueryContext(ctx, longQuerySelectable) 1345 require.NoError(t, err) 1346 1347 var n int 1348 for rows.Next() { 1349 if err := rows.Scan(&n); err != nil { 1350 break 1351 } 1352 } 1353 1354 // rows.Next or rows.Scan should fail with timeout 1355 if err == nil { 1356 err = rows.Err() 1357 } 1358 assert.ErrorIs(t, err, context.DeadlineExceeded) 1359 } 1360 1361 func TestTimeoutQueryContextDuringExec(t *testing.T) { 1362 testDsn := GetTestDSN("test_timeout_query_context_exec_") 1363 conn, err := sql.Open("firebirdsql_createdb", testDsn) 1364 require.NoError(t, err) 1365 ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 1366 defer cancel() 1367 _, err = conn.QueryContext(ctx, longQueryNonSelectable) 1368 assert.EqualError(t, err, "operation was cancelled\n") 1369 assert.ErrorIs(t, ctx.Err(), context.DeadlineExceeded) 1370 } 1371 1372 func TestTimeoutExecContext(t *testing.T) { 1373 testDsn := GetTestDSN("test_timeout_exec_context_") 1374 conn, err := sql.Open("firebirdsql_createdb", testDsn) 1375 require.NoError(t, err) 1376 ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 1377 defer cancel() 1378 _, err = conn.ExecContext(ctx, longQueryNonSelectable) 1379 assert.EqualError(t, err, "operation was cancelled\n") 1380 assert.ErrorIs(t, ctx.Err(), context.DeadlineExceeded) 1381 } 1382 1383 func TestReuseConnectionAfterTimeout(t *testing.T) { 1384 testDsn := GetTestDSN("test_timeout_conn_reuse_") 1385 conn, err := sql.Open("firebirdsql_createdb", testDsn) 1386 require.NoError(t, err) 1387 ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 1388 defer cancel() 1389 _, err = conn.QueryContext(ctx, longQueryNonSelectable) 1390 assert.EqualError(t, err, "operation was cancelled\n") 1391 assert.ErrorIs(t, ctx.Err(), context.DeadlineExceeded) 1392 1393 ctx, cancel = context.WithTimeout(context.Background(), time.Second*2) 1394 defer cancel() 1395 1396 _, err = conn.QueryContext(ctx, "select * from rdb$database") 1397 require.NoError(t, err) 1398 }