-
-
Notifications
You must be signed in to change notification settings - Fork 212
/
globals.go
231 lines (201 loc) · 6.08 KB
/
globals.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
package oci8
/*
#cgo !noPkgConfig pkg-config: oci8
#include "oci8.go.h"
*/
import "C"
// noPkgConfig is a Go tag for disabling using pkg-config and using environmental settings like CGO_CFLAGS and CGO_LDFLAGS instead
import (
"context"
"database/sql"
"errors"
"io/ioutil"
"log"
"reflect"
"regexp"
"strconv"
"sync"
"time"
"unsafe"
)
const (
lobBufferSize = 4000
useOCISessionBegin = true
sizeOfNilPointer = unsafe.Sizeof(unsafe.Pointer(nil))
)
type (
// DSN is Oracle Data Source Name
DSN struct {
Connect string
Username string
Password string
prefetchRows C.ub4
prefetchMemory C.ub4
timeLocation *time.Location
transactionMode C.ub4
enableQMPlaceholders bool
operationMode C.ub4
stmtCacheSize C.ub4
}
// DriverStruct is Oracle driver struct
DriverStruct struct {
// Logger is used to log connection ping errors, defaults to discard
// To log set it to something like: log.New(os.Stderr, "oci8 ", log.Ldate|log.Ltime|log.LUTC|log.Lshortfile)
Logger *log.Logger
}
// Connector is the sql driver connector
Connector struct {
// Logger is used to log connection ping errors
Logger *log.Logger
}
// Conn is Oracle connection
Conn struct {
svc *C.OCISvcCtx
srv *C.OCIServer
env *C.OCIEnv
errHandle *C.OCIError
usrSession *C.OCISession
txHandle *C.OCITrans
prefetchRows C.ub4
prefetchMemory C.ub4
transactionMode C.ub4
operationMode C.ub4
stmtCacheSize C.ub4
inTransaction bool
enableQMPlaceholders bool
closed bool
timeLocation *time.Location
logger *log.Logger
}
// Tx is Oracle transaction
Tx struct {
conn *Conn
}
// Stmt is Oracle statement
Stmt struct {
conn *Conn
stmt *C.OCIStmt
closed bool
ctx context.Context
cacheKey string // if statement caching is enabled, this is the key for this statement into the cache
releaseMode C.ub4
}
// Rows is Oracle rows
Rows struct {
stmt *Stmt
defines []defineStruct
closed bool
}
// Result is Oracle result
Result struct {
rowsAffected int64
rowsAffectedErr error
rowid string
rowidErr error
stmt *Stmt
}
defineStruct struct {
name string
dataType C.ub2
pbuf unsafe.Pointer
maxSize C.sb4
length *C.ub2
indicator *C.sb2
defineHandle *C.OCIDefine
subDefines []defineStruct
}
bindStruct struct {
dataType C.ub2
pbuf unsafe.Pointer
maxSize C.sb4
length *C.ub2
indicator *C.sb2
bindHandle *C.OCIBind
out sql.Out
}
)
var (
// ErrOCIInvalidHandle is OCI_INVALID_HANDLE
ErrOCIInvalidHandle = errors.New("OCI_INVALID_HANDLE")
// ErrOCISuccessWithInfo is OCI_SUCCESS_WITH_INFO
ErrOCISuccessWithInfo = errors.New("OCI_SUCCESS_WITH_INFO")
// ErrOCIReservedForIntUse is OCI_RESERVED_FOR_INT_USE
ErrOCIReservedForIntUse = errors.New("OCI_RESERVED_FOR_INT_USE")
// ErrOCINoData is OCI_NO_DATA
ErrOCINoData = errors.New("OCI_NO_DATA")
// ErrOCINeedData is OCI_NEED_DATA
ErrOCINeedData = errors.New("OCI_NEED_DATA")
// ErrOCIStillExecuting is OCI_STILL_EXECUTING
ErrOCIStillExecuting = errors.New("OCI_STILL_EXECUTING")
// ErrNoRowid is result has no rowid
ErrNoRowid = errors.New("result has no rowid")
phre = regexp.MustCompile(`\?`)
defaultCharset = C.ub2(0)
typeNil = reflect.TypeOf(nil)
typeString = reflect.TypeOf("a")
typeSliceByte = reflect.TypeOf([]byte{})
typeInt64 = reflect.TypeOf(int64(1))
typeFloat64 = reflect.TypeOf(float64(1))
typeTime = reflect.TypeOf(time.Time{})
// Driver is the sql driver
Driver = &DriverStruct{
Logger: log.New(ioutil.Discard, "", 0),
}
timeLocations []*time.Location
byteBufferPool = sync.Pool{
New: func() interface{} {
return make([]byte, lobBufferSize)
},
}
)
func init() {
sql.Register("oci8", Driver)
// set defaultCharset to AL32UTF8
var envP *C.OCIEnv
envPP := &envP
var result C.sword
result = C.OCIEnvCreate(envPP, C.OCI_DEFAULT, nil, nil, nil, nil, 0, nil)
if result != C.OCI_SUCCESS {
panic("OCIEnvCreate error")
}
nlsLang := cString("AL32UTF8")
defaultCharset = C.OCINlsCharSetNameToId(unsafe.Pointer(*envPP), (*C.oratext)(nlsLang))
C.free(unsafe.Pointer(nlsLang))
C.OCIHandleFree(unsafe.Pointer(*envPP), C.OCI_HTYPE_ENV)
// build timeLocations: GMT -12 to 14
timeLocationNames := []string{"Etc/GMT+12", "Pacific/Pago_Pago", // -12 to -11
"Pacific/Honolulu", "Pacific/Gambier", "Pacific/Pitcairn", "America/Phoenix", "America/Costa_Rica", // -10 to -6
"America/Panama", "America/Puerto_Rico", "America/Punta_Arenas", "America/Noronha", "Atlantic/Cape_Verde", // -5 to -1
"GMT", // 0
"Africa/Lagos", "Africa/Cairo", "Europe/Moscow", "Asia/Dubai", "Asia/Karachi", // 1 to 5
"Asia/Dhaka", "Asia/Jakarta", "Asia/Shanghai", "Asia/Tokyo", "Australia/Brisbane", // 6 to 10
"Pacific/Noumea", "Asia/Anadyr", "Pacific/Enderbury", "Pacific/Kiritimati", // 11 to 14
}
var err error
timeLocations = make([]*time.Location, len(timeLocationNames))
for i := 0; i < len(timeLocations); i++ {
timeLocations[i], err = time.LoadLocation(timeLocationNames[i])
if err != nil {
name := "GMT"
if i < 12 {
name += strconv.FormatInt(int64(i-12), 10)
} else if i > 12 {
name += "+" + strconv.FormatInt(int64(i-12), 10)
}
timeLocations[i] = time.FixedZone(name, 3600*(i-12))
}
}
}
/*
OCI Documentation Notes
Datatypes:
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/lnoci/data-types.html
Handle and Descriptor Attributes:
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/lnoci/handle-and-descriptor-attributes.html
OCI Function Server Round Trips:
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/lnoci/oci-function-server-round-trips.html
OCI examples:
https://github.com/alexeyvo/oracle_oci_examples
Oracle datatypes:
https://ss64.com/ora/syntax-datatypes.html
*/