package oci8 // #include "oci8.go.h" import "C" import ( "unsafe" ) // getInt64 gets int64 from pointer func getInt64(p unsafe.Pointer) int64 { return int64(*(*C.sb8)(p)) } // getUint64 gets uint64 from pointer func getUint64(p unsafe.Pointer) uint64 { return uint64(*(*C.sb8)(p)) } // cByte converts byte slice to OraText. // must be freed func cByte(b []byte) *C.OraText { p := C.malloc(C.size_t(len(b))) pp := (*[1 << 30]byte)(p) copy(pp[:], b) return (*C.OraText)(p) } // cByteN converts byte slice to C OraText with size. // must be freed func cByteN(b []byte, size int) *C.OraText { p := C.malloc(C.size_t(size)) pp := (*[1 << 30]byte)(p) copy(pp[:], b) return (*C.OraText)(p) } // cString coverts string to C OraText. // must be freed func cString(s string) *C.OraText { p := C.malloc(C.size_t(len(s) + 1)) pp := (*[1 << 30]byte)(p) copy(pp[:], s) pp[len(s)] = 0 return (*C.OraText)(p) } // cStringN coverts string to C OraText with size. // must be freed func cStringN(s string, size int) *C.OraText { p := C.malloc(C.size_t(size)) pp := (*[1 << 30]byte)(p) copy(pp[:], s) if len(s) < size { pp[len(s)] = 0 } else { pp[size-1] = 0 } return (*C.OraText)(p) } // CGoStringN coverts C OraText to Go string func cGoStringN(s *C.OraText, size int) string { if size == 0 { return "" } p := (*[1 << 30]byte)(unsafe.Pointer(s)) buf := make([]byte, size) copy(buf, p[:]) return *(*string)(unsafe.Pointer(&buf)) } // freeDefines frees defines func freeDefines(defines []defineStruct) { for i := 0; i < len(defines); i++ { if len(defines[i].subDefines) > 0 { freeDefines(defines[i].subDefines) } defines[i].subDefines = nil if defines[i].pbuf != nil { freeBuffer(defines[i].pbuf, defines[i].dataType) defines[i].pbuf = nil } if defines[i].length != nil { C.free(unsafe.Pointer(defines[i].length)) defines[i].length = nil } if defines[i].indicator != nil { C.free(unsafe.Pointer(defines[i].indicator)) defines[i].indicator = nil } defines[i].defineHandle = nil // should be freed by oci statement close } } // freeBinds frees binds func freeBinds(binds []bindStruct) { for _, bind := range binds { if bind.pbuf != nil { freeBuffer(bind.pbuf, bind.dataType) bind.pbuf = nil } if bind.length != nil { C.free(unsafe.Pointer(bind.length)) bind.length = nil } if bind.indicator != nil { C.free(unsafe.Pointer(bind.indicator)) bind.indicator = nil } bind.bindHandle = nil // freed by oci statement close } } // freeBuffer calles OCIDescriptorFree to free double pointer to buffer // or calles C free to free pointer to buffer func freeBuffer(buffer unsafe.Pointer, dataType C.ub2) { switch dataType { case C.SQLT_CLOB, C.SQLT_BLOB: C.OCIDescriptorFree(*(*unsafe.Pointer)(buffer), C.OCI_DTYPE_LOB) case C.SQLT_TIMESTAMP: C.OCIDescriptorFree(*(*unsafe.Pointer)(buffer), C.OCI_DTYPE_TIMESTAMP) case C.SQLT_TIMESTAMP_TZ: C.OCIDescriptorFree(*(*unsafe.Pointer)(buffer), C.OCI_DTYPE_TIMESTAMP_TZ) case C.SQLT_TIMESTAMP_LTZ: C.OCIDescriptorFree(*(*unsafe.Pointer)(buffer), C.OCI_DTYPE_TIMESTAMP_LTZ) case C.SQLT_INTERVAL_DS: C.OCIDescriptorFree(*(*unsafe.Pointer)(buffer), C.OCI_DTYPE_INTERVAL_DS) case C.SQLT_INTERVAL_YM: C.OCIDescriptorFree(*(*unsafe.Pointer)(buffer), C.OCI_DTYPE_INTERVAL_YM) case C.SQLT_RSET: C.OCIDescriptorFree(*(*unsafe.Pointer)(buffer), C.OCI_HTYPE_STMT) default: C.free(buffer) } }