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

Implement sqlexp Messages for Query/QueryContext #690

Merged
merged 15 commits into from Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pipelines/TestSql2017.yml
Expand Up @@ -58,9 +58,9 @@ steps:
workingDirectory: '$(Build.SourcesDirectory)'
displayName: 'run tests'
env:
SQLSERVER_DSN: 'server=.;user id=sa;password=$(TESTPASSWORD)'
SQLPASSWORD: $(SQLPASSWORD)
AZURESERVER_DSN: $(AZURESERVER_DSN)

SQLSERVER_DSN: $(SQLSERVER_DSN)
continueOnError: true
- task: PublishTestResults@2
displayName: "Publish junit-style results"
Expand Down
1 change: 1 addition & 0 deletions appveyor.yml
Expand Up @@ -49,6 +49,7 @@ install:
- go version
- go env
- go get -u github.com/golang-sql/civil
- go get -u github.com/golang-sql/sqlexp
shueybubbles marked this conversation as resolved.
Show resolved Hide resolved

build_script:
- go build
Expand Down
14 changes: 1 addition & 13 deletions bulkimport_example_test.go
@@ -1,11 +1,10 @@
//go:build go1.10
// +build go1.10

package mssql_test

import (
"database/sql"
"flag"
"fmt"
"log"
"strings"
"unicode/utf8"
Expand All @@ -32,19 +31,8 @@ const (

// This example shows how to perform bulk imports
func ExampleCopyIn() {
flag.Parse()

if *debug {
fmt.Printf(" password:%s\n", *password)
fmt.Printf(" port:%d\n", *port)
fmt.Printf(" server:%s\n", *server)
fmt.Printf(" user:%s\n", *user)
}

connString := makeConnURL().String()
if *debug {
fmt.Printf(" connString:%s\n", connString)
}

db, err := sql.Open("sqlserver", connString)
if err != nil {
Expand Down
13 changes: 1 addition & 12 deletions datetimeoffset_example_test.go
@@ -1,10 +1,10 @@
//go:build go1.10
// +build go1.10

package mssql_test

import (
"database/sql"
"flag"
"fmt"
"log"
"time"
Expand All @@ -15,19 +15,8 @@ import (

// This example shows how to insert and retrieve date and time types data
func ExampleDateTimeOffset() {
flag.Parse()

if *debug {
fmt.Printf(" password:%s\n", *password)
fmt.Printf(" port:%d\n", *port)
fmt.Printf(" server:%s\n", *server)
fmt.Printf(" user:%s\n", *user)
}

connString := makeConnURL().String()
if *debug {
fmt.Printf(" connString:%s\n", connString)
}

db, err := sql.Open("sqlserver", connString)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -6,5 +6,6 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
)
2 changes: 2 additions & 0 deletions go.sum
Expand Up @@ -10,6 +10,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4=
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
Expand Down
14 changes: 1 addition & 13 deletions lastinsertid_example_test.go
@@ -1,29 +1,17 @@
//go:build go1.10
// +build go1.10

package mssql_test

import (
"database/sql"
"flag"
"fmt"
"log"
)

// This example shows the usage of Connector type
func ExampleLastInsertId() {
flag.Parse()

if *debug {
fmt.Printf(" password:%s\n", *password)
fmt.Printf(" port:%d\n", *port)
fmt.Printf(" server:%s\n", *server)
fmt.Printf(" user:%s\n", *user)
}

connString := makeConnURL().String()
if *debug {
fmt.Printf(" connString:%s\n", connString)
}

db, err := sql.Open("sqlserver", connString)
if err != nil {
Expand Down
63 changes: 63 additions & 0 deletions messages_benchmark_test.go
@@ -0,0 +1,63 @@
// +build go1.14

package mssql

import (
"testing"
)

func BenchmarkMessageQueue(b *testing.B) {
conn, logger := open(b)
defer conn.Close()
defer logger.StopLogging()

b.Run("BlockingQuery", func(b *testing.B) {
var errs, results float64
for i := 0; i < b.N; i++ {
r, err := conn.Query(mixedQuery)
if err != nil {
b.Fatal(err.Error())
}
defer r.Close()
active := true
first := true
for active {
active = r.Next()
if active && first {
results++
}
first = false
if !active {
if r.Err() != nil {
b.Logf("r.Err:%v", r.Err())
errs++
}
active = r.NextResultSet()
if active {
first = true
}
}
}
}
b.ReportMetric(float64(0), "msgs/op")
b.ReportMetric(errs/float64(b.N), "errors/op")
b.ReportMetric(results/float64(b.N), "results/op")
})
b.Run("NonblockingQuery", func(b *testing.B) {
var msgs, errs, results, rowcounts float64
for i := 0; i < b.N; i++ {
m, e, r, rc := testMixedQuery(conn, b)
msgs += float64(m)
errs += float64(e)
results += float64(r)
rowcounts += float64(rc)
if r != 4 {
b.Fatalf("Got wrong results count: %d, expected 4", r)
}
}
b.ReportMetric(msgs/float64(b.N), "msgs/op")
b.ReportMetric(errs/float64(b.N), "errors/op")
b.ReportMetric(results/float64(b.N), "results/op")
b.ReportMetric(rowcounts/float64(b.N), "rowcounts/op")
})
}
76 changes: 76 additions & 0 deletions messages_example_test.go
@@ -0,0 +1,76 @@
//go:build go1.10
// +build go1.10

package mssql_test

import (
"context"
"database/sql"
"fmt"
"log"

mssql "github.com/denisenkom/go-mssqldb"
"github.com/golang-sql/sqlexp"
)

const (
msgQuery = `select 'name' as Name
PRINT N'This is a message'
select 199
RAISERROR (N'Testing!' , 11, 1)
select 300
`
)

// This example shows the usage of sqlexp/Messages
func ExampleRows_usingmessages() {
shueybubbles marked this conversation as resolved.
Show resolved Hide resolved

connString := makeConnURL().String()

// Create a new connector object by calling NewConnector
connector, err := mssql.NewConnector(connString)
if err != nil {
log.Println(err)
return
}

// Pass connector to sql.OpenDB to get a sql.DB object
db := sql.OpenDB(connector)
defer db.Close()
retmsg := &sqlexp.ReturnMessage{}
ctx := context.Background()
rows, err := db.QueryContext(ctx, msgQuery, retmsg)
if err != nil {
log.Fatalf("QueryContext failed: %v", err)
}
active := true
for active {
msg := retmsg.Message(ctx)
switch m := msg.(type) {
case sqlexp.MsgNotice:
fmt.Println(m.Message)
case sqlexp.MsgNext:
inresult := true
for inresult {
inresult = rows.Next()
if inresult {
cols, err := rows.Columns()
if err != nil {
log.Fatalf("Columns failed: %v", err)
}
fmt.Println(cols)
var d interface{}
if err = rows.Scan(&d); err == nil {
fmt.Println(d)
}
}
}
case sqlexp.MsgNextResultSet:
active = rows.NextResultSet()
case sqlexp.MsgError:
fmt.Println("Error:", m.Error)
case sqlexp.MsgRowsAffected:
fmt.Println("Rows affected:", m.Count)
}
}
}