-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathcursorRows_test.go
154 lines (134 loc) · 3.11 KB
/
cursorRows_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// SPDX-FileCopyrightText: 2021 SAP SE
// SPDX-FileCopyrightText: 2022 SAP SE
// SPDX-FileCopyrightText: 2023 SAP SE
//
// SPDX-License-Identifier: Apache-2.0
package ase
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
"io"
"strconv"
"sync"
"testing"
"github.com/SAP/go-dblib/dsn"
)
var (
tablePrepared = &sync.Once{}
tablename = "benchmark"
query = "select a, b from " + tablename
)
func prepare(b *testing.B, fn func(*testing.B, *Conn)) {
info, err := NewInfoWithEnv()
if err != nil {
b.Errorf("error reading DSN info from env: %v", err)
return
}
db, err := sql.Open("ase", dsn.FormatSimple(info))
if err != nil {
b.Errorf("failed to open connection to database: %v", err)
return
}
defer db.Close()
errored := false
tablePrepared.Do(func() {
if _, err = db.Exec("if object_id('" + tablename + "') is not null drop table " + tablename); err != nil {
b.Errorf("error dropping table if exists: %v", err)
errored = true
return
}
if _, err := db.Exec("create table " + tablename + " (a bigint, b varchar(100))"); err != nil {
b.Errorf("error creating table: %v", err)
errored = true
return
}
stmt, err := db.Prepare("insert into " + tablename + " values (?, ?)")
if err != nil {
b.Errorf("error preparing insert statement: %v", err)
errored = true
return
}
defer stmt.Close()
for i := 0; i < 1000000; i++ {
iStr := strconv.Itoa(i)
if _, err := stmt.Exec(i, iStr); err != nil {
b.Errorf("error inserting values (%d, %s): %v", i, iStr, err)
errored = true
return
}
}
})
if errored {
return
}
conn, err := db.Conn(context.Background())
if err != nil {
b.Errorf("error getting conn: %v", err)
return
}
defer conn.Close()
_ = conn.Raw(func(driverConn interface{}) error {
conn, ok := driverConn.(*Conn)
if !ok {
b.Errorf("driverConn is not *Conn, is %T", driverConn)
return nil
}
fn(b, conn)
return nil
})
}
func BenchmarkCursorRows_Next(b *testing.B) {
prepare(b, cursorRows_Next)
}
func cursorRows_Next(b *testing.B, conn *Conn) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
cursor, err := conn.NewCursor(context.Background(), query)
if err != nil {
b.Errorf("error creating cursor: %v", err)
return
}
defer cursor.Close(context.Background())
rows, err := cursor.Fetch(context.Background())
if err != nil {
b.Errorf("error fetching rows: %v", err)
return
}
defer rows.Close()
values := []driver.Value{0, ""}
for {
if err := rows.Next(values); err != nil {
if errors.Is(err, io.EOF) {
break
}
b.Errorf("error scanning fields: %v", err)
return
}
}
}
}
func BenchmarkRows_Next(b *testing.B) {
prepare(b, rows_Next)
}
func rows_Next(b *testing.B, conn *Conn) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
rows, _, err := conn.DirectExec(context.Background(), query)
if err != nil {
b.Errorf("error executing statement: %v", err)
return
}
values := []driver.Value{0, ""}
for {
if err := rows.Next(values); err != nil {
if errors.Is(err, io.EOF) {
break
}
b.Errorf("error scanning fields: %v", err)
return
}
}
}
}