Skip to content

Commit e538731

Browse files
authored
Implement sqlexp Messages for Query/QueryContext (#690)
* Ask for usedb and set language messages * add functional test for message queue * first basic version of msg queue * complete messages implementation * fix lint and build issues * fix test to avoid 0 rows in a query * add sqlexp to appveyor yml * fix build * fix the merge * move messageq tests to go1.9 * fix example function and support env vars * implement data type discovery * fix pipeline variables for tests
1 parent b979f7a commit e538731

20 files changed

+762
-85
lines changed

.pipelines/TestSql2017.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ steps:
5858
workingDirectory: '$(Build.SourcesDirectory)'
5959
displayName: 'run tests'
6060
env:
61-
SQLSERVER_DSN: 'server=.;user id=sa;password=$(TESTPASSWORD)'
61+
SQLPASSWORD: $(SQLPASSWORD)
6262
AZURESERVER_DSN: $(AZURESERVER_DSN)
63-
63+
SQLSERVER_DSN: $(SQLSERVER_DSN)
6464
continueOnError: true
6565
- task: PublishTestResults@2
6666
displayName: "Publish junit-style results"

appveyor.yml

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ install:
4949
- go version
5050
- go env
5151
- go get -u github.com/golang-sql/civil
52+
- go get -u github.com/golang-sql/sqlexp
5253

5354
build_script:
5455
- go build

bulkimport_example_test.go

+1-13
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1+
//go:build go1.10
12
// +build go1.10
23

34
package mssql_test
45

56
import (
67
"database/sql"
7-
"flag"
8-
"fmt"
98
"log"
109
"strings"
1110
"unicode/utf8"
@@ -32,19 +31,8 @@ const (
3231

3332
// This example shows how to perform bulk imports
3433
func ExampleCopyIn() {
35-
flag.Parse()
36-
37-
if *debug {
38-
fmt.Printf(" password:%s\n", *password)
39-
fmt.Printf(" port:%d\n", *port)
40-
fmt.Printf(" server:%s\n", *server)
41-
fmt.Printf(" user:%s\n", *user)
42-
}
4334

4435
connString := makeConnURL().String()
45-
if *debug {
46-
fmt.Printf(" connString:%s\n", connString)
47-
}
4836

4937
db, err := sql.Open("sqlserver", connString)
5038
if err != nil {

datetimeoffset_example_test.go

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
//go:build go1.10
12
// +build go1.10
23

34
package mssql_test
45

56
import (
67
"database/sql"
7-
"flag"
88
"fmt"
99
"log"
1010
"time"
@@ -15,19 +15,8 @@ import (
1515

1616
// This example shows how to insert and retrieve date and time types data
1717
func ExampleDateTimeOffset() {
18-
flag.Parse()
19-
20-
if *debug {
21-
fmt.Printf(" password:%s\n", *password)
22-
fmt.Printf(" port:%d\n", *port)
23-
fmt.Printf(" server:%s\n", *server)
24-
fmt.Printf(" user:%s\n", *user)
25-
}
2618

2719
connString := makeConnURL().String()
28-
if *debug {
29-
fmt.Printf(" connString:%s\n", connString)
30-
}
3120

3221
db, err := sql.Open("sqlserver", connString)
3322
if err != nil {

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ require (
66
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0
77
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0
88
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe
9+
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188
910
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
1011
)

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
1010
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
1111
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
1212
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
13+
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4=
14+
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8=
1315
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
1416
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
1517
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=

lastinsertid_example_test.go

+1-13
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,17 @@
1+
//go:build go1.10
12
// +build go1.10
23

34
package mssql_test
45

56
import (
67
"database/sql"
7-
"flag"
8-
"fmt"
98
"log"
109
)
1110

1211
// This example shows the usage of Connector type
1312
func ExampleLastInsertId() {
14-
flag.Parse()
15-
16-
if *debug {
17-
fmt.Printf(" password:%s\n", *password)
18-
fmt.Printf(" port:%d\n", *port)
19-
fmt.Printf(" server:%s\n", *server)
20-
fmt.Printf(" user:%s\n", *user)
21-
}
2213

2314
connString := makeConnURL().String()
24-
if *debug {
25-
fmt.Printf(" connString:%s\n", connString)
26-
}
2715

2816
db, err := sql.Open("sqlserver", connString)
2917
if err != nil {

messages_benchmark_test.go

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// +build go1.14
2+
3+
package mssql
4+
5+
import (
6+
"testing"
7+
)
8+
9+
func BenchmarkMessageQueue(b *testing.B) {
10+
conn, logger := open(b)
11+
defer conn.Close()
12+
defer logger.StopLogging()
13+
14+
b.Run("BlockingQuery", func(b *testing.B) {
15+
var errs, results float64
16+
for i := 0; i < b.N; i++ {
17+
r, err := conn.Query(mixedQuery)
18+
if err != nil {
19+
b.Fatal(err.Error())
20+
}
21+
defer r.Close()
22+
active := true
23+
first := true
24+
for active {
25+
active = r.Next()
26+
if active && first {
27+
results++
28+
}
29+
first = false
30+
if !active {
31+
if r.Err() != nil {
32+
b.Logf("r.Err:%v", r.Err())
33+
errs++
34+
}
35+
active = r.NextResultSet()
36+
if active {
37+
first = true
38+
}
39+
}
40+
}
41+
}
42+
b.ReportMetric(float64(0), "msgs/op")
43+
b.ReportMetric(errs/float64(b.N), "errors/op")
44+
b.ReportMetric(results/float64(b.N), "results/op")
45+
})
46+
b.Run("NonblockingQuery", func(b *testing.B) {
47+
var msgs, errs, results, rowcounts float64
48+
for i := 0; i < b.N; i++ {
49+
m, e, r, rc := testMixedQuery(conn, b)
50+
msgs += float64(m)
51+
errs += float64(e)
52+
results += float64(r)
53+
rowcounts += float64(rc)
54+
if r != 4 {
55+
b.Fatalf("Got wrong results count: %d, expected 4", r)
56+
}
57+
}
58+
b.ReportMetric(msgs/float64(b.N), "msgs/op")
59+
b.ReportMetric(errs/float64(b.N), "errors/op")
60+
b.ReportMetric(results/float64(b.N), "results/op")
61+
b.ReportMetric(rowcounts/float64(b.N), "rowcounts/op")
62+
})
63+
}

messages_example_test.go

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//go:build go1.10
2+
// +build go1.10
3+
4+
package mssql_test
5+
6+
import (
7+
"context"
8+
"database/sql"
9+
"fmt"
10+
"log"
11+
12+
mssql "github.com/denisenkom/go-mssqldb"
13+
"github.com/golang-sql/sqlexp"
14+
)
15+
16+
const (
17+
msgQuery = `select 'name' as Name
18+
PRINT N'This is a message'
19+
select 199
20+
RAISERROR (N'Testing!' , 11, 1)
21+
select 300
22+
`
23+
)
24+
25+
// This example shows the usage of sqlexp/Messages
26+
func ExampleRows_usingmessages() {
27+
28+
connString := makeConnURL().String()
29+
30+
// Create a new connector object by calling NewConnector
31+
connector, err := mssql.NewConnector(connString)
32+
if err != nil {
33+
log.Println(err)
34+
return
35+
}
36+
37+
// Pass connector to sql.OpenDB to get a sql.DB object
38+
db := sql.OpenDB(connector)
39+
defer db.Close()
40+
retmsg := &sqlexp.ReturnMessage{}
41+
ctx := context.Background()
42+
rows, err := db.QueryContext(ctx, msgQuery, retmsg)
43+
if err != nil {
44+
log.Fatalf("QueryContext failed: %v", err)
45+
}
46+
active := true
47+
for active {
48+
msg := retmsg.Message(ctx)
49+
switch m := msg.(type) {
50+
case sqlexp.MsgNotice:
51+
fmt.Println(m.Message)
52+
case sqlexp.MsgNext:
53+
inresult := true
54+
for inresult {
55+
inresult = rows.Next()
56+
if inresult {
57+
cols, err := rows.Columns()
58+
if err != nil {
59+
log.Fatalf("Columns failed: %v", err)
60+
}
61+
fmt.Println(cols)
62+
var d interface{}
63+
if err = rows.Scan(&d); err == nil {
64+
fmt.Println(d)
65+
}
66+
}
67+
}
68+
case sqlexp.MsgNextResultSet:
69+
active = rows.NextResultSet()
70+
case sqlexp.MsgError:
71+
fmt.Println("Error:", m.Error)
72+
case sqlexp.MsgRowsAffected:
73+
fmt.Println("Rows affected:", m.Count)
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)