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  }