44 "context"
55 "database/sql"
66 "errors"
7+ "log"
78 "testing"
89 "time"
910
@@ -80,68 +81,98 @@ select _function='OtherTestFunction', time=42, money=convert(money, 12345.67);
8081 Y string
8182 }
8283
84+ var ctx context.Context
8385 var hook LogHook
84- logger := logrus .StandardLogger ()
85- logger .Hooks .Add (& hook )
86- ctx := querysql .WithLogger (context .Background (), querysql .LogrusMSSQLLogger (logger , logrus .InfoLevel ))
87- ctx = querysql .WithDispatcher (ctx , querysql .GoMSSQLDispatcher ([]interface {}{
88- testhelper .TestFunction ,
89- testhelper .OtherTestFunction ,
90- }))
91- rs := querysql .New (ctx , sqldb , qry , "world" )
92- rows := rs .Rows
93- testhelper .ResetTestFunctionsCalled ()
9486
95- // select 2
96- assert .Equal (t , 2 , querysql .MustNextResult (rs , querysql .SingleOf [int ]))
87+ testcases := []struct {
88+ name string
89+ init func ()
90+ checkLog func ()
91+ }{
92+ {
93+ name : "With logrus logger" ,
94+ init : func () {
95+ logger := logrus .StandardLogger ()
96+ logger .Hooks .Add (& hook )
97+ ctx = querysql .WithLogger (context .Background (), querysql .LogrusMSSQLLogger (logger , logrus .InfoLevel ))
98+ },
99+ checkLog : func () {
100+ // Check that we have exhausted the logging select before we do the call that gets ErrNoMoreSets
101+ assert .Equal (t , []logrus.Fields {
102+ {"x" : "hello world" , "y" : int64 (1 )},
103+ {"x" : "hello world2" , "y" : int64 (2 )},
104+ {"x" : "hello world3" , "y" : int64 (3 )},
105+ {"x" : "hello world3" , "y" : int64 (4 )},
106+ {"_norows" : true , "x" : "" },
107+ {"log" : "at end" },
108+ }, hook .lines )
109+ },
110+ },
111+ {
112+ name : "With std logger" ,
113+ init : func () {
114+ logger := log .Default ()
115+ ctx = querysql .WithLogger (context .Background (), querysql .StdMSSQLLogger (logger ))
116+ },
117+ checkLog : func () {},
118+ },
119+ }
120+ for _ , tc := range testcases {
121+ t .Run (tc .name , func (t * testing.T ) {
122+ tc .init ()
123+ ctx = querysql .WithDispatcher (ctx , querysql .GoMSSQLDispatcher ([]interface {}{
124+ testhelper .TestFunction ,
125+ testhelper .OtherTestFunction ,
126+ }))
127+ rs := querysql .New (ctx , sqldb , qry , "world" )
128+ rows := rs .Rows
129+ testhelper .ResetTestFunctionsCalled ()
97130
98- // select X = 1, Y = 'one';
99- assert .Equal (t , row { 1 , "one" }, querysql .MustNextResult (rs , querysql .SingleOf [row ]))
131+ // select 2
132+ assert .Equal (t , 2 , querysql .MustNextResult (rs , querysql .SingleOf [int ]))
100133
101- // select 'hello' union all select @p1 ;
102- assert .Equal (t , [] string { "hello" , "world " }, querysql .MustNextResult (rs , querysql .SliceOf [ string ]))
134+ // select X = 1, Y = 'one' ;
135+ assert .Equal (t , row { 1 , "one " }, querysql .MustNextResult (rs , querysql .SingleOf [ row ]))
103136
104- // select X = 1, Y = 'one' where 1 = 0 ;
105- assert .Equal (t , []row ( nil ), querysql .MustNextResult (rs , querysql .SliceOf [row ]))
137+ // select 'hello' union all select @p1 ;
138+ assert .Equal (t , []string { "hello" , "world" }, querysql .MustNextResult (rs , querysql .SliceOf [string ]))
106139
107- // select X = 1, Y = 'one'
108- // union all select X = 2, Y = 'two';
109- assert .Equal (t , []row {{1 , "one" }, {2 , "two" }}, querysql .MustNextResult (rs , querysql .SliceOf [row ]))
140+ // select X = 1, Y = 'one' where 1 = 0;
141+ assert .Equal (t , []row (nil ), querysql .MustNextResult (rs , querysql .SliceOf [row ]))
110142
111- // select 0x0102030405 union all select 0x0102030406
112- assert .Equal (t , []MyArray {{1 , 2 , 3 , 4 , 5 }, {1 , 2 , 3 , 4 , 6 }}, querysql .MustNextResult (rs , querysql .SliceOf [MyArray ]))
143+ // select X = 1, Y = 'one'
144+ // union all select X = 2, Y = 'two';
145+ assert .Equal (t , []row {{1 , "one" }, {2 , "two" }}, querysql .MustNextResult (rs , querysql .SliceOf [row ]))
113146
114- // select concat('hello ', @p1);
115- assert .Equal (t , "hello world" , querysql .MustNextResult (rs , querysql .SingleOf [ string ]))
147+ // select 0x0102030405 union all select 0x0102030406
148+ assert .Equal (t , [] MyArray {{ 1 , 2 , 3 , 4 , 5 }, { 1 , 2 , 3 , 4 , 6 }}, querysql .MustNextResult (rs , querysql .SliceOf [ MyArray ]))
116149
117- // select 0x0102030405
118- assert .Equal (t , MyArray { 1 , 2 , 3 , 4 , 5 }, querysql .MustNextResult (rs , querysql .SingleOf [MyArray ]))
150+ // select concat('hello ', @p1);
151+ assert .Equal (t , "hello world" , querysql .MustNextResult (rs , querysql .SingleOf [string ]))
119152
120- // select newid()
121- assert .Equal (t , 16 , len ( querysql .MustNextResult (rs , querysql.SingleOf [[] uint8 ]) ))
153+ // select 0x0102030405
154+ assert .Equal (t , MyArray { 1 , 2 , 3 , 4 , 5 }, querysql .MustNextResult (rs , querysql .SingleOf [MyArray ] ))
122155
123- // Check that we have exhausted the logging select before we do the call that gets ErrNoMoreSets
124- assert .Equal (t , []logrus.Fields {
125- {"x" : "hello world" , "y" : int64 (1 )},
126- {"x" : "hello world2" , "y" : int64 (2 )},
127- {"x" : "hello world3" , "y" : int64 (3 )},
128- {"x" : "hello world3" , "y" : int64 (4 )},
129- {"_norows" : true , "x" : "" },
130- {"log" : "at end" },
131- }, hook .lines )
156+ // select newid()
157+ assert .Equal (t , 16 , len (querysql .MustNextResult (rs , querysql.SingleOf [[]uint8 ])))
132158
133- querysql .NextResult (rs , querysql .SliceOf [string ]) // This will process all dispatcher function calls
134- assert .True (t , testhelper .TestFunctionsCalled ["TestFunction" ])
135- assert .True (t , testhelper .TestFunctionsCalled ["OtherTestFunction" ])
159+ tc .checkLog ()
136160
137- _ , err := querysql .NextResult (rs , querysql .SingleOf [ int ])
138- assert .Equal ( t , querysql . ErrNoMoreSets , err )
139- assert .True (t , isClosed ( rows ) )
140- assert .True (t , rs . Done () )
161+ _ , err := querysql .NextResult (rs , querysql .SliceOf [ string ]) // This will process all dispatcher function calls
162+ assert .NoError ( t , err )
163+ assert .True (t , testhelper . TestFunctionsCalled [ "TestFunction" ] )
164+ assert .True (t , testhelper . TestFunctionsCalled [ "OtherTestFunction" ] )
141165
142- rs .Close ()
143- assert .True (t , isClosed (rows ))
166+ _ , err = querysql .NextResult (rs , querysql .SingleOf [int ])
167+ assert .Equal (t , querysql .ErrNoMoreSets , err )
168+ assert .True (t , isClosed (rows ))
169+ assert .True (t , rs .Done ())
144170
171+ err = rs .Close ()
172+ assert .NoError (t , err )
173+ assert .True (t , isClosed (rows ))
174+ })
175+ }
145176}
146177
147178func TestInvalidLogLevel (t * testing.T ) {
@@ -151,19 +182,45 @@ select _log=1, x = 'hello world', y = 1;
151182`
152183
153184 var hook LogHook
154- logger := logrus .StandardLogger ()
155- logger .Hooks .Add (& hook )
156- ctx := querysql .WithLogger (context .Background (), querysql .LogrusMSSQLLogger (logger , logrus .InfoLevel ))
157- rs := querysql .New (ctx , sqldb , qry , "world" )
158- err := querysql .NextNoScanner (rs )
159- assert .Error (t , err )
160- assert .Equal (t , "no more result sets" , err .Error ())
185+ var ctx context.Context
186+ testcases := []struct {
187+ name string
188+ init func ()
189+ checkLog func ()
190+ }{
191+ {
192+ name : "With logrus logger" ,
193+ init : func () {
194+ logger := logrus .StandardLogger ()
195+ logger .Hooks .Add (& hook )
196+ ctx = querysql .WithLogger (context .Background (), querysql .LogrusMSSQLLogger (logger , logrus .InfoLevel ))
197+ },
198+ checkLog : func () {
199+ // Check that we have exhausted the logging select before we do the call that gets ErrNoMoreSets
200+ assert .Equal (t , []logrus.Fields {
201+ {"event" : "invalid.log.level" , "invalid.level" : "1" },
202+ {"x" : "hello world" , "y" : int64 (1 )},
203+ }, hook .lines )
204+ },
205+ },
206+ {
207+ name : "With std logger" ,
208+ init : func () {
209+ logger := log .Default ()
210+ ctx = querysql .WithLogger (context .Background (), querysql .StdMSSQLLogger (logger ))
211+ },
212+ checkLog : func () {},
213+ },
214+ }
161215
162- // Check that we have exhausted the logging select before we do the call that gets ErrNoMoreSets
163- assert .Equal (t , []logrus.Fields {
164- {"event" : "invalid.log.level" , "invalid.level" : "1" },
165- {"x" : "hello world" , "y" : int64 (1 )},
166- }, hook .lines )
216+ for _ , tc := range testcases {
217+ tc .init ()
218+ rs := querysql .New (ctx , sqldb , qry , "world" )
219+ err := querysql .NextNoScanner (rs )
220+ assert .Error (t , err )
221+ assert .Equal (t , "no more result sets" , err .Error ())
222+ tc .checkLog ()
223+ }
167224}
168225
169226func Test_LogAndException (t * testing.T ) {
@@ -218,16 +275,13 @@ select 2;
218275
219276func TestDispatcherSetupError (t * testing.T ) {
220277 var mustNotBeTrue bool
221- var hook LogHook
222- logger := logrus .StandardLogger ()
223- logger .Hooks .Add (& hook )
224278 defer func () {
225279 r := recover ()
226280 assert .NotNil (t , r ) // nil if a panic didn't happen, not nil if a panic happened
227281 assert .False (t , mustNotBeTrue )
228282 }()
229283
230- ctx := querysql . WithLogger ( context .Background (), querysql . LogrusMSSQLLogger ( logger , logrus . InfoLevel ) )
284+ ctx := context .Background ()
231285 ctx = querysql .WithDispatcher (ctx , querysql .GoMSSQLDispatcher ([]interface {}{
232286 "SomethingThatIsNotAFunctionPointer" , // This should cause a panic
233287 }))
@@ -312,7 +366,8 @@ func TestDispatcherRuntimeErrorsAndCornerCases(t *testing.T) {
312366 assert .True (t , isClosed (rows ))
313367 assert .True (t , rs .Done ())
314368
315- rs .Close ()
369+ err = rs .Close ()
370+ assert .NoError (t , err )
316371 assert .True (t , isClosed (rows ))
317372 }
318373}
@@ -433,13 +488,13 @@ func TestEmptyStruct(t *testing.T) {
433488
434489func TestEmptyResultWithError (t * testing.T ) {
435490 qry := `
436- if OBJECT_ID('dbo.MyUsers', 'U') is not null drop table MyUsers
491+ drop table if exists MyUsers
437492create table MyUsers (
438493 ID INT IDENTITY(1,1) PRIMARY KEY,
439494 Username NVARCHAR(50) not null,
440495 Userage int
441496);
442- insert into MyUsers (Userage)
497+ insert into MyUsers (Userage)
443498output inserted.ID
444499values (42);
445500`
@@ -585,7 +640,7 @@ func TestStructScanError(t *testing.T) {
585640
586641func TestExecContext (t * testing.T ) {
587642 qry := `
588- if OBJECT_ID('dbo.MyUsers', 'U') is not null drop table MyUsers
643+ drop table if exists MyUsers
589644create table MyUsers (
590645 ID INT IDENTITY(1,1) PRIMARY KEY,
591646 Username NVARCHAR(50)
@@ -655,7 +710,7 @@ type MyType struct {
655710 b string
656711}
657712
658- func (m MyType ) Scan (src any ) error {
713+ func (m MyType ) Scan (_ any ) error {
659714 return nil
660715}
661716
@@ -717,26 +772,20 @@ values (42.00);
717772
718773func TestAnonDispatcherFunc (t * testing.T ) {
719774 qry := `
720- if OBJECT_ID('dbo.MyUsers', 'U') is not null drop table MyUsers
775+ drop table if exists MyUsers
721776create table MyUsers (
722777 ID INT IDENTITY(1,1) PRIMARY KEY,
723778 Username NVARCHAR(50)
724779);
725780insert into MyUsers (Username) values ('JohnDoe');
726781
727- -- logging
728- select _log='info', Y = 'one';
729-
730782-- dispatcher
731783select _function='TestFunction', component = 'abc', val=1, time=1.23;
732784
733785select _function='ReturnAnonFunc', label = 'myLabel', time=1.23;
734786`
735787
736- var hook LogHook
737- logger := logrus .StandardLogger ()
738- logger .Hooks .Add (& hook )
739- ctx := querysql .WithLogger (context .Background (), querysql .LogrusMSSQLLogger (logger , logrus .InfoLevel ))
788+ ctx := context .Background ()
740789 ctx = querysql .WithDispatcher (ctx , querysql .GoMSSQLDispatcher ([]interface {}{
741790 testhelper .TestFunction ,
742791 testhelper .ReturnAnonFunc ("myComponent" ),
@@ -748,11 +797,6 @@ select _function='ReturnAnonFunc', label = 'myLabel', time=1.23;
748797
749798 assert .True (t , testhelper .TestFunctionsCalled ["ReturnAnonFunc.myComponent" ])
750799
751- // Check that we have exhausted the logging select before we do the call that gets ErrNoMoreSets
752- assert .Equal (t , []logrus.Fields {
753- {"Y" : "one" },
754- }, hook .lines )
755-
756800 assert .True (t , testhelper .TestFunctionsCalled ["TestFunction" ])
757801}
758802
@@ -767,7 +811,7 @@ func TestDispatcherPanicsWithTwoAnonFuncs(t *testing.T) {
767811 assert .False (t , mustNotBeTrue )
768812 }()
769813
770- ctx := querysql . WithLogger ( context .Background (), querysql . LogrusMSSQLLogger ( logger , logrus . InfoLevel ) )
814+ ctx := context .Background ()
771815 ctx = querysql .WithDispatcher (ctx , querysql .GoMSSQLDispatcher ([]interface {}{
772816 testhelper .ReturnAnonFunc ("myComponent" ),
773817 testhelper .ReturnAnonFunc ("myComponent2" ), // This should cause a panic
0 commit comments