├── .gitattributes ├── .gitignore ├── .idea └── vcs.xml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── appveyor.yml ├── bndBfile.go ├── bndBin.go ├── bndBinSlice.go ├── bndBool.go ├── bndBoolPtr.go ├── bndBoolSlice.go ├── bndDate.go ├── bndDatePtr.go ├── bndDateSlice.go ├── bndFloat32.go ├── bndFloat32Ptr.go ├── bndFloat32Slice.go ├── bndFloat64.go ├── bndFloat64Ptr.go ├── bndFloat64Slice.go ├── bndInt16.go ├── bndInt16Ptr.go ├── bndInt16Slice.go ├── bndInt32.go ├── bndInt32Ptr.go ├── bndInt32Slice.go ├── bndInt64.go ├── bndInt64Ptr.go ├── bndInt64Slice.go ├── bndInt8.go ├── bndInt8Ptr.go ├── bndInt8Slice.go ├── bndIntervalDS.go ├── bndIntervalDSSlice.go ├── bndIntervalYM.go ├── bndIntervalYMSlice.go ├── bndLob.go ├── bndLobPtr.go ├── bndLobSlice.go ├── bndNil.go ├── bndNumString.go ├── bndNumStringPtr.go ├── bndNumStringSlice.go ├── bndOCINum.go ├── bndOCINumPtr.go ├── bndOCINumSlice.go ├── bndRset.go ├── bndString.go ├── bndStringPtr.go ├── bndStringSlice.go ├── bndTime.go ├── bndTimePtr.go ├── bndTimeSlice.go ├── bndUint16.go ├── bndUint16Ptr.go ├── bndUint16Slice.go ├── bndUint32.go ├── bndUint32Ptr.go ├── bndUint32Slice.go ├── bndUint64.go ├── bndUint64Ptr.go ├── bndUint64Slice.go ├── bndUint8.go ├── bndUint8Ptr.go ├── bndUint8Slice.go ├── bnd_hlp.go ├── conn.go ├── conn_go1_7.go ├── conn_go1_8.go ├── const.go ├── contrib ├── oci8.pc ├── oci8_darwin.pc ├── oci8_linux_386.pc ├── oci8_linux_amd64.pc ├── oci8_windows_amd64.pc └── pre-commit ├── ctx.go ├── date ├── date.go ├── date_gen_test.go ├── date_test.go └── date_test.sh ├── defBfile.go ├── defBool.go ├── defDate.go ├── defFloat32.go ├── defFloat64.go ├── defInt16.go ├── defInt32.go ├── defInt64.go ├── defInt8.go ├── defIntervalDS.go ├── defIntervalYM.go ├── defLob.go ├── defLongRaw.go ├── defOCINum.go ├── defRaw.go ├── defRowid.go ├── defRset.go ├── defString.go ├── defTime.go ├── defUint16.go ├── defUint32.go ├── defUint64.go ├── defUint8.go ├── doc.go ├── drv.go ├── drvExecResult.go ├── drvQueryResult.go ├── drvStmt.go ├── drvStmt_go1_8.go ├── env.go ├── examples ├── bench │ ├── .gitignore │ ├── README.md │ ├── gen.go │ ├── oci8 │ │ └── bench_oci8.go │ ├── ora │ │ └── bench_ora.go │ └── run.sh ├── connect │ └── flags.go ├── conntest │ ├── conn_test.go │ └── main.go ├── csvdump │ ├── README.md │ └── csvdump.go └── csvload │ └── csvload.go ├── gen.go ├── glg └── glg.go ├── lg └── lg.go ├── lg15 └── lg15.go ├── list.go ├── logger.go ├── num ├── .gitignore ├── ocinum.go ├── ocinum_fuzz.go └── ocinum_test.go ├── ora.go ├── orm.go ├── pool.go ├── rset.go ├── rsetCfg.go ├── rsetCfg_test.go ├── ses.go ├── srv.go ├── stmt.go ├── stmtCfg.go ├── stmt_go1.go ├── stmt_go1_8.go ├── test-one-by-one.sh ├── test.sh ├── tstlg └── tstlg.go ├── tx.go ├── type.go ├── util.go ├── util_arr.go ├── util_test.go ├── version.c ├── version.h ├── z_benchmem_test.go ├── z_bfile_session_test.go ├── z_bool_session_test.go ├── z_bytes_session_test.go ├── z_db_go1_8_test.go ├── z_db_test.go ├── z_environment_test.go ├── z_example_test.go ├── z_interval_session_test.go ├── z_issue131.go ├── z_issue197.go ├── z_lob_test.go ├── z_numeric_session_test.go ├── z_oracle_test.go ├── z_plsarr_session_test.go ├── z_race.go ├── z_reconn.go ├── z_resultSet_session_test.go ├── z_rowid_session_test.go ├── z_server_session_test.go ├── z_session_test.go ├── z_statement_session_test.go ├── z_string_session_test.go └── z_time_session_test.go /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Rana Ian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | 3 | platform: x64 4 | 5 | branches: 6 | only: 7 | - v4 8 | 9 | clone_depth: 1 10 | 11 | build: 12 | verbosity: detailed 13 | 14 | clone_folder: c:\gopath\src\golang.org\rana\ora.v4 15 | 16 | environment: 17 | GOPATH: c:\gopath 18 | 19 | install: 20 | - echo %PATH% 21 | - echo %GOPATH% 22 | - go version 23 | - go env 24 | - curl -sS -o c:\gopath\instantclient-sdk-windows.zip https://s3.amazonaws.com/tgulacsi-oracle-instantclient/instantclient-sdk-windows.x64-12.1.0.2.0.zip 25 | - 7z x -oc:\ c:\gopath\instantclient-sdk-windows.zip 26 | - curl -sS -o c:\gopath\instantclient-basiclite-windows.zip https://s3.amazonaws.com/tgulacsi-oracle-instantclient/instantclient-basiclite-windows.x64-12.1.0.2.0.zip 27 | - 7z x -oc:\ c:\gopath\instantclient-basiclite-windows.zip 28 | - go get -v -t ./... 29 | 30 | build_script: 31 | - go install -v . 32 | 33 | artifacts: 34 | - path: c:\gopath\pkg\windows_amd64\gopkg.in\rana\ora.v4 35 | name: binary 36 | 37 | deploy: 38 | release: ora.v4-$(appveyor_build_version) 39 | description: 'Release of precompiled windows binaries' 40 | provider: GitHub 41 | artifact: binary 42 | draft: true 43 | on: 44 | branch: v4 45 | 46 | # vim: set filetype=yaml et shiftwidth=2: 47 | -------------------------------------------------------------------------------- /bndBin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type bndBin struct { 16 | stmt *Stmt 17 | ocibnd *C.OCIBind 18 | } 19 | 20 | func (bnd *bndBin) bind(value []byte, position namedPos, stmt *Stmt) (err error) { 21 | bnd.stmt = stmt 22 | ph, phLen, phFree := position.CString() 23 | if ph != nil { 24 | defer phFree() 25 | } 26 | r := C.bindByNameOrPos( 27 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 28 | &bnd.ocibnd, //OCIBind **bindpp, 29 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 30 | C.ub4(position.Ordinal), //ub4 position, 31 | ph, 32 | phLen, 33 | unsafe.Pointer(&value[0]), //void *valuep, 34 | C.LENGTH_TYPE(len(value)), //sb8 value_sz, 35 | C.SQLT_LBI, //ub2 dty, 36 | nil, //void *indp, 37 | nil, //ub2 *alenp, 38 | nil, //ub2 *rcodep, 39 | 0, //ub4 maxarr_len, 40 | nil, //ub4 *curelep, 41 | C.OCI_DEFAULT) //ub4 mode ); 42 | if r == C.OCI_ERROR { 43 | return bnd.stmt.ses.srv.env.ociError() 44 | } 45 | return nil 46 | } 47 | 48 | func (bnd *bndBin) setPtr() error { 49 | return nil 50 | } 51 | 52 | func (bnd *bndBin) free() { 53 | } 54 | 55 | func (bnd *bndBin) close() (err error) { 56 | defer func() { 57 | if value := recover(); value != nil { 58 | err = errR(value) 59 | } 60 | }() 61 | stmt := bnd.stmt 62 | bnd.stmt = nil 63 | stmt.putBnd(bndIdxBin, bnd) 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /bndBinSlice.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | type bndBinSlice struct { 17 | stmt *Stmt 18 | ocibnd *C.OCIBind 19 | buf []byte 20 | arrHlp 21 | } 22 | 23 | func (bnd *bndBinSlice) bindOra(values []Raw, position namedPos, lobBufferSize int, stmt *Stmt, isAssocArray bool) (iterations uint32, err error) { 24 | binValues := make([][]byte, len(values)) 25 | nullInds := make([]C.sb2, len(values)) 26 | for i := range values { 27 | if values[i].IsNull { 28 | nullInds[i] = C.sb2(-1) 29 | } else { 30 | binValues[i] = values[i].Value 31 | } 32 | } 33 | return bnd.bind(binValues, nullInds, position, lobBufferSize, stmt, isAssocArray) 34 | } 35 | 36 | func (bnd *bndBinSlice) bind(values [][]byte, nullInds []C.sb2, position namedPos, lobBufferSize int, stmt *Stmt, isAssocArray bool) (iterations uint32, err error) { 37 | bnd.stmt = stmt 38 | L, C := len(values), cap(values) 39 | iterations, curlenp, needAppend := bnd.ensureBindArrLength(&L, &C, isAssocArray) 40 | if needAppend { 41 | values = append(values, []byte{}) 42 | } 43 | var maxLen int 44 | for _, b := range values { 45 | if len(b) > maxLen { 46 | maxLen = len(b) 47 | } 48 | } 49 | if maxLen == 0 { 50 | maxLen = 1 51 | } 52 | n := maxLen * L 53 | if cap(bnd.buf) < n { 54 | //bnd.buf = make([]byte, n) 55 | bnd.buf = bytesPool.Get(n)[:n] 56 | } else { 57 | bnd.buf = bnd.buf[:n] 58 | // reset buffer 59 | for i := range bnd.buf { 60 | bnd.buf[i] = 0 61 | } 62 | } 63 | for i, b := range values { 64 | copy(bnd.buf[i*maxLen:], b) 65 | bnd.alen[i] = C.ACTUAL_LENGTH_TYPE(len(b)) 66 | } 67 | ph, phLen, phFree := position.CString() 68 | if ph != nil { 69 | defer phFree() 70 | } 71 | r := C.bindByNameOrPos( 72 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 73 | &bnd.ocibnd, //OCIBind **bindpp, 74 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 75 | C.ub4(position.Ordinal), //ub4 position, 76 | ph, 77 | phLen, 78 | unsafe.Pointer(&bnd.buf[0]), //void *valuep, 79 | C.LENGTH_TYPE(maxLen), //sb8 value_sz, 80 | C.SQLT_LBI, //ub2 dty, 81 | unsafe.Pointer(&bnd.nullInds[0]), //void *indp, 82 | &bnd.alen[0], //ub4 *alenp, 83 | &bnd.rcode[0], //ub2 *rcodep, 84 | getMaxarrLen(C, isAssocArray), //ub4 maxarr_len, 85 | curlenp, //ub4 *curelep, 86 | C.OCI_DEFAULT) //ub4 mode ); 87 | if r == C.OCI_ERROR { 88 | return iterations, bnd.stmt.ses.srv.env.ociError() 89 | } 90 | r = C.OCIBindArrayOfStruct( 91 | bnd.ocibnd, 92 | bnd.stmt.ses.srv.env.ocierr, 93 | C.ub4(maxLen), //ub4 pvskip, 94 | C.ub4(C.sizeof_sb2), //ub4 indskip, 95 | C.ub4(C.sizeof_ub4), //ub4 alskip, 96 | C.ub4(C.sizeof_ub2)) //ub4 rcskip 97 | if r == C.OCI_ERROR { 98 | return iterations, bnd.stmt.ses.srv.env.ociError() 99 | } 100 | return iterations, nil 101 | } 102 | 103 | func (bnd *bndBinSlice) setPtr() error { 104 | return nil 105 | } 106 | 107 | func (bnd *bndBinSlice) close() (err error) { 108 | defer func() { 109 | if value := recover(); value != nil { 110 | err = errR(value) 111 | } 112 | }() 113 | stmt := bnd.stmt 114 | bnd.stmt = nil 115 | bnd.ocibnd = nil 116 | bytesPool.Put(bnd.buf) 117 | bnd.buf = nil 118 | bnd.arrHlp.close() 119 | stmt.putBnd(bndIdxBinSlice, bnd) 120 | return nil 121 | } 122 | -------------------------------------------------------------------------------- /bndBool.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "strconv" 15 | "unsafe" 16 | ) 17 | 18 | type bndBool struct { 19 | stmt *Stmt 20 | ocibnd *C.OCIBind 21 | cString *C.char 22 | } 23 | 24 | func (bnd *bndBool) bind(value bool, position namedPos, c StmtCfg, stmt *Stmt) (err error) { 25 | //Log.Infof("%s.bind(%t, %d)", bnd, value, position) 26 | bnd.stmt = stmt 27 | var str string 28 | if value { 29 | str, err = strconv.Unquote(strconv.QuoteRune(c.TrueRune)) 30 | } else { 31 | str, err = strconv.Unquote(strconv.QuoteRune(c.FalseRune)) 32 | } 33 | if err != nil { 34 | return err 35 | } 36 | bnd.cString = C.CString(str) 37 | ph, phLen, phFree := position.CString() 38 | if ph != nil { 39 | defer phFree() 40 | } 41 | r := C.bindByNameOrPos( 42 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 43 | &bnd.ocibnd, //OCIBind **bindpp, 44 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 45 | C.ub4(position.Ordinal), //ub4 position, 46 | ph, 47 | phLen, 48 | unsafe.Pointer(bnd.cString), //void *valuep, 49 | C.LENGTH_TYPE(1), //sb8 value_sz, 50 | C.SQLT_AFC, //ub2 dty, 51 | nil, //void *indp, 52 | nil, //ub2 *alenp, 53 | nil, //ub2 *rcodep, 54 | 0, //ub4 maxarr_len, 55 | nil, //ub4 *curelep, 56 | C.OCI_DEFAULT) //ub4 mode ); 57 | if r == C.OCI_ERROR { 58 | return bnd.stmt.ses.srv.env.ociError() 59 | } 60 | return nil 61 | } 62 | 63 | func (bnd *bndBool) setPtr() error { 64 | return nil 65 | } 66 | 67 | func (bnd *bndBool) close() (err error) { 68 | defer func() { 69 | if value := recover(); value != nil { 70 | err = errR(value) 71 | } 72 | }() 73 | 74 | C.free(unsafe.Pointer(bnd.cString)) 75 | stmt := bnd.stmt 76 | bnd.stmt = nil 77 | bnd.ocibnd = nil 78 | bnd.cString = nil 79 | stmt.putBnd(bndIdxBool, bnd) 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /bndBoolPtr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "bytes" 14 | "unicode/utf8" 15 | "unsafe" 16 | ) 17 | 18 | type bndBoolPtr struct { 19 | stmt *Stmt 20 | ocibnd *C.OCIBind 21 | value *bool 22 | buf []byte 23 | trueRune rune 24 | nullp 25 | } 26 | 27 | func (bnd *bndBoolPtr) bind(value *bool, position namedPos, trueRune rune, stmt *Stmt) error { 28 | //Log.Infof("%v.bind(%t, %d)", bnd, value, position) 29 | bnd.stmt = stmt 30 | bnd.value = value 31 | bnd.trueRune = trueRune 32 | if cap(bnd.buf) < 2 { 33 | bnd.buf = make([]byte, 2) 34 | } 35 | if value != nil && *value { 36 | if _, err := bytes.NewBuffer(bnd.buf).WriteRune(trueRune); err != nil { 37 | return err 38 | } 39 | } 40 | ph, phLen, phFree := position.CString() 41 | if ph != nil { 42 | defer phFree() 43 | } 44 | r := C.bindByNameOrPos( 45 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 46 | &bnd.ocibnd, 47 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 48 | C.ub4(position.Ordinal), //ub4 position, 49 | ph, 50 | phLen, 51 | unsafe.Pointer(&bnd.buf[0]), //void *valuep, 52 | C.LENGTH_TYPE(len(bnd.buf)), //sb8 value_sz, 53 | C.SQLT_CHR, //ub2 dty, 54 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 55 | nil, //ub2 *alenp, 56 | nil, //ub2 *rcodep, 57 | 0, //ub4 maxarr_len, 58 | nil, //ub4 *curelep, 59 | C.OCI_DEFAULT) //ub4 mode ); 60 | if r == C.OCI_ERROR { 61 | return bnd.stmt.ses.srv.env.ociError() 62 | } 63 | return nil 64 | } 65 | 66 | func (bnd *bndBoolPtr) setPtr() error { 67 | //Log.Infof("%s.setPtr()", bnd) 68 | if !bnd.nullp.IsNull() { 69 | r, _ := utf8.DecodeRune(bnd.buf) 70 | *bnd.value = r == bnd.trueRune 71 | } else { 72 | bnd.value = nil 73 | } 74 | return nil 75 | } 76 | 77 | func (bnd *bndBoolPtr) close() (err error) { 78 | defer func() { 79 | if value := recover(); value != nil { 80 | err = errR(value) 81 | } 82 | }() 83 | 84 | stmt := bnd.stmt 85 | bnd.stmt = nil 86 | bnd.ocibnd = nil 87 | bnd.value = nil 88 | bnd.nullp.Free() 89 | clear(bnd.buf, 0) 90 | stmt.putBnd(bndIdxBoolPtr, bnd) 91 | return nil 92 | } 93 | -------------------------------------------------------------------------------- /bndBoolSlice.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "bytes" 14 | "unsafe" 15 | ) 16 | 17 | type bndBoolSlice struct { 18 | stmt *Stmt 19 | ocibnd *C.OCIBind 20 | buf bytes.Buffer 21 | bytes []byte 22 | } 23 | 24 | func (bnd *bndBoolSlice) bindOra(values []Bool, position namedPos, falseRune rune, trueRune rune, stmt *Stmt) error { 25 | boolValues := make([]bool, len(values)) 26 | nullInds := make([]C.sb2, len(values)) 27 | for n := range values { 28 | if values[n].IsNull { 29 | nullInds[n] = C.sb2(-1) 30 | } else { 31 | boolValues[n] = values[n].Value 32 | } 33 | } 34 | return bnd.bind(boolValues, nullInds, position, falseRune, trueRune, stmt) 35 | } 36 | 37 | func (bnd *bndBoolSlice) bind(values []bool, nullInds []C.sb2, position namedPos, falseRune rune, trueRune rune, stmt *Stmt) (err error) { 38 | bnd.stmt = stmt 39 | if nullInds == nil { 40 | nullInds = make([]C.sb2, len(values)) 41 | } 42 | alenp := make([]C.ACTUAL_LENGTH_TYPE, len(values)) 43 | rcodep := make([]C.ub2, len(values)) 44 | var maxLen = 1 45 | for n, bValue := range values { 46 | if bValue { 47 | _, err = bnd.buf.WriteRune(trueRune) 48 | if err != nil { 49 | return err 50 | } 51 | } else { 52 | _, err = bnd.buf.WriteRune(falseRune) 53 | if err != nil { 54 | return err 55 | } 56 | } 57 | alenp[n] = 1 58 | } 59 | bnd.bytes = bnd.buf.Bytes() 60 | 61 | ph, phLen, phFree := position.CString() 62 | if ph != nil { 63 | defer phFree() 64 | } 65 | r := C.bindByNameOrPos( 66 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 67 | &bnd.ocibnd, 68 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 69 | C.ub4(position.Ordinal), //ub4 position, 70 | ph, 71 | phLen, 72 | unsafe.Pointer(&bnd.bytes[0]), //void *valuep, 73 | C.LENGTH_TYPE(maxLen), //sb8 value_sz, 74 | C.SQLT_CHR, //ub2 dty, 75 | unsafe.Pointer(&nullInds[0]), //void *indp, 76 | &alenp[0], //ub4 *alenp, 77 | &rcodep[0], //ub2 *rcodep, 78 | 0, //ub4 maxarr_len, 79 | nil, //ub4 *curelep, 80 | C.OCI_DEFAULT) //ub4 mode ); 81 | if r == C.OCI_ERROR { 82 | return bnd.stmt.ses.srv.env.ociError() 83 | } 84 | 85 | r = C.OCIBindArrayOfStruct( 86 | bnd.ocibnd, //OCIBind *bindp, 87 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 88 | C.ub4(maxLen), //ub4 pvskip, 89 | C.ub4(C.sizeof_sb2), //ub4 indskip, 90 | C.ub4(C.sizeof_ub4), //ub4 alskip, 91 | C.ub4(C.sizeof_ub2)) //ub4 rcskip 92 | if r == C.OCI_ERROR { 93 | return bnd.stmt.ses.srv.env.ociError() 94 | } 95 | 96 | return nil 97 | } 98 | 99 | func (bnd *bndBoolSlice) setPtr() error { 100 | return nil 101 | } 102 | 103 | func (bnd *bndBoolSlice) close() (err error) { 104 | defer func() { 105 | if value := recover(); value != nil { 106 | err = errR(value) 107 | } 108 | }() 109 | 110 | stmt := bnd.stmt 111 | bnd.stmt = nil 112 | bnd.ocibnd = nil 113 | bnd.bytes = nil 114 | bnd.buf.Reset() 115 | stmt.putBnd(bndIdxBoolSlice, bnd) 116 | return nil 117 | } 118 | -------------------------------------------------------------------------------- /bndDate.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include 11 | #include "version.h" 12 | */ 13 | import "C" 14 | import ( 15 | "unsafe" 16 | 17 | "gopkg.in/rana/ora.v4/date" 18 | ) 19 | 20 | type bndDate struct { 21 | stmt *Stmt 22 | ocibnd *C.OCIBind 23 | } 24 | 25 | func (bnd *bndDate) bind(dt date.Date, position namedPos, stmt *Stmt) error { 26 | bnd.stmt = stmt 27 | ph, phLen, phFree := position.CString() 28 | if ph != nil { 29 | defer phFree() 30 | } 31 | r := C.bindByNameOrPos( 32 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 33 | &bnd.ocibnd, //OCIBind **bindpp, 34 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 35 | C.ub4(position.Ordinal), //ub4 position, 36 | ph, 37 | phLen, 38 | unsafe.Pointer(&dt), //void *valuep, 39 | C.LENGTH_TYPE(7), //sb8 value_sz, 40 | C.SQLT_DAT, //ub2 dty, 41 | nil, //void *indp, 42 | nil, //ub2 *alenp, 43 | nil, //ub2 *rcodep, 44 | 0, //ub4 maxarr_len, 45 | nil, //ub4 *curelep, 46 | C.OCI_DEFAULT) //ub4 mode ); 47 | if r == C.OCI_ERROR { 48 | return bnd.stmt.ses.srv.env.ociError() 49 | } 50 | return nil 51 | } 52 | 53 | func (bnd *bndDate) setPtr() (err error) { 54 | return nil 55 | } 56 | 57 | func (bnd *bndDate) close() (err error) { 58 | defer func() { 59 | if value := recover(); value != nil { 60 | err = errR(value) 61 | } 62 | }() 63 | 64 | stmt := bnd.stmt 65 | bnd.stmt = nil 66 | bnd.ocibnd = nil 67 | stmt.putBnd(bndIdxDate, bnd) 68 | return nil 69 | } 70 | -------------------------------------------------------------------------------- /bndDatePtr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "time" 15 | "unsafe" 16 | 17 | "gopkg.in/rana/ora.v4/date" 18 | ) 19 | 20 | type bndDatePtr struct { 21 | stmt *Stmt 22 | ocibnd *C.OCIBind 23 | value *Date 24 | ocidate [1]date.Date 25 | nullp 26 | } 27 | 28 | func (bnd *bndDatePtr) bind(value *Date, position namedPos, stmt *Stmt) error { 29 | bnd.stmt = stmt 30 | bnd.value = value 31 | bnd.nullp.Set(value == nil || value.IsNull()) 32 | if value != nil { 33 | bnd.ocidate[0] = value.Date 34 | } 35 | //bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "bind val=%#v null?=%t datep=%#v (%v)\n", bnd.value, bnd.nullp.IsNull(), bnd.datep, bnd.datep.Get()) 36 | ph, phLen, phFree := position.CString() 37 | if ph != nil { 38 | defer phFree() 39 | } 40 | r := C.bindByNameOrPos( 41 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 42 | &bnd.ocibnd, //OCIBind **bindpp, 43 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 44 | C.ub4(position.Ordinal), //ub4 position, 45 | ph, 46 | phLen, 47 | unsafe.Pointer(&bnd.ocidate[0]), //void *valuep, 48 | C.LENGTH_TYPE(7), //sb8 value_sz, 49 | C.SQLT_DAT, //ub2 dty, 50 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 51 | nil, //ub2 *alenp, 52 | nil, //ub2 *rcodep, 53 | 0, //ub4 maxarr_len, 54 | nil, //ub4 *curelep, 55 | C.OCI_DEFAULT) //ub4 mode ); 56 | if r == C.OCI_ERROR { 57 | return bnd.stmt.ses.srv.env.ociError() 58 | } 59 | return nil 60 | } 61 | 62 | func (bnd *bndDatePtr) setPtr() (err error) { 63 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "setPtr val=%#v nullp=%#v datep=%#v (%v)\n", bnd.value, bnd.nullp, bnd.ocidate[0], bnd.ocidate[0].Get()) 64 | 65 | if bnd.value == nil { 66 | return nil 67 | } 68 | if bnd.nullp.IsNull() { 69 | bnd.value.Set(time.Time{}) 70 | return nil 71 | } 72 | bnd.value.Date = bnd.ocidate[0] 73 | return nil 74 | } 75 | 76 | func (bnd *bndDatePtr) close() (err error) { 77 | defer func() { 78 | if value := recover(); value != nil { 79 | err = errR(value) 80 | } 81 | }() 82 | 83 | stmt := bnd.stmt 84 | bnd.stmt = nil 85 | bnd.ocibnd = nil 86 | bnd.value = nil 87 | bnd.nullp.Free() 88 | stmt.putBnd(bndIdxDatePtr, bnd) 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /bndFloat32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | type bndFloat32 struct { 17 | stmt *Stmt 18 | ocibnd *C.OCIBind 19 | ociNumber [1]C.OCINumber 20 | } 21 | 22 | func (bnd *bndFloat32) bind(value float32, position namedPos, stmt *Stmt) error { 23 | bnd.stmt = stmt 24 | r := C.OCINumberFromReal( 25 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 26 | unsafe.Pointer(&value), //const void *rnum, 27 | byteWidth32, //uword rnum_length, 28 | &bnd.ociNumber[0]) //OCINumber *number ); 29 | if r == C.OCI_ERROR { 30 | return bnd.stmt.ses.srv.env.ociError() 31 | } 32 | 33 | ph, phLen, phFree := position.CString() 34 | if ph != nil { 35 | defer phFree() 36 | } 37 | r = C.bindByNameOrPos( 38 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 39 | &bnd.ocibnd, 40 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 41 | C.ub4(position.Ordinal), //ub4 position, 42 | ph, 43 | phLen, 44 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 45 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 46 | C.SQLT_VNU, //ub2 dty, 47 | nil, //void *indp, 48 | nil, //ub2 *alenp, 49 | nil, //ub2 *rcodep, 50 | 0, //ub4 maxarr_len, 51 | nil, //ub4 *curelep, 52 | C.OCI_DEFAULT) //ub4 mode ); 53 | if r == C.OCI_ERROR { 54 | return bnd.stmt.ses.srv.env.ociError() 55 | } 56 | return nil 57 | } 58 | 59 | func (bnd *bndFloat32) setPtr() error { 60 | return nil 61 | } 62 | 63 | func (bnd *bndFloat32) close() (err error) { 64 | defer func() { 65 | if value := recover(); value != nil { 66 | err = errR(value) 67 | } 68 | }() 69 | 70 | stmt := bnd.stmt 71 | bnd.stmt = nil 72 | bnd.ocibnd = nil 73 | stmt.putBnd(bndIdxFloat32, bnd) 74 | return nil 75 | } 76 | -------------------------------------------------------------------------------- /bndFloat32Ptr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | type bndFloat32Ptr struct { 17 | stmt *Stmt 18 | ocibnd *C.OCIBind 19 | ociNumber [1]C.OCINumber 20 | value *float32 21 | valueIsNull *bool 22 | nullp 23 | } 24 | 25 | func (bnd *bndFloat32Ptr) bind(value *float32, valueIsNull *bool, position namedPos, stmt *Stmt) error { 26 | bnd.stmt = stmt 27 | bnd.value = value 28 | bnd.valueIsNull = valueIsNull 29 | bnd.nullp.Set(value == nil) 30 | if value != nil { 31 | if err := bnd.stmt.ses.srv.env.OCINumberFromFloat(&bnd.ociNumber[0], float64(*value), byteWidth32); err != nil { 32 | return err 33 | } 34 | } 35 | ph, phLen, phFree := position.CString() 36 | if ph != nil { 37 | defer phFree() 38 | } 39 | r := C.bindByNameOrPos( 40 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 41 | &bnd.ocibnd, 42 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 43 | C.ub4(position.Ordinal), //ub4 position, 44 | ph, 45 | phLen, 46 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 47 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 48 | C.SQLT_VNU, //ub2 dty, 49 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 50 | nil, //ub2 *alenp, 51 | nil, //ub2 *rcodep, 52 | 0, //ub4 maxarr_len, 53 | nil, //ub4 *curelep, 54 | C.OCI_DEFAULT) //ub4 mode ); 55 | if r == C.OCI_ERROR { 56 | return bnd.stmt.ses.srv.env.ociError() 57 | } 58 | return nil 59 | } 60 | 61 | func (bnd *bndFloat32Ptr) setPtr() error { 62 | if bnd.valueIsNull != nil { 63 | *bnd.valueIsNull = bnd.nullp.IsNull() 64 | } 65 | if bnd.nullp.IsNull() { 66 | return nil 67 | } 68 | f, err := bnd.stmt.ses.srv.env.OCINumberToFloat(&bnd.ociNumber[0], byteWidth32) 69 | *bnd.value = float32(f) 70 | 71 | return err 72 | } 73 | 74 | func (bnd *bndFloat32Ptr) close() (err error) { 75 | defer func() { 76 | if value := recover(); value != nil { 77 | err = errR(value) 78 | } 79 | }() 80 | 81 | stmt := bnd.stmt 82 | bnd.stmt = nil 83 | bnd.ocibnd = nil 84 | bnd.value = nil 85 | bnd.valueIsNull = nil 86 | bnd.nullp.Free() 87 | stmt.putBnd(bndIdxFloat32Ptr, bnd) 88 | return nil 89 | } 90 | -------------------------------------------------------------------------------- /bndFloat64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | type bndFloat64 struct { 17 | stmt *Stmt 18 | ocibnd *C.OCIBind 19 | ociNumber [1]C.OCINumber 20 | } 21 | 22 | func (bnd *bndFloat64) bind(value float64, position namedPos, stmt *Stmt) error { 23 | bnd.stmt = stmt 24 | r := C.OCINumberFromReal( 25 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 26 | unsafe.Pointer(&value), //const void *rnum, 27 | byteWidth64, //uword rnum_length, 28 | &bnd.ociNumber[0]) //OCINumber *number ); 29 | if r == C.OCI_ERROR { 30 | return bnd.stmt.ses.srv.env.ociError() 31 | } 32 | 33 | ph, phLen, phFree := position.CString() 34 | if ph != nil { 35 | defer phFree() 36 | } 37 | r = C.bindByNameOrPos( 38 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 39 | &bnd.ocibnd, 40 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 41 | C.ub4(position.Ordinal), //ub4 position, 42 | ph, 43 | phLen, 44 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 45 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 46 | C.SQLT_VNU, //ub2 dty, 47 | nil, //void *indp, 48 | nil, //ub2 *alenp, 49 | nil, //ub2 *rcodep, 50 | 0, //ub4 maxarr_len, 51 | nil, //ub4 *curelep, 52 | C.OCI_DEFAULT) //ub4 mode ); 53 | if r == C.OCI_ERROR { 54 | return bnd.stmt.ses.srv.env.ociError() 55 | } 56 | return nil 57 | } 58 | 59 | func (bnd *bndFloat64) setPtr() error { 60 | return nil 61 | } 62 | 63 | func (bnd *bndFloat64) close() (err error) { 64 | defer func() { 65 | if value := recover(); value != nil { 66 | err = errR(value) 67 | } 68 | }() 69 | 70 | stmt := bnd.stmt 71 | bnd.stmt = nil 72 | bnd.ocibnd = nil 73 | stmt.putBnd(bndIdxFloat64, bnd) 74 | return nil 75 | } 76 | -------------------------------------------------------------------------------- /bndFloat64Ptr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | type bndFloat64Ptr struct { 17 | stmt *Stmt 18 | ocibnd *C.OCIBind 19 | ociNumber [1]C.OCINumber 20 | value *float64 21 | valueIsNull *bool 22 | nullp 23 | } 24 | 25 | func (bnd *bndFloat64Ptr) bind(value *float64, valueIsNull *bool, position namedPos, stmt *Stmt) error { 26 | bnd.stmt = stmt 27 | bnd.value = value 28 | bnd.valueIsNull = valueIsNull 29 | bnd.nullp.Set(value == nil) 30 | if value != nil { 31 | if err := bnd.stmt.ses.srv.env.OCINumberFromFloat(&bnd.ociNumber[0], floatSixtyFour(*value), byteWidth64); err != nil { 32 | return err 33 | } 34 | } 35 | ph, phLen, phFree := position.CString() 36 | if ph != nil { 37 | defer phFree() 38 | } 39 | r := C.bindByNameOrPos( 40 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 41 | &bnd.ocibnd, 42 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 43 | C.ub4(position.Ordinal), //ub4 position, 44 | ph, 45 | phLen, 46 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 47 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 48 | C.SQLT_VNU, //ub2 dty, 49 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 50 | nil, //ub2 *alenp, 51 | nil, //ub2 *rcodep, 52 | 0, //ub4 maxarr_len, 53 | nil, //ub4 *curelep, 54 | C.OCI_DEFAULT) //ub4 mode ); 55 | if r == C.OCI_ERROR { 56 | return bnd.stmt.ses.srv.env.ociError() 57 | } 58 | return nil 59 | } 60 | 61 | func (bnd *bndFloat64Ptr) setPtr() error { 62 | if bnd.valueIsNull != nil { 63 | *bnd.valueIsNull = bnd.nullp.IsNull() 64 | } 65 | if bnd.nullp.IsNull() { 66 | return nil 67 | } 68 | f, err := bnd.stmt.ses.srv.env.OCINumberToFloat(&bnd.ociNumber[0], byteWidth64) 69 | *bnd.value = float64(f) 70 | 71 | return err 72 | } 73 | 74 | func (bnd *bndFloat64Ptr) close() (err error) { 75 | defer func() { 76 | if value := recover(); value != nil { 77 | err = errR(value) 78 | } 79 | }() 80 | 81 | stmt := bnd.stmt 82 | bnd.stmt = nil 83 | bnd.ocibnd = nil 84 | bnd.value = nil 85 | bnd.valueIsNull = nil 86 | bnd.nullp.Free() 87 | stmt.putBnd(bndIdxFloat64Ptr, bnd) 88 | return nil 89 | } 90 | -------------------------------------------------------------------------------- /bndInt16.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type bndInt16 struct { 15 | stmt *Stmt 16 | ocibnd *C.OCIBind 17 | ociNumber [1]C.OCINumber 18 | } 19 | 20 | func (bnd *bndInt16) bind(value int16, position namedPos, stmt *Stmt) error { 21 | bnd.stmt = stmt 22 | r := C.OCINumberFromInt( 23 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 24 | unsafe.Pointer(&value), //const void *inum, 25 | byteWidth16, //uword inum_length, 26 | C.OCI_NUMBER_SIGNED, //uword inum_s_flag, 27 | &bnd.ociNumber[0]) //OCINumber *number ); 28 | if r == C.OCI_ERROR { 29 | return bnd.stmt.ses.srv.env.ociError() 30 | } 31 | ph, phLen, phFree := position.CString() 32 | if ph != nil { 33 | defer phFree() 34 | } 35 | r = C.bindByNameOrPos( 36 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 37 | &bnd.ocibnd, 38 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 39 | C.ub4(position.Ordinal), //ub4 position, 40 | ph, 41 | phLen, 42 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 43 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 44 | C.SQLT_VNU, //ub2 dty, 45 | nil, //void *indp, 46 | nil, //ub2 *alenp, 47 | nil, //ub2 *rcodep, 48 | 0, //ub4 maxarr_len, 49 | nil, //ub4 *curelep, 50 | C.OCI_DEFAULT) //ub4 mode ); 51 | if r == C.OCI_ERROR { 52 | return bnd.stmt.ses.srv.env.ociError() 53 | } 54 | return nil 55 | } 56 | 57 | func (bnd *bndInt16) setPtr() error { 58 | return nil 59 | } 60 | 61 | func (bnd *bndInt16) close() (err error) { 62 | defer func() { 63 | if value := recover(); value != nil { 64 | err = errR(value) 65 | } 66 | }() 67 | 68 | stmt := bnd.stmt 69 | bnd.stmt = nil 70 | bnd.ocibnd = nil 71 | stmt.putBnd(bndIdxInt16, bnd) 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /bndInt16Ptr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type bndInt16Ptr struct { 16 | stmt *Stmt 17 | ocibnd *C.OCIBind 18 | ociNumber [1]C.OCINumber 19 | value *int16 20 | valueIsNull *bool 21 | nullp 22 | } 23 | 24 | func (bnd *bndInt16Ptr) bind(value *int16, valueIsNull *bool, position namedPos, stmt *Stmt) error { 25 | //bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "Int16Ptr.bind(%d) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 26 | bnd.stmt = stmt 27 | bnd.value = value 28 | bnd.valueIsNull = valueIsNull 29 | bnd.nullp.Set(value == nil) 30 | if value != nil { 31 | if err := bnd.stmt.ses.srv.env.OCINumberFromInt(&bnd.ociNumber[0], int64(*value), byteWidth16); err != nil { 32 | return err 33 | } 34 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, 35 | "Int16Ptr.bind(%v) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 36 | } 37 | ph, phLen, phFree := position.CString() 38 | if ph != nil { 39 | defer phFree() 40 | } 41 | r := C.bindByNameOrPos( 42 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 43 | &bnd.ocibnd, 44 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 45 | C.ub4(position.Ordinal), //ub4 position, 46 | ph, 47 | phLen, 48 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 49 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 50 | C.SQLT_VNU, //ub2 dty, 51 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 52 | nil, //ub2 *alenp, 53 | nil, //ub2 *rcodep, 54 | 0, //ub4 maxarr_len, 55 | nil, //ub4 *curelep, 56 | C.OCI_DEFAULT) //ub4 mode ); 57 | if r == C.OCI_ERROR { 58 | return bnd.stmt.ses.srv.env.ociError() 59 | } 60 | return nil 61 | } 62 | 63 | func (bnd *bndInt16Ptr) setPtr() error { 64 | if bnd.valueIsNull != nil { 65 | *bnd.valueIsNull = bnd.nullp.IsNull() 66 | } 67 | if bnd.nullp.IsNull() { 68 | return nil 69 | } 70 | i, err := bnd.stmt.ses.srv.env.OCINumberToInt(&bnd.ociNumber[0], byteWidth16) 71 | *bnd.value = int16(i) 72 | 73 | return err 74 | } 75 | 76 | func (bnd *bndInt16Ptr) close() (err error) { 77 | defer func() { 78 | if value := recover(); value != nil { 79 | err = errR(value) 80 | } 81 | }() 82 | 83 | stmt := bnd.stmt 84 | bnd.stmt = nil 85 | bnd.ocibnd = nil 86 | bnd.value = nil 87 | bnd.valueIsNull = nil 88 | bnd.nullp.Free() 89 | stmt.putBnd(bndIdxInt16Ptr, bnd) 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /bndInt32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type bndInt32 struct { 15 | stmt *Stmt 16 | ocibnd *C.OCIBind 17 | ociNumber [1]C.OCINumber 18 | } 19 | 20 | func (bnd *bndInt32) bind(value int32, position namedPos, stmt *Stmt) error { 21 | bnd.stmt = stmt 22 | r := C.OCINumberFromInt( 23 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 24 | unsafe.Pointer(&value), //const void *inum, 25 | byteWidth32, //uword inum_length, 26 | C.OCI_NUMBER_SIGNED, //uword inum_s_flag, 27 | &bnd.ociNumber[0]) //OCINumber *number ); 28 | if r == C.OCI_ERROR { 29 | return bnd.stmt.ses.srv.env.ociError() 30 | } 31 | ph, phLen, phFree := position.CString() 32 | if ph != nil { 33 | defer phFree() 34 | } 35 | r = C.bindByNameOrPos( 36 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 37 | &bnd.ocibnd, 38 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 39 | C.ub4(position.Ordinal), //ub4 position, 40 | ph, 41 | phLen, 42 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 43 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 44 | C.SQLT_VNU, //ub2 dty, 45 | nil, //void *indp, 46 | nil, //ub2 *alenp, 47 | nil, //ub2 *rcodep, 48 | 0, //ub4 maxarr_len, 49 | nil, //ub4 *curelep, 50 | C.OCI_DEFAULT) //ub4 mode ); 51 | if r == C.OCI_ERROR { 52 | return bnd.stmt.ses.srv.env.ociError() 53 | } 54 | return nil 55 | } 56 | 57 | func (bnd *bndInt32) setPtr() error { 58 | return nil 59 | } 60 | 61 | func (bnd *bndInt32) close() (err error) { 62 | defer func() { 63 | if value := recover(); value != nil { 64 | err = errR(value) 65 | } 66 | }() 67 | 68 | stmt := bnd.stmt 69 | bnd.stmt = nil 70 | bnd.ocibnd = nil 71 | stmt.putBnd(bndIdxInt32, bnd) 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /bndInt32Ptr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type bndInt32Ptr struct { 16 | stmt *Stmt 17 | ocibnd *C.OCIBind 18 | ociNumber [1]C.OCINumber 19 | value *int32 20 | valueIsNull *bool 21 | nullp 22 | } 23 | 24 | func (bnd *bndInt32Ptr) bind(value *int32, valueIsNull *bool, position namedPos, stmt *Stmt) error { 25 | //bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "Int32Ptr.bind(%d) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 26 | bnd.stmt = stmt 27 | bnd.value = value 28 | bnd.valueIsNull = valueIsNull 29 | bnd.nullp.Set(value == nil) 30 | if value != nil { 31 | if err := bnd.stmt.ses.srv.env.OCINumberFromInt(&bnd.ociNumber[0], int64(*value), byteWidth32); err != nil { 32 | return err 33 | } 34 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, 35 | "Int32Ptr.bind(%v) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 36 | } 37 | ph, phLen, phFree := position.CString() 38 | if ph != nil { 39 | defer phFree() 40 | } 41 | r := C.bindByNameOrPos( 42 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 43 | &bnd.ocibnd, 44 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 45 | C.ub4(position.Ordinal), //ub4 position, 46 | ph, 47 | phLen, 48 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 49 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 50 | C.SQLT_VNU, //ub2 dty, 51 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 52 | nil, //ub2 *alenp, 53 | nil, //ub2 *rcodep, 54 | 0, //ub4 maxarr_len, 55 | nil, //ub4 *curelep, 56 | C.OCI_DEFAULT) //ub4 mode ); 57 | if r == C.OCI_ERROR { 58 | return bnd.stmt.ses.srv.env.ociError() 59 | } 60 | return nil 61 | } 62 | 63 | func (bnd *bndInt32Ptr) setPtr() error { 64 | if bnd.valueIsNull != nil { 65 | *bnd.valueIsNull = bnd.nullp.IsNull() 66 | } 67 | if bnd.nullp.IsNull() { 68 | return nil 69 | } 70 | i, err := bnd.stmt.ses.srv.env.OCINumberToInt(&bnd.ociNumber[0], byteWidth32) 71 | *bnd.value = int32(i) 72 | 73 | return err 74 | } 75 | 76 | func (bnd *bndInt32Ptr) close() (err error) { 77 | defer func() { 78 | if value := recover(); value != nil { 79 | err = errR(value) 80 | } 81 | }() 82 | 83 | stmt := bnd.stmt 84 | bnd.stmt = nil 85 | bnd.ocibnd = nil 86 | bnd.value = nil 87 | bnd.valueIsNull = nil 88 | bnd.nullp.Free() 89 | stmt.putBnd(bndIdxInt32Ptr, bnd) 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /bndInt64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type bndInt64 struct { 15 | stmt *Stmt 16 | ocibnd *C.OCIBind 17 | ociNumber [1]C.OCINumber 18 | } 19 | 20 | func (bnd *bndInt64) bind(value int64, position namedPos, stmt *Stmt) error { 21 | bnd.stmt = stmt 22 | r := C.OCINumberFromInt( 23 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 24 | unsafe.Pointer(&value), //const void *inum, 25 | byteWidth64, //uword inum_length, 26 | C.OCI_NUMBER_SIGNED, //uword inum_s_flag, 27 | &bnd.ociNumber[0]) //OCINumber *number ); 28 | if r == C.OCI_ERROR { 29 | return bnd.stmt.ses.srv.env.ociError() 30 | } 31 | ph, phLen, phFree := position.CString() 32 | if ph != nil { 33 | defer phFree() 34 | } 35 | r = C.bindByNameOrPos( 36 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 37 | &bnd.ocibnd, 38 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 39 | C.ub4(position.Ordinal), //ub4 position, 40 | ph, 41 | phLen, 42 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 43 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 44 | C.SQLT_VNU, //ub2 dty, 45 | nil, //void *indp, 46 | nil, //ub2 *alenp, 47 | nil, //ub2 *rcodep, 48 | 0, //ub4 maxarr_len, 49 | nil, //ub4 *curelep, 50 | C.OCI_DEFAULT) //ub4 mode ); 51 | if r == C.OCI_ERROR { 52 | return bnd.stmt.ses.srv.env.ociError() 53 | } 54 | return nil 55 | } 56 | 57 | func (bnd *bndInt64) setPtr() error { 58 | return nil 59 | } 60 | 61 | func (bnd *bndInt64) close() (err error) { 62 | defer func() { 63 | if value := recover(); value != nil { 64 | err = errR(value) 65 | } 66 | }() 67 | 68 | stmt := bnd.stmt 69 | bnd.stmt = nil 70 | bnd.ocibnd = nil 71 | stmt.putBnd(bndIdxInt64, bnd) 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /bndInt64Ptr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type bndInt64Ptr struct { 16 | stmt *Stmt 17 | ocibnd *C.OCIBind 18 | ociNumber [1]C.OCINumber 19 | value *int64 20 | valueIsNull *bool 21 | nullp 22 | } 23 | 24 | func (bnd *bndInt64Ptr) bind(value *int64, valueIsNull *bool, position namedPos, stmt *Stmt) error { 25 | //bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "Int64Ptr.bind(%d) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 26 | bnd.stmt = stmt 27 | bnd.value = value 28 | bnd.valueIsNull = valueIsNull 29 | bnd.nullp.Set(value == nil) 30 | if value != nil { 31 | if err := bnd.stmt.ses.srv.env.OCINumberFromInt(&bnd.ociNumber[0], intSixtyFour(*value), byteWidth64); err != nil { 32 | return err 33 | } 34 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, 35 | "Int64Ptr.bind(%v) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 36 | } 37 | ph, phLen, phFree := position.CString() 38 | if ph != nil { 39 | defer phFree() 40 | } 41 | r := C.bindByNameOrPos( 42 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 43 | &bnd.ocibnd, 44 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 45 | C.ub4(position.Ordinal), //ub4 position, 46 | ph, 47 | phLen, 48 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 49 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 50 | C.SQLT_VNU, //ub2 dty, 51 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 52 | nil, //ub2 *alenp, 53 | nil, //ub2 *rcodep, 54 | 0, //ub4 maxarr_len, 55 | nil, //ub4 *curelep, 56 | C.OCI_DEFAULT) //ub4 mode ); 57 | if r == C.OCI_ERROR { 58 | return bnd.stmt.ses.srv.env.ociError() 59 | } 60 | return nil 61 | } 62 | 63 | func (bnd *bndInt64Ptr) setPtr() error { 64 | if bnd.valueIsNull != nil { 65 | *bnd.valueIsNull = bnd.nullp.IsNull() 66 | } 67 | if bnd.nullp.IsNull() { 68 | return nil 69 | } 70 | i, err := bnd.stmt.ses.srv.env.OCINumberToInt(&bnd.ociNumber[0], byteWidth64) 71 | *bnd.value = int64(i) 72 | 73 | return err 74 | } 75 | 76 | func (bnd *bndInt64Ptr) close() (err error) { 77 | defer func() { 78 | if value := recover(); value != nil { 79 | err = errR(value) 80 | } 81 | }() 82 | 83 | stmt := bnd.stmt 84 | bnd.stmt = nil 85 | bnd.ocibnd = nil 86 | bnd.value = nil 87 | bnd.valueIsNull = nil 88 | bnd.nullp.Free() 89 | stmt.putBnd(bndIdxInt64Ptr, bnd) 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /bndInt8.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type bndInt8 struct { 15 | stmt *Stmt 16 | ocibnd *C.OCIBind 17 | ociNumber [1]C.OCINumber 18 | } 19 | 20 | func (bnd *bndInt8) bind(value int8, position namedPos, stmt *Stmt) error { 21 | bnd.stmt = stmt 22 | r := C.OCINumberFromInt( 23 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 24 | unsafe.Pointer(&value), //const void *inum, 25 | byteWidth8, //uword inum_length, 26 | C.OCI_NUMBER_SIGNED, //uword inum_s_flag, 27 | &bnd.ociNumber[0]) //OCINumber *number ); 28 | if r == C.OCI_ERROR { 29 | return bnd.stmt.ses.srv.env.ociError() 30 | } 31 | ph, phLen, phFree := position.CString() 32 | if ph != nil { 33 | defer phFree() 34 | } 35 | r = C.bindByNameOrPos( 36 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 37 | &bnd.ocibnd, 38 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 39 | C.ub4(position.Ordinal), //ub4 position, 40 | ph, 41 | phLen, 42 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 43 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 44 | C.SQLT_VNU, //ub2 dty, 45 | nil, //void *indp, 46 | nil, //ub2 *alenp, 47 | nil, //ub2 *rcodep, 48 | 0, //ub4 maxarr_len, 49 | nil, //ub4 *curelep, 50 | C.OCI_DEFAULT) //ub4 mode ); 51 | if r == C.OCI_ERROR { 52 | return bnd.stmt.ses.srv.env.ociError() 53 | } 54 | return nil 55 | } 56 | 57 | func (bnd *bndInt8) setPtr() error { 58 | return nil 59 | } 60 | 61 | func (bnd *bndInt8) close() (err error) { 62 | defer func() { 63 | if value := recover(); value != nil { 64 | err = errR(value) 65 | } 66 | }() 67 | 68 | stmt := bnd.stmt 69 | bnd.stmt = nil 70 | bnd.ocibnd = nil 71 | stmt.putBnd(bndIdxInt8, bnd) 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /bndInt8Ptr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type bndInt8Ptr struct { 16 | stmt *Stmt 17 | ocibnd *C.OCIBind 18 | ociNumber [1]C.OCINumber 19 | value *int8 20 | valueIsNull *bool 21 | nullp 22 | } 23 | 24 | func (bnd *bndInt8Ptr) bind(value *int8, valueIsNull *bool, position namedPos, stmt *Stmt) error { 25 | //bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "Int8Ptr.bind(%d) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 26 | bnd.stmt = stmt 27 | bnd.value = value 28 | bnd.valueIsNull = valueIsNull 29 | bnd.nullp.Set(value == nil) 30 | if value != nil { 31 | if err := bnd.stmt.ses.srv.env.OCINumberFromInt(&bnd.ociNumber[0], int64(*value), byteWidth8); err != nil { 32 | return err 33 | } 34 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, 35 | "Int8Ptr.bind(%v) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 36 | } 37 | ph, phLen, phFree := position.CString() 38 | if ph != nil { 39 | defer phFree() 40 | } 41 | r := C.bindByNameOrPos( 42 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 43 | &bnd.ocibnd, 44 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 45 | C.ub4(position.Ordinal), //ub4 position, 46 | ph, 47 | phLen, 48 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 49 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 50 | C.SQLT_VNU, //ub2 dty, 51 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 52 | nil, //ub2 *alenp, 53 | nil, //ub2 *rcodep, 54 | 0, //ub4 maxarr_len, 55 | nil, //ub4 *curelep, 56 | C.OCI_DEFAULT) //ub4 mode ); 57 | if r == C.OCI_ERROR { 58 | return bnd.stmt.ses.srv.env.ociError() 59 | } 60 | return nil 61 | } 62 | 63 | func (bnd *bndInt8Ptr) setPtr() error { 64 | if bnd.valueIsNull != nil { 65 | *bnd.valueIsNull = bnd.nullp.IsNull() 66 | } 67 | if bnd.nullp.IsNull() { 68 | return nil 69 | } 70 | i, err := bnd.stmt.ses.srv.env.OCINumberToInt(&bnd.ociNumber[0], byteWidth8) 71 | *bnd.value = int8(i) 72 | 73 | return err 74 | } 75 | 76 | func (bnd *bndInt8Ptr) close() (err error) { 77 | defer func() { 78 | if value := recover(); value != nil { 79 | err = errR(value) 80 | } 81 | }() 82 | 83 | stmt := bnd.stmt 84 | bnd.stmt = nil 85 | bnd.ocibnd = nil 86 | bnd.value = nil 87 | bnd.valueIsNull = nil 88 | bnd.nullp.Free() 89 | stmt.putBnd(bndIdxInt8Ptr, bnd) 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /bndIntervalDS.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | type bndIntervalDS struct { 17 | stmt *Stmt 18 | ocibnd *C.OCIBind 19 | intervalp 20 | } 21 | 22 | func (bnd *bndIntervalDS) bind(value IntervalDS, position namedPos, stmt *Stmt) error { 23 | bnd.stmt = stmt 24 | r := C.OCIDescriptorAlloc( 25 | unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv), //CONST dvoid *parenth, 26 | (*unsafe.Pointer)(unsafe.Pointer(bnd.intervalp.Pointer())), //dvoid **descpp, 27 | C.OCI_DTYPE_INTERVAL_DS, //ub4 type, 28 | 0, //size_t xtramem_sz, 29 | nil) //dvoid **usrmempp); 30 | if r == C.OCI_ERROR { 31 | return bnd.stmt.ses.srv.env.ociError() 32 | } else if r == C.OCI_INVALID_HANDLE { 33 | return errNew("unable to allocate oci interval handle during bind") 34 | } 35 | r = C.OCIIntervalSetDaySecond( 36 | unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv), //void *hndl, 37 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 38 | C.sb4(value.Day), //sb4 dy, 39 | C.sb4(value.Hour), //sb4 hr, 40 | C.sb4(value.Minute), //sb4 mm, 41 | C.sb4(value.Second), //sb4 ss, 42 | C.sb4(value.Nanosecond), //sb4 fsec, 43 | bnd.intervalp.Value()) //OCIInterval *result ); 44 | if r == C.OCI_ERROR { 45 | return bnd.stmt.ses.srv.env.ociError() 46 | } 47 | ph, phLen, phFree := position.CString() 48 | if ph != nil { 49 | defer phFree() 50 | } 51 | r = C.bindByNameOrPos( 52 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 53 | &bnd.ocibnd, 54 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 55 | C.ub4(position.Ordinal), //ub4 position, 56 | ph, 57 | phLen, 58 | unsafe.Pointer(bnd.intervalp.Pointer()), //void *valuep, 59 | C.LENGTH_TYPE(bnd.intervalp.Size()), //sb8 value_sz, 60 | C.SQLT_INTERVAL_DS, //ub2 dty, 61 | nil, //void *indp, 62 | nil, //ub2 *alenp, 63 | nil, //ub2 *rcodep, 64 | 0, //ub4 maxarr_len, 65 | nil, //ub4 *curelep, 66 | C.OCI_DEFAULT) //ub4 mode ); 67 | if r == C.OCI_ERROR { 68 | return bnd.stmt.ses.srv.env.ociError() 69 | } 70 | return nil 71 | } 72 | 73 | func (bnd *bndIntervalDS) setPtr() error { 74 | return nil 75 | } 76 | 77 | func (bnd *bndIntervalDS) close() (err error) { 78 | defer func() { 79 | if value := recover(); value != nil { 80 | err = errR(value) 81 | } 82 | }() 83 | 84 | C.OCIDescriptorFree( 85 | unsafe.Pointer(bnd.intervalp.Pointer()), //void *descp, 86 | C.OCI_DTYPE_INTERVAL_DS) //timeDefine.descTypeCode) 87 | stmt := bnd.stmt 88 | bnd.stmt = nil 89 | bnd.ocibnd = nil 90 | bnd.intervalp.Free() 91 | stmt.putBnd(bndIdxIntervalDS, bnd) 92 | return nil 93 | } 94 | -------------------------------------------------------------------------------- /bndIntervalYM.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | type bndIntervalYM struct { 17 | stmt *Stmt 18 | ocibnd *C.OCIBind 19 | intervalp 20 | } 21 | 22 | func (bnd *bndIntervalYM) bind(value IntervalYM, position namedPos, stmt *Stmt) error { 23 | bnd.stmt = stmt 24 | r := C.OCIDescriptorAlloc( 25 | unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv), //CONST dvoid *parenth, 26 | (*unsafe.Pointer)(unsafe.Pointer(bnd.intervalp.Pointer())), //dvoid **descpp, 27 | C.OCI_DTYPE_INTERVAL_YM, //ub4 type, 28 | 0, //size_t xtramem_sz, 29 | nil) //dvoid **usrmempp); 30 | if r == C.OCI_ERROR { 31 | return bnd.stmt.ses.srv.env.ociError() 32 | } else if r == C.OCI_INVALID_HANDLE { 33 | return errNew("unable to allocate oci interval handle during bind") 34 | } 35 | r = C.OCIIntervalSetYearMonth( 36 | unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv), //void *hndl, 37 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 38 | C.sb4(value.Year), //sb4 yr, 39 | C.sb4(value.Month), //sb4 mnth, 40 | bnd.intervalp.Value()) //OCIInterval *result ); 41 | if r == C.OCI_ERROR { 42 | return bnd.stmt.ses.srv.env.ociError() 43 | } 44 | ph, phLen, phFree := position.CString() 45 | if ph != nil { 46 | defer phFree() 47 | } 48 | r = C.bindByNameOrPos( 49 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 50 | &bnd.ocibnd, 51 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 52 | C.ub4(position.Ordinal), //ub4 position, 53 | ph, 54 | phLen, 55 | unsafe.Pointer(bnd.intervalp.Pointer()), //void *valuep, 56 | C.LENGTH_TYPE(bnd.intervalp.Size()), //sb8 value_sz, 57 | C.SQLT_INTERVAL_YM, //ub2 dty, 58 | nil, //void *indp, 59 | nil, //ub2 *alenp, 60 | nil, //ub2 *rcodep, 61 | 0, //ub4 maxarr_len, 62 | nil, //ub4 *curelep, 63 | C.OCI_DEFAULT) //ub4 mode ); 64 | if r == C.OCI_ERROR { 65 | return bnd.stmt.ses.srv.env.ociError() 66 | } 67 | return nil 68 | } 69 | 70 | func (bnd *bndIntervalYM) setPtr() error { 71 | return nil 72 | } 73 | 74 | func (bnd *bndIntervalYM) close() (err error) { 75 | defer func() { 76 | if value := recover(); value != nil { 77 | err = errR(value) 78 | } 79 | }() 80 | 81 | C.OCIDescriptorFree( 82 | unsafe.Pointer(bnd.intervalp.Value()), //void *descp, 83 | C.OCI_DTYPE_INTERVAL_YM) //timeDefine.descTypeCode) //ub4 type ); 84 | stmt := bnd.stmt 85 | bnd.stmt = nil 86 | bnd.ocibnd = nil 87 | bnd.intervalp.Free() 88 | stmt.putBnd(bndIdxIntervalYM, bnd) 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /bndNil.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | type bndNil struct { 17 | stmt *Stmt 18 | ocibnd *C.OCIBind 19 | } 20 | 21 | func (bnd *bndNil) bind(position namedPos, sqlt C.ub2, stmt *Stmt) error { 22 | bnd.stmt = stmt 23 | indp := C.sb2(-1) 24 | ph, phLen, phFree := position.CString() 25 | if ph != nil { 26 | defer phFree() 27 | } 28 | r := C.bindByNameOrPos( 29 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 30 | &bnd.ocibnd, //OCIBind **bindpp, 31 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 32 | C.ub4(position.Ordinal), //ub4 position, 33 | ph, 34 | phLen, 35 | nil, //void *valuep, 36 | 0, //sb8 value_sz, 37 | sqlt, //C.SQLT_CHR, //ub2 dty, 38 | unsafe.Pointer(&indp), //void *indp, 39 | nil, //ub2 *alenp, 40 | nil, //ub2 *rcodep, 41 | 0, //ub4 maxarr_len, 42 | nil, //ub4 *curelep, 43 | C.OCI_DEFAULT) //ub4 mode ); 44 | if r == C.OCI_ERROR { 45 | return bnd.stmt.ses.srv.env.ociError() 46 | } 47 | 48 | return nil 49 | } 50 | 51 | func (bnd *bndNil) setPtr() error { 52 | return nil 53 | } 54 | 55 | func (bnd *bndNil) close() (err error) { 56 | defer func() { 57 | if value := recover(); value != nil { 58 | err = errR(value) 59 | } 60 | }() 61 | 62 | stmt := bnd.stmt 63 | bnd.stmt = nil 64 | bnd.ocibnd = nil 65 | stmt.putBnd(bndIdxNil, bnd) 66 | return nil 67 | } 68 | -------------------------------------------------------------------------------- /bndNumStringPtr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type bndNumStringPtr struct { 15 | stmt *Stmt 16 | ocibnd *C.OCIBind 17 | ociNumber [1]C.OCINumber 18 | value *Num 19 | buf [numStringLen]byte 20 | nullp 21 | } 22 | 23 | func (bnd *bndNumStringPtr) bind(value *Num, position namedPos, stmt *Stmt) error { 24 | bnd.stmt = stmt 25 | bnd.value = value 26 | bnd.nullp.Set(value == nil || *value == "") 27 | //length := C.ub4(0) 28 | if value != nil && *value != "" { 29 | //length = C.ub4(copy(bnd.buf[:], string(*value))) 30 | //fmt.Printf("NumberFromtext %q [%d]\n", value, length) 31 | if err := bnd.stmt.ses.srv.env.numberFromText(&bnd.ociNumber[0], string(*value)); err != nil { 32 | return err 33 | } 34 | } 35 | ph, phLen, phFree := position.CString() 36 | if ph != nil { 37 | defer phFree() 38 | } 39 | r := C.bindByNameOrPos( 40 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 41 | &bnd.ocibnd, 42 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 43 | C.ub4(position.Ordinal), //ub4 position, 44 | ph, 45 | phLen, 46 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 47 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 48 | C.SQLT_VNU, //ub2 dty, 49 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 50 | nil, //ub2 *alenp, 51 | nil, //ub2 *rcodep, 52 | 0, //ub4 maxarr_len, 53 | nil, //ub4 *curelep, 54 | C.OCI_DEFAULT) //ub4 mode ); 55 | if r == C.OCI_ERROR { 56 | return bnd.stmt.ses.srv.env.ociError() 57 | } 58 | return nil 59 | } 60 | 61 | func (bnd *bndNumStringPtr) setPtr() error { 62 | if bnd.nullp.IsNull() { 63 | return nil 64 | } 65 | bufLen := C.ub4(numStringLen) 66 | r := C.OCINumberToText( 67 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 68 | &bnd.ociNumber[0], //const OCINumber *number, 69 | numberFmtC, 70 | C.ub4(numberFmtLen), //ub4 fmt_length, 71 | numberNLSC, //CONST OraText *nls_params, 72 | C.ub4(numberNLSLen), //ub4 nls_p_length, 73 | &bufLen, 74 | (*C.oratext)(unsafe.Pointer(&bnd.buf[0])), //void *rsl ); 75 | ) 76 | if r == C.OCI_ERROR { 77 | return bnd.stmt.ses.srv.env.ociError() 78 | } 79 | if bufLen > 0 && bnd.buf[0] == '.' { 80 | *bnd.value = Num(append(append(make([]byte, 0, int(bufLen)+1), 81 | '0'), 82 | bnd.buf[:int(bufLen)]...)) 83 | } else { 84 | *bnd.value = Num(bnd.buf[:int(bufLen)]) 85 | } 86 | return nil 87 | } 88 | 89 | func (bnd *bndNumStringPtr) close() (err error) { 90 | defer func() { 91 | if value := recover(); value != nil { 92 | err = errR(value) 93 | } 94 | }() 95 | 96 | stmt := bnd.stmt 97 | bnd.stmt = nil 98 | bnd.ocibnd = nil 99 | bnd.value = nil 100 | bnd.nullp.Free() 101 | stmt.putBnd(bndIdxNumStringPtr, bnd) 102 | return nil 103 | } 104 | -------------------------------------------------------------------------------- /bndNumStringSlice.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | 11 | */ 12 | import "C" 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | type bndNumStringSlice struct { 18 | stmt *Stmt 19 | ocibnd *C.OCIBind 20 | ociNumbers []C.OCINumber 21 | arrHlp 22 | } 23 | 24 | func (bnd *bndNumStringSlice) bindOra(values []OraNum, position namedPos, stmt *Stmt, isAssocArray bool) (iterations uint32, err error) { 25 | stringValues := make([]Num, len(values)) 26 | if cap(bnd.nullInds) < len(values) { 27 | bnd.nullInds = make([]C.sb2, len(values)) 28 | } else { 29 | bnd.nullInds = bnd.nullInds[:len(values)] 30 | } 31 | for n := range values { 32 | if values[n].IsNull { 33 | bnd.nullInds[n] = C.sb2(-1) 34 | } else { 35 | stringValues[n] = Num(values[n].Value) 36 | } 37 | } 38 | return bnd.bind(stringValues, bnd.nullInds, position, stmt, isAssocArray) 39 | } 40 | 41 | func (bnd *bndNumStringSlice) bind(values []Num, nullInds []C.sb2, position namedPos, stmt *Stmt, isAssocArray bool) (iterations uint32, err error) { 42 | bnd.stmt = stmt 43 | L, C := len(values), cap(values) 44 | if nullInds != nil { 45 | bnd.nullInds = nullInds 46 | } 47 | iterations, curlenp, needAppend := bnd.ensureBindArrLength(&L, &C, isAssocArray) 48 | if needAppend { 49 | values = append(values, Num("0")) 50 | } 51 | bnd.ociNumbers = make([]C.OCINumber, len(values)) 52 | alen := C.ACTUAL_LENGTH_TYPE(C.sizeof_OCINumber) 53 | for n := range values { 54 | bnd.alen[n] = alen 55 | numbers := bnd.ociNumbers[n : n+1 : n+1] // against _cgoCheckPointer0 56 | if err := bnd.stmt.ses.srv.env.numberFromText(&numbers[0], string(values[n])); err != nil { 57 | return iterations, err 58 | } 59 | } 60 | ph, phLen, phFree := position.CString() 61 | if ph != nil { 62 | defer phFree() 63 | } 64 | r := C.bindByNameOrPos( 65 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 66 | &bnd.ocibnd, 67 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 68 | C.ub4(position.Ordinal), //ub4 position, 69 | ph, 70 | phLen, 71 | unsafe.Pointer(&bnd.ociNumbers[0]), //void *valuep, 72 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 73 | C.SQLT_VNU, //ub2 dty, 74 | unsafe.Pointer(&bnd.nullInds[0]), //void *indp, 75 | &bnd.alen[0], //ub4 *alenp, 76 | &bnd.rcode[0], //ub2 *rcodep, 77 | getMaxarrLen(C, isAssocArray), //ub4 maxarr_len, 78 | curlenp, //ub4 *curelep, 79 | C.OCI_DEFAULT) //ub4 mode ); 80 | if r == C.OCI_ERROR { 81 | return iterations, bnd.stmt.ses.srv.env.ociError() 82 | } 83 | r = C.OCIBindArrayOfStruct( 84 | bnd.ocibnd, 85 | bnd.stmt.ses.srv.env.ocierr, 86 | C.ub4(C.sizeof_OCINumber), //ub4 pvskip, 87 | C.ub4(C.sizeof_sb2), //ub4 indskip, 88 | C.ub4(C.sizeof_ub4), //ub4 alskip, 89 | C.ub4(C.sizeof_ub2)) //ub4 rcskip 90 | if r == C.OCI_ERROR { 91 | return iterations, bnd.stmt.ses.srv.env.ociError() 92 | } 93 | return iterations, nil 94 | } 95 | 96 | func (bnd *bndNumStringSlice) setPtr() error { 97 | return nil 98 | } 99 | 100 | func (bnd *bndNumStringSlice) close() (err error) { 101 | defer func() { 102 | if value := recover(); value != nil { 103 | err = errR(value) 104 | } 105 | }() 106 | 107 | stmt := bnd.stmt 108 | bnd.stmt = nil 109 | bnd.ocibnd = nil 110 | bnd.ociNumbers = nil 111 | bnd.arrHlp.close() 112 | stmt.putBnd(bndIdxNumStringSlice, bnd) 113 | return nil 114 | } 115 | -------------------------------------------------------------------------------- /bndOCINum.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Tamás Gulácsi. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // FromC converts from the given C.OCINumber. 16 | func (num *OCINum) FromC(x C.OCINumber) { 17 | a := *(*[22]byte)(unsafe.Pointer(&x)) 18 | length := int(a[0]) 19 | if length < 0 || length > 21 { 20 | num.OCINum = num.OCINum[:0] 21 | return 22 | } 23 | 24 | if cap(num.OCINum) < length { 25 | num.OCINum = make([]byte, length, 22-1) 26 | } else { 27 | num.OCINum = num.OCINum[:length] 28 | } 29 | copy(num.OCINum[:length], a[1:1+length]) 30 | } 31 | 32 | // ToC converts the OCINum into the given *C.OCINumber. 33 | func (num OCINum) ToC(x *C.OCINumber) { 34 | a := ((*[22]byte)(unsafe.Pointer(x))) 35 | a[0] = byte(len(num.OCINum)) 36 | copy(a[1:1+len(num.OCINum)], num.OCINum) 37 | for i := 1 + len(num.OCINum); i < 22; i++ { 38 | a[i] = 0 39 | } 40 | } 41 | 42 | type bndOCINum struct { 43 | stmt *Stmt 44 | ocibnd *C.OCIBind 45 | ociNumber [1]C.OCINumber 46 | } 47 | 48 | func (bnd *bndOCINum) bind(value OCINum, position namedPos, stmt *Stmt) error { 49 | bnd.stmt = stmt 50 | value.ToC(&bnd.ociNumber[0]) 51 | ph, phLen, phFree := position.CString() 52 | if ph != nil { 53 | defer phFree() 54 | } 55 | r := C.bindByNameOrPos( 56 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 57 | &bnd.ocibnd, 58 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 59 | C.ub4(position.Ordinal), //ub4 position, 60 | ph, 61 | phLen, 62 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 63 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 64 | C.SQLT_VNU, //ub2 dty, 65 | nil, //void *indp, 66 | nil, //ub2 *alenp, 67 | nil, //ub2 *rcodep, 68 | 0, //ub4 maxarr_len, 69 | nil, //ub4 *curelep, 70 | C.OCI_DEFAULT) //ub4 mode ); 71 | if r == C.OCI_ERROR { 72 | return bnd.stmt.ses.srv.env.ociError() 73 | } 74 | return nil 75 | } 76 | 77 | func (bnd *bndOCINum) setPtr() error { 78 | return nil 79 | } 80 | 81 | func (bnd *bndOCINum) close() (err error) { 82 | defer func() { 83 | if value := recover(); value != nil { 84 | err = errR(value) 85 | } 86 | }() 87 | 88 | stmt := bnd.stmt 89 | bnd.stmt = nil 90 | bnd.ocibnd = nil 91 | stmt.putBnd(bndIdxOCINum, bnd) 92 | return nil 93 | } 94 | -------------------------------------------------------------------------------- /bndOCINumPtr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type bndOCINumPtr struct { 15 | stmt *Stmt 16 | ocibnd *C.OCIBind 17 | ociNumber [1]C.OCINumber 18 | value *OCINum 19 | nullp 20 | } 21 | 22 | func (bnd *bndOCINumPtr) bind(value *OCINum, position namedPos, stmt *Stmt) error { 23 | bnd.stmt = stmt 24 | bnd.value = value 25 | bnd.nullp.Set(value == nil || value.IsNull()) 26 | if value != nil && !value.IsNull() { 27 | value.ToC(&bnd.ociNumber[0]) 28 | } 29 | ph, phLen, phFree := position.CString() 30 | if ph != nil { 31 | defer phFree() 32 | } 33 | r := C.bindByNameOrPos( 34 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 35 | &bnd.ocibnd, 36 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 37 | C.ub4(position.Ordinal), //ub4 position, 38 | ph, 39 | phLen, 40 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 41 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 42 | C.SQLT_VNU, //ub2 dty, 43 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 44 | nil, //ub2 *alenp, 45 | nil, //ub2 *rcodep, 46 | 0, //ub4 maxarr_len, 47 | nil, //ub4 *curelep, 48 | C.OCI_DEFAULT) //ub4 mode ); 49 | if r == C.OCI_ERROR { 50 | return bnd.stmt.ses.srv.env.ociError() 51 | } 52 | return nil 53 | } 54 | 55 | func (bnd *bndOCINumPtr) setPtr() error { 56 | if bnd.nullp.IsNull() { 57 | return nil 58 | } 59 | bnd.value.FromC(bnd.ociNumber[0]) 60 | return nil 61 | } 62 | 63 | func (bnd *bndOCINumPtr) close() (err error) { 64 | defer func() { 65 | if value := recover(); value != nil { 66 | err = errR(value) 67 | } 68 | }() 69 | 70 | stmt := bnd.stmt 71 | bnd.stmt = nil 72 | bnd.ocibnd = nil 73 | bnd.value = nil 74 | bnd.nullp.Free() 75 | stmt.putBnd(bndIdxOCINumPtr, bnd) 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /bndOCINumSlice.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | 11 | */ 12 | import "C" 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | type bndOCINumSlice struct { 18 | stmt *Stmt 19 | ocibnd *C.OCIBind 20 | ociNumbers []C.OCINumber 21 | arrHlp 22 | } 23 | 24 | func (bnd *bndOCINumSlice) bind(values []OCINum, nullInds []C.sb2, position namedPos, stmt *Stmt, isAssocArray bool) (iterations uint32, err error) { 25 | bnd.stmt = stmt 26 | L, C := len(values), cap(values) 27 | if nullInds != nil { 28 | bnd.nullInds = nullInds 29 | } 30 | iterations, curlenp, needAppend := bnd.ensureBindArrLength(&L, &C, isAssocArray) 31 | if needAppend { 32 | values = append(values, OCINum{}) 33 | } 34 | bnd.ociNumbers = make([]C.OCINumber, len(values)) 35 | alen := C.ACTUAL_LENGTH_TYPE(C.sizeof_OCINumber) 36 | for n := range values { 37 | bnd.alen[n] = alen 38 | values[n].ToC(&bnd.ociNumbers[n]) 39 | } 40 | ph, phLen, phFree := position.CString() 41 | if ph != nil { 42 | defer phFree() 43 | } 44 | r := C.bindByNameOrPos( 45 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 46 | &bnd.ocibnd, 47 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 48 | C.ub4(position.Ordinal), //ub4 position, 49 | ph, 50 | phLen, 51 | unsafe.Pointer(&bnd.ociNumbers[0]), //void *valuep, 52 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 53 | C.SQLT_VNU, //ub2 dty, 54 | unsafe.Pointer(&bnd.nullInds[0]), //void *indp, 55 | &bnd.alen[0], //ub4 *alenp, 56 | &bnd.rcode[0], //ub2 *rcodep, 57 | getMaxarrLen(C, isAssocArray), //ub4 maxarr_len, 58 | curlenp, //ub4 *curelep, 59 | C.OCI_DEFAULT) //ub4 mode ); 60 | if r == C.OCI_ERROR { 61 | return iterations, bnd.stmt.ses.srv.env.ociError() 62 | } 63 | r = C.OCIBindArrayOfStruct( 64 | bnd.ocibnd, 65 | bnd.stmt.ses.srv.env.ocierr, 66 | C.ub4(C.sizeof_OCINumber), //ub4 pvskip, 67 | C.ub4(C.sizeof_sb2), //ub4 indskip, 68 | C.ub4(C.sizeof_ub4), //ub4 alskip, 69 | C.ub4(C.sizeof_ub2)) //ub4 rcskip 70 | if r == C.OCI_ERROR { 71 | return iterations, bnd.stmt.ses.srv.env.ociError() 72 | } 73 | return iterations, nil 74 | } 75 | 76 | func (bnd *bndOCINumSlice) setPtr() error { 77 | return nil 78 | } 79 | 80 | func (bnd *bndOCINumSlice) close() (err error) { 81 | defer func() { 82 | if value := recover(); value != nil { 83 | err = errR(value) 84 | } 85 | }() 86 | 87 | stmt := bnd.stmt 88 | bnd.stmt = nil 89 | bnd.ocibnd = nil 90 | bnd.ociNumbers = nil 91 | bnd.arrHlp.close() 92 | stmt.putBnd(bndIdxOCINumSlice, bnd) 93 | return nil 94 | } 95 | -------------------------------------------------------------------------------- /bndRset.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Ora Authors. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | type bndRset struct { 17 | stmt *Stmt 18 | ocibnd *C.OCIBind 19 | ocistmt [1]*C.OCIStmt 20 | value *Rset 21 | nullp 22 | } 23 | 24 | func (bnd *bndRset) bind(value *Rset, position namedPos, stmt *Stmt) error { 25 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "%p pos=%v", bnd, position) 26 | 27 | bnd.stmt = stmt 28 | bnd.value = value 29 | // Allocate a statement handle 30 | ocistmt, err := bnd.stmt.ses.srv.env.allocOciHandle(C.OCI_HTYPE_STMT) 31 | bnd.ocistmt[0] = (*C.OCIStmt)(ocistmt) 32 | if err != nil { 33 | return err 34 | } 35 | ph, phLen, phFree := position.CString() 36 | if ph != nil { 37 | defer phFree() 38 | } 39 | r := C.bindByNameOrPos( 40 | stmt.ocistmt, //OCIStmt *stmtp, 41 | &bnd.ocibnd, 42 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 43 | C.ub4(position.Ordinal), //ub4 position, 44 | ph, 45 | phLen, 46 | unsafe.Pointer(&bnd.ocistmt[0]), //void *valuep, 47 | 0, //sb8 value_sz, 48 | C.SQLT_RSET, //ub2 dty, 49 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 50 | nil, //ub2 *alenp, 51 | nil, //ub2 *rcodep, 52 | 0, //ub4 maxarr_len, 53 | nil, //ub4 *curelep, 54 | C.OCI_DEFAULT) //ub4 mode ); 55 | if r == C.OCI_ERROR { 56 | return bnd.stmt.ses.srv.env.ociError() 57 | } 58 | 59 | return nil 60 | } 61 | 62 | func (bnd *bndRset) setPtr() error { 63 | if bnd.IsNull() || bnd.ocistmt[0] == nil { 64 | return nil 65 | } 66 | err := bnd.value.open(bnd.stmt, bnd.ocistmt[0]) 67 | bnd.ocistmt[0] = nil 68 | if err != nil { 69 | if cerr, ok := err.(interface { 70 | Code() int 71 | }); ok && cerr.Code() == 24337 { // statement is not prepared 72 | bnd.value = nil 73 | return nil 74 | } 75 | return err 76 | } 77 | // open result set is successful; will be freed by Rset 78 | bnd.stmt.openRsets.add(bnd.value) 79 | return bnd.stmt.setPrefetchSize() 80 | } 81 | 82 | func (bnd *bndRset) close() (err error) { 83 | defer func() { 84 | if value := recover(); value != nil { 85 | err = errR(value) 86 | } 87 | }() 88 | stmt := bnd.stmt 89 | bnd.stmt = nil 90 | bnd.ocibnd = nil 91 | bnd.ocistmt[0] = nil 92 | bnd.value = nil 93 | bnd.nullp.Free() 94 | stmt.putBnd(bndIdxRset, bnd) 95 | return nil 96 | } 97 | -------------------------------------------------------------------------------- /bndString.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | type bndString struct { 18 | stmt *Stmt 19 | ocibnd *C.OCIBind 20 | cString *C.char 21 | alen [1]C.ACTUAL_LENGTH_TYPE 22 | nullp 23 | } 24 | 25 | // https://ellebaek.wordpress.com/2011/02/25/oracle-type-code-mappings/ 26 | 27 | func (bnd *bndString) bind(value string, position namedPos, stmt *Stmt) error { 28 | bnd.stmt = stmt 29 | bnd.cString = C.CString(value) 30 | bnd.alen[0] = C.ACTUAL_LENGTH_TYPE(len(value)) 31 | bnd.nullp.Set(value == "") 32 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, 33 | "%p pos=%v alen=%d", 34 | bnd, position, bnd.alen[0]) 35 | 36 | ph, phLen, phFree := position.CString() 37 | if ph != nil { 38 | defer phFree() 39 | } 40 | r := C.bindByNameOrPos( 41 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 42 | &bnd.ocibnd, //OCIBind **bindpp, 43 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 44 | C.ub4(position.Ordinal), //ub4 position, 45 | ph, 46 | phLen, 47 | unsafe.Pointer(bnd.cString), //void *valuep, 48 | C.LENGTH_TYPE(len(value)), //sb8 value_sz, 49 | // http://www.devsuperpage.com/search/Articles.aspx?G=4&ArtID=560386 50 | // "You may find that trailing spaces are truncated when you use SQLT_CHR or SQLT_STR." 51 | C.SQLT_CHR, //ub2 dty, 52 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 53 | &bnd.alen[0], //ub2 *alenp, 54 | nil, //ub2 *rcodep, 55 | 0, //ub4 maxarr_len, 56 | nil, //ub4 *curelep, 57 | C.OCI_DEFAULT) //ub4 mode ); 58 | if r == C.OCI_ERROR { 59 | return bnd.stmt.ses.srv.env.ociError() 60 | } 61 | return nil 62 | } 63 | 64 | func (bnd *bndString) setPtr() error { 65 | return nil 66 | } 67 | 68 | func (bnd *bndString) close() (err error) { 69 | defer func() { 70 | if value := recover(); value != nil { 71 | err = errR(value) 72 | } 73 | }() 74 | if bnd.cString != nil { 75 | C.free(unsafe.Pointer(bnd.cString)) 76 | } 77 | stmt := bnd.stmt 78 | bnd.stmt = nil 79 | bnd.ocibnd = nil 80 | bnd.cString = nil 81 | stmt.putBnd(bndIdxString, bnd) 82 | return nil 83 | } 84 | -------------------------------------------------------------------------------- /bndTime.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "time" 15 | "unsafe" 16 | ) 17 | 18 | type bndTime struct { 19 | stmt *Stmt 20 | ocibnd *C.OCIBind 21 | dateTimep 22 | } 23 | 24 | func (bnd *bndTime) bind(value time.Time, position namedPos, stmt *Stmt) error { 25 | bnd.stmt = stmt 26 | if err := bnd.dateTimep.Set(bnd.stmt.ses.srv.env, value); err != nil { 27 | return err 28 | } 29 | ph, phLen, phFree := position.CString() 30 | if ph != nil { 31 | defer phFree() 32 | } 33 | r := C.bindByNameOrPos( 34 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 35 | &bnd.ocibnd, //OCIBind **bindpp, 36 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 37 | C.ub4(position.Ordinal), //ub4 position, 38 | ph, 39 | phLen, 40 | unsafe.Pointer(bnd.dateTimep.Pointer()), //void *valuep, 41 | C.LENGTH_TYPE(bnd.dateTimep.Size()), //sb8 value_sz, 42 | C.SQLT_TIMESTAMP_TZ, //ub2 dty, 43 | nil, //void *indp, 44 | nil, //ub2 *alenp, 45 | nil, //ub2 *rcodep, 46 | 0, //ub4 maxarr_len, 47 | nil, //ub4 *curelep, 48 | C.OCI_DEFAULT) //ub4 mode ); 49 | if r == C.OCI_ERROR { 50 | return bnd.stmt.ses.srv.env.ociError() 51 | } 52 | return nil 53 | } 54 | 55 | func (bnd *bndTime) setPtr() (err error) { 56 | return nil 57 | } 58 | 59 | func (bnd *bndTime) close() (err error) { 60 | defer func() { 61 | if value := recover(); value != nil { 62 | err = errR(value) 63 | } 64 | }() 65 | 66 | bnd.dateTimep.Free() 67 | stmt := bnd.stmt 68 | bnd.stmt = nil 69 | bnd.ocibnd = nil 70 | stmt.putBnd(bndIdxTime, bnd) 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /bndTimePtr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "time" 15 | "unsafe" 16 | ) 17 | 18 | type bndTimePtr struct { 19 | stmt *Stmt 20 | ocibnd *C.OCIBind 21 | value *time.Time 22 | dateTimep 23 | nullp 24 | } 25 | 26 | func (bnd *bndTimePtr) bind(value *time.Time, position namedPos, stmt *Stmt) error { 27 | bnd.stmt = stmt 28 | bnd.nullp.Set(value == nil || value.IsZero()) 29 | if err := bnd.dateTimep.Alloc(bnd.stmt.ses.srv.env); err != nil { 30 | return err 31 | } 32 | bnd.value = value 33 | if value != nil { 34 | if err := bnd.dateTimep.Set(bnd.stmt.ses.srv.env, *value); err != nil { 35 | return err 36 | } 37 | } 38 | ph, phLen, phFree := position.CString() 39 | if ph != nil { 40 | defer phFree() 41 | } 42 | r := C.bindByNameOrPos( 43 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 44 | &bnd.ocibnd, 45 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 46 | C.ub4(position.Ordinal), //ub4 position, 47 | ph, 48 | phLen, 49 | unsafe.Pointer(bnd.dateTimep.Pointer()), //void *valuep, 50 | C.LENGTH_TYPE(bnd.dateTimep.Size()), //sb8 value_sz, 51 | C.SQLT_TIMESTAMP_TZ, //ub2 dty, 52 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 53 | nil, //ub2 *alenp, 54 | nil, //ub2 *rcodep, 55 | 0, //ub4 maxarr_len, 56 | nil, //ub4 *curelep, 57 | C.OCI_DEFAULT) //ub4 mode ); 58 | if r == C.OCI_ERROR { 59 | return bnd.stmt.ses.srv.env.ociError() 60 | } 61 | return nil 62 | } 63 | 64 | func (bnd *bndTimePtr) setPtr() (err error) { 65 | if bnd.value == nil { // cannot set on a nil pointer 66 | return nil 67 | } 68 | if bnd.nullp.IsNull() { 69 | *bnd.value = time.Time{} // zero time 70 | return nil 71 | } 72 | *bnd.value, err = getTime(bnd.stmt.ses.srv.env, bnd.dateTimep.Value()) 73 | return err 74 | } 75 | 76 | func (bnd *bndTimePtr) close() (err error) { 77 | defer func() { 78 | if value := recover(); value != nil { 79 | err = errR(value) 80 | } 81 | }() 82 | 83 | stmt := bnd.stmt 84 | bnd.stmt = nil 85 | bnd.ocibnd = nil 86 | bnd.value = nil 87 | bnd.dateTimep.Free() 88 | bnd.nullp.Free() 89 | stmt.putBnd(bndIdxTimePtr, bnd) 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /bndUint16.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type bndUint16 struct { 15 | stmt *Stmt 16 | ocibnd *C.OCIBind 17 | ociNumber [1]C.OCINumber 18 | } 19 | 20 | func (bnd *bndUint16) bind(value uint16, position namedPos, stmt *Stmt) error { 21 | bnd.stmt = stmt 22 | r := C.OCINumberFromInt( 23 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 24 | unsafe.Pointer(&value), //const void *inum, 25 | byteWidth16, //uword inum_length, 26 | C.OCI_NUMBER_UNSIGNED, //uword inum_s_flag, 27 | &bnd.ociNumber[0]) //OCINumber *number ); 28 | if r == C.OCI_ERROR { 29 | return bnd.stmt.ses.srv.env.ociError() 30 | } 31 | ph, phLen, phFree := position.CString() 32 | if ph != nil { 33 | defer phFree() 34 | } 35 | r = C.bindByNameOrPos( 36 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 37 | &bnd.ocibnd, 38 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 39 | C.ub4(position.Ordinal), //ub4 position, 40 | ph, 41 | phLen, 42 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 43 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 44 | C.SQLT_VNU, //ub2 dty, 45 | nil, //void *indp, 46 | nil, //ub2 *alenp, 47 | nil, //ub2 *rcodep, 48 | 0, //ub4 maxarr_len, 49 | nil, //ub4 *curelep, 50 | C.OCI_DEFAULT) //ub4 mode ); 51 | if r == C.OCI_ERROR { 52 | return bnd.stmt.ses.srv.env.ociError() 53 | } 54 | return nil 55 | } 56 | 57 | func (bnd *bndUint16) setPtr() error { 58 | return nil 59 | } 60 | 61 | func (bnd *bndUint16) close() (err error) { 62 | defer func() { 63 | if value := recover(); value != nil { 64 | err = errR(value) 65 | } 66 | }() 67 | 68 | stmt := bnd.stmt 69 | bnd.stmt = nil 70 | bnd.ocibnd = nil 71 | stmt.putBnd(bndIdxUint16, bnd) 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /bndUint16Ptr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type bndUint16Ptr struct { 16 | stmt *Stmt 17 | ocibnd *C.OCIBind 18 | ociNumber [1]C.OCINumber 19 | value *uint16 20 | valueIsNull *bool 21 | nullp 22 | } 23 | 24 | func (bnd *bndUint16Ptr) bind(value *uint16, valueIsNull *bool, position namedPos, stmt *Stmt) error { 25 | //bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "Uint16Ptr.bind(%d) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 26 | bnd.stmt = stmt 27 | bnd.value = value 28 | bnd.valueIsNull = valueIsNull 29 | bnd.nullp.Set(value == nil) 30 | if value != nil { 31 | if err := bnd.stmt.ses.srv.env.OCINumberFromInt(&bnd.ociNumber[0], int64(*value), byteWidth16); err != nil { 32 | return err 33 | } 34 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, 35 | "Uint16Ptr.bind(%v) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 36 | } 37 | ph, phLen, phFree := position.CString() 38 | if ph != nil { 39 | defer phFree() 40 | } 41 | r := C.bindByNameOrPos( 42 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 43 | &bnd.ocibnd, 44 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 45 | C.ub4(position.Ordinal), //ub4 position, 46 | ph, 47 | phLen, 48 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 49 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 50 | C.SQLT_VNU, //ub2 dty, 51 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 52 | nil, //ub2 *alenp, 53 | nil, //ub2 *rcodep, 54 | 0, //ub4 maxarr_len, 55 | nil, //ub4 *curelep, 56 | C.OCI_DEFAULT) //ub4 mode ); 57 | if r == C.OCI_ERROR { 58 | return bnd.stmt.ses.srv.env.ociError() 59 | } 60 | return nil 61 | } 62 | 63 | func (bnd *bndUint16Ptr) setPtr() error { 64 | if bnd.valueIsNull != nil { 65 | *bnd.valueIsNull = bnd.nullp.IsNull() 66 | } 67 | if bnd.nullp.IsNull() { 68 | return nil 69 | } 70 | i, err := bnd.stmt.ses.srv.env.OCINumberToInt(&bnd.ociNumber[0], byteWidth16) 71 | *bnd.value = uint16(i) 72 | 73 | return err 74 | } 75 | 76 | func (bnd *bndUint16Ptr) close() (err error) { 77 | defer func() { 78 | if value := recover(); value != nil { 79 | err = errR(value) 80 | } 81 | }() 82 | 83 | stmt := bnd.stmt 84 | bnd.stmt = nil 85 | bnd.ocibnd = nil 86 | bnd.value = nil 87 | bnd.valueIsNull = nil 88 | bnd.nullp.Free() 89 | stmt.putBnd(bndIdxUint16Ptr, bnd) 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /bndUint32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type bndUint32 struct { 15 | stmt *Stmt 16 | ocibnd *C.OCIBind 17 | ociNumber [1]C.OCINumber 18 | } 19 | 20 | func (bnd *bndUint32) bind(value uint32, position namedPos, stmt *Stmt) error { 21 | bnd.stmt = stmt 22 | r := C.OCINumberFromInt( 23 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 24 | unsafe.Pointer(&value), //const void *inum, 25 | byteWidth32, //uword inum_length, 26 | C.OCI_NUMBER_UNSIGNED, //uword inum_s_flag, 27 | &bnd.ociNumber[0]) //OCINumber *number ); 28 | if r == C.OCI_ERROR { 29 | return bnd.stmt.ses.srv.env.ociError() 30 | } 31 | ph, phLen, phFree := position.CString() 32 | if ph != nil { 33 | defer phFree() 34 | } 35 | r = C.bindByNameOrPos( 36 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 37 | &bnd.ocibnd, 38 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 39 | C.ub4(position.Ordinal), //ub4 position, 40 | ph, 41 | phLen, 42 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 43 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 44 | C.SQLT_VNU, //ub2 dty, 45 | nil, //void *indp, 46 | nil, //ub2 *alenp, 47 | nil, //ub2 *rcodep, 48 | 0, //ub4 maxarr_len, 49 | nil, //ub4 *curelep, 50 | C.OCI_DEFAULT) //ub4 mode ); 51 | if r == C.OCI_ERROR { 52 | return bnd.stmt.ses.srv.env.ociError() 53 | } 54 | return nil 55 | } 56 | 57 | func (bnd *bndUint32) setPtr() error { 58 | return nil 59 | } 60 | 61 | func (bnd *bndUint32) close() (err error) { 62 | defer func() { 63 | if value := recover(); value != nil { 64 | err = errR(value) 65 | } 66 | }() 67 | 68 | stmt := bnd.stmt 69 | bnd.stmt = nil 70 | bnd.ocibnd = nil 71 | stmt.putBnd(bndIdxUint32, bnd) 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /bndUint32Ptr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type bndUint32Ptr struct { 16 | stmt *Stmt 17 | ocibnd *C.OCIBind 18 | ociNumber [1]C.OCINumber 19 | value *uint32 20 | valueIsNull *bool 21 | nullp 22 | } 23 | 24 | func (bnd *bndUint32Ptr) bind(value *uint32, valueIsNull *bool, position namedPos, stmt *Stmt) error { 25 | //bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "Uint32Ptr.bind(%d) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 26 | bnd.stmt = stmt 27 | bnd.value = value 28 | bnd.valueIsNull = valueIsNull 29 | bnd.nullp.Set(value == nil) 30 | if value != nil { 31 | if err := bnd.stmt.ses.srv.env.OCINumberFromInt(&bnd.ociNumber[0], int64(*value), byteWidth32); err != nil { 32 | return err 33 | } 34 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, 35 | "Uint32Ptr.bind(%v) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 36 | } 37 | ph, phLen, phFree := position.CString() 38 | if ph != nil { 39 | defer phFree() 40 | } 41 | r := C.bindByNameOrPos( 42 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 43 | &bnd.ocibnd, 44 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 45 | C.ub4(position.Ordinal), //ub4 position, 46 | ph, 47 | phLen, 48 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 49 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 50 | C.SQLT_VNU, //ub2 dty, 51 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 52 | nil, //ub2 *alenp, 53 | nil, //ub2 *rcodep, 54 | 0, //ub4 maxarr_len, 55 | nil, //ub4 *curelep, 56 | C.OCI_DEFAULT) //ub4 mode ); 57 | if r == C.OCI_ERROR { 58 | return bnd.stmt.ses.srv.env.ociError() 59 | } 60 | return nil 61 | } 62 | 63 | func (bnd *bndUint32Ptr) setPtr() error { 64 | if bnd.valueIsNull != nil { 65 | *bnd.valueIsNull = bnd.nullp.IsNull() 66 | } 67 | if bnd.nullp.IsNull() { 68 | return nil 69 | } 70 | i, err := bnd.stmt.ses.srv.env.OCINumberToInt(&bnd.ociNumber[0], byteWidth32) 71 | *bnd.value = uint32(i) 72 | 73 | return err 74 | } 75 | 76 | func (bnd *bndUint32Ptr) close() (err error) { 77 | defer func() { 78 | if value := recover(); value != nil { 79 | err = errR(value) 80 | } 81 | }() 82 | 83 | stmt := bnd.stmt 84 | bnd.stmt = nil 85 | bnd.ocibnd = nil 86 | bnd.value = nil 87 | bnd.valueIsNull = nil 88 | bnd.nullp.Free() 89 | stmt.putBnd(bndIdxUint32Ptr, bnd) 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /bndUint64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type bndUint64 struct { 15 | stmt *Stmt 16 | ocibnd *C.OCIBind 17 | ociNumber [1]C.OCINumber 18 | } 19 | 20 | func (bnd *bndUint64) bind(value uint64, position namedPos, stmt *Stmt) error { 21 | bnd.stmt = stmt 22 | r := C.OCINumberFromInt( 23 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 24 | unsafe.Pointer(&value), //const void *inum, 25 | byteWidth64, //uword inum_length, 26 | C.OCI_NUMBER_UNSIGNED, //uword inum_s_flag, 27 | &bnd.ociNumber[0]) //OCINumber *number ); 28 | if r == C.OCI_ERROR { 29 | return bnd.stmt.ses.srv.env.ociError() 30 | } 31 | ph, phLen, phFree := position.CString() 32 | if ph != nil { 33 | defer phFree() 34 | } 35 | r = C.bindByNameOrPos( 36 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 37 | &bnd.ocibnd, 38 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 39 | C.ub4(position.Ordinal), //ub4 position, 40 | ph, 41 | phLen, 42 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 43 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 44 | C.SQLT_VNU, //ub2 dty, 45 | nil, //void *indp, 46 | nil, //ub2 *alenp, 47 | nil, //ub2 *rcodep, 48 | 0, //ub4 maxarr_len, 49 | nil, //ub4 *curelep, 50 | C.OCI_DEFAULT) //ub4 mode ); 51 | if r == C.OCI_ERROR { 52 | return bnd.stmt.ses.srv.env.ociError() 53 | } 54 | return nil 55 | } 56 | 57 | func (bnd *bndUint64) setPtr() error { 58 | return nil 59 | } 60 | 61 | func (bnd *bndUint64) close() (err error) { 62 | defer func() { 63 | if value := recover(); value != nil { 64 | err = errR(value) 65 | } 66 | }() 67 | 68 | stmt := bnd.stmt 69 | bnd.stmt = nil 70 | bnd.ocibnd = nil 71 | stmt.putBnd(bndIdxUint64, bnd) 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /bndUint64Ptr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type bndUint64Ptr struct { 16 | stmt *Stmt 17 | ocibnd *C.OCIBind 18 | ociNumber [1]C.OCINumber 19 | value *uint64 20 | valueIsNull *bool 21 | nullp 22 | } 23 | 24 | func (bnd *bndUint64Ptr) bind(value *uint64, valueIsNull *bool, position namedPos, stmt *Stmt) error { 25 | //bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "Uint64Ptr.bind(%d) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 26 | bnd.stmt = stmt 27 | bnd.value = value 28 | bnd.valueIsNull = valueIsNull 29 | bnd.nullp.Set(value == nil) 30 | if value != nil { 31 | if err := bnd.stmt.ses.srv.env.OCINumberFromInt(&bnd.ociNumber[0], intSixtyFour(*value), byteWidth64); err != nil { 32 | return err 33 | } 34 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, 35 | "Uint64Ptr.bind(%v) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 36 | } 37 | ph, phLen, phFree := position.CString() 38 | if ph != nil { 39 | defer phFree() 40 | } 41 | r := C.bindByNameOrPos( 42 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 43 | &bnd.ocibnd, 44 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 45 | C.ub4(position.Ordinal), //ub4 position, 46 | ph, 47 | phLen, 48 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 49 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 50 | C.SQLT_VNU, //ub2 dty, 51 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 52 | nil, //ub2 *alenp, 53 | nil, //ub2 *rcodep, 54 | 0, //ub4 maxarr_len, 55 | nil, //ub4 *curelep, 56 | C.OCI_DEFAULT) //ub4 mode ); 57 | if r == C.OCI_ERROR { 58 | return bnd.stmt.ses.srv.env.ociError() 59 | } 60 | return nil 61 | } 62 | 63 | func (bnd *bndUint64Ptr) setPtr() error { 64 | if bnd.valueIsNull != nil { 65 | *bnd.valueIsNull = bnd.nullp.IsNull() 66 | } 67 | if bnd.nullp.IsNull() { 68 | return nil 69 | } 70 | i, err := bnd.stmt.ses.srv.env.OCINumberToInt(&bnd.ociNumber[0], byteWidth64) 71 | *bnd.value = uint64(i) 72 | 73 | return err 74 | } 75 | 76 | func (bnd *bndUint64Ptr) close() (err error) { 77 | defer func() { 78 | if value := recover(); value != nil { 79 | err = errR(value) 80 | } 81 | }() 82 | 83 | stmt := bnd.stmt 84 | bnd.stmt = nil 85 | bnd.ocibnd = nil 86 | bnd.value = nil 87 | bnd.valueIsNull = nil 88 | bnd.nullp.Free() 89 | stmt.putBnd(bndIdxUint64Ptr, bnd) 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /bndUint8.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type bndUint8 struct { 15 | stmt *Stmt 16 | ocibnd *C.OCIBind 17 | ociNumber [1]C.OCINumber 18 | } 19 | 20 | func (bnd *bndUint8) bind(value uint8, position namedPos, stmt *Stmt) error { 21 | bnd.stmt = stmt 22 | r := C.OCINumberFromInt( 23 | bnd.stmt.ses.srv.env.ocierr, //OCIError *err, 24 | unsafe.Pointer(&value), //const void *inum, 25 | byteWidth8, //uword inum_length, 26 | C.OCI_NUMBER_UNSIGNED, //uword inum_s_flag, 27 | &bnd.ociNumber[0]) //OCINumber *number ); 28 | if r == C.OCI_ERROR { 29 | return bnd.stmt.ses.srv.env.ociError() 30 | } 31 | ph, phLen, phFree := position.CString() 32 | if ph != nil { 33 | defer phFree() 34 | } 35 | r = C.bindByNameOrPos( 36 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 37 | &bnd.ocibnd, 38 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 39 | C.ub4(position.Ordinal), //ub4 position, 40 | ph, 41 | phLen, 42 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 43 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 44 | C.SQLT_VNU, //ub2 dty, 45 | nil, //void *indp, 46 | nil, //ub2 *alenp, 47 | nil, //ub2 *rcodep, 48 | 0, //ub4 maxarr_len, 49 | nil, //ub4 *curelep, 50 | C.OCI_DEFAULT) //ub4 mode ); 51 | if r == C.OCI_ERROR { 52 | return bnd.stmt.ses.srv.env.ociError() 53 | } 54 | return nil 55 | } 56 | 57 | func (bnd *bndUint8) setPtr() error { 58 | return nil 59 | } 60 | 61 | func (bnd *bndUint8) close() (err error) { 62 | defer func() { 63 | if value := recover(); value != nil { 64 | err = errR(value) 65 | } 66 | }() 67 | 68 | stmt := bnd.stmt 69 | bnd.stmt = nil 70 | bnd.ocibnd = nil 71 | stmt.putBnd(bndIdxUint8, bnd) 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /bndUint8Ptr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type bndUint8Ptr struct { 16 | stmt *Stmt 17 | ocibnd *C.OCIBind 18 | ociNumber [1]C.OCINumber 19 | value *uint8 20 | valueIsNull *bool 21 | nullp 22 | } 23 | 24 | func (bnd *bndUint8Ptr) bind(value *uint8, valueIsNull *bool, position namedPos, stmt *Stmt) error { 25 | //bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, "Uint8Ptr.bind(%d) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 26 | bnd.stmt = stmt 27 | bnd.value = value 28 | bnd.valueIsNull = valueIsNull 29 | bnd.nullp.Set(value == nil) 30 | if value != nil { 31 | if err := bnd.stmt.ses.srv.env.OCINumberFromInt(&bnd.ociNumber[0], int64(*value), byteWidth8); err != nil { 32 | return err 33 | } 34 | bnd.stmt.logF(_drv.Cfg().Log.Stmt.Bind, 35 | "Uint8Ptr.bind(%v) value=%#v => number=%#v", position, value, bnd.ociNumber[0]) 36 | } 37 | ph, phLen, phFree := position.CString() 38 | if ph != nil { 39 | defer phFree() 40 | } 41 | r := C.bindByNameOrPos( 42 | bnd.stmt.ocistmt, //OCIStmt *stmtp, 43 | &bnd.ocibnd, 44 | bnd.stmt.ses.srv.env.ocierr, //OCIError *errhp, 45 | C.ub4(position.Ordinal), //ub4 position, 46 | ph, 47 | phLen, 48 | unsafe.Pointer(&bnd.ociNumber[0]), //void *valuep, 49 | C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8 value_sz, 50 | C.SQLT_VNU, //ub2 dty, 51 | unsafe.Pointer(bnd.nullp.Pointer()), //void *indp, 52 | nil, //ub2 *alenp, 53 | nil, //ub2 *rcodep, 54 | 0, //ub4 maxarr_len, 55 | nil, //ub4 *curelep, 56 | C.OCI_DEFAULT) //ub4 mode ); 57 | if r == C.OCI_ERROR { 58 | return bnd.stmt.ses.srv.env.ociError() 59 | } 60 | return nil 61 | } 62 | 63 | func (bnd *bndUint8Ptr) setPtr() error { 64 | if bnd.valueIsNull != nil { 65 | *bnd.valueIsNull = bnd.nullp.IsNull() 66 | } 67 | if bnd.nullp.IsNull() { 68 | return nil 69 | } 70 | i, err := bnd.stmt.ses.srv.env.OCINumberToInt(&bnd.ociNumber[0], byteWidth8) 71 | *bnd.value = uint8(i) 72 | 73 | return err 74 | } 75 | 76 | func (bnd *bndUint8Ptr) close() (err error) { 77 | defer func() { 78 | if value := recover(); value != nil { 79 | err = errR(value) 80 | } 81 | }() 82 | 83 | stmt := bnd.stmt 84 | bnd.stmt = nil 85 | bnd.ocibnd = nil 86 | bnd.value = nil 87 | bnd.valueIsNull = nil 88 | bnd.nullp.Free() 89 | stmt.putBnd(bndIdxUint8Ptr, bnd) 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /conn_go1_7.go: -------------------------------------------------------------------------------- 1 | // +build !go1.8 2 | 3 | // Copyright 2017 Tamás Gulácsi. All rights reserved. 4 | // Use of this source code is governed by The MIT License 5 | // found in the accompanying LICENSE file. 6 | 7 | package ora 8 | 9 | import "database/sql/driver" 10 | 11 | // Prepare readies a sql string for use. 12 | // 13 | // Prepare is a member of the driver.Conn interface. 14 | func (con *Con) Prepare(query string) (driver.Stmt, error) { 15 | con.log(_drv.Cfg().Log.Con.Prepare) 16 | if err := con.checkIsOpen(); err != nil { 17 | return nil, err 18 | } 19 | stmt, err := con.ses.Prep(query) 20 | if err != nil { 21 | return nil, maybeBadConn(err) 22 | } 23 | return &DrvStmt{stmt: stmt}, err 24 | } 25 | -------------------------------------------------------------------------------- /conn_go1_8.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | // Copyright 2017 Tamás Gulácsi. All rights reserved. 4 | // Use of this source code is governed by The MIT License 5 | // found in the accompanying LICENSE file. 6 | 7 | package ora 8 | 9 | import ( 10 | "context" 11 | "database/sql" 12 | "database/sql/driver" 13 | "fmt" 14 | ) 15 | 16 | /* 17 | #include 18 | */ 19 | import "C" 20 | 21 | var ( 22 | // Ensure that Con implements the needed ...Context interfaces. 23 | _ = driver.Conn((*Con)(nil)) 24 | _ = driver.ConnBeginTx((*Con)(nil)) 25 | _ = driver.ConnPrepareContext((*Con)(nil)) 26 | _ = driver.Pinger((*Con)(nil)) 27 | 28 | // Ensure that DrvStmt implements the needed ...Context interfaces. 29 | _ = driver.Stmt((*DrvStmt)(nil)) 30 | _ = driver.StmtQueryContext((*DrvStmt)(nil)) 31 | _ = driver.StmtExecContext((*DrvStmt)(nil)) 32 | ) 33 | 34 | // Prepare readies a sql string for use. 35 | // 36 | // Prepare is a member of the driver.Conn interface. 37 | func (con *Con) Prepare(query string) (driver.Stmt, error) { 38 | return con.PrepareContext(context.Background(), query) 39 | } 40 | 41 | // PrepareContext returns a prepared statement, bound to this connection. 42 | // context is for the preparation of the statement, 43 | // it must not store the context within the statement itself. 44 | func (con *Con) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { 45 | con.log(_drv.Cfg().Log.Con.Prepare) 46 | if err := con.checkIsOpen(); err != nil { 47 | return nil, err 48 | } 49 | stmt, err := con.ses.Prep(query) 50 | if err != nil { 51 | return nil, maybeBadConn(err) 52 | } 53 | return &DrvStmt{stmt: stmt}, err 54 | } 55 | 56 | // BeginTx starts and returns a new transaction. 57 | // The provided context should be used to roll the transaction back 58 | // if it is cancelled. 59 | // 60 | // If the driver does not support setting the isolation 61 | // level and one is set or if there is a set isolation level 62 | // but the set level is not supported, an error must be returned. 63 | // 64 | // If the read-only value is true to either 65 | // set the read-only transaction property if supported 66 | // or return an error if it is not supported. 67 | func (con *Con) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { 68 | if err := ctx.Err(); err != nil { 69 | return nil, err 70 | } 71 | var flags C.ub4 72 | if opts.ReadOnly { 73 | flags |= C.OCI_TRANS_READONLY 74 | } 75 | switch level := sql.IsolationLevel(opts.Isolation); level { 76 | case sql.LevelDefault, sql.LevelReadCommitted: 77 | // this is the default level 78 | case sql.LevelSerializable: 79 | flags |= C.OCI_TRANS_SERIALIZABLE 80 | default: 81 | return nil, fmt.Errorf("Isolation level %v not supported.", level) 82 | } 83 | con.log(_drv.Cfg().Log.Con.Begin) 84 | if err := con.checkIsOpen(); err != nil { 85 | return nil, err 86 | } 87 | var tx *Tx 88 | done := make(chan error, 1) 89 | go func() { 90 | defer close(done) 91 | var err error 92 | tx, err = con.ses.StartTx(TxFlags(uint32(flags))) 93 | done <- err 94 | }() 95 | var err error 96 | select { 97 | case err = <-done: 98 | return tx, err 99 | case <-ctx.Done(): 100 | // select again to avoid race condition if both are done 101 | select { 102 | case err = <-done: 103 | return tx, err 104 | default: 105 | if err = ctx.Err(); isCanceled(err) { 106 | con.ses.Break() 107 | } 108 | } 109 | } 110 | return nil, maybeBadConn(err) 111 | } 112 | 113 | // vim: set fileencoding=utf-8 noet: 114 | -------------------------------------------------------------------------------- /contrib/oci8.pc: -------------------------------------------------------------------------------- 1 | oci8_linux_amd64.pc -------------------------------------------------------------------------------- /contrib/oci8_darwin.pc: -------------------------------------------------------------------------------- 1 | prefix=/Users/dfils/src/oracle/instantclient_12_1 2 | 3 | version=12.1 4 | build=client64 5 | 6 | libdir=${prefix} 7 | includedir=${prefix}/sdk/include 8 | 9 | Name: oci8 10 | Description: Oracle database engine 11 | Version: ${version} 12 | Libs: -L${libdir} -lclntsh 13 | Libs.private: 14 | Cflags: -I${includedir} 15 | -------------------------------------------------------------------------------- /contrib/oci8_linux_386.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr 2 | 3 | version=12.1 4 | build=client32 5 | 6 | libdir=${prefix}/lib/oracle/${version}/${build}/lib 7 | includedir=${prefix}/include/oracle/${version}/${build} 8 | 9 | Name: oci8 10 | Description: Oracle database engine 11 | Version: ${version} 12 | Libs: -L${libdir} -lclntsh 13 | Libs.private: 14 | Cflags: -I${includedir} 15 | -------------------------------------------------------------------------------- /contrib/oci8_linux_amd64.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr 2 | 3 | version=12.1 4 | build=client64 5 | 6 | libdir=${prefix}/lib/oracle/${version}/${build}/lib 7 | includedir=${prefix}/include/oracle/${version}/${build} 8 | 9 | Name: oci8 10 | Description: Oracle database engine 11 | Version: ${version} 12 | Libs: -L${libdir} -lclntsh 13 | Libs.private: 14 | Cflags: -I${includedir} 15 | -------------------------------------------------------------------------------- /contrib/oci8_windows_amd64.pc: -------------------------------------------------------------------------------- 1 | prefix=c:/Oracle64Instant/sdk 2 | 3 | version=12.1 4 | build=client64 5 | 6 | libdir=${prefix}/lib 7 | includedir=${prefix}/include 8 | 9 | glib_genmarshal=glib-genmarshal 10 | gobject_query=gobject-query 11 | glib_mkenums=glib-mkenums 12 | 13 | Name: oci8 14 | Description: Oracle database engine 15 | Version: ${version} 16 | Libs: -L${libdir} -loci 17 | Libs.private: 18 | Cflags: -I${includedir} 19 | -------------------------------------------------------------------------------- /contrib/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | output="$(gofmt -l "$@")" 5 | 6 | if [ -n "$output" ]; then 7 | echo >&2 "Go files must be formatted with gofmt. Please run:" 8 | for f in $output; do 9 | echo >&2 " gofmt -w $PWD/$f" 10 | done 11 | exit 1 12 | fi 13 | 14 | #--enable=vetshadow \ 15 | gometalinter --vendor --disable-all \ 16 | --enable=deadcode \ 17 | --enable=ineffassign \ 18 | --enable=gosimple \ 19 | --enable=staticcheck \ 20 | --enable=unused \ 21 | -e 'z_.*_test' \ 22 | ./... 23 | -------------------------------------------------------------------------------- /ctx.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Tamás Gulácsi. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | import "context" 8 | 9 | const ( 10 | stmtCfgKey = "stmtCfg" 11 | ) 12 | 13 | // ctxStmtCfg returns the StmtCfg from the context, and 14 | // whether it exist at all. 15 | func ctxStmtCfg(ctx context.Context) (StmtCfg, bool) { 16 | cfg, ok := ctx.Value(stmtCfgKey).(StmtCfg) 17 | return cfg, ok 18 | } 19 | 20 | // WithStmtCfg returns a new context, with the given cfg that 21 | // can be used to configure several parameters. 22 | // 23 | // WARNING: the StmtCfg must be derived from Cfg(), or NewStmtCfg(), 24 | // as an empty StmtCfg is not usable! 25 | func WithStmtCfg(ctx context.Context, cfg StmtCfg) context.Context { 26 | return context.WithValue(ctx, stmtCfgKey, cfg) 27 | } 28 | -------------------------------------------------------------------------------- /date/date.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Tamás Gulácsi. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | // Package date implements encoding of 7 byte Oracle DATE storage formats. 6 | package date 7 | 8 | import ( 9 | "bytes" 10 | "encoding/json" 11 | "fmt" 12 | "time" 13 | ) 14 | 15 | // Date is an OCIDate 16 | // 17 | // SQLT_ODT: 7 bytes 18 | // 19 | // http://www.orafaq.com/wiki/Date 20 | // 21 | /* 22 | The internal format is the following one: 23 | 24 | century + 100 25 | year in the century + 100 26 | month 27 | day 28 | hour + 1 29 | minute + 1 30 | second + 1 31 | 32 | So in the previous example the date was 19-DEC-2007 at 22:35:10. 33 | */ 34 | type Date [7]byte 35 | 36 | func (dt *Date) Set(t time.Time) { 37 | if t.IsZero() { 38 | for i := range dt[:] { 39 | dt[i] = 0 40 | } 41 | return 42 | } 43 | y := t.Year() 44 | if y < -4711 { 45 | y = -4711 46 | } else if y > 9999 { 47 | y = 9999 48 | } 49 | dt[0] = byte(y/100 + 100) 50 | dt[1] = byte(y%100 + 100) 51 | dt[2] = byte(t.Month()) 52 | dt[3] = byte(t.Day()) 53 | dt[4] = byte(t.Hour() + 1) 54 | dt[5] = byte(t.Minute() + 1) 55 | dt[6] = byte(t.Second() + 1) 56 | } 57 | 58 | func (dt Date) Bytes() []byte { 59 | return dt[:] 60 | } 61 | 62 | func (dt Date) IsNull() bool { 63 | for _, b := range dt[:] { 64 | if b != 0 { 65 | return false 66 | } 67 | } 68 | return true 69 | } 70 | func (dt Date) MarshalJSON() ([]byte, error) { 71 | if dt.IsNull() { 72 | return []byte("null"), nil 73 | } 74 | return dt.Get().MarshalJSON() 75 | } 76 | func (dt *Date) UnmarshalJSON(p []byte) error { 77 | if bytes.Equal(p, []byte("null")) || bytes.Equal(p, []byte(`""`)) { 78 | for i := range dt[:] { 79 | dt[i] = 0 80 | } 81 | return nil 82 | } 83 | var t time.Time 84 | if err := json.Unmarshal(p, &t); err != nil { 85 | return err 86 | } 87 | dt.Set(t) 88 | return nil 89 | } 90 | 91 | // FromTime returns a Date from a time.Time 92 | // Does the allocation inside, so easier to use. 93 | func FromTime(t time.Time) Date { 94 | var dt Date 95 | dt.Set(t) 96 | return dt 97 | } 98 | 99 | func (dt Date) Equal(other Date) bool { 100 | return bytes.Equal(dt[:], other[:]) 101 | } 102 | 103 | func (dt Date) String() string { 104 | if dt.IsNull() { 105 | return (time.Time{}).Format("2006-01-02T15:04:05") 106 | } 107 | return fmt.Sprintf("%04d-%02d-%02dT%02d:%02d:%02d", 108 | (int(dt[0])-100)*100+(int(dt[1])-100), 109 | time.Month(dt[2]), 110 | int(dt[3]), 111 | int(dt[4]-1), 112 | int(dt[5]-1), 113 | int(dt[6]-1), 114 | ) 115 | } 116 | 117 | func (dt Date) Get() time.Time { 118 | return dt.GetIn(nil) 119 | } 120 | func (dt Date) GetIn(zone *time.Location) time.Time { 121 | if dt.IsNull() { 122 | return time.Time{} 123 | } 124 | if zone == nil { 125 | zone = time.Local 126 | } 127 | return time.Date( 128 | (int(dt[0])-100)*100+(int(dt[1])-100), 129 | time.Month(dt[2]), 130 | int(dt[3]), 131 | int(dt[4]-1), 132 | int(dt[5]-1), 133 | int(dt[6]-1), 134 | 0, 135 | zone, 136 | ) 137 | } 138 | -------------------------------------------------------------------------------- /date/date_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Tamás Gulácsi. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package date_test 6 | 7 | import ( 8 | "bytes" 9 | "testing" 10 | 11 | "gopkg.in/rana/ora.v4/date" 12 | ) 13 | 14 | func TestDate(t *testing.T) { 15 | format := "2006-01-02T15:04:05" 16 | dt := new(date.Date) 17 | for tN, tC := range dateTestData { 18 | tim := date.Date(tC.B).Get() 19 | if got := tim.Format(format); got != tC.S { 20 | t.Errorf("%d. got %q, want %q (from %v).", tN, got, tC.S, tC.B) 21 | continue 22 | } 23 | dt.Set(tim) 24 | if !bytes.Equal(dt[:], tC.B[:]) { 25 | t.Errorf("%d. got %v, want %v (from %q).", tN, dt[:], tC.B[:], tC.S) 26 | } 27 | } 28 | } 29 | func TestNull(t *testing.T) { 30 | var dt date.Date 31 | t.Log(dt.String()) 32 | if !dt.IsNull() { 33 | t.Errorf("want NULL, got %t for %#v", dt.IsNull(), dt) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /date/date_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export ORACLE_HOME=${ORACLE_HOME:-/u01/app/oracle/product/11.2.0/xe} 3 | set -x 4 | { 5 | cat <date_gen_test.go 27 | -------------------------------------------------------------------------------- /defBool.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "unicode/utf8" 15 | "unsafe" 16 | ) 17 | 18 | type defBool struct { 19 | ociDef 20 | isNullable bool 21 | columnSize int 22 | buf []byte 23 | } 24 | 25 | func (def *defBool) define(position int, columnSize int, isNullable bool, rset *Rset) error { 26 | def.rset = rset 27 | def.isNullable = isNullable 28 | def.columnSize = columnSize 29 | if n := rset.fetchLen * columnSize; cap(def.buf) < n { 30 | //def.buf = make([]byte, n) 31 | def.buf = bytesPool.Get(n) 32 | } else { 33 | def.buf = def.buf[:n] 34 | } 35 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.buf[0]), columnSize, C.SQLT_AFC) 36 | } 37 | 38 | func (def *defBool) value(offset int) (value interface{}, err error) { 39 | if def.nullInds[offset] < 0 { 40 | if def.isNullable { 41 | return Bool{IsNull: true}, nil 42 | } 43 | return nil, nil 44 | } 45 | //Log.Infof("%v.value", def) 46 | buf := def.buf[offset*def.columnSize : (offset+1)*def.columnSize] 47 | if def.isNullable { 48 | r, _ := utf8.DecodeRune(buf) 49 | return Bool{Value: r == def.rset.stmt.Cfg().TrueRune}, nil 50 | } 51 | r, _ := utf8.DecodeRune(buf) 52 | return r == def.rset.stmt.Cfg().TrueRune, nil 53 | } 54 | 55 | func (def *defBool) alloc() error { 56 | return nil 57 | } 58 | 59 | func (def *defBool) free() { 60 | if def.buf != nil { 61 | bytesPool.Put(def.buf) 62 | def.buf = nil 63 | } 64 | def.arrHlp.close() 65 | } 66 | 67 | func (def *defBool) close() (err error) { 68 | defer func() { 69 | if value := recover(); value != nil { 70 | err = errR(value) 71 | } 72 | }() 73 | 74 | def.free() 75 | rset := def.rset 76 | def.rset = nil 77 | def.ocidef = nil 78 | rset.putDef(defIdxBool, def) 79 | return nil 80 | } 81 | -------------------------------------------------------------------------------- /defDate.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "time" 15 | "unsafe" 16 | 17 | "gopkg.in/rana/ora.v4/date" 18 | ) 19 | 20 | type defDate struct { 21 | ociDef 22 | ociDate []date.Date 23 | isNullable bool 24 | timezone *time.Location 25 | } 26 | 27 | func (def *defDate) define(position int, isNullable bool, rset *Rset) error { 28 | var err error 29 | if def.timezone, err = rset.stmt.ses.Timezone(); err != nil { 30 | return err 31 | } 32 | def.rset = rset 33 | def.isNullable = isNullable 34 | if def.ociDate != nil { 35 | C.free(unsafe.Pointer(&def.ociDate[0])) 36 | } 37 | def.ociDate = (*((*[MaxFetchLen]date.Date)(C.malloc(C.size_t(rset.fetchLen) * 7))))[:rset.fetchLen] 38 | 39 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociDate[0]), 7, C.SQLT_DAT) 40 | } 41 | 42 | func (def *defDate) value(offset int) (value interface{}, err error) { 43 | if def.nullInds[offset] < 0 { 44 | if def.isNullable { 45 | return Time{IsNull: true}, nil 46 | } 47 | return nil, nil 48 | } 49 | if def.isNullable { 50 | return Time{Value: def.ociDate[offset].GetIn(def.timezone)}, nil 51 | } 52 | return def.ociDate[offset].GetIn(def.timezone), nil 53 | } 54 | 55 | func (def *defDate) alloc() error { return nil } 56 | func (def *defDate) free() { 57 | if def.ociDate != nil { 58 | C.free(unsafe.Pointer(&def.ociDate[0])) 59 | def.ociDate = nil 60 | } 61 | def.arrHlp.close() 62 | } 63 | 64 | func (def *defDate) close() (err error) { 65 | defer func() { 66 | if value := recover(); value != nil { 67 | err = errR(value) 68 | } 69 | }() 70 | 71 | rset := def.rset 72 | def.rset = nil 73 | def.ocidef = nil 74 | def.free() 75 | rset.putDef(defIdxDate, def) 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /defFloat32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // defFloat32.go is generated from defFloat32.go! 16 | 17 | type defFloat32 struct { 18 | ociDef 19 | ociNumber []C.OCINumber 20 | isNullable bool 21 | } 22 | 23 | func (def *defFloat32) define(position int, isNullable bool, rset *Rset) error { 24 | def.rset = rset 25 | def.isNullable = isNullable 26 | if def.ociNumber != nil { 27 | C.free(unsafe.Pointer(&def.ociNumber[0])) 28 | } 29 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 30 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 31 | } 32 | 33 | func (def *defFloat32) value(offset int) (value interface{}, err error) { 34 | if def.nullInds[offset] < 0 { 35 | if def.isNullable { 36 | return Float32{IsNull: true}, nil 37 | } 38 | return nil, nil 39 | } 40 | var float32Value float32 41 | on := def.ociNumber[offset] 42 | r := C.OCINumberToReal( 43 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 44 | &on, //const OCINumber *number, 45 | byteWidth32, //uword rsl_length, 46 | unsafe.Pointer(&float32Value)) //void *rsl ); 47 | if r == C.OCI_ERROR { 48 | err = def.rset.stmt.ses.srv.env.ociError() 49 | } 50 | //fmt.Printf("%d. %#v = %#v\n", offset, on, float32Value) 51 | if def.isNullable { 52 | return Float32{Value: float32Value}, err 53 | } 54 | return float32Value, err 55 | } 56 | 57 | func (def *defFloat32) alloc() error { 58 | return nil 59 | } 60 | 61 | func (def *defFloat32) free() { 62 | def.arrHlp.close() 63 | } 64 | 65 | func (def *defFloat32) close() (err error) { 66 | defer func() { 67 | if value := recover(); value != nil { 68 | err = errR(value) 69 | } 70 | }() 71 | 72 | rset := def.rset 73 | def.rset = nil 74 | def.ocidef = nil 75 | if def.ociNumber != nil { 76 | C.free(unsafe.Pointer(&def.ociNumber[0])) 77 | def.ociNumber = nil 78 | } 79 | rset.putDef(defIdxFloat32, def) 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /defFloat64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // defFloat32.go is generated from defFloat64.go! 16 | 17 | type defFloat64 struct { 18 | ociDef 19 | ociNumber []C.OCINumber 20 | isNullable bool 21 | } 22 | 23 | func (def *defFloat64) define(position int, isNullable bool, rset *Rset) error { 24 | def.rset = rset 25 | def.isNullable = isNullable 26 | if def.ociNumber != nil { 27 | C.free(unsafe.Pointer(&def.ociNumber[0])) 28 | } 29 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 30 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 31 | } 32 | 33 | func (def *defFloat64) value(offset int) (value interface{}, err error) { 34 | if def.nullInds[offset] < 0 { 35 | if def.isNullable { 36 | return Float64{IsNull: true}, nil 37 | } 38 | return nil, nil 39 | } 40 | var float64Value float64 41 | on := def.ociNumber[offset] 42 | r := C.OCINumberToReal( 43 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 44 | &on, //const OCINumber *number, 45 | byteWidth64, //uword rsl_length, 46 | unsafe.Pointer(&float64Value)) //void *rsl ); 47 | if r == C.OCI_ERROR { 48 | err = def.rset.stmt.ses.srv.env.ociError() 49 | } 50 | //fmt.Printf("%d. %#v = %#v\n", offset, on, float64Value) 51 | if def.isNullable { 52 | return Float64{Value: float64Value}, err 53 | } 54 | return float64Value, err 55 | } 56 | 57 | func (def *defFloat64) alloc() error { 58 | return nil 59 | } 60 | 61 | func (def *defFloat64) free() { 62 | def.arrHlp.close() 63 | } 64 | 65 | func (def *defFloat64) close() (err error) { 66 | defer func() { 67 | if value := recover(); value != nil { 68 | err = errR(value) 69 | } 70 | }() 71 | 72 | rset := def.rset 73 | def.rset = nil 74 | def.ocidef = nil 75 | if def.ociNumber != nil { 76 | C.free(unsafe.Pointer(&def.ociNumber[0])) 77 | def.ociNumber = nil 78 | } 79 | rset.putDef(defIdxFloat64, def) 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /defInt16.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // Generate all the def[IU]int{8,16,32,16}.go from defInt16.go 16 | // 17 | // Generated from defInt16.go by go run gen.go 18 | 19 | type defInt16 struct { 20 | ociDef 21 | ociNumber []C.OCINumber 22 | isNullable bool 23 | } 24 | 25 | func (def *defInt16) define(position int, isNullable bool, rset *Rset) error { 26 | def.rset = rset 27 | def.isNullable = isNullable 28 | if def.ociNumber != nil { 29 | C.free(unsafe.Pointer(&def.ociNumber[0])) 30 | } 31 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 32 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 33 | } 34 | 35 | func (def *defInt16) value(offset int) (value interface{}, err error) { 36 | if def.nullInds[offset] < 0 { 37 | if def.isNullable { 38 | return Int16{IsNull: true}, nil 39 | } 40 | return nil, nil 41 | } 42 | var int16Value int16 43 | on := def.ociNumber[offset] 44 | r := C.OCINumberToInt( 45 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 46 | &on, //const OCINumber *number, 47 | byteWidth16, //uword rsl_length, 48 | C.OCI_NUMBER_SIGNED, //uword rsl_flag, 49 | unsafe.Pointer(&int16Value)) //void *rsl ); 50 | if r == C.OCI_ERROR { 51 | err = def.rset.stmt.ses.srv.env.ociError() 52 | } 53 | if def.isNullable { 54 | return Int16{Value: int16Value}, err 55 | } 56 | return int16Value, err 57 | } 58 | 59 | func (def *defInt16) alloc() error { return nil } 60 | func (def *defInt16) free() { 61 | def.arrHlp.close() 62 | } 63 | 64 | func (def *defInt16) close() (err error) { 65 | defer func() { 66 | if value := recover(); value != nil { 67 | err = errR(value) 68 | } 69 | }() 70 | rset := def.rset 71 | def.rset = nil 72 | def.ocidef = nil 73 | if def.ociNumber != nil { 74 | C.free(unsafe.Pointer(&def.ociNumber[0])) 75 | def.ociNumber = nil 76 | } 77 | rset.putDef(defIdxInt16, def) 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /defInt32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // Generate all the def[IU]int{8,16,32,32}.go from defInt32.go 16 | // 17 | // Generated from defInt32.go by go run gen.go 18 | 19 | type defInt32 struct { 20 | ociDef 21 | ociNumber []C.OCINumber 22 | isNullable bool 23 | } 24 | 25 | func (def *defInt32) define(position int, isNullable bool, rset *Rset) error { 26 | def.rset = rset 27 | def.isNullable = isNullable 28 | if def.ociNumber != nil { 29 | C.free(unsafe.Pointer(&def.ociNumber[0])) 30 | } 31 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 32 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 33 | } 34 | 35 | func (def *defInt32) value(offset int) (value interface{}, err error) { 36 | if def.nullInds[offset] < 0 { 37 | if def.isNullable { 38 | return Int32{IsNull: true}, nil 39 | } 40 | return nil, nil 41 | } 42 | var int32Value int32 43 | on := def.ociNumber[offset] 44 | r := C.OCINumberToInt( 45 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 46 | &on, //const OCINumber *number, 47 | byteWidth32, //uword rsl_length, 48 | C.OCI_NUMBER_SIGNED, //uword rsl_flag, 49 | unsafe.Pointer(&int32Value)) //void *rsl ); 50 | if r == C.OCI_ERROR { 51 | err = def.rset.stmt.ses.srv.env.ociError() 52 | } 53 | if def.isNullable { 54 | return Int32{Value: int32Value}, err 55 | } 56 | return int32Value, err 57 | } 58 | 59 | func (def *defInt32) alloc() error { return nil } 60 | func (def *defInt32) free() { 61 | def.arrHlp.close() 62 | } 63 | 64 | func (def *defInt32) close() (err error) { 65 | defer func() { 66 | if value := recover(); value != nil { 67 | err = errR(value) 68 | } 69 | }() 70 | rset := def.rset 71 | def.rset = nil 72 | def.ocidef = nil 73 | if def.ociNumber != nil { 74 | C.free(unsafe.Pointer(&def.ociNumber[0])) 75 | def.ociNumber = nil 76 | } 77 | rset.putDef(defIdxInt32, def) 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /defInt64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // Generate all the def[IU]int{8,16,32,64}.go from defInt64.go 16 | // 17 | //go:generate go run gen.go 18 | 19 | type defInt64 struct { 20 | ociDef 21 | ociNumber []C.OCINumber 22 | isNullable bool 23 | } 24 | 25 | func (def *defInt64) define(position int, isNullable bool, rset *Rset) error { 26 | def.rset = rset 27 | def.isNullable = isNullable 28 | if def.ociNumber != nil { 29 | C.free(unsafe.Pointer(&def.ociNumber[0])) 30 | } 31 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 32 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 33 | } 34 | 35 | func (def *defInt64) value(offset int) (value interface{}, err error) { 36 | if def.nullInds[offset] < 0 { 37 | if def.isNullable { 38 | return Int64{IsNull: true}, nil 39 | } 40 | return nil, nil 41 | } 42 | var int64Value int64 43 | on := def.ociNumber[offset] 44 | r := C.OCINumberToInt( 45 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 46 | &on, //const OCINumber *number, 47 | byteWidth64, //uword rsl_length, 48 | C.OCI_NUMBER_SIGNED, //uword rsl_flag, 49 | unsafe.Pointer(&int64Value)) //void *rsl ); 50 | if r == C.OCI_ERROR { 51 | err = def.rset.stmt.ses.srv.env.ociError() 52 | } 53 | if def.isNullable { 54 | return Int64{Value: int64Value}, err 55 | } 56 | return int64Value, err 57 | } 58 | 59 | func (def *defInt64) alloc() error { return nil } 60 | func (def *defInt64) free() { 61 | def.arrHlp.close() 62 | } 63 | 64 | func (def *defInt64) close() (err error) { 65 | defer func() { 66 | if value := recover(); value != nil { 67 | err = errR(value) 68 | } 69 | }() 70 | rset := def.rset 71 | def.rset = nil 72 | def.ocidef = nil 73 | if def.ociNumber != nil { 74 | C.free(unsafe.Pointer(&def.ociNumber[0])) 75 | def.ociNumber = nil 76 | } 77 | rset.putDef(defIdxInt64, def) 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /defInt8.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // Generate all the def[IU]int{8,16,32,8}.go from defInt8.go 16 | // 17 | // Generated from defInt8.go by go run gen.go 18 | 19 | type defInt8 struct { 20 | ociDef 21 | ociNumber []C.OCINumber 22 | isNullable bool 23 | } 24 | 25 | func (def *defInt8) define(position int, isNullable bool, rset *Rset) error { 26 | def.rset = rset 27 | def.isNullable = isNullable 28 | if def.ociNumber != nil { 29 | C.free(unsafe.Pointer(&def.ociNumber[0])) 30 | } 31 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 32 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 33 | } 34 | 35 | func (def *defInt8) value(offset int) (value interface{}, err error) { 36 | if def.nullInds[offset] < 0 { 37 | if def.isNullable { 38 | return Int8{IsNull: true}, nil 39 | } 40 | return nil, nil 41 | } 42 | var int8Value int8 43 | on := def.ociNumber[offset] 44 | r := C.OCINumberToInt( 45 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 46 | &on, //const OCINumber *number, 47 | byteWidth8, //uword rsl_length, 48 | C.OCI_NUMBER_SIGNED, //uword rsl_flag, 49 | unsafe.Pointer(&int8Value)) //void *rsl ); 50 | if r == C.OCI_ERROR { 51 | err = def.rset.stmt.ses.srv.env.ociError() 52 | } 53 | if def.isNullable { 54 | return Int8{Value: int8Value}, err 55 | } 56 | return int8Value, err 57 | } 58 | 59 | func (def *defInt8) alloc() error { return nil } 60 | func (def *defInt8) free() { 61 | def.arrHlp.close() 62 | } 63 | 64 | func (def *defInt8) close() (err error) { 65 | defer func() { 66 | if value := recover(); value != nil { 67 | err = errR(value) 68 | } 69 | }() 70 | rset := def.rset 71 | def.rset = nil 72 | def.ocidef = nil 73 | if def.ociNumber != nil { 74 | C.free(unsafe.Pointer(&def.ociNumber[0])) 75 | def.ociNumber = nil 76 | } 77 | rset.putDef(defIdxInt8, def) 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /defIntervalYM.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | type defIntervalYM struct { 18 | ociDef 19 | intervals []*C.OCIInterval 20 | } 21 | 22 | func (def *defIntervalYM) define(position int, rset *Rset) error { 23 | def.rset = rset 24 | if def.intervals != nil { 25 | C.free(unsafe.Pointer(&def.intervals[0])) 26 | } 27 | def.intervals = (*((*[MaxFetchLen]*C.OCIInterval)(C.malloc(C.size_t(rset.fetchLen) * C.sof_Intervalp))))[:rset.fetchLen] 28 | def.ensureAllocatedLength(len(def.intervals)) 29 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.intervals[0]), int(C.sof_Intervalp), C.SQLT_INTERVAL_YM) 30 | } 31 | 32 | func (def *defIntervalYM) value(offset int) (value interface{}, err error) { 33 | intervalYM := IntervalYM{IsNull: def.nullInds[offset] < 0} 34 | if !intervalYM.IsNull { 35 | var year C.sb4 36 | var month C.sb4 37 | r := C.OCIIntervalGetYearMonth( 38 | unsafe.Pointer(def.rset.stmt.ses.srv.env.ocienv), //void *hndl, 39 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 40 | &year, //sb4 *yr, 41 | &month, //sb4 *mnth, 42 | def.intervals[offset]) //const OCIInterval *interval ); 43 | if r == C.OCI_ERROR { 44 | err = def.rset.stmt.ses.srv.env.ociError() 45 | } 46 | intervalYM.Year = int32(year) 47 | intervalYM.Month = int32(month) 48 | } 49 | return intervalYM, err 50 | } 51 | 52 | func (def *defIntervalYM) alloc() error { 53 | for i, p := range def.intervals { 54 | if p != nil { 55 | def.intervals[i] = nil 56 | //C.OCIDescriptorFree(unsafe.Pointer(p), C.OCI_DTYPE_INTERVAL_YM) 57 | } 58 | def.allocated[i] = false 59 | r := C.OCIDescriptorAlloc( 60 | unsafe.Pointer(def.rset.stmt.ses.srv.env.ocienv), //CONST dvoid *parenth, 61 | (*unsafe.Pointer)(unsafe.Pointer(&def.intervals[i])), //dvoid **descpp, 62 | C.OCI_DTYPE_INTERVAL_YM, //ub4 type, 63 | 0, //size_t xtramem_sz, 64 | nil) //dvoid **usrmempp); 65 | if r == C.OCI_ERROR { 66 | return def.rset.stmt.ses.srv.env.ociError() 67 | } else if r == C.OCI_INVALID_HANDLE { 68 | return errNew("unable to allocate oci interval handle during define") 69 | } 70 | def.allocated[i] = true 71 | } 72 | return nil 73 | } 74 | 75 | func (def *defIntervalYM) free() { 76 | for i, p := range def.intervals { 77 | if p == nil { 78 | continue 79 | } 80 | def.intervals[i] = nil 81 | if !def.allocated[i] { 82 | continue 83 | } 84 | C.OCIDescriptorFree( 85 | unsafe.Pointer(p), //void *descp, 86 | C.OCI_DTYPE_INTERVAL_YM) //timeDefine.descTypeCode) //ub4 type ); 87 | } 88 | def.arrHlp.close() 89 | } 90 | 91 | func (def *defIntervalYM) close() (err error) { 92 | defer func() { 93 | if value := recover(); value != nil { 94 | err = errR(value) 95 | } 96 | }() 97 | 98 | def.free() 99 | if def.intervals != nil { 100 | C.free(unsafe.Pointer(&def.intervals[0])) 101 | def.intervals = nil 102 | } 103 | rset := def.rset 104 | def.rset = nil 105 | def.ocidef = nil 106 | rset.putDef(defIdxIntervalYM, def) 107 | return nil 108 | } 109 | -------------------------------------------------------------------------------- /defLongRaw.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | type defLongRaw struct { 18 | ociDef 19 | isNullable bool 20 | buf []byte 21 | bufSize int 22 | } 23 | 24 | func (def *defLongRaw) define(position int, bufSize uint32, isNullable bool, rset *Rset) error { 25 | def.rset = rset 26 | def.isNullable = isNullable 27 | if n := rset.fetchLen * int(bufSize); cap(def.buf) < n { 28 | //def.buf = make([]byte, n) 29 | def.buf = bytesPool.Get(n) 30 | } else { 31 | def.buf = def.buf[:n] 32 | } 33 | def.bufSize = int(bufSize) 34 | 35 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.buf[0]), int(bufSize), C.SQLT_LBI) 36 | } 37 | 38 | func (def *defLongRaw) value(offset int) (value interface{}, err error) { 39 | if def.nullInds[offset] < 0 { 40 | if def.isNullable { 41 | return Raw{IsNull: true}, nil 42 | } 43 | return nil, nil 44 | } 45 | // Make a slice of length equal to the return length 46 | result := make([]byte, def.alen[offset]) 47 | // Copy returned data 48 | copyLength := copy(result, def.buf[offset*def.bufSize:(offset+1)*def.bufSize]) 49 | if C.ACTUAL_LENGTH_TYPE(copyLength) != def.alen[offset] { 50 | return nil, errNew("unable to copy LONG RAW result data from buffer") 51 | } 52 | 53 | if def.isNullable { 54 | return Raw{Value: result}, nil 55 | } 56 | return result, nil 57 | } 58 | 59 | func (def *defLongRaw) alloc() error { return nil } 60 | func (def *defLongRaw) free() { 61 | def.arrHlp.close() 62 | if def.buf != nil { 63 | bytesPool.Put(def.buf) 64 | def.buf = nil 65 | } 66 | } 67 | 68 | func (def *defLongRaw) close() (err error) { 69 | defer func() { 70 | if value := recover(); value != nil { 71 | err = errR(value) 72 | } 73 | }() 74 | 75 | rset := def.rset 76 | def.rset = nil 77 | def.ocidef = nil 78 | def.free() 79 | rset.putDef(defIdxLongRaw, def) 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /defOCINum.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type defOCINum struct { 16 | ociDef 17 | ociNumber []C.OCINumber 18 | isNullable bool 19 | } 20 | 21 | func (def *defOCINum) define(position int, isNullable bool, rset *Rset) error { 22 | def.rset = rset 23 | def.isNullable = isNullable 24 | if def.ociNumber != nil { 25 | C.free(unsafe.Pointer(&def.ociNumber[0])) 26 | } 27 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 28 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 29 | } 30 | func (def *defOCINum) value(offset int) (value interface{}, err error) { 31 | if def.nullInds[offset] < 0 { 32 | if def.isNullable { 33 | return OraOCINum{IsNull: true}, nil 34 | } 35 | return nil, nil 36 | } 37 | var num OCINum 38 | num.FromC(def.ociNumber[offset]) 39 | if def.isNullable { 40 | return OraOCINum{Value: num.OCINum}, nil 41 | } 42 | return OCINum{OCINum: num.OCINum}, nil 43 | } 44 | 45 | func (def *defOCINum) alloc() error { return nil } 46 | func (def *defOCINum) free() { 47 | def.arrHlp.close() 48 | } 49 | 50 | func (def *defOCINum) close() (err error) { 51 | defer func() { 52 | if value := recover(); value != nil { 53 | err = errR(value) 54 | } 55 | }() 56 | 57 | rset := def.rset 58 | def.rset = nil 59 | def.ocidef = nil 60 | if def.ociNumber != nil { 61 | C.free(unsafe.Pointer(&def.ociNumber[0])) 62 | def.ociNumber = nil 63 | } 64 | rset.putDef(defIdxOCINum, def) 65 | return nil 66 | } 67 | 68 | func (env *Env) numberToText(dest []byte, number C.OCINumber) ([]byte, error) { 69 | if cap(dest) < numStringLen { 70 | dest = make([]byte, numStringLen) 71 | } else { 72 | dest = dest[:numStringLen] 73 | } 74 | bufSize := C.ub4(len(dest)) 75 | r := C.OCINumberToText( 76 | env.ocierr, //OCIError *err, 77 | &number, //const OCINumber *number, 78 | numberFmtC, 79 | C.ub4(numberFmtLen), //ub4 fmt_length, 80 | numberNLSC, //CONST OraText *nls_params, 81 | C.ub4(numberNLSLen), //ub4 nls_p_length, 82 | &bufSize, //ub4 , 83 | (*C.oratext)(unsafe.Pointer(&dest[0])), //OraText *rsl ); 84 | ) 85 | if r == C.OCI_ERROR { 86 | return dest, env.ociError() 87 | } 88 | return dest[:bufSize], nil 89 | } 90 | -------------------------------------------------------------------------------- /defRaw.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | type defRaw struct { 18 | ociDef 19 | ociRaw *C.OCIRaw 20 | isNullable bool 21 | buf []byte 22 | columnSize int 23 | } 24 | 25 | func (def *defRaw) define(position int, columnSize int, isNullable bool, rset *Rset) error { 26 | def.rset = rset 27 | def.isNullable = isNullable 28 | def.columnSize = columnSize 29 | if n := rset.fetchLen * columnSize; cap(def.buf) < n { 30 | //def.buf = make([]byte, n) 31 | def.buf = bytesPool.Get(n) 32 | } else { 33 | def.buf = def.buf[:n] 34 | } 35 | 36 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.buf[0]), columnSize, C.SQLT_BIN) 37 | } 38 | 39 | func (def *defRaw) value(offset int) (value interface{}, err error) { 40 | if def.nullInds[offset] < 0 { 41 | if def.isNullable { 42 | return Raw{IsNull: true}, nil 43 | } 44 | return nil, nil 45 | } 46 | n := int(def.alen[offset]) 47 | off := offset * def.columnSize 48 | if def.isNullable { 49 | return Raw{Value: def.buf[off : off+n]}, nil 50 | } 51 | return def.buf[off : off+n], nil 52 | } 53 | 54 | func (def *defRaw) alloc() error { 55 | return nil 56 | } 57 | 58 | func (def *defRaw) free() { 59 | def.arrHlp.close() 60 | if def.buf != nil { 61 | bytesPool.Put(def.buf) 62 | def.buf = nil 63 | } 64 | } 65 | 66 | func (def *defRaw) close() (err error) { 67 | defer func() { 68 | if value := recover(); value != nil { 69 | err = errR(value) 70 | } 71 | }() 72 | 73 | rset := def.rset 74 | def.rset = nil 75 | def.ocidef = nil 76 | def.ociRaw = nil 77 | def.free() 78 | rset.putDef(defIdxRaw, def) 79 | return nil 80 | } 81 | -------------------------------------------------------------------------------- /defRowid.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include "version.h" 10 | */ 11 | import "C" 12 | import ( 13 | "bytes" 14 | "unsafe" 15 | ) 16 | 17 | const rowidLen = 19 18 | 19 | type defRowid struct { 20 | ociDef 21 | buf []byte 22 | } 23 | 24 | func (def *defRowid) define(position int, rset *Rset) error { 25 | def.rset = rset 26 | // using a character host variable of width between 19 27 | // (18 bytes plus the null-terminator) and 4001 as the 28 | // host bind variable for universal ROWID. 29 | if n := rset.fetchLen * rowidLen; cap(def.buf) < n { 30 | //def.buf = make([]byte, n) 31 | def.buf = bytesPool.Get(n) 32 | } else { 33 | def.buf = def.buf[:n] 34 | } 35 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.buf[0]), rowidLen, C.SQLT_STR) 36 | } 37 | 38 | func (def *defRowid) value(offset int) (value interface{}, err error) { 39 | n := bytes.Index(def.buf[offset*rowidLen:(offset+1)*rowidLen], []byte{0}) 40 | if n == -1 { 41 | n = rowidLen 42 | } 43 | value = string(def.buf[offset*rowidLen : offset*rowidLen+n]) 44 | return value, err 45 | } 46 | 47 | func (def *defRowid) alloc() error { return nil } 48 | func (def *defRowid) free() { 49 | def.arrHlp.close() 50 | if def.buf != nil { 51 | bytesPool.Put(def.buf) 52 | def.buf = nil 53 | } 54 | } 55 | 56 | func (def *defRowid) close() (err error) { 57 | defer func() { 58 | if value := recover(); value != nil { 59 | err = errR(value) 60 | } 61 | }() 62 | 63 | rset := def.rset 64 | def.rset = nil 65 | def.ocidef = nil 66 | def.free() 67 | rset.putDef(defIdxRowid, def) 68 | return nil 69 | } 70 | -------------------------------------------------------------------------------- /defRset.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Tamás Gulácsi. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | type defRset struct { 16 | ociDef 17 | ocistmt []*C.OCIStmt 18 | result []*Rset 19 | } 20 | 21 | func (def *defRset) define(position int, rset *Rset) error { 22 | def.rset = rset 23 | if def.ocistmt != nil { 24 | C.free(unsafe.Pointer(&def.ocistmt[0])) 25 | } 26 | def.ocistmt = (*((*[MaxFetchLen]*C.OCIStmt)(C.malloc(C.size_t(rset.fetchLen) * C.sof_Stmtp))))[:rset.fetchLen] 27 | def.result = make([]*Rset, len(def.ocistmt)) 28 | 29 | // create result set 30 | for i := range def.result { 31 | result := _drv.rsetPool.Get().(*Rset) 32 | if result.id == 0 { 33 | result.id = _drv.rsetId.nextId() 34 | } 35 | result.autoClose = true 36 | result.env = def.rset.env 37 | result.stmt = rset.stmt 38 | result.ocistmt = rset.ocistmt 39 | def.result[i] = result 40 | 41 | upOciStmt, err := def.rset.stmt.ses.srv.env.allocOciHandle(C.OCI_HTYPE_STMT) 42 | if err != nil { 43 | return errE(err) 44 | } 45 | def.ocistmt[i] = (*C.OCIStmt)(upOciStmt) 46 | } 47 | 48 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ocistmt[0]), int(C.sof_Stmtp), C.SQLT_RSET) 49 | } 50 | 51 | func (def *defRset) value(offset int) (value interface{}, err error) { 52 | rst := def.result[offset] 53 | 54 | err = rst.open(rst.stmt, def.ocistmt[offset]) 55 | rst.stmt.openRsets.add(rst) 56 | 57 | return rst, err 58 | } 59 | 60 | func (def *defRset) alloc() error { 61 | return nil 62 | } 63 | 64 | func (def *defRset) free() { 65 | def.arrHlp.close() 66 | for i, p := range def.ocistmt { 67 | if p == nil { 68 | continue 69 | } 70 | def.ocistmt[i] = nil 71 | def.rset.stmt.ses.srv.env.freeOciHandle(unsafe.Pointer(p), C.OCI_HTYPE_STMT) 72 | } 73 | } 74 | 75 | func (def *defRset) close() (err error) { 76 | defer func() { 77 | if value := recover(); value != nil { 78 | err = errR(value) 79 | } 80 | }() 81 | 82 | def.free() 83 | if def.ocistmt != nil { 84 | C.free(unsafe.Pointer(&def.ocistmt[0])) 85 | def.ocistmt = nil 86 | } 87 | rset := def.rset 88 | def.rset = nil 89 | def.ocidef = nil 90 | rset.putDef(defIdxRset, def) 91 | return nil 92 | } 93 | -------------------------------------------------------------------------------- /defString.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import ( 14 | "fmt" 15 | "os" 16 | "strings" 17 | "sync" 18 | "unsafe" 19 | ) 20 | 21 | type defString struct { 22 | ociDef 23 | sync.RWMutex 24 | buf []byte 25 | isNullable, rTrim bool 26 | columnSize int 27 | } 28 | 29 | type defNumString struct { 30 | defString 31 | } 32 | 33 | func (def *defNumString) define(position int, isNullable bool, rset *Rset) error { 34 | return def.defString.define(position, 40, isNullable, false, rset) 35 | } 36 | 37 | func (def *defString) define(position int, columnSize int, isNullable, rTrim bool, rset *Rset) error { 38 | def.Lock() 39 | defer def.Unlock() 40 | def.rset = rset 41 | def.isNullable, def.rTrim = isNullable, rTrim 42 | //Log.Infof("defString position=%d columnSize=%d", position, columnSize) 43 | n := columnSize 44 | // AL32UTF8: one db "char" can be 4 bytes on wire, esp. if the database's 45 | // character set is not AL32UTF8 (e.g. some 8bit fixed width charset), and 46 | // the column is VARCHAR2 with byte semantics. 47 | // 48 | // For example when the db's charset is EE8ISO8859P2, then a VARCHAR2(1) can 49 | // contain an "ű", which is 2 bytes AL32UTF8. 50 | rset.stmt.RLock() 51 | rset.stmt.ses.RLock() 52 | isUTF8 := rset.stmt.ses.srv.IsUTF8() 53 | rset.stmt.ses.RUnlock() 54 | rset.stmt.RUnlock() 55 | if !isUTF8 { 56 | n *= 2 57 | } 58 | if n == 0 { 59 | n = 2 60 | } 61 | if n%2 != 0 { 62 | n++ 63 | } 64 | def.columnSize = n 65 | if n := rset.fetchLen * def.columnSize; cap(def.buf) < n { 66 | //def.buf = make([]byte, n) 67 | def.buf = bytesPool.Get(n) 68 | } else { 69 | def.buf = def.buf[:n] 70 | } 71 | 72 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.buf[0]), def.columnSize, C.SQLT_CHR) 73 | } 74 | 75 | func (def *defString) value(offset int) (value interface{}, err error) { 76 | def.RLock() 77 | defer def.RUnlock() 78 | if offset < 0 || offset >= len(def.nullInds) { 79 | fmt.Fprintf(os.Stderr, "offset=%d nullInds=%d\n", offset, len(def.nullInds)) 80 | } 81 | if def.nullInds[offset] < 0 { 82 | if def.isNullable { 83 | return String{IsNull: true}, nil 84 | } 85 | return "", nil 86 | } 87 | var s string 88 | //def.rset.logF(_drv.Cfg().Log.Stmt.Bind, 89 | // "%p offset=%d alen=%v, colSize=%d, buf=%v", 90 | // def, offset, def.alen, def.columnSize, def.buf[offset*def.columnSize:offset*def.columnSize+int(def.alen[offset])]) 91 | if def.alen[offset] > 0 { 92 | off := offset * def.columnSize 93 | s = string(def.buf[off : off+int(def.alen[offset])]) 94 | if def.rTrim { 95 | s = strings.TrimRight(s, " ") 96 | } 97 | } 98 | if def.isNullable { 99 | return String{Value: s}, nil 100 | } 101 | return s, nil 102 | } 103 | 104 | func (def *defString) alloc() error { 105 | return nil 106 | } 107 | 108 | func (def *defString) free() { 109 | def.Lock() 110 | def.arrHlp.close() 111 | if def.buf != nil { 112 | bytesPool.Put(def.buf) 113 | def.buf = nil 114 | } 115 | def.Unlock() 116 | } 117 | 118 | func (def *defString) close() (err error) { 119 | defer func() { 120 | if value := recover(); value != nil { 121 | err = errR(value) 122 | } 123 | }() 124 | 125 | def.free() 126 | rset := def.rset 127 | def.rset = nil 128 | def.ocidef = nil 129 | rset.putDef(defIdxString, def) 130 | return nil 131 | } 132 | -------------------------------------------------------------------------------- /defUint16.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // Generate all the def[IU]int{8,16,32,16}.go from defUint16.go 16 | // 17 | // Generated from defUint16.go by go run gen.go 18 | 19 | type defUint16 struct { 20 | ociDef 21 | ociNumber []C.OCINumber 22 | isNullable bool 23 | } 24 | 25 | func (def *defUint16) define(position int, isNullable bool, rset *Rset) error { 26 | def.rset = rset 27 | def.isNullable = isNullable 28 | if def.ociNumber != nil { 29 | C.free(unsafe.Pointer(&def.ociNumber[0])) 30 | } 31 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 32 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 33 | } 34 | 35 | func (def *defUint16) value(offset int) (value interface{}, err error) { 36 | if def.nullInds[offset] < 0 { 37 | if def.isNullable { 38 | return Uint16{IsNull: true}, nil 39 | } 40 | return nil, nil 41 | } 42 | var uint16Value uint16 43 | on := def.ociNumber[offset] 44 | r := C.OCINumberToInt( 45 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 46 | &on, //const OCINumber *number, 47 | byteWidth16, //uword rsl_length, 48 | C.OCI_NUMBER_UNSIGNED, //uword rsl_flag, 49 | unsafe.Pointer(&uint16Value)) //void *rsl ); 50 | if r == C.OCI_ERROR { 51 | err = def.rset.stmt.ses.srv.env.ociError() 52 | } 53 | if def.isNullable { 54 | return Uint16{Value: uint16Value}, err 55 | } 56 | return uint16Value, err 57 | } 58 | 59 | func (def *defUint16) alloc() error { return nil } 60 | func (def *defUint16) free() { 61 | def.arrHlp.close() 62 | } 63 | 64 | func (def *defUint16) close() (err error) { 65 | defer func() { 66 | if value := recover(); value != nil { 67 | err = errR(value) 68 | } 69 | }() 70 | rset := def.rset 71 | def.rset = nil 72 | def.ocidef = nil 73 | if def.ociNumber != nil { 74 | C.free(unsafe.Pointer(&def.ociNumber[0])) 75 | def.ociNumber = nil 76 | } 77 | rset.putDef(defIdxUint16, def) 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /defUint32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // Generate all the def[IU]int{8,16,32,32}.go from defUint32.go 16 | // 17 | // Generated from defUint32.go by go run gen.go 18 | 19 | type defUint32 struct { 20 | ociDef 21 | ociNumber []C.OCINumber 22 | isNullable bool 23 | } 24 | 25 | func (def *defUint32) define(position int, isNullable bool, rset *Rset) error { 26 | def.rset = rset 27 | def.isNullable = isNullable 28 | if def.ociNumber != nil { 29 | C.free(unsafe.Pointer(&def.ociNumber[0])) 30 | } 31 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 32 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 33 | } 34 | 35 | func (def *defUint32) value(offset int) (value interface{}, err error) { 36 | if def.nullInds[offset] < 0 { 37 | if def.isNullable { 38 | return Uint32{IsNull: true}, nil 39 | } 40 | return nil, nil 41 | } 42 | var uint32Value uint32 43 | on := def.ociNumber[offset] 44 | r := C.OCINumberToInt( 45 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 46 | &on, //const OCINumber *number, 47 | byteWidth32, //uword rsl_length, 48 | C.OCI_NUMBER_UNSIGNED, //uword rsl_flag, 49 | unsafe.Pointer(&uint32Value)) //void *rsl ); 50 | if r == C.OCI_ERROR { 51 | err = def.rset.stmt.ses.srv.env.ociError() 52 | } 53 | if def.isNullable { 54 | return Uint32{Value: uint32Value}, err 55 | } 56 | return uint32Value, err 57 | } 58 | 59 | func (def *defUint32) alloc() error { return nil } 60 | func (def *defUint32) free() { 61 | def.arrHlp.close() 62 | } 63 | 64 | func (def *defUint32) close() (err error) { 65 | defer func() { 66 | if value := recover(); value != nil { 67 | err = errR(value) 68 | } 69 | }() 70 | rset := def.rset 71 | def.rset = nil 72 | def.ocidef = nil 73 | if def.ociNumber != nil { 74 | C.free(unsafe.Pointer(&def.ociNumber[0])) 75 | def.ociNumber = nil 76 | } 77 | rset.putDef(defIdxUint32, def) 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /defUint64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // Generate all the def[IU]int{8,16,32,64}.go from defUint64.go 16 | // 17 | // Generated from defUint64.go by go run gen.go 18 | 19 | type defUint64 struct { 20 | ociDef 21 | ociNumber []C.OCINumber 22 | isNullable bool 23 | } 24 | 25 | func (def *defUint64) define(position int, isNullable bool, rset *Rset) error { 26 | def.rset = rset 27 | def.isNullable = isNullable 28 | if def.ociNumber != nil { 29 | C.free(unsafe.Pointer(&def.ociNumber[0])) 30 | } 31 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 32 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 33 | } 34 | 35 | func (def *defUint64) value(offset int) (value interface{}, err error) { 36 | if def.nullInds[offset] < 0 { 37 | if def.isNullable { 38 | return Uint64{IsNull: true}, nil 39 | } 40 | return nil, nil 41 | } 42 | var uint64Value uint64 43 | on := def.ociNumber[offset] 44 | r := C.OCINumberToInt( 45 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 46 | &on, //const OCINumber *number, 47 | byteWidth64, //uword rsl_length, 48 | C.OCI_NUMBER_UNSIGNED, //uword rsl_flag, 49 | unsafe.Pointer(&uint64Value)) //void *rsl ); 50 | if r == C.OCI_ERROR { 51 | err = def.rset.stmt.ses.srv.env.ociError() 52 | } 53 | if def.isNullable { 54 | return Uint64{Value: uint64Value}, err 55 | } 56 | return uint64Value, err 57 | } 58 | 59 | func (def *defUint64) alloc() error { return nil } 60 | func (def *defUint64) free() { 61 | def.arrHlp.close() 62 | } 63 | 64 | func (def *defUint64) close() (err error) { 65 | defer func() { 66 | if value := recover(); value != nil { 67 | err = errR(value) 68 | } 69 | }() 70 | rset := def.rset 71 | def.rset = nil 72 | def.ocidef = nil 73 | if def.ociNumber != nil { 74 | C.free(unsafe.Pointer(&def.ociNumber[0])) 75 | def.ociNumber = nil 76 | } 77 | rset.putDef(defIdxUint64, def) 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /defUint8.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | /* 8 | #include 9 | #include 10 | #include "version.h" 11 | */ 12 | import "C" 13 | import "unsafe" 14 | 15 | // Generate all the def[IU]int{8,16,32,8}.go from defUint8.go 16 | // 17 | // Generated from defUint8.go by go run gen.go 18 | 19 | type defUint8 struct { 20 | ociDef 21 | ociNumber []C.OCINumber 22 | isNullable bool 23 | } 24 | 25 | func (def *defUint8) define(position int, isNullable bool, rset *Rset) error { 26 | def.rset = rset 27 | def.isNullable = isNullable 28 | if def.ociNumber != nil { 29 | C.free(unsafe.Pointer(&def.ociNumber[0])) 30 | } 31 | def.ociNumber = (*((*[MaxFetchLen]C.OCINumber)(C.malloc(C.size_t(rset.fetchLen) * C.sizeof_OCINumber))))[:rset.fetchLen] 32 | return def.ociDef.defineByPos(position, unsafe.Pointer(&def.ociNumber[0]), C.sizeof_OCINumber, C.SQLT_VNU) 33 | } 34 | 35 | func (def *defUint8) value(offset int) (value interface{}, err error) { 36 | if def.nullInds[offset] < 0 { 37 | if def.isNullable { 38 | return Uint8{IsNull: true}, nil 39 | } 40 | return nil, nil 41 | } 42 | var uint8Value uint8 43 | on := def.ociNumber[offset] 44 | r := C.OCINumberToInt( 45 | def.rset.stmt.ses.srv.env.ocierr, //OCIError *err, 46 | &on, //const OCINumber *number, 47 | byteWidth8, //uword rsl_length, 48 | C.OCI_NUMBER_UNSIGNED, //uword rsl_flag, 49 | unsafe.Pointer(&uint8Value)) //void *rsl ); 50 | if r == C.OCI_ERROR { 51 | err = def.rset.stmt.ses.srv.env.ociError() 52 | } 53 | if def.isNullable { 54 | return Uint8{Value: uint8Value}, err 55 | } 56 | return uint8Value, err 57 | } 58 | 59 | func (def *defUint8) alloc() error { return nil } 60 | func (def *defUint8) free() { 61 | def.arrHlp.close() 62 | } 63 | 64 | func (def *defUint8) close() (err error) { 65 | defer func() { 66 | if value := recover(); value != nil { 67 | err = errR(value) 68 | } 69 | }() 70 | rset := def.rset 71 | def.rset = nil 72 | def.ocidef = nil 73 | if def.ociNumber != nil { 74 | C.free(unsafe.Pointer(&def.ociNumber[0])) 75 | def.ociNumber = nil 76 | } 77 | rset.putDef(defIdxUint8, def) 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /drvExecResult.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | import ( 8 | "math" 9 | ) 10 | 11 | // DrvExecResult is an Oracle execution result. 12 | // 13 | // DrvExecResult implements the driver.Result interface. 14 | type DrvExecResult struct { 15 | lastInsertId int64 16 | rowsAffected uint64 17 | } 18 | 19 | // LastInsertId returns the identity value from an insert statement. 20 | // 21 | // There are two setup steps required to reteive the LastInsertId. 22 | // One, specify a 'returning into' clause in the SQL insert statement. 23 | // And, two, specify a nil parameter to DB.Exec or DrvStmt.Exec. 24 | // 25 | // For example: 26 | // 27 | // db, err := sql.Open("ora", "scott/tiger@orcl") 28 | // 29 | // db.Exec("CREATE TABLE T1 (C1 NUMBER(19,0) GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), C2 VARCHAR2(48 CHAR))") 30 | // 31 | // result, err := db.Exec("INSERT INTO T1 (C2) VALUES ('GO') RETURNING C1 /*lastInsertId*/ INTO :C1", nil) 32 | // 33 | // id, err := result.LastInsertId() 34 | func (er *DrvExecResult) LastInsertId() (int64, error) { 35 | return er.lastInsertId, nil 36 | } 37 | 38 | // RowsAffected returns the number of rows affected by the exec statement. 39 | func (er *DrvExecResult) RowsAffected() (int64, error) { 40 | var rowsAffected int64 41 | if er.rowsAffected > math.MaxInt64 { 42 | rowsAffected = math.MaxInt64 43 | } else { 44 | rowsAffected = int64(er.rowsAffected) 45 | } 46 | return rowsAffected, nil 47 | } 48 | -------------------------------------------------------------------------------- /drvStmt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | import ( 8 | "database/sql/driver" 9 | "fmt" 10 | ) 11 | 12 | // DrvStmt is an Oracle statement associated with a session. 13 | // 14 | // DrvStmt wraps Stmt and is intended for use by the database/sql/driver package. 15 | // 16 | // DrvStmt implements the driver.Stmt interface. 17 | type DrvStmt struct { 18 | stmt *Stmt 19 | } 20 | 21 | // checkIsOpen validates that the server is open. 22 | func (ds *DrvStmt) checkIsOpen() error { 23 | if ds.stmt == nil { 24 | return er("DrvStmt is closed.") 25 | } 26 | return nil 27 | } 28 | 29 | // Close closes the SQL statement. 30 | // 31 | // Close is a member of the driver.Stmt interface. 32 | func (ds *DrvStmt) Close() error { 33 | ds.log(true) 34 | if err := ds.checkIsOpen(); err != nil { 35 | return errE(err) 36 | } 37 | if err := ds.stmt.Close(); err != nil { 38 | return errE(err) 39 | } 40 | return nil 41 | } 42 | 43 | // NumInput returns the number of placeholders in a sql statement. 44 | // 45 | // NumInput is a member of the driver.Stmt interface. 46 | func (ds *DrvStmt) NumInput() int { 47 | if ds.stmt == nil { 48 | return 0 49 | } 50 | return ds.stmt.NumInput() 51 | } 52 | 53 | // Exec executes an Oracle SQL statement on a server. Exec returns a driver.Result 54 | // and a possible error. 55 | // 56 | // Exec is a member of the driver.Stmt interface. 57 | func (ds *DrvStmt) Exec(values []driver.Value) (driver.Result, error) { 58 | ds.log(true) 59 | if err := ds.checkIsOpen(); err != nil { 60 | return nil, errE(err) 61 | } 62 | params := make([]interface{}, len(values)) 63 | for n := range values { 64 | params[n] = values[n] 65 | } 66 | rowsAffected, lastInsertId, err := ds.stmt.exe(params, false) 67 | if err != nil { 68 | return nil, maybeBadConn(err) 69 | } 70 | if rowsAffected == 0 { 71 | return driver.RowsAffected(0), nil 72 | } 73 | return &DrvExecResult{rowsAffected: rowsAffected, lastInsertId: lastInsertId}, nil 74 | } 75 | 76 | // Query runs a SQL query on an Oracle server. Query returns driver.Rows and a 77 | // possible error. 78 | // 79 | // Query is a member of the driver.Stmt interface. 80 | func (ds *DrvStmt) Query(values []driver.Value) (driver.Rows, error) { 81 | ds.log(true) 82 | if err := ds.checkIsOpen(); err != nil { 83 | return nil, errE(err) 84 | } 85 | params := make([]interface{}, len(values)) 86 | for n := range values { 87 | params[n] = values[n] 88 | } 89 | rset, err := ds.stmt.qry(params) 90 | if err != nil { 91 | return nil, maybeBadConn(err) 92 | } 93 | return &DrvQueryResult{rset: rset}, nil 94 | } 95 | 96 | // sysName returns a string representing the DrvStmt. 97 | func (ds *DrvStmt) sysName() string { 98 | if ds == nil { 99 | return "E_S_S_S_S_" 100 | } 101 | return ds.stmt.sysName() + fmt.Sprintf("S%v", ds.stmt.id) 102 | } 103 | 104 | // log writes a message with an DrvStmt system name and caller info. 105 | func (ds *DrvStmt) log(enabled bool, v ...interface{}) { 106 | cfg := _drv.Cfg() 107 | if !cfg.Log.IsEnabled(enabled) { 108 | return 109 | } 110 | if len(v) == 0 { 111 | cfg.Log.Logger.Infof("%v %v", ds.sysName(), callInfo(1)) 112 | } else { 113 | cfg.Log.Logger.Infof("%v %v %v", ds.sysName(), callInfo(1), fmt.Sprint(v...)) 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /drvStmt_go1_8.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | // Copyright 2017 Tamás Gulácsi. All rights reserved. 4 | // Use of this source code is governed by The MIT License 5 | // found in the accompanying LICENSE file. 6 | 7 | package ora 8 | 9 | import ( 10 | "context" 11 | "database/sql/driver" 12 | ) 13 | 14 | // ExecContext enhances the Stmt interface by providing Exec with context. 15 | // ExecContext must honor the context timeout and return when it is cancelled. 16 | func (ds *DrvStmt) ExecContext(ctx context.Context, values []driver.NamedValue) (driver.Result, error) { 17 | ds.log(true) 18 | if err := ds.checkIsOpen(); err != nil { 19 | return nil, errE(err) 20 | } 21 | params := make([]interface{}, len(values)) 22 | for n, v := range values { 23 | params[n] = v 24 | } 25 | if err := ctx.Err(); err != nil { 26 | return nil, err 27 | } 28 | 29 | done := make(chan struct{}) 30 | go func() { 31 | select { 32 | case <-done: 33 | case <-ctx.Done(): 34 | // select again to avoid race condition if both are done 35 | select { 36 | case <-done: 37 | default: 38 | if isCanceled(ctx.Err()) { 39 | ds.stmt.RLock() 40 | ses := ds.stmt.ses 41 | ds.stmt.RUnlock() 42 | ses.Break() 43 | } 44 | } 45 | } 46 | }() 47 | 48 | var err error 49 | var res DrvExecResult 50 | res.rowsAffected, res.lastInsertId, err = ds.stmt.exeC(ctx, params, false) 51 | close(done) 52 | 53 | if err != nil { 54 | return nil, maybeBadConn(err) 55 | } 56 | if res.rowsAffected == 0 { 57 | return driver.RowsAffected(0), nil 58 | } 59 | return &res, nil 60 | } 61 | 62 | // QueryContext enhances the Stmt interface by providing Query with context. 63 | // QueryContext must honor the context timeout and return when it is cancelled. 64 | func (ds *DrvStmt) QueryContext(ctx context.Context, values []driver.NamedValue) (driver.Rows, error) { 65 | ds.log(true) 66 | if err := ds.checkIsOpen(); err != nil { 67 | return nil, errE(err) 68 | } 69 | params := make([]interface{}, len(values)) 70 | for n, v := range values { 71 | params[n] = v 72 | } 73 | if err := ctx.Err(); err != nil { 74 | return nil, err 75 | } 76 | done := make(chan struct{}) 77 | go func() { 78 | select { 79 | case <-done: 80 | case <-ctx.Done(): 81 | // select again to avoid race condition if both are done 82 | select { 83 | case <-done: 84 | default: 85 | if isCanceled(ctx.Err()) { 86 | ds.stmt.RLock() 87 | ses := ds.stmt.ses 88 | ds.stmt.RUnlock() 89 | ses.Break() 90 | } 91 | } 92 | } 93 | }() 94 | 95 | rset, err := ds.stmt.qryC(ctx, params) 96 | close(done) 97 | 98 | if err != nil { 99 | return nil, maybeBadConn(err) 100 | } 101 | return &DrvQueryResult{rset: rset}, nil 102 | } 103 | 104 | // vim: set fileencoding=utf-8 noet: 105 | -------------------------------------------------------------------------------- /examples/bench/.gitignore: -------------------------------------------------------------------------------- 1 | *.pprof 2 | *.test 3 | *.bench 4 | -------------------------------------------------------------------------------- /examples/bench/README.md: -------------------------------------------------------------------------------- 1 | # Benchmark ora vs. oci8 2 | Compile a simple SELECT benchmark with `github.com/mattn/go-oci8` and `gopkg.in/rana/ora.v4`, and compare them: 3 | 4 | ./run.sh 5 | 6 | ## Result 7 | 8 | ``` 9 | $ ./run.sh 10 | Compile ... 11 | Benchmarks on DSN=boma/boma@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=p520.unosoft.local)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=cigf.unosoft.local))) ... 12 | go-oci8 13 | 2016/03/30 11:10:37 Write CPU profile to "oci8.pprof". 14 | 2016/03/30 11:10:42 Iterated 5000 rows in 3.518387308s. 15 | 2016/03/30 11:10:42 1 3518345504 ns/op 0.00 MB/s 16 | Entering interactive mode (type "help" for commands) 17 | (pprof) (pprof) 20ms of 20ms total ( 100%) 18 | flat flat% sum% cum cum% 19 | 0 0% 0% 20ms 100% database/sql.(*Rows).Next 20 | 0 0% 0% 20ms 100% github.com/mattn/go-oci8.(*OCI8Rows).Next 21 | 0 0% 0% 20ms 100% github.com/mattn/go-oci8._Cfunc_OCIStmtFetch 22 | 0 0% 0% 20ms 100% main.BenchmarkIter 23 | 20ms 100% 100% 20ms 100% runtime.cgocall 24 | 0 0% 100% 20ms 100% runtime.goexit 25 | 0 0% 100% 20ms 100% testing.(*B).launch 26 | 0 0% 100% 20ms 100% testing.(*B).runN 27 | (pprof) ora 28 | 2016/03/30 11:10:42 Write CPU profile to "ora.pprof". 29 | 2016/03/30 11:10:56 Iterated 5000 rows in 12.527146357s. 30 | 2016/03/30 11:10:56 1 12527036391 ns/op 0.00 MB/s 31 | Entering interactive mode (type "help" for commands) 32 | (pprof) (pprof) 110ms of 110ms total ( 100%) 33 | flat flat% sum% cum cum% 34 | 0 0% 0% 110ms 100% database/sql.(*Rows).Next 35 | 0 0% 0% 110ms 100% gopkg.in/rana/ora%2ev3.(*DrvQueryResult).Next 36 | 0 0% 0% 110ms 100% gopkg.in/rana/ora%2ev3.(*Rset).beginRow 37 | 0 0% 0% 110ms 100% gopkg.in/rana/ora%2ev3._Cfunc_OCIStmtFetch2 38 | 0 0% 0% 110ms 100% main.BenchmarkIter 39 | 110ms 100% 100% 110ms 100% runtime.cgocall 40 | 0 0% 100% 110ms 100% runtime.goexit 41 | 0 0% 100% 110ms 100% testing.(*B).launch 42 | 0 0% 100% 110ms 100% testing.(*B).runN 43 | (pprof) :tgulacsi@tgulacsi-laptop: ~/src/gopkg.in/rana/ora.v4/examples/bench 44 | ``` 45 | -------------------------------------------------------------------------------- /examples/bench/gen.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //go:generate mkdir -p ora 4 | //go:generate sh -c "sed -e 's:github.com/mattn/go-oci8:gopkg.in/rana/ora.v4:;s/Oci8/Ora/g;s/oci8/ora/g' oci8/bench_oci8.go >ora/bench_ora.go" 5 | -------------------------------------------------------------------------------- /examples/bench/oci8/bench_oci8.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Tamás Gulácsi, Jia Lu. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "database/sql" 9 | "flag" 10 | "log" 11 | "os" 12 | "runtime/pprof" 13 | "testing" 14 | "time" 15 | 16 | _ "github.com/mattn/go-oci8" 17 | ) 18 | 19 | var ( 20 | DB *sql.DB 21 | cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") 22 | N = flag.Int("N", 1000, "row count") 23 | ) 24 | 25 | func init() { 26 | flag.Parse() 27 | drv, dsn := "oci8", os.ExpandEnv(flag.Arg(0)) 28 | var err error 29 | if DB, err = sql.Open(drv, dsn); err != nil { 30 | log.Fatalf("cannot connect with %q to %q: %v", drv, dsn, err) 31 | } 32 | if err = DB.Ping(); err != nil { 33 | log.Fatalf("cannot connect with %q to %q: %v", drv, dsn, err) 34 | } 35 | } 36 | 37 | func main() { 38 | if *cpuprofile != "" { 39 | f, err := os.Create(*cpuprofile) 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | log.Printf("Write CPU profile to %q.", f.Name()) 44 | pprof.StartCPUProfile(f) 45 | defer pprof.StopCPUProfile() 46 | } 47 | 48 | result := testing.Benchmark(BenchmarkIter) 49 | log.Println(result) 50 | } 51 | 52 | func BenchmarkIter(b *testing.B) { 53 | rows, err := DB.Query("SELECT A.object_name from all_objects, all_objects A") 54 | if err != nil { 55 | b.Fatal(err) 56 | } 57 | defer rows.Close() 58 | b.ReportAllocs() 59 | start := time.Now() 60 | b.ResetTimer() 61 | i := 0 62 | N := *N 63 | for rows.Next() && i < N { 64 | i++ 65 | } 66 | b.StopTimer() 67 | d := time.Since(start) 68 | b.SetBytes(int64(i)) 69 | log.Printf("Iterated %d rows in %s: %.3f row/s.", 70 | i, d, float64(i)/(float64(d)/float64(time.Second))) 71 | } 72 | -------------------------------------------------------------------------------- /examples/bench/ora/bench_ora.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Tamás Gulácsi, Jia Lu. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "database/sql" 9 | "flag" 10 | "log" 11 | "os" 12 | "runtime/pprof" 13 | "testing" 14 | "time" 15 | 16 | _ "gopkg.in/rana/ora.v4" 17 | ) 18 | 19 | var ( 20 | DB *sql.DB 21 | cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") 22 | N = flag.Int("N", 1000, "row count") 23 | ) 24 | 25 | func init() { 26 | flag.Parse() 27 | drv, dsn := "ora", os.ExpandEnv(flag.Arg(0)) 28 | var err error 29 | if DB, err = sql.Open(drv, dsn); err != nil { 30 | log.Fatalf("cannot connect with %q to %q: %v", drv, dsn, err) 31 | } 32 | if err = DB.Ping(); err != nil { 33 | log.Fatalf("cannot connect with %q to %q: %v", drv, dsn, err) 34 | } 35 | } 36 | 37 | func main() { 38 | if *cpuprofile != "" { 39 | f, err := os.Create(*cpuprofile) 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | log.Printf("Write CPU profile to %q.", f.Name()) 44 | pprof.StartCPUProfile(f) 45 | defer pprof.StopCPUProfile() 46 | } 47 | 48 | result := testing.Benchmark(BenchmarkIter) 49 | log.Println(result) 50 | } 51 | 52 | func BenchmarkIter(b *testing.B) { 53 | rows, err := DB.Query("SELECT A.object_name from all_objects, all_objects A") 54 | if err != nil { 55 | b.Fatal(err) 56 | } 57 | defer rows.Close() 58 | b.ReportAllocs() 59 | start := time.Now() 60 | b.ResetTimer() 61 | i := 0 62 | N := *N 63 | for rows.Next() && i < N { 64 | i++ 65 | } 66 | b.StopTimer() 67 | d := time.Since(start) 68 | b.SetBytes(int64(i)) 69 | log.Printf("Iterated %d rows in %s: %.3f row/s.", 70 | i, d, float64(i)/(float64(d)/float64(time.Second))) 71 | } 72 | -------------------------------------------------------------------------------- /examples/bench/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | DSN="$1" 3 | BENCHTIME="${BENCHTIME:-1s}" 4 | N=${N:-5000} 5 | if [ -z "$DSN" ]; then 6 | DSN=${GO_ORA_DRV_TEST_USERNAME}/${GO_ORA_DRV_TEST_PASSWORD}@${GO_ORA_DRV_TEST_DB} 7 | fi 8 | echo "Compile ..." >&2 9 | go build -o oci8.bench ./oci8 & 10 | go build -o ora.bench ./ora 11 | wait 12 | 13 | run () { 14 | nm="$1" 15 | echo "$nm" >&2 16 | ./"$nm".bench -cpuprofile="$nm".pprof -N=$N -test.benchtime=$BENCHTIME "$DSN" 17 | echo "cum\ntop20" | go tool pprof ./"$nm".bench "$nm".pprof 18 | } 19 | 20 | echo "Benchmarks on DSN=${DSN} ..." >&2 21 | run oci8 22 | run ora 23 | -------------------------------------------------------------------------------- /examples/conntest/conn_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Tamás Gulácsi 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "testing" 21 | ) 22 | 23 | func TestListObjects(t *testing.T) { 24 | ListObjects(t) 25 | } 26 | -------------------------------------------------------------------------------- /examples/conntest/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package main in conntest represents a connection testing program. 3 | 4 | Copyright 2013 Tamás Gulácsi 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | package main 19 | 20 | import ( 21 | "flag" 22 | "log" 23 | "os" 24 | "os/signal" 25 | "sync" 26 | "syscall" 27 | "testing" 28 | 29 | "gopkg.in/rana/ora.v4/examples/connect" 30 | ) 31 | 32 | var fWait = flag.Bool("wait", false, "wait for USR1 signal?") 33 | 34 | func ListObjects(t *testing.T) { 35 | conn, err := connect.GetConnection("") 36 | if err != nil { 37 | t.Errorf("error connectiong: %s", err) 38 | t.FailNow() 39 | return 40 | } 41 | defer conn.Close() 42 | 43 | qry := "SELECT owner, object_name, object_id FROM all_objects WHERE ROWNUM < 20" 44 | log.Printf(`executing "%s"`, qry) 45 | rows, err := conn.Query(qry) 46 | if err != nil { 47 | t.Logf(`error with %q: %s`, qry, err) 48 | t.FailNow() 49 | return 50 | } 51 | var ( 52 | owner, objectName string 53 | objectID int 54 | ) 55 | for rows.Next() { 56 | if err = rows.Scan(&owner, &objectName, &objectID); err != nil { 57 | t.Errorf("error fetching: %s", err) 58 | break 59 | } 60 | t.Logf(`row: "%s";"%s";%d`, owner, objectName, objectID) 61 | } 62 | } 63 | 64 | func main() { 65 | flag.Parse() 66 | t := new(testing.T) 67 | if *fWait { 68 | c := make(chan os.Signal) 69 | var wg sync.WaitGroup 70 | wg.Add(1) 71 | go func() { 72 | log.Printf("waiting for signal...") 73 | sig := <-c 74 | log.Printf("got signal %s", sig) 75 | ListObjects(t) 76 | wg.Done() 77 | }() 78 | signal.Notify(c, syscall.SIGUSR1) 79 | wg.Wait() 80 | } else { 81 | ListObjects(t) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /examples/csvdump/README.md: -------------------------------------------------------------------------------- 1 | # csvdump # 2 | ## Usage ## 3 | ./csvdump -db.dsn=user/passw@sid all_objects >x.csv 4 | -------------------------------------------------------------------------------- /gen.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // Copyright 2016 Tamás Gulácsi. All rights reserved. 4 | // Use of this source code is governed by The MIT License 5 | // found in the accompanying LICENSE file. 6 | 7 | package main 8 | 9 | import ( 10 | "bytes" 11 | "io/ioutil" 12 | "log" 13 | ) 14 | 15 | func main() { 16 | src := "defFloat64.go" 17 | b := readFile(src) 18 | dst := "defFloat32.go" 19 | log.Printf("%s => %s", src, dst) 20 | if err := ioutil.WriteFile( 21 | dst, 22 | bytes.Replace(b, []byte("64"), []byte("32"), -1), 23 | 0644, 24 | ); err != nil { 25 | log.Fatal(err) 26 | } 27 | 28 | src = "defInt64.go" 29 | b = readFile(src) 30 | for _, s := range []string{"8", "16", "32"} { 31 | dst = "defInt" + s + ".go" 32 | log.Printf("%s => %s", src, dst) 33 | if err := ioutil.WriteFile( 34 | dst, 35 | bytes.Replace(b, []byte("64"), []byte(s), -1), 36 | 0644, 37 | ); err != nil { 38 | log.Fatal(err) 39 | } 40 | } 41 | 42 | for _, pair := range [][2]string{ 43 | {"OCI_NUMBER_SIGNED", "OCI_NUMBER_UNSIGNED"}, 44 | {"int64", "uint64"}, 45 | {"Int64", "Uint64"}, 46 | } { 47 | b = bytes.Replace(b, []byte(pair[0]), []byte(pair[1]), -1) 48 | } 49 | dst = "defUint64.go" 50 | if err := ioutil.WriteFile(dst, b, 0644); err != nil { 51 | log.Fatal(err) 52 | } 53 | for _, s := range []string{"8", "16", "32"} { 54 | dst = "defUint" + s + ".go" 55 | log.Printf("%s => %s", src, dst) 56 | if err := ioutil.WriteFile( 57 | dst, 58 | bytes.Replace(b, []byte("64"), []byte(s), -1), 59 | 0644, 60 | ); err != nil { 61 | log.Fatal(err) 62 | } 63 | } 64 | 65 | for _, plus := range []string{"", "Ptr", "Slice"} { 66 | src = "bndFloat64" + plus + ".go" 67 | b := readFile(src) 68 | dst = "bndFloat32" + plus + ".go" 69 | log.Printf("%s => %s", src, dst) 70 | if err := ioutil.WriteFile( 71 | dst, 72 | bytes.Replace( 73 | bytes.Replace(b, []byte("64"), []byte("32"), -1), 74 | []byte("floatSixtyFour("), []byte("float64("), -1), 75 | 0644, 76 | ); err != nil { 77 | log.Fatal(err) 78 | } 79 | 80 | src = "bndInt64" + plus + ".go" 81 | b = readFile(src) 82 | for _, s := range []string{"8", "16", "32"} { 83 | dst = "bndInt" + s + plus + ".go" 84 | log.Printf("%s => %s", src, dst) 85 | if err := ioutil.WriteFile( 86 | dst, 87 | bytes.Replace( 88 | bytes.Replace(b, []byte("64"), []byte(s), -1), 89 | []byte("intSixtyFour("), []byte("int64("), -1), 90 | 0644, 91 | ); err != nil { 92 | log.Fatal(err) 93 | } 94 | } 95 | 96 | for _, pair := range [][2]string{ 97 | {"OCI_NUMBER_SIGNED", "OCI_NUMBER_UNSIGNED"}, 98 | {"int64", "uint64"}, 99 | {"Int64", "Uint64"}, 100 | } { 101 | b = bytes.Replace(b, []byte(pair[0]), []byte(pair[1]), -1) 102 | } 103 | dst = "bndUint64" + plus + ".go" 104 | if err := ioutil.WriteFile(dst, b, 0644); err != nil { 105 | log.Fatal(err) 106 | } 107 | for _, s := range []string{"8", "16", "32"} { 108 | dst = "bndUint" + s + plus + ".go" 109 | log.Printf("%s => %s", src, dst) 110 | if err := ioutil.WriteFile( 111 | dst, 112 | bytes.Replace( 113 | bytes.Replace(b, []byte("64"), []byte(s), -1), 114 | []byte("intSixtyFour("), []byte("int64("), -1), 115 | 0644, 116 | ); err != nil { 117 | log.Fatal(err) 118 | } 119 | } 120 | } 121 | } 122 | 123 | func readFile(fn string) []byte { 124 | src, err := ioutil.ReadFile(fn) 125 | if err != nil { 126 | log.Fatal(err) 127 | } 128 | src = bytes.Replace(src, []byte("//go:generate "), []byte("// Generated from "+fn+" by "), -1) 129 | return src 130 | } 131 | -------------------------------------------------------------------------------- /glg/glg.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Tamás Gulácsi. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package glg 6 | 7 | import ( 8 | "fmt" 9 | "github.com/golang/glog" 10 | ) 11 | 12 | var Log = gLgr{} 13 | 14 | type gLgr struct{} 15 | 16 | func (l gLgr) Infof(format string, v ...interface{}) { 17 | glog.InfoDepth(2, fmt.Sprintf(format, v...)) 18 | } 19 | func (l gLgr) Infoln(v ...interface{}) { 20 | glog.InfoDepth(2, v...) 21 | } 22 | func (l gLgr) Errorf(format string, v ...interface{}) { 23 | glog.ErrorDepth(2, fmt.Sprintf(format, v...)) 24 | } 25 | func (l gLgr) Errorln(v ...interface{}) { 26 | glog.ErrorDepth(2, v...) 27 | } 28 | -------------------------------------------------------------------------------- /lg/lg.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package lg 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | "os" 11 | ) 12 | 13 | var Log = Std{L: log.New(os.Stderr, "[ora] ", log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile)} 14 | 15 | type Std struct { 16 | L *log.Logger 17 | } 18 | 19 | func (s Std) Infof(format string, v ...interface{}) { 20 | s.L.SetPrefix("ORA I ") 21 | s.L.Output(2, fmt.Sprintf(format, v...)) 22 | } 23 | func (s Std) Infoln(v ...interface{}) { 24 | s.L.SetPrefix("ORA I ") 25 | s.L.Output(2, fmt.Sprintln(v...)) 26 | } 27 | func (s Std) Errorf(format string, v ...interface{}) { 28 | s.L.SetPrefix("ORA E ") 29 | s.L.Output(2, fmt.Sprintf(format, v...)) 30 | } 31 | func (s Std) Errorln(v ...interface{}) { 32 | s.L.SetPrefix("ORA E ") 33 | s.L.Output(2, fmt.Sprintln(v...)) 34 | } 35 | -------------------------------------------------------------------------------- /lg15/lg15.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Tamás Gulácsi. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package lg15 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | 11 | "gopkg.in/inconshreveable/log15.v2" 12 | ) 13 | 14 | var Log = lgr{log15.New("lib", "ora")} 15 | 16 | type lgr struct { 17 | log15.Logger 18 | } 19 | 20 | func (s lgr) Infof(format string, args ...interface{}) { s.Debug(fmt.Sprintf(format, args...)) } 21 | func (s lgr) Infoln(args ...interface{}) { s.Debug(strings.Join(asStrings(args), " ")) } 22 | func (s lgr) Errorf(format string, args ...interface{}) { s.Error(fmt.Sprintf(format, args...)) } 23 | func (s lgr) Errorln(args ...interface{}) { s.Error(strings.Join(asStrings(args), " ")) } 24 | 25 | func asStrings(args ...interface{}) []string { 26 | arr := make([]string, len(args)) 27 | for i, a := range args { 28 | if s, ok := a.(string); ok { 29 | arr[i] = s 30 | continue 31 | } 32 | if s, ok := a.(fmt.Stringer); ok { 33 | arr[i] = s.String() 34 | continue 35 | } 36 | arr[i] = fmt.Sprintf("%v", a) 37 | } 38 | return arr 39 | } 40 | -------------------------------------------------------------------------------- /logger.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Tamás Gulácsi. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | // Logger interface is for logging. 8 | type Logger interface { 9 | Infof(format string, args ...interface{}) 10 | Infoln(args ...interface{}) 11 | Errorf(format string, args ...interface{}) 12 | Errorln(args ...interface{}) 13 | } 14 | 15 | type EmpLgr struct{} 16 | 17 | func (e EmpLgr) Infof(format string, v ...interface{}) {} 18 | func (e EmpLgr) Infoln(v ...interface{}) {} 19 | func (e EmpLgr) Errorf(format string, v ...interface{}) {} 20 | func (e EmpLgr) Errorln(v ...interface{}) {} 21 | -------------------------------------------------------------------------------- /num/.gitignore: -------------------------------------------------------------------------------- 1 | num-fuzz.zip 2 | -------------------------------------------------------------------------------- /num/ocinum_fuzz.go: -------------------------------------------------------------------------------- 1 | // +build gofuzz 2 | 3 | // Copyright 2016 Tamás Gulácsi. All rights reserved. 4 | // Use of this source code is governed by The MIT License 5 | // found in the accompanying LICENSE file. 6 | 7 | package num 8 | 9 | import "strings" 10 | 11 | //go:generate go-fuzz-build gopkg.in/rana/ora.v4/num 12 | 13 | // Fuzz: 14 | // go-fuzz -bin=./num-fuzz.zip -workdir=/tmp/fuzz 15 | func Fuzz(p []byte) int { 16 | pS := string(p) 17 | var q [22]byte 18 | n := OCINum(q[:0]) 19 | if err := n.SetString(pS); err != nil { 20 | return -1 21 | } 22 | s := n.String() 23 | if s != strings.TrimSpace(pS) { 24 | return 1 25 | } 26 | return 0 27 | } 28 | -------------------------------------------------------------------------------- /rsetCfg_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Tamás Gulácsi. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora 6 | 7 | import "testing" 8 | 9 | // TestNumericColumnType tests RsetCfg.numericColumnType. 10 | func TestNumericColumnType(t *testing.T) { 11 | c := NewRsetCfg() 12 | // be exact 13 | c.float, c.numberFloat, c.numberInt = F32, F64, I64 14 | for i, tc := range []struct { 15 | precision, scale int 16 | want GoColumnType 17 | }{ 18 | {6, 3, F64}, 19 | {3, 0, I64}, 20 | {0, -127, F32}, 21 | {0, 0, N}, 22 | } { 23 | got := c.numericColumnType(tc.precision, tc.scale) 24 | if got != tc.want { 25 | t.Errorf("%d. (%d,%d) got %s, want %s.", 26 | i, tc.precision, tc.scale, GctName(got), GctName(tc.want)) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /stmt_go1.go: -------------------------------------------------------------------------------- 1 | // +build !go1.8 2 | 3 | //Copyright 2016 Tamás Gulácsi. All rights reserved. 4 | //Use of this source code is governed by The MIT License 5 | //found in the accompanying LICENSE file. 6 | 7 | package ora 8 | 9 | /* 10 | #include 11 | #include 12 | */ 13 | import "C" 14 | 15 | // NumInput returns the number of placeholders in a sql statement. 16 | func (stmt *Stmt) NumInput() int { 17 | bc, err := stmt.attr(4, C.OCI_ATTR_BIND_COUNT) 18 | if err != nil { 19 | return 0 20 | } 21 | bindCount := int(*((*C.ub4)(bc))) 22 | C.free(bc) 23 | return bindCount 24 | } 25 | 26 | func nameAndValue(v interface{}) (string, interface{}) { 27 | return "", v 28 | } 29 | -------------------------------------------------------------------------------- /stmt_go1_8.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | //Copyright 2016 Tamás Gulácsi. All rights reserved. 4 | //Use of this source code is governed by The MIT License 5 | //found in the accompanying LICENSE file. 6 | 7 | package ora 8 | 9 | import "database/sql/driver" 10 | 11 | // NumInput returns the number of placeholders in a sql statement. 12 | // 13 | // This returns a constant -1, as named params can be less, then positional params. 14 | func (stmt *Stmt) NumInput() int { 15 | if bindNames, _, duplicates, err := stmt.getBindInfo(); err == nil { 16 | n := len(bindNames) 17 | for _, d := range duplicates { 18 | if d { 19 | n-- 20 | } 21 | } 22 | return n 23 | } 24 | return -1 25 | } 26 | 27 | func nameAndValue(v interface{}) (string, interface{}) { 28 | if nv, ok := v.(driver.NamedValue); ok { 29 | return nv.Name, nv.Value 30 | } 31 | return "", v 32 | } 33 | -------------------------------------------------------------------------------- /test-one-by-one.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | n="${1:-10}" 3 | 4 | PRG=./ora.v4.test 5 | if time echo '' >/dev/null 2>&1; then 6 | PRG="time $PRG" 7 | elif /usr/bin/time echo '' >/dev/null 2>&1; then 8 | PRG="/usr/bin/time $PRG" 9 | fi 10 | 11 | go install -race && go test -race -c && \ 12 | grep -h '^func Test' *_test.go|cut -c10-|cut -d'(' -f1 \ 13 | | sort -R | xargs -n "$n" | sed -e 's/ /|/g' | \ 14 | while read nm; 15 | do 16 | echo '' 17 | echo "$nm" 18 | $PRG -test.run=$nm || break 19 | done 20 | 21 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -x 4 | ulimit -v unlimited 5 | CGO_CFLAGS=-fsanitize=address CGO_LDFLAGS=-lasan go test -c 6 | exec ./ora.v4.test "$@" 7 | -------------------------------------------------------------------------------- /tstlg/tstlg.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package tstlg 6 | 7 | import "testing" 8 | 9 | func New(t *testing.T) Tst { 10 | return Tst{t} 11 | } 12 | 13 | type Tst struct { 14 | *testing.T 15 | } 16 | 17 | func (t Tst) Infof(format string, v ...interface{}) { 18 | t.Logf("ORA I "+format, v...) 19 | } 20 | func (t Tst) Infoln(v ...interface{}) { 21 | v = append(make([]interface{}, 1, len(v)+1), v) 22 | v[0] = "ORA I" 23 | t.Log(v...) 24 | } 25 | func (t Tst) Errorf(format string, v ...interface{}) { 26 | t.Logf("ORA E "+format, v...) 27 | } 28 | func (t Tst) Errorln(v ...interface{}) { 29 | v = append(make([]interface{}, 1, len(v)+1), v) 30 | v[0] = "ORA E" 31 | t.Log(v...) 32 | } 33 | -------------------------------------------------------------------------------- /util_test.go: -------------------------------------------------------------------------------- 1 | package ora 2 | 3 | import "testing" 4 | 5 | func TestBoundingPower(t *testing.T) { 6 | for i, inOut := range [][2]int{ 7 | {0, 0}, 8 | {1, 0}, 9 | {2, 1}, 10 | {3, 2}, 11 | {4, 2}, 12 | {5, 3}, 13 | {7, 3}, 14 | {8, 3}, 15 | {1024, 10}, 16 | {1025, 11}, 17 | } { 18 | got := boundingPower(inOut[0]) 19 | if got != inOut[1] { 20 | t.Errorf("%d. (%d) got %d, wanted %d.", i, inOut[0], got, inOut[1]) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /version.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "version.h" 3 | 4 | sword 5 | bindByNameOrPos( 6 | OCIStmt *stmtp, 7 | OCIBind **bindpp, 8 | OCIError *errhp, 9 | ub4 position, 10 | const OraText *placeholder, 11 | sb4 placeholder_length, 12 | void *valuep, 13 | LENGTH_TYPE value_sz, 14 | ub2 dty, 15 | void *indp, 16 | ACTUAL_LENGTH_TYPE *alenp, 17 | ub2 *rcodep, 18 | ub4 maxarr_len, 19 | ub4 *curelep, 20 | ub4 mode 21 | ) { 22 | if( placeholder != NULL && placeholder_length > 0 ) { 23 | return OCIBINDBYNAME( 24 | stmtp, 25 | bindpp, 26 | errhp, 27 | placeholder, 28 | placeholder_length, 29 | valuep, 30 | value_sz, 31 | dty, 32 | indp, 33 | alenp, 34 | rcodep, 35 | maxarr_len, 36 | curelep, 37 | mode); 38 | } 39 | return OCIBINDBYPOS( 40 | stmtp, 41 | bindpp, 42 | errhp, 43 | position, 44 | valuep, 45 | value_sz, 46 | dty, 47 | indp, 48 | alenp, 49 | rcodep, 50 | maxarr_len, 51 | curelep, 52 | mode); 53 | } 54 | 55 | sword 56 | numberFromIntSlice( 57 | OCIError *err, 58 | void *inum, 59 | uword inum_length, 60 | uword inum_s_flag, 61 | OCINumber *numbers, 62 | ub4 arr_length 63 | ) { 64 | sword rc; 65 | int i; 66 | for(i=0; i < arr_length; i++) { 67 | rc = OCINumberFromInt(err, inum + (i * inum_length), inum_length, inum_s_flag, &(numbers[i])); 68 | if(rc == OCI_ERROR) { 69 | return rc; 70 | } 71 | } 72 | return OCI_SUCCESS; 73 | } 74 | 75 | sword 76 | numberFromFloatSlice( 77 | OCIError *err, 78 | void *inum, 79 | uword inum_length, 80 | OCINumber *numbers, 81 | ub4 arr_length 82 | ) { 83 | sword rc; 84 | int i; 85 | for(i=0; i < arr_length; i++) { 86 | rc = OCINumberFromReal(err, inum + (i * inum_length), inum_length, &(numbers[i])); 87 | if(rc == OCI_ERROR) { 88 | return rc; 89 | } 90 | } 91 | return OCI_SUCCESS; 92 | } 93 | 94 | 95 | sword 96 | decriptorAllocSlice( 97 | OCIEnv *env, 98 | void *dest, 99 | ub4 elem_size, 100 | ub4 type, 101 | size_t length 102 | ) { 103 | sword rc; 104 | int i; 105 | for(i=0; i < length; i++) { 106 | rc = OCIDescriptorAlloc( 107 | env, //CONST dvoid *parenth, 108 | dest + i * elem_size, //dvoid **descpp, 109 | type, //ub4 type, 110 | 0, //size_t xtramem_sz, 111 | 0); //dvoid **usrmempp); 112 | if(rc == OCI_ERROR) { 113 | return rc; 114 | } 115 | } 116 | return OCI_SUCCESS; 117 | } 118 | -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Tamás Gulácsi. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | #include 6 | 7 | // define simple way to respresent Oracle version 8 | #define ORACLE_VERSION(major, minor) \ 9 | ((major << 8) | minor) 10 | 11 | // define what version of Oracle we are building as 2 byte hex number 12 | #if !defined(OCI_MAJOR_VERSION) && defined(OCI_ATTR_MODULE) 13 | #define OCI_MAJOR_VERSION 10 14 | #define OCI_MINOR_VERSION 1 15 | #endif 16 | 17 | #if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION) 18 | #define ORACLE_VERSION_HEX \ 19 | ORACLE_VERSION(OCI_MAJOR_VERSION, OCI_MINOR_VERSION) 20 | #else 21 | #error Unsupported version of OCI. 22 | #endif 23 | 24 | #if ORACLE_VERSION_HEX >= ORACLE_VERSION(12,1) 25 | #define OCIBINDBYNAME OCIBindByName2 26 | #define OCIBINDBYPOS OCIBindByPos2 27 | #define OCIDEFINEBYPOS OCIDefineByPos2 28 | #define ACTUAL_LENGTH_TYPE ub4 29 | #define ACTUAL_LENGTH_LENGTH 4 30 | #define MAX_BINARY_BYTES 32767 31 | #define LENGTH_TYPE sb8 32 | #define LENGTH_LENGTH 8 33 | 34 | #define ROW_COUNT_TYPE ub8 35 | #define ROW_COUNT_LENGTH 8 36 | #else 37 | #define OCIBINDBYNAME OCIBindByName 38 | #define OCIBINDBYPOS OCIBindByPos 39 | #define OCIDEFINEBYPOS OCIDefineByPos 40 | #define ACTUAL_LENGTH_TYPE ub2 41 | #define ACTUAL_LENGTH_LENGTH 2 42 | #define MAX_BINARY_BYTES 4000 43 | #define LENGTH_TYPE sb4 44 | #define LENGTH_LENGTH 4 45 | 46 | #define OCI_ATTR_UB8_ROW_COUNT OCI_ATTR_ROW_COUNT 47 | #define ROW_COUNT_TYPE ub4 48 | #define ROW_COUNT_LENGTH 4 49 | #endif 50 | 51 | #if ORACLE_VERSION_HEX >= ORACLE_VERSION(10,1) 52 | #define LOB_LENGTH_TYPE oraub8 53 | #define OCILOBGETLENGTH OCILobGetLength2 54 | #define OCILOBTRIM OCILobTrim2 55 | #define OCILOBWRITE OCILobWrite2 56 | #else 57 | #define LOB_LENGTH_TYPE ub4 58 | #define OCILOBGETLENGTH OCILobGetLength 59 | #define OCILOBTRIM OCILobTrim 60 | #define OCILOBWRITE OCILobWrite 61 | #endif 62 | 63 | #define sof_DateTimep sizeof(OCIDateTime*) 64 | #define sof_Intervalp sizeof(OCIInterval*) 65 | #define sof_LobLocatorp sizeof(OCILobLocator*) 66 | #define sof_Stmtp sizeof(OCIStmt*) 67 | 68 | sword 69 | bindByNameOrPos( 70 | OCIStmt *stmtp, 71 | OCIBind **bindpp, 72 | OCIError *errhp, 73 | ub4 position, 74 | const OraText *placeholder, 75 | sb4 placeholder_length, 76 | void *valuep, 77 | LENGTH_TYPE value_sz, 78 | ub2 dty, 79 | void *indp, 80 | ACTUAL_LENGTH_TYPE *alenp, 81 | ub2 *rcodep, 82 | ub4 maxarr_len, 83 | ub4 *curelep, 84 | ub4 mode 85 | ); 86 | 87 | sword 88 | numberFromIntSlice( 89 | OCIError *err, 90 | void *inum, 91 | uword inum_length, 92 | uword inum_s_flag, 93 | OCINumber *numbers, 94 | ub4 arr_length 95 | ); 96 | 97 | sword 98 | numberFromFloatSlice( 99 | OCIError *err, 100 | void *inum, 101 | uword inum_length, 102 | OCINumber *numbers, 103 | ub4 arr_length 104 | ); 105 | 106 | sword 107 | decriptorAllocSlice( 108 | OCIEnv *env, 109 | void *dest, 110 | ub4 elem_size, 111 | ub4 type, 112 | size_t length 113 | ); 114 | -------------------------------------------------------------------------------- /z_bfile_session_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Rana Ian. All rights reserved. 2 | // Use of this source code is governed by The MIT License 3 | // found in the accompanying LICENSE file. 4 | 5 | package ora_test 6 | 7 | import ( 8 | "fmt" 9 | "testing" 10 | 11 | "gopkg.in/rana/ora.v4" 12 | ) 13 | 14 | //// bfile 15 | //bfile oracleColumnType = "bfile not null" 16 | //bfileNull oracleColumnType = "bfile null" 17 | 18 | //////////////////////////////////////////////////////////////////////////////// 19 | // bfile 20 | //////////////////////////////////////////////////////////////////////////////// 21 | func TestBindDefine_bfile(t *testing.T) { 22 | sc := ora.NewStmtCfg() 23 | t.Run("bfile", func(t *testing.T) { 24 | t.Parallel() 25 | //enableLogging(t) 26 | testBindDefine(gen_OraBfile(false), bfile, t, sc) 27 | }) 28 | for _, isNull := range []bool{true, false} { 29 | t.Run(fmt.Sprintf("bfileNull_%t", isNull), func(t *testing.T) { 30 | t.Parallel() 31 | //enableLogging(t) 32 | testBindDefine(gen_OraBfile(isNull), bfileNull, t, sc) 33 | }) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /z_db_go1_8_test.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | //Copyright 2016 Tamás Gulácsi. All rights reserved. 4 | //Use of this source code is governed by The MIT License 5 | //found in the accompanying LICENSE file. 6 | 7 | package ora_test 8 | 9 | import ( 10 | "context" 11 | "database/sql" 12 | "strings" 13 | "sync/atomic" 14 | "testing" 15 | "time" 16 | 17 | "golang.org/x/sync/errgroup" 18 | 19 | "github.com/pkg/errors" 20 | ) 21 | 22 | func TestNamedArgs(t *testing.T) { 23 | t.Parallel() 24 | qry := "SELECT object_name FROM user_objects WHERE object_type = :typ AND ROWNUM < :num AND object_name <> :typ" 25 | stmt, err := testDb.Prepare(qry) 26 | if err != nil { 27 | t.Fatal(errors.Wrap(err, qry)) 28 | } 29 | defer stmt.Close() 30 | var s string 31 | if err := stmt.QueryRow(sql.Named("typ", "TABLE"), sql.Named("num", 2)).Scan(&s); err != nil { 32 | t.Fatal(err) 33 | } 34 | t.Log(s) 35 | } 36 | 37 | func TestRapidCancelIssue192(t *testing.T) { 38 | wait := uint64(500) 39 | dbQuery := func(db *sql.DB) error { 40 | w := atomic.LoadUint64(&wait) 41 | ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*time.Duration(w)) 42 | defer cancel() 43 | if w > 100 { 44 | atomic.StoreUint64(&wait, w>>2) 45 | } 46 | 47 | rows, err := db.QueryContext(ctx, "select table_name from all_tables") 48 | w = atomic.LoadUint64(&wait) 49 | if err != nil { 50 | t.Log(w, err) 51 | if err == context.DeadlineExceeded && !strings.Contains(err.Error(), "ORA-01013") { 52 | atomic.StoreUint64(&wait, w+1) 53 | } 54 | return err 55 | } 56 | return rows.Close() 57 | } 58 | 59 | breakStuff := func(ctx context.Context, db *sql.DB) error { 60 | for ctx.Err() == nil { 61 | if err := dbQuery(db); err != nil && err != context.DeadlineExceeded && !strings.Contains(err.Error(), "ORA-01013") { 62 | return err 63 | } 64 | time.Sleep(100 * time.Millisecond) 65 | } 66 | return nil 67 | } 68 | 69 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 70 | defer cancel() 71 | grp, ctx := errgroup.WithContext(ctx) 72 | for i := 0; i < 8; i++ { 73 | grp.Go(func() error { return breakStuff(ctx, testDb) }) 74 | } 75 | 76 | if err := grp.Wait(); err != nil { 77 | t.Error(err) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /z_issue131.go: -------------------------------------------------------------------------------- 1 | // +build never 2 | 3 | package main 4 | 5 | import ( 6 | "context" 7 | "database/sql" 8 | "fmt" 9 | "log" 10 | "math/rand" 11 | "net/http" 12 | "os" 13 | "sync" 14 | "time" 15 | 16 | _ "net/http/pprof" 17 | 18 | _ "gopkg.in/rana/ora.v4" 19 | ) 20 | 21 | var db *sql.DB 22 | 23 | func startDB(dsn string) { 24 | var err error 25 | db, err = sql.Open("ora", dsn) 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | db.SetMaxIdleConns(32) 30 | db.SetConnMaxLifetime(10 * time.Second) 31 | } 32 | 33 | func dbRoutine(ctx context.Context) { 34 | for { 35 | select { 36 | case <-ctx.Done(): 37 | log.Printf(" %v. finished.", ctx.Value("id")) 38 | return 39 | default: 40 | } 41 | var temp int 42 | i := rand.Int() 43 | if i%100 == 0 { 44 | log.Printf(" %v. starts", ctx.Value("id")) 45 | } 46 | db.QueryRow("select 1 from dual").Scan(&temp) 47 | if i%100 == 0 { 48 | log.Printf(" %v. ends", ctx.Value("id")) 49 | } 50 | if i%10 == 0 { 51 | time.Sleep(50 * time.Millisecond) 52 | } 53 | } 54 | } 55 | 56 | func main() { 57 | dur, _ := time.ParseDuration(os.Getenv("DURATION")) 58 | if dur == 0 { 59 | dur = 24 * time.Hour 60 | } 61 | 62 | go func() { 63 | addr := "localhost:6131" 64 | log.Println("go tool pprof " + addr + "/debug/pprof/heap") 65 | log.Println(http.ListenAndServe(addr, nil)) 66 | }() 67 | 68 | log.SetPrefix("#131 ") 69 | log.Println("starting") 70 | startDB(fmt.Sprintf("%s/%s@%s", os.Getenv("GO_ORA_DRV_TEST_USERNAME"), os.Getenv("GO_ORA_DRV_TEST_PASSWORD"), os.Getenv("GO_ORA_DRV_TEST_DB"))) 71 | 72 | go func() { 73 | http.ListenAndServe(":8889", nil) 74 | }() 75 | 76 | ctx, cancel := context.WithTimeout(context.Background(), dur) 77 | defer cancel() 78 | var wg sync.WaitGroup 79 | for i := 0; i < 40; i++ { 80 | wg.Add(1) 81 | ctx := context.WithValue(ctx, "id", i) 82 | go func() { 83 | defer wg.Done() 84 | dbRoutine(ctx) 85 | }() 86 | } 87 | wg.Wait() 88 | log.Println("finished.") 89 | } 90 | 91 | // vim: set fileencoding=utf-8 noet: 92 | -------------------------------------------------------------------------------- /z_issue197.go: -------------------------------------------------------------------------------- 1 | // +build never 2 | 3 | package main 4 | 5 | import ( 6 | "log" 7 | "os" 8 | "strconv" 9 | "time" 10 | 11 | "github.com/pkg/errors" 12 | 13 | "gopkg.in/rana/ora.v4" 14 | ) 15 | 16 | const insellpid = "0000000048A16C23433210AC068C" 17 | 18 | func main() { 19 | Pool, err := ora.NewPool(os.Getenv("GO_ORA_DRV_TEST_USERNAME")+"/"+os.Getenv("GO_ORA_DRV_TEST_PASSWORD")+"@"+os.Getenv("GO_ORA_DRV_TEST_DB"), 4) 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | defer Pool.Close() 24 | ses, err := Pool.Get() 25 | if err != nil { 26 | log.Fatal(err) 27 | } 28 | defer ses.Close() 29 | qry := `CREATE OR REPLACE PROCEDURE test_p1(insellpid IN VARCHAR2, procRset OUT SYS_REFCURSOR) IS 30 | BEGIN 31 | OPEN procRset FOR SELECT * FROM all_objects WHERE ROWNUM < 100; 32 | END;` 33 | if _, err := ses.PrepAndExe(qry); err != nil { 34 | log.Fatal(errors.Wrap(err, qry)) 35 | } 36 | 37 | deadline := time.Now().Add(5 * time.Minute) 38 | for time.Now().Before(deadline) { 39 | ses, err := Pool.Get() 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | if err := work(ses); err != nil { 44 | log.Println(err) 45 | } 46 | ses.Close() 47 | ses.Close() 48 | //os.Stdout.Write([]byte{'.'}) 49 | } 50 | } 51 | 52 | func work(ses *ora.Ses) error { 53 | qry := "CALL test_P1(:1,:2)" 54 | 55 | procRset := &ora.Rset{} 56 | stmtProcCall, err := ses.Prep(qry) 57 | if err != nil { 58 | return errors.Wrap(err, qry) 59 | } 60 | defer stmtProcCall.Close() 61 | 62 | if _, err = stmtProcCall.Exe(insellpid, procRset); err != nil { 63 | return err 64 | } 65 | if !procRset.IsOpen() { 66 | return nil 67 | } 68 | 69 | rmapArr := make([]map[string]interface{}, 0) 70 | for procRset.Next() { 71 | rmap := make(map[string]interface{}) 72 | cols := procRset.Columns 73 | row := procRset.Row 74 | for j := 0; j < len(row); j++ { 75 | clo := cols[j].Name 76 | switch x := row[j].(type) { 77 | case ora.OCINum: 78 | va_n := x.String() 79 | if "" == va_n { 80 | rmap[clo] = nil 81 | } else { 82 | fl_64, err_ := strconv.ParseFloat(va_n, 64) 83 | if err_ != nil { 84 | return errors.Wrapf(err, "strconv.ParseFloat(%q)", va_n) 85 | panic(err_) 86 | } 87 | rmap[clo] = fl_64 88 | } 89 | 90 | case time.Time: 91 | rmap[clo] = x.Format("20060102 15:04:05") 92 | case string: 93 | if "" == row[j] { 94 | rmap[clo] = nil 95 | } else { 96 | rmap[clo] = row[j] 97 | } 98 | default: 99 | rmap[clo] = row[j] 100 | } 101 | 102 | } 103 | rmapArr = append(rmapArr, rmap) 104 | } 105 | log.Printf("%d rows, each with %d columns", len(rmapArr), len(rmapArr[0])) 106 | 107 | return nil 108 | } 109 | -------------------------------------------------------------------------------- /z_race.go: -------------------------------------------------------------------------------- 1 | // +build never 2 | 3 | package main 4 | 5 | import ( 6 | "context" 7 | "flag" 8 | "log" 9 | "os" 10 | "os/exec" 11 | "time" 12 | 13 | "golang.org/x/sync/errgroup" 14 | ) 15 | 16 | var issues = []string{"z_issue131.go"} 17 | 18 | func main() { 19 | flagDur := flag.Duration("duration", 24*time.Hour, "test duration") 20 | flag.Parse() 21 | 22 | cmd := exec.Command("go", "install", "-race") 23 | cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr 24 | if err := cmd.Run(); err != nil { 25 | log.Fatal(err) 26 | } 27 | os.Setenv("DURATION", flagDur.String()) 28 | 29 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) 30 | defer cancel() 31 | grp, ctx := errgroup.WithContext(ctx) 32 | for _, nm := range issues { 33 | nm := nm 34 | grp.Go(func() error { 35 | cmd := exec.CommandContext(ctx, "go", "run", "-race", nm) 36 | cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr 37 | return cmd.Run() 38 | }) 39 | } 40 | log.Fatal(grp.Wait()) 41 | } 42 | -------------------------------------------------------------------------------- /z_reconn.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // Copyright 2017 Tamás Gulácsi. All rights reserved. 4 | // Use of this source code is governed by The MIT License 5 | // found in the accompanying LICENSE file. 6 | 7 | package main 8 | 9 | import ( 10 | "database/sql" 11 | "log" 12 | "os" 13 | "time" 14 | 15 | _ "gopkg.in/rana/ora.v4" 16 | ) 17 | 18 | func main() { 19 | db, err := sql.Open("ora", os.Args[1]) 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | defer db.Close() 24 | 25 | db.SetMaxOpenConns(20) 26 | err = db.Ping() 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | 31 | for { 32 | log.Printf("Current open connections: %d", db.Stats().OpenConnections) 33 | if err := executeSQL(db); err != nil { 34 | log.Printf("%s\n%#v %T", err, err, err) 35 | //panic(err) 36 | log.Println("code:", err.(interface { 37 | Code() int 38 | }).Code()) 39 | } 40 | 41 | log.Println("Loop finish, wait for next.") 42 | time.Sleep(5 * time.Second) 43 | } 44 | 45 | //log.Printf("All collect finished\nCurrent open connections: %d", db.Stats().OpenConnections) 46 | } 47 | 48 | func executeSQL(db *sql.DB) error { 49 | var n int64 50 | return db.QueryRow("SELECT COUNT(0) FROM cat").Scan(&n) 51 | } 52 | -------------------------------------------------------------------------------- /z_resultSet_session_test.go: -------------------------------------------------------------------------------- 1 | //Copyright 2014 Rana Ian. All rights reserved. 2 | //Use of this source code is governed by The MIT License 3 | //found in the accompanying LICENSE file. 4 | 5 | package ora_test 6 | 7 | import ( 8 | "fmt" 9 | "testing" 10 | 11 | "gopkg.in/rana/ora.v4" 12 | ) 13 | 14 | func Test_cursor1_session(t *testing.T) { 15 | t.Parallel() 16 | testSes := getSes(t) 17 | defer testSes.Close() 18 | 19 | // create table 20 | tableName := tableName() 21 | createTblStmt, err := testSes.Prep(fmt.Sprintf("create table %v (c1 varchar2(48 char), c2 integer)", tableName)) 22 | defer createTblStmt.Close() 23 | testErr(err, t) 24 | defer dropTable(tableName, testSes, t) 25 | _, err = createTblStmt.Exe() 26 | testErr(err, t) 27 | 28 | // insert records 29 | expectedStrs := []string{ 30 | "Go is expressive, concise, clean, and efficient.", 31 | "Its concurrency mechanisms make it easy to", 32 | "Go compiles quickly to machine code yet has", 33 | } 34 | expectedInt64s := []int64{3, 7, 9} 35 | rowsAffected, err := testSes.PrepAndExe( 36 | fmt.Sprintf("insert into %v (c1, c2) values (:1, :2)", tableName), 37 | expectedStrs, expectedInt64s, 38 | ) 39 | testErr(err, t) 40 | if rowsAffected != 3 { 41 | t.Fatalf("Expected 3 rows affected. (rowsAffected %v)", rowsAffected) 42 | } 43 | 44 | // create proc 45 | _, err = testSes.PrepAndExe(fmt.Sprintf("create or replace procedure proc1(p1 out sys_refcursor) as begin open p1 for select c1, c2 from %v order by c2; end proc1;", tableName)) 46 | testErr(err, t) 47 | 48 | //enableLogging(t) 49 | // call proc 50 | stmt, err := testSes.Prep("call proc1(:1)") 51 | testErr(err, t) 52 | var rset ora.Rset 53 | _, err = stmt.Exe(&rset) 54 | testErr(err, t) 55 | 56 | if !rset.IsOpen() { 57 | t.Fatalf("rset %#v is closed!", rset) 58 | } 59 | for rset.Next() { 60 | if len(rset.Row) != 2 { 61 | t.Fatalf("select column count: expected(%v), actual(%v)", 2, len(rset.Row)) 62 | } 63 | //fmt.Println("rset.Row ", rset.Row) 64 | compare(expectedStrs[0], rset.Row[0], ora.S, t) 65 | compare(expectedInt64s[0], rset.Row[1], ora.I64, t) 66 | expectedStrs = expectedStrs[1:] 67 | expectedInt64s = expectedInt64s[1:] 68 | } 69 | testErr(rset.Err(), t) 70 | if len(expectedStrs) > 0 { 71 | t.Errorf("didn't get wanted %v", expectedStrs) 72 | } 73 | } 74 | 75 | func Test_nested_rset(t *testing.T) { 76 | t.Parallel() 77 | testSes := getSes(t) 78 | defer testSes.Close() 79 | 80 | _, err := testSes.PrepAndExe(`CREATE OR REPLACE PROCEDURE proc2(p_cur OUT SYS_REFCURSOR) IS 81 | BEGIN 82 | OPEN p_cur FOR 83 | SELECT CURSOR(SELECT A.* FROM user_objects A, (SELECT 1 FROM DUAL)) cur FROM DUAL; 84 | END;`) 85 | if err != nil { 86 | t.Fatal(err) 87 | } 88 | //enableLogging(t) 89 | stmt, err := testSes.Prep("call proc2(:1)") 90 | testErr(err, t) 91 | //enableLogging(t) 92 | var rset ora.Rset 93 | func() { 94 | defer func() { 95 | if r := recover(); r != nil { 96 | t.Fatal(r) 97 | } 98 | }() 99 | _, err = stmt.Exe(&rset) 100 | }() 101 | if err != nil { 102 | errs, _ := GetCompileErrors(testSes, false) 103 | t.Errorf("errs: %#v", errs) 104 | t.Fatal(err) 105 | } 106 | 107 | for rset.Next() { 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /z_rowid_session_test.go: -------------------------------------------------------------------------------- 1 | //Copyright 2014 Rana Ian. All rights reserved. 2 | //Use of this source code is governed by The MIT License 3 | //found in the accompanying LICENSE file. 4 | 5 | package ora_test 6 | 7 | import ( 8 | "fmt" 9 | "testing" 10 | ) 11 | 12 | // test on heap table to retreive ROWID 13 | func TestDefine_string_rowid_session(t *testing.T) { 14 | t.Parallel() 15 | testRowid(false, t) 16 | } 17 | 18 | // test on indexed table to retrieve UROWID 19 | func TestDefine_string_urowid_session(t *testing.T) { 20 | t.Parallel() 21 | testRowid(true, t) 22 | } 23 | 24 | func testRowid(isUrowid bool, t *testing.T) { 25 | testSes := getSes(t) 26 | defer testSes.Close() 27 | 28 | for n := 0; n < testIterations(); n++ { 29 | tableName := tableName() 30 | stmt, err := testSes.Prep(fmt.Sprintf("create table %v (c1 varchar2(48 byte))", tableName)) 31 | defer stmt.Close() 32 | testErr(err, t) 33 | _, err = stmt.Exe() 34 | defer dropTable(tableName, testSes, t) 35 | testErr(err, t) 36 | // ROWID is returned from a table without an index 37 | // UROWID is returned from indexed tables 38 | if isUrowid { 39 | stmt, err := testSes.Prep(fmt.Sprintf("create unique index t1_pk on %v (c1)", tableName)) 40 | defer stmt.Close() 41 | testErr(err, t) 42 | _, err = stmt.Exe() 43 | testErr(err, t) 44 | } 45 | 46 | // insert 47 | insertStmt, err := testSes.Prep(fmt.Sprintf("insert into %v (c1) values ('go')", tableName)) 48 | defer insertStmt.Close() 49 | testErr(err, t) 50 | rowsAffected, err := insertStmt.Exe() 51 | testErr(err, t) 52 | if rowsAffected != 1 { 53 | t.Fatalf("insert rows affected: expected(%v), actual(%v)", 1, rowsAffected) 54 | } 55 | 56 | // select 57 | selectStmt, err := testSes.Prep(fmt.Sprintf("select rowid from %v", tableName)) 58 | defer selectStmt.Close() 59 | testErr(err, t) 60 | rset, err := selectStmt.Qry() 61 | testErr(err, t) 62 | hasRow := rset.Next() 63 | testErr(rset.Err(), t) 64 | if !hasRow { 65 | t.Fatalf("%d. no row returned", n) 66 | } else if len(rset.Row) != 1 { 67 | t.Fatalf("%d. select column count: expected(%v), actual(%v)", n, 1, len(rset.Row)) 68 | } 69 | 70 | rowid, ok := rset.Row[0].(string) 71 | if !ok { 72 | t.Fatalf("%d. Expected string rowid. (%T, %v)", n, rset.Row[0], rset.Row[0]) 73 | } 74 | if rowid == "" { 75 | t.Fatalf("%d. Expected non-empty rowid string. (%v)", n, rowid) 76 | } 77 | //fmt.Printf("rowid (%v)\n", rowid) 78 | 79 | want := "go go go" 80 | updateStmt, err := testSes.Prep(fmt.Sprintf("update %v set c1 = :1 where rowid = :2", tableName)) 81 | defer updateStmt.Close() 82 | testErr(err, t) 83 | rowsAffected, err = updateStmt.Exe(want, rowid) 84 | testErr(err, t) 85 | if rowsAffected != 1 { 86 | t.Fatalf("%d. update rows affected: expected(%v), actual(%v)", n, 1, rowsAffected) 87 | } 88 | 89 | stmtSelect2, err := testSes.Prep(fmt.Sprintf("select c1 from %v", tableName)) 90 | defer stmtSelect2.Close() 91 | testErr(err, t) 92 | rset2, err := stmtSelect2.Qry() 93 | testErr(err, t) 94 | rset2.Next() 95 | testErr(rset2.Err(), t) 96 | c1, ok := rset2.Row[0].(string) 97 | if !ok { 98 | t.Fatalf("%d. Expected string for c1 column. (%T, %v)", n, rset2.Row[0], rset2.Row[0]) 99 | } 100 | //fmt.Printf("c1 (%v)\n", c1) 101 | if c1 != want { 102 | t.Fatalf("%d. Got %q, wanted %q.", n, c1, want) 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /z_time_session_test.go: -------------------------------------------------------------------------------- 1 | //Copyright 2014 Rana Ian. All rights reserved. 2 | //Use of this source code is governed by The MIT License 3 | //found in the accompanying LICENSE file. 4 | 5 | package ora_test 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | "testing" 11 | 12 | ora "gopkg.in/rana/ora.v4" 13 | ) 14 | 15 | var _T_timeCols = []string{ 16 | "date", "dateNull", 17 | "time", "timeNull", 18 | "timestampP9", "timestampP9Null", 19 | "timestampTzP9", "timestampTzP9Null", 20 | "timestampLtzP9", "timestampLtzP9Null", 21 | } 22 | 23 | func TestBindDefine_time(t *testing.T) { 24 | sc := ora.NewStmtCfg() 25 | for valName, gen := range map[string](func() interface{}){ 26 | "date": func() interface{} { return gen_date() }, 27 | "OraDate": func() interface{} { return gen_OraDate(false) }, 28 | "OraDateNull": func() interface{} { return gen_OraDate(true) }, 29 | "dateSlice": func() interface{} { return gen_dateSlice() }, 30 | "OraDateSlice": func() interface{} { return gen_OraDateSlice(false) }, 31 | "OraDateSliceNull": func() interface{} { return gen_OraDateSlice(true) }, 32 | 33 | "time": func() interface{} { return gen_time() }, 34 | "OraTime": func() interface{} { return gen_OraTime(false) }, 35 | "OraTimeNull": func() interface{} { return gen_OraTime(true) }, 36 | "timeSlice": func() interface{} { return gen_timeSlice() }, 37 | "OraTimeSlice": func() interface{} { return gen_OraTimeSlice(false) }, 38 | "OraTimeSliceNull": func() interface{} { return gen_OraTimeSlice(true) }, 39 | } { 40 | valName := valName 41 | gen := gen 42 | for _, ctName := range _T_timeCols { 43 | if strings.HasSuffix(valName, "Null") && !strings.HasSuffix(ctName, "Null") { 44 | continue 45 | } 46 | if strings.HasPrefix(ctName, "time") && !strings.Contains(valName, "ime") { 47 | continue 48 | } 49 | if strings.HasPrefix(ctName, "date") && !strings.Contains(valName, "ate") { 50 | continue 51 | } 52 | ct := _T_colType[ctName] 53 | t.Run(fmt.Sprintf("%s_%s", valName, ctName), func(t *testing.T) { 54 | t.Parallel() 55 | v := gen() 56 | testBindDefine(v, ct, t, sc) 57 | if vName := fmt.Sprintf("%T", v); strings.HasPrefix(vName, "[]") || strings.EqualFold(vName[:3], "ora") { 58 | return 59 | } 60 | testBindPtr(v, ct, t) 61 | }) 62 | } 63 | } 64 | } 65 | 66 | func TestMultiDefine_date_session(t *testing.T) { 67 | for _, ctName := range []string{"date"} { 68 | t.Run(ctName, func(t *testing.T) { 69 | testMultiDefine(gen_date(), _T_colType[ctName], t) 70 | }) 71 | } 72 | } 73 | 74 | func TestWorkload_date_session(t *testing.T) { 75 | for _, ctName := range _T_timeCols { 76 | t.Run(ctName, func(t *testing.T) { 77 | testWorkload(_T_colType[ctName], t) 78 | }) 79 | } 80 | } 81 | --------------------------------------------------------------------------------