/
bndLobPtr.go
123 lines (109 loc) · 3.13 KB
/
bndLobPtr.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
// Copyright 2014 Rana Ian. All rights reserved.
// Use of this source code is governed by The MIT License
// found in the accompanying LICENSE file.
package ora
/*
#include <oci.h>
#include "version.h"
*/
import "C"
import "unsafe"
type bndLobPtr struct {
stmt *Stmt
ocibnd *C.OCIBind
ociLobLocator *C.OCILobLocator
value *Lob
}
func (bnd *bndLobPtr) bindLob(lob *Lob, position int, lobBufferSize int, stmt *Stmt) (err error) {
bnd.stmt = stmt
bnd.value = lob
if lobBufferSize <= 0 {
lobBufferSize = lobChunkSize
}
finish, err := bnd.allocTempLob()
if err != nil {
return err
}
if lob != nil && lob.Reader != nil {
if err = writeLob(bnd.ociLobLocator, bnd.stmt, lob.Reader, lobBufferSize); err != nil {
bnd.stmt.ses.Break()
finish()
return err
}
}
if err = bnd.bindByPos(position); err != nil {
finish()
return err
}
return nil
}
func (bnd *bndLobPtr) setPtr() error {
//Log.Infof("%s.setPtr()", bnd)
if bnd.value == nil {
return nil
}
//Log.Infof("setPtr OCILobOpen %p", bnd.ociLobLocator)
lobLength, err := lobOpen(bnd.stmt.ses, bnd.ociLobLocator, C.OCI_LOB_READONLY)
if err != nil {
lobClose(bnd.stmt.ses, bnd.ociLobLocator)
bnd.ociLobLocator = nil
return err
}
lr := &lobReader{
ses: bnd.stmt.ses,
ociLobLocator: bnd.ociLobLocator,
piece: C.OCI_FIRST_PIECE,
Length: lobLength,
}
bnd.value.Reader, bnd.value.Closer = lr, lr
bnd.ociLobLocator = nil
return nil
}
func (bnd *bndLobPtr) close() (err error) {
defer func() {
if value := recover(); value != nil {
err = errR(value)
}
}()
// no need to clear bnd.buf
// free temporary lob
C.OCILobFreeTemporary(
bnd.stmt.ses.ocisvcctx, //OCISvcCtx *svchp,
bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp,
bnd.ociLobLocator) //OCILobLocator *locp,
// free lob locator handle
C.OCIDescriptorFree(
unsafe.Pointer(bnd.ociLobLocator), //void *descp,
C.OCI_DTYPE_LOB) //ub4 type );
stmt := bnd.stmt
bnd.stmt = nil
bnd.value = nil
bnd.ocibnd = nil
bnd.ociLobLocator = nil
stmt.putBnd(bndIdxLobPtr, bnd)
return nil
}
func (bnd *bndLobPtr) allocTempLob() (finish func(), err error) {
bnd.ociLobLocator, finish, err = allocTempLob(bnd.stmt)
return
}
func (bnd *bndLobPtr) bindByPos(position int) error {
r := C.OCIBINDBYPOS(
bnd.stmt.ocistmt, //OCIStmt *stmtp,
(**C.OCIBind)(&bnd.ocibnd), //OCIBind **bindpp,
bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp,
C.ub4(position), //ub4 position,
unsafe.Pointer(&bnd.ociLobLocator), //void *valuep,
C.LENGTH_TYPE(unsafe.Sizeof(bnd.ociLobLocator)), //sb8 value_sz,
C.SQLT_BLOB, //ub2 dty,
nil, //void *indp,
nil, //ub2 *alenp,
nil, //ub2 *rcodep,
0, //ub4 maxarr_len,
nil, //ub4 *curelep,
C.OCI_DEFAULT) //ub4 mode );
if r == C.OCI_ERROR {
return bnd.stmt.ses.srv.env.ociError()
}
return nil
}