Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle nil params in ExecuteSql #75

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ create table freetds_types (
long bigint null,
smallint smallint null,
tinyint tinyint null,
numeric numeric(5,3) null,
varchar varchar(255) COLLATE latin1_general_ci_as null ,
nvarchar nvarchar(255) COLLATE latin1_general_ci_as null,
char char(255) COLLATE latin1_general_ci_as null,
Expand All @@ -42,11 +43,11 @@ create table freetds_types (
)
;

insert into freetds_types (int, long, smallint, tinyint, varchar, nvarchar, char, nchar, text, ntext, datetime, smalldatetime, money, smallmoney, real, float, bit, binary)
values (2147483647, 9223372036854775807, 32767, 255, 'išo medo u dućan ',N'išo medo u dućan 2','išo medo u dućan 3',N'išo medo u dućan 4','išo medo u dućan 5',N'išo medo u dućan 6', '1972-08-08T10:11:12','1972-08-08T10:11:12', 1234.5678, 1234.5678, 1234.5678, 1234.5678, 0, 0x123567890)
insert into freetds_types (int, long, smallint, tinyint, numeric, varchar, nvarchar, char, nchar, text, ntext, datetime, smalldatetime, money, smallmoney, real, float, bit, binary)
values (2147483647, 9223372036854775807, 32767, 255, 99.999, 'išo medo u dućan ',N'išo medo u dućan 2','išo medo u dućan 3',N'išo medo u dućan 4','išo medo u dućan 5',N'išo medo u dućan 6', '1972-08-08T10:11:12','1972-08-08T10:11:12', 1234.5678, 1234.5678, 1234.5678, 1234.5678, 0, 0x123567890)

insert into freetds_types (int, long, smallint, tinyint, varchar, nvarchar, char, nchar, text, ntext, datetime, smalldatetime, money, smallmoney, real, float, bit, binary)
values (-2147483648, -9223372036854775808, -32768, 0, 'nije reko dobar dan',N'nije reko dobar dan 2','nije reko dobar dan 3',N'nije reko dobar dan 4','nije reko dobar dan 5',N'nije reko dobar dan 6', '1998-10-10T16:17:18','1998-10-10T16:17:18', -1234.5678, -1234.5678, -1234.5678, -1234.5678, 1, 0x0987654321abcd)
insert into freetds_types (int, long, smallint, tinyint, numeric, varchar, nvarchar, char, nchar, text, ntext, datetime, smalldatetime, money, smallmoney, real, float, bit, binary)
values (-2147483648, -9223372036854775808, -32768, 0, -99.999, 'nije reko dobar dan',N'nije reko dobar dan 2','nije reko dobar dan 3',N'nije reko dobar dan 4','nije reko dobar dan 5',N'nije reko dobar dan 6', '1998-10-10T16:17:18','1998-10-10T16:17:18', -1234.5678, -1234.5678, -1234.5678, -1234.5678, 1, 0x0987654321abcd)

insert into freetds_types (int) values (3)
`, `
Expand Down Expand Up @@ -74,6 +75,7 @@ create table freetds_types (
long decimal(19,0) null,
smallint smallint null,
tinyint tinyint null,
numeric numeric(5,3) null,
varchar varchar(255) null ,
nvarchar nvarchar(255) null,
char char(255) null,
Expand All @@ -95,11 +97,11 @@ create table freetds_types (
)


insert into freetds_types (int, long, smallint, tinyint, varchar, nvarchar, char, nchar, text, ntext, datetime, smalldatetime, money, smallmoney, real, float, bit, binary)
values (2147483647, 9223372036854775807, 32767, 255, 'išo medo u dućan ',N'išo medo u dućan 2','išo medo u dućan 3',N'išo medo u dućan 4','išo medo u dućan 5',N'išo medo u dućan 6', '1972-08-08 10:11:12','1972-08-08 10:11:12', 1234.5678, 1234.5678, 1234.5678, 1234.5678, 0, 0x123567890)
insert into freetds_types (int, long, smallint, tinyint, numeric, varchar, nvarchar, char, nchar, text, ntext, datetime, smalldatetime, money, smallmoney, real, float, bit, binary)
values (2147483647, 9223372036854775807, 32767, 255, 99.999, 'išo medo u dućan ',N'išo medo u dućan 2','išo medo u dućan 3',N'išo medo u dućan 4','išo medo u dućan 5',N'išo medo u dućan 6', '1972-08-08 10:11:12','1972-08-08 10:11:12', 1234.5678, 1234.5678, 1234.5678, 1234.5678, 0, 0x123567890)

insert into freetds_types (int, long, smallint, tinyint, varchar, nvarchar, char, nchar, text, ntext, datetime, smalldatetime, money, smallmoney, real, float, bit, binary)
values (-2147483648, -9223372036854775808, -32768, 0, 'nije reko dobar dan',N'nije reko dobar dan 2','nije reko dobar dan 3',N'nije reko dobar dan 4','nije reko dobar dan 5',N'nije reko dobar dan 6', '1998-10-10 16:17:18','1998-10-10 16:17:18', -1234.5678, -1234.5678, -1234.5678, -1234.5678, 1, 0x0987654321abcd)
insert into freetds_types (int, long, smallint, tinyint, numeric, varchar, nvarchar, char, nchar, text, ntext, datetime, smalldatetime, money, smallmoney, real, float, bit, binary)
values (-2147483648, -9223372036854775808, -32768, 0, -99.999, 'nije reko dobar dan',N'nije reko dobar dan 2','nije reko dobar dan 3',N'nije reko dobar dan 4','nije reko dobar dan 5',N'nije reko dobar dan 6', '1998-10-10 16:17:18','1998-10-10 16:17:18', -1234.5678, -1234.5678, -1234.5678, -1234.5678, 1, 0x0987654321abcd)

insert into freetds_types (int, bit) values (3, 0)
`, `
Expand Down
2 changes: 2 additions & 0 deletions executesql.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ func go2SqlDataType(value interface{}) (string, string, error) {

strValue := fmt.Sprintf("%v", value)
switch t := value.(type) {
case nil:
return "nvarchar (1)", "NULL", nil
case bool:
bitStrValue := "0"
if strValue == "true" {
Expand Down
1 change: 1 addition & 0 deletions executesql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func TestGoTo2SqlDataType(t *testing.T) {
checker([]byte{1, 2, 3, 4, 5, 6, 7, 8}, "varbinary (8)", "0x0102030405060708")

checker("", "nvarchar (1)", "''")
checker(nil, "nvarchar (1)", "NULL")
checker(true, "bit", "1")
checker(false, "bit", "0")
}
Expand Down
260 changes: 259 additions & 1 deletion mssql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"strings"
"testing"
"time"

"github.com/stretchr/testify/assert"
"os"
Expand Down Expand Up @@ -44,7 +45,6 @@ func TestMssqlConnOpenSybase125(t *testing.T) {
c.Close()
}


func TestGoSqlDbQueryRow(t *testing.T) {
db, err, _ := open(t)
defer db.Close()
Expand Down Expand Up @@ -240,3 +240,261 @@ func TestBlobs(t *testing.T) {
assert.Equal(t, strWant, strGot)
assert.Equal(t, want, got)
}

var insertQuery = `
insert into freetds_types (
int,
long,
smallint,
tinyint,
numeric,
varchar,
nvarchar,
char,
nchar,
text,
ntext,
datetime,
smalldatetime,
money,
smallmoney,
real,
float,
bit,
-- We cannot insert NULL for timestamp, binary, and varbinary_max
-- timestamp,
-- binary,
nvarchar_max,
varchar_max
-- varbinary_max
) values (
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?
)
`

func TestNullInserts(t *testing.T) {
db, _, _ := open(t)
defer db.Close()

// First clear out the nil one(s)
_, err := db.Exec(`delete from freetds_types where int is null`)
assert.Nil(t, err)

_, err = db.Exec(insertQuery, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
// Because sybase 12.5 does not allow null bit, making it non-null to resort to lowest common denominator.
true,
nil, nil)
assert.Nil(t, err)

rows, err := db.Query("select * from freetds_types where int is null")
defer rows.Close()
assert.Nil(t, err)
assertRowNil(t, rows)
}

func TestSQLNullInserts(t *testing.T) {
db, _, _ := open(t)
defer db.Close()

// First clear out the nil one(s)
_, err := db.Exec(`delete from freetds_types where int is null`)
assert.Nil(t, err)

_, err = db.Exec(insertQuery,
// sql.NullInt32{Valid: true, Int32: 100},
sql.NullInt32{},
sql.NullInt64{},
sql.NullInt32{},
sql.NullInt32{},
sql.NullFloat64{},
sql.NullString{},
sql.NullString{},
sql.NullString{},
sql.NullString{},
sql.NullString{},
sql.NullString{},
sql.NullTime{},
sql.NullTime{},
sql.NullFloat64{},
sql.NullFloat64{},
sql.NullFloat64{},
sql.NullFloat64{},
// Because sybase 12.5 does not allow null bit, making it non-null to resort to lowest common denominator.
sql.NullBool{Valid: true, Bool: true},
sql.NullString{},
sql.NullString{},
)
assert.Nil(t, err)

rows, err := db.Query("select * from freetds_types where int is null")
defer rows.Close()
assert.Nil(t, err)
assertRowNil(t, rows)
}

func TestTypedNilNullInserts(t *testing.T) {
db, _, _ := open(t)
defer db.Close()

// First clear out the nil one(s)
_, err := db.Exec(`delete from freetds_types where int is null`)
assert.Nil(t, err)

var (
myInt *int32
myLong *int64
mySmallInt *int16
myTinyInt *int8
myNumeric *float64
myVarchar *string
myNVarchar *string
myChar *byte
myNChar *[]byte
myText *string
myNText *string
myDateTime *time.Time
mySmallDateTime *time.Time
myMoney *float64
mySmallMoney *float64
myReal *float64
myFloat *float64
myBit *bool
myNVarcharMax *string
myVarcharMax *string
)
// Because sybase 12.5 does not allow null bit, making it non-null to resort to lowest common denominator.
myTrue := true
myBit = &myTrue
_, err = db.Exec(insertQuery,
myInt,
myLong,
mySmallInt,
myTinyInt,
myNumeric,
myVarchar,
myNVarchar,
myChar,
myNChar,
myText,
myNText,
myDateTime,
mySmallDateTime,
myMoney,
mySmallMoney,
myReal,
myFloat,
myBit,
myNVarcharMax,
myVarcharMax,
)
assert.Nil(t, err)

rows, err := db.Query("select * from freetds_types where int is null")
defer rows.Close()
assert.Nil(t, err)
assertRowNil(t, rows)
}

func assertRowNil(t *testing.T, rows *sql.Rows) {
rowCount := 0
for rows.Next() {
rowCount++
var (
myInt *int32
myLong *int64
mySmallInt *int16
myTinyInt *int8
myNumeric *float64
myVarchar *string
myNVarchar *string
myChar *byte
myNChar *[]byte
myText *string
myNText *string
myDateTime *time.Time
mySmallDateTime *time.Time
myMoney *float64
mySmallMoney *float64
myReal *float64
myFloat *float64
myBit *bool
myTimestamp *[]byte
myBinary *[]byte
myNVarcharMax *string
myVarcharMax *string
myVarBinaryMax *string
)

err := rows.Scan(
&myInt,
&myLong,
&mySmallInt,
&myTinyInt,
&myNumeric,
&myVarchar,
&myNVarchar,
&myChar,
&myNChar,
&myText,
&myNText,
&myDateTime,
&mySmallDateTime,
&myMoney,
&mySmallMoney,
&myReal,
&myFloat,
&myBit,
&myTimestamp,
&myBinary,
&myNVarcharMax,
&myVarcharMax,
&myVarBinaryMax,
)
assert.Nil(t, err)

assert.Nil(t, myInt)
assert.Nil(t, myLong)
assert.Nil(t, mySmallInt)
assert.Nil(t, myTinyInt)
assert.Nil(t, myNumeric)
assert.Nil(t, myVarchar)
assert.Nil(t, myChar)
assert.Nil(t, myNChar)
assert.Nil(t, myText)
assert.Nil(t, myNText)
assert.Nil(t, myDateTime)
assert.Nil(t, mySmallDateTime)
assert.Nil(t, myMoney)
assert.Nil(t, myReal)
assert.Nil(t, myFloat)
// Because sybase 12.5 does not allow null bit, we made it non-null to resort to lowest common denominator.
assert.True(t, *myBit)

assert.Nil(t, myBinary)
assert.Nil(t, myNVarcharMax)
assert.Nil(t, myVarcharMax)
assert.Nil(t, myVarBinaryMax)
assert.Nil(t, err)
}

assert.Equal(t, rowCount, 1)
}