func (s *OCI8Stmt) Exec(args []driver.Value) (r driver.Result, err error) { var ( freeBoundParameters func() ) if freeBoundParameters, err = s.bind(args); err != nil { return nil, err } defer freeBoundParameters() rv := C.OCIStmtExecute( (*C.OCISvcCtx)(s.c.svc), (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), 1, 0, nil, nil, C.OCI_DEFAULT) if rv == C.OCI_ERROR { return nil, ociGetError(s.c.err) } return &OCI8Result{s}, nil }
// Perform the work of executing a cursor and set the rowcount appropriately // regardless of whether an error takes place. func (cur *Cursor) internalExecute(numIters uint) error { var mode C.ub4 if cur.connection.autocommit { mode = C.OCI_COMMIT_ON_SUCCESS } else { mode = C.OCI_DEFAULT } // Py_BEGIN_ALLOW_THREADS debug("%p.StmtExecute(%s, mode=%d) in internalExecute", cur, cur.statement, mode) if CTrace { ctrace("OCIStmtExecute", cur.connection.handle, cur.handle, cur.environment.errorHandle, numIters, 0, nil, nil, mode) } if err := cur.environment.CheckStatus( C.OCIStmtExecute(cur.connection.handle, cur.handle, cur.environment.errorHandle, C.ub4(numIters), 0, // iters, rowOff nil, nil, // snapIn, snapOut mode), "internalExecute"); err != nil { cur.setErrorOffset(err) return err } return cur.setRowCount() }
func (s *OCI8Stmt) Exec(args []driver.Value) (r driver.Result, err error) { var ( freeBoundParameters func() ) if freeBoundParameters, err = s.bind(args); err != nil { return nil, err } defer freeBoundParameters() mode := C.OCI_DEFAULT if !s.c.inTx { mode = C.OCI_COMMIT_ON_SUCCESS } rv := C.OCIStmtExecute( (*C.OCISvcCtx)(s.c.svc), (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), 1, 0, nil, nil, (C.ub4)(mode)) if err := s.c.check(rv, "OCI8Stmt.Exec"); err != nil { return nil, err } return &OCI8Result{s}, nil }
// Exec executes a query that doesn't return rows, such // as an INSERT or UPDATE. func (stmt *statement) Exec(args []driver.Value) (driver.Result, error) { if err := stmt.bind(args); err != nil { return nil, err } if C.OCIStmtExecute((*C.OCIServer)(stmt.conn.svr), (*C.OCIStmt)(stmt.handle), (*C.OCIError)(stmt.conn.err), 1, 0, nil, nil, C.OCI_DEFAULT) != C.OCI_SUCCESS { return nil, ociGetError(stmt.conn.err) } return &result{stmt}, nil }
// qry runs a SQL query on an Oracle server returning a *Rset and possible error. func (stmt *Stmt) qry(params []interface{}) (rset *Rset, err error) { stmt.mu.Lock() defer stmt.mu.Unlock() defer func() { if value := recover(); value != nil { err = errR(value) } }() stmt.log(_drv.cfg.Log.Stmt.Qry) err = stmt.checkClosed() if err != nil { return nil, errE(err) } _, err = stmt.bind(params) // bind parameters if err != nil { return nil, errE(err) } err = stmt.setPrefetchSize() // set prefetch size if err != nil { return nil, errE(err) } // Query statement on Oracle server r := C.OCIStmtExecute( stmt.ses.ocisvcctx, //OCISvcCtx *svchp, stmt.ocistmt, //OCIStmt *stmtp, stmt.ses.srv.env.ocierr, //OCIError *errhp, C.ub4(0), //ub4 iters, C.ub4(0), //ub4 rowoff, nil, //const OCISnapshot *snap_in, nil, //OCISnapshot *snap_out, C.OCI_DEFAULT) //ub4 mode ); if r == C.OCI_ERROR { return nil, errE(stmt.ses.srv.env.ociError()) } if stmt.hasPtrBind { // set any bind pointers err = stmt.setBindPtrs() if err != nil { return nil, errE(err) } } // create result set and open rset = _drv.rsetPool.Get().(*Rset) if rset.id == 0 { rset.id = _drv.rsetId.nextId() } err = rset.open(stmt, stmt.ocistmt) if err != nil { rset.close() return nil, errE(err) } stmt.openRsets.add(rset) return rset, nil }
func (s *OCI8Stmt) exec(ctx context.Context, args []namedValue) (r driver.Result, err error) { var ( fbp []oci8bind ) if fbp, err = s.bind(args); err != nil { return nil, err } defer freeBoundParameters(fbp) mode := C.ub4(C.OCI_DEFAULT) if s.c.inTransaction == false { mode = mode | C.OCI_COMMIT_ON_SUCCESS } done := make(chan struct{}) defer close(done) go func() { select { case <-ctx.Done(): C.OCIBreak( unsafe.Pointer(s.c.svc), (*C.OCIError)(s.c.err)) case <-done: } }() rv := C.OCIStmtExecute( (*C.OCISvcCtx)(s.c.svc), (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), 1, 0, nil, nil, mode) if rv != C.OCI_SUCCESS { return nil, ociGetError(rv, s.c.err) } n, en := s.rowsAffected() var id int64 var ei error if n > 0 { id, ei = s.lastInsertId() } return &OCI8Result{s: s, n: n, errn: en, id: id, errid: ei}, nil }
func (s *OCI8Stmt) Exec(args []driver.Value) (r driver.Result, err error) { var ( fbp []oci8bind ) if fbp, err = s.bind(args); err != nil { return nil, err } defer freeBoundParameters(fbp) mode := C.ub4(C.OCI_DEFAULT) if s.c.inTransaction == false { mode = mode | C.OCI_COMMIT_ON_SUCCESS } rv := C.OCIStmtExecute( (*C.OCISvcCtx)(s.c.svc), (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), 1, 0, nil, nil, mode) if rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } /* rv = C.OCIStmtFetch( (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), 1, C.OCI_FETCH_NEXT, C.OCI_DEFAULT) if rv == C.OCI_NO_DATA { return nil, io.EOF } else if rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } n, en := s.rowsAffected() id, ei := s.lastInsertId() return &OCI8Result{s: s, n: n, errn: en, id: id, errid: ei}, nil */ return &OCI8Result{s: s}, nil }
func (s *OCI8Stmt) Exec(args []driver.Value) (driver.Result, error) { if err := s.bind(args); err != nil { return nil, err } rv := C.OCIStmtExecute( (*C.OCIServer)(s.c.svc), (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), 1, 0, nil, nil, OCI_MODE) if rv == C.OCI_ERROR { return nil, ociGetError(s.c.err) } return &OCI8Result{s}, nil }
// Parse the statement without executing it. This also retrieves information // about the select list for select statements. func (cur *Cursor) Parse(statement string) error { var mode C.ub4 // statement text is expected if statement == "" { return nil } // make sure the cursor is open if !cur.isOpen { return nil } // prepare the statement if err := cur.internalPrepare(statement, ""); err != nil { return err } // parse the statement if cur.statementType == C.OCI_STMT_SELECT { mode = C.OCI_DESCRIBE_ONLY } else { mode = C.OCI_PARSE_ONLY } // Py_BEGIN_ALLOW_THREADS log.Printf("%p.StmtExecute(%s, mode=%d) in Parse", cur, cur.statement, mode) if CTrace { ctrace("OCIStmtExecute", cur.connection.handle, cur.handle, cur.environment.errorHandle, 0, 0, nil, nil, mode) } if err := cur.environment.CheckStatus( C.OCIStmtExecute(cur.connection.handle, cur.handle, cur.environment.errorHandle, 0, 0, //iters, rowoff nil, nil, //snapIn, snapOut mode), "parse"); err != nil { // Py_END_ALLOW_THREADS return err } return nil }
// Exec executes a query that may return rows, such as SELECT. func (stmt *statement) Query(v []driver.Value) (driver.Rows, error) { if err := stmt.bind(v); err != nil { return nil, err } // determine the type of statement. For select statements iter is set to zero, for other statements, only execute once. // * NOTE * Should an error be returned if the statement is a non-select type? var stmt_type C.int if C.OCIAttrGet(stmt.handle, C.OCI_HTYPE_STMT, unsafe.Pointer(&stmt_type), nil, C.OCI_ATTR_STMT_TYPE, (*C.OCIError)(stmt.conn.err)) != C.OCI_SUCCESS { log.Println(ociGetError(stmt.conn.err)) } iter := C.ub4(1) if stmt_type == C.OCI_STMT_SELECT { iter = 0 } // set the row prefetch. Only one extra row per fetch will be returned unless this is set. prefetchSize := C.ub4(100) if C.OCIAttrSet(stmt.handle, C.OCI_HTYPE_STMT, unsafe.Pointer(&prefetchSize), 0, C.OCI_ATTR_PREFETCH_ROWS, (*C.OCIError)(stmt.conn.err)) != C.OCI_SUCCESS { log.Println(ociGetError(stmt.conn.err)) } // execute the statement if C.OCIStmtExecute((*C.OCIServer)(stmt.conn.svr), (*C.OCIStmt)(stmt.handle), (*C.OCIError)(stmt.conn.err), iter, 0, nil, nil, C.OCI_DEFAULT) != C.OCI_SUCCESS { err := ociGetError(stmt.conn.err) log.Println(err) return nil, err } // find out how many output columns there are var cols C.ub2 if C.OCIAttrGet(stmt.handle, C.OCI_HTYPE_STMT, unsafe.Pointer(&cols), nil, C.OCI_ATTR_PARAM_COUNT, (*C.OCIError)(stmt.conn.err)) != C.OCI_SUCCESS { err := ociGetError(stmt.conn.err) log.Println(err) return nil, err } // build column meta-data columns := make([]column, int(cols)) for pos := 0; pos < int(cols); pos++ { col := &columns[pos] var param unsafe.Pointer var colType C.ub2 var colSize C.ub4 var colName *C.char var nameSize C.ub4 if C.OCIParamGet(stmt.handle, C.OCI_HTYPE_STMT, (*C.OCIError)(stmt.conn.err), (*unsafe.Pointer)(unsafe.Pointer(¶m)), C.ub4(pos+1)) != C.OCI_SUCCESS { err := ociGetError(stmt.conn.err) log.Println(err) return nil, err } C.OCIAttrGet(param, C.OCI_DTYPE_PARAM, unsafe.Pointer(&colType), nil, C.OCI_ATTR_DATA_TYPE, (*C.OCIError)(stmt.conn.err)) C.OCIAttrGet(param, C.OCI_DTYPE_PARAM, unsafe.Pointer(&colName), &nameSize, C.OCI_ATTR_NAME, (*C.OCIError)(stmt.conn.err)) C.OCIAttrGet(param, C.OCI_DTYPE_PARAM, unsafe.Pointer(&colSize), nil, C.OCI_ATTR_DATA_SIZE, (*C.OCIError)(stmt.conn.err)) col.kind = int(colType) col.size = int(colSize) col.name = C.GoStringN(colName, (C.int)(nameSize)) col.raw = make([]byte, int(colSize+1)) var def *C.OCIDefine result := C.OCIDefineByPos((*C.OCIStmt)(stmt.handle), &def, (*C.OCIError)(stmt.conn.err), C.ub4(pos+1), unsafe.Pointer(&col.raw[0]), C.sb4(colSize+1), C.SQLT_CHR, nil, nil, nil, C.OCI_DEFAULT) if result != C.OCI_SUCCESS { return nil, ociGetError(stmt.conn.err) } } return &rows{stmt, columns}, nil }
func (s *OCI8Stmt) Query(args []driver.Value) (rows driver.Rows, err error) { var ( fbp []oci8bind ) if fbp, err = s.bind(args); err != nil { return nil, err } defer freeBoundParameters(fbp) iter := C.ub4(1) if retUb2 := C.WrapOCIAttrGetUb2(s.s, C.OCI_HTYPE_STMT, C.OCI_ATTR_STMT_TYPE, (*C.OCIError)(s.c.err)); retUb2.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else if retUb2.num == C.OCI_STMT_SELECT { iter = 0 } // set the row prefetch. Only one extra row per fetch will be returned unless this is set. if prefetch_size := C.ub4(s.c.attrs.Get("prefetch_rows").(int)); prefetch_size > 0 { if rv := C.WrapOCIAttrSetUb4(s.s, C.OCI_HTYPE_STMT, prefetch_size, C.OCI_ATTR_PREFETCH_ROWS, (*C.OCIError)(s.c.err)); rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } } // if non-zero, oci will fetch rows until the memory limit or row prefetch limit is hit. // useful for memory constrained systems if prefetch_memory := C.ub4(s.c.attrs.Get("prefetch_memory").(int64)); prefetch_memory > 0 { if rv := C.WrapOCIAttrSetUb4(s.s, C.OCI_HTYPE_STMT, prefetch_memory, C.OCI_ATTR_PREFETCH_MEMORY, (*C.OCIError)(s.c.err)); rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } } mode := C.ub4(C.OCI_DEFAULT) if !s.c.inTransaction { mode = mode | C.OCI_COMMIT_ON_SUCCESS } if rv := C.OCIStmtExecute( (*C.OCISvcCtx)(s.c.svc), (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), iter, 0, nil, nil, mode); rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } var rc int if retUb2 := C.WrapOCIAttrGetUb2(s.s, C.OCI_HTYPE_STMT, C.OCI_ATTR_PARAM_COUNT, (*C.OCIError)(s.c.err)); retUb2.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else { rc = int(retUb2.num) } oci8cols := make([]oci8col, rc) for i := 0; i < rc; i++ { var p unsafe.Pointer var tp C.ub2 var lp C.ub2 if rp := C.WrapOCIParamGet(s.s, C.OCI_HTYPE_STMT, (*C.OCIError)(s.c.err), C.ub4(i+1)); rp.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else { p = rp.ptr } if tpr := C.WrapOCIAttrGetUb2(p, C.OCI_DTYPE_PARAM, C.OCI_ATTR_DATA_TYPE, (*C.OCIError)(s.c.err)); tpr.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else { tp = tpr.num } if nsr := C.WrapOCIAttrGetString(p, C.OCI_DTYPE_PARAM, C.OCI_ATTR_NAME, (*C.OCIError)(s.c.err)); nsr.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else { oci8cols[i].name = string((*[1 << 30]byte)(unsafe.Pointer(nsr.ptr))[0:int(nsr.size)]) } if lpr := C.WrapOCIAttrGetUb2(p, C.OCI_DTYPE_PARAM, C.OCI_ATTR_DATA_SIZE, (*C.OCIError)(s.c.err)); lpr.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else { lp = lpr.num } /* var ( defp *C.OCIDefine ) */ *s.defp = nil switch tp { case C.SQLT_CHR, C.SQLT_AFC, C.SQLT_VCS, C.SQLT_AVC: // TODO: transfer as clob, read all bytes in loop // lp *= 4 // utf8 enc oci8cols[i].kind = C.SQLT_CHR // tp oci8cols[i].size = int(lp) * 4 // utf8 enc oci8cols[i].pbuf = C.malloc(C.size_t(oci8cols[i].size) + 1) case C.SQLT_BIN: oci8cols[i].kind = C.SQLT_BIN oci8cols[i].size = int(lp) oci8cols[i].pbuf = C.malloc(C.size_t(oci8cols[i].size)) case C.SQLT_NUM: oci8cols[i].kind = C.SQLT_CHR oci8cols[i].size = int(lp * 4) oci8cols[i].pbuf = C.malloc(C.size_t(oci8cols[i].size) + 1) case C.SQLT_IBDOUBLE, C.SQLT_IBFLOAT: oci8cols[i].kind = C.SQLT_IBDOUBLE oci8cols[i].size = int(8) oci8cols[i].pbuf = C.malloc(8) case C.SQLT_CLOB, C.SQLT_BLOB: // allocate +io buffers + ub4 size := int(unsafe.Sizeof(unsafe.Pointer(nil)) + unsafe.Sizeof(C.ub4(0))) if oci8cols[i].size < blobBufSize { size += blobBufSize } else { size += oci8cols[i].size } if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_LOB, C.size_t(size)); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else { oci8cols[i].kind = tp oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil))) oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } // testing // case C.SQLT_DAT: // // oci8cols[i].kind = C.SQLT_DAT // oci8cols[i].size = int(lp) // oci8cols[i].pbuf = C.malloc(C.size_t(lp)) // case C.SQLT_TIMESTAMP, C.SQLT_DAT: if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_TIMESTAMP, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else { oci8cols[i].kind = C.SQLT_TIMESTAMP oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil))) oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } case C.SQLT_TIMESTAMP_TZ, C.SQLT_TIMESTAMP_LTZ: if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_TIMESTAMP_TZ, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else { oci8cols[i].kind = C.SQLT_TIMESTAMP_TZ oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil))) oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } case C.SQLT_INTERVAL_DS: if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_INTERVAL_DS, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else { oci8cols[i].kind = C.SQLT_INTERVAL_DS oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil))) oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } case C.SQLT_INTERVAL_YM: if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_INTERVAL_YM, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } else { oci8cols[i].kind = C.SQLT_INTERVAL_YM oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil))) oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } case C.SQLT_RDD: // rowid lp = 40 oci8cols[i].pbuf = C.malloc(C.size_t(lp) + 1) oci8cols[i].kind = C.SQLT_CHR // tp oci8cols[i].size = int(lp + 1) default: oci8cols[i].pbuf = C.malloc(C.size_t(lp) + 1) oci8cols[i].kind = C.SQLT_CHR // tp oci8cols[i].size = int(lp + 1) } if rv := C.OCIDefineByPos( (*C.OCIStmt)(s.s), s.defp, (*C.OCIError)(s.c.err), C.ub4(i+1), oci8cols[i].pbuf, C.sb4(oci8cols[i].size), oci8cols[i].kind, unsafe.Pointer(&oci8cols[i].ind), &oci8cols[i].rlen, nil, C.OCI_DEFAULT); rv != C.OCI_SUCCESS { return nil, ociGetError(s.c.err) } } return &OCI8Rows{s, oci8cols, false}, nil }
func (s *OCI8Stmt) Query(args []driver.Value) (driver.Rows, error) { if err := s.bind(args); err != nil { return nil, err } var t C.int C.OCIAttrGet( s.s, C.OCI_HTYPE_STMT, unsafe.Pointer(&t), nil, C.OCI_ATTR_STMT_TYPE, (*C.OCIError)(s.c.err)) iter := C.ub4(1) if t == C.OCI_STMT_SELECT { iter = 0 } rv := C.OCIStmtExecute( (*C.OCIServer)(s.c.svc), (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), iter, 0, nil, nil, OCI_MODE) if rv == C.OCI_ERROR { return nil, ociGetError(s.c.err) } var rc C.ub2 C.OCIAttrGet( s.s, C.OCI_HTYPE_STMT, unsafe.Pointer(&rc), nil, C.OCI_ATTR_PARAM_COUNT, (*C.OCIError)(s.c.err)) oci8cols := make([]oci8col, int(rc)) for i := 0; i < int(rc); i++ { var p unsafe.Pointer var np *C.char var ns C.ub4 var tp C.ub2 var lp C.ub2 C.OCIParamGet( s.s, C.OCI_HTYPE_STMT, (*C.OCIError)(s.c.err), (*unsafe.Pointer)(unsafe.Pointer(&p)), C.ub4(i+1)) C.OCIAttrGet( p, C.OCI_DTYPE_PARAM, unsafe.Pointer(&tp), nil, C.OCI_ATTR_DATA_TYPE, (*C.OCIError)(s.c.err)) C.OCIAttrGet( p, C.OCI_DTYPE_PARAM, unsafe.Pointer(&np), &ns, C.OCI_ATTR_NAME, (*C.OCIError)(s.c.err)) C.OCIAttrGet( p, C.OCI_DTYPE_PARAM, unsafe.Pointer(&lp), nil, C.OCI_ATTR_DATA_SIZE, (*C.OCIError)(s.c.err)) oci8cols[i].name = string((*[1 << 30]byte)(unsafe.Pointer(np))[0:int(ns)]) oci8cols[i].kind = int(tp) oci8cols[i].size = int(lp) oci8cols[i].pbuf = make([]byte, int(lp)+1) var defp *C.OCIDefine rv = C.OCIDefineByPos( (*C.OCIStmt)(s.s), &defp, (*C.OCIError)(s.c.err), C.ub4(i+1), unsafe.Pointer(&oci8cols[i].pbuf[0]), C.sb4(lp+1), C.SQLT_CHR, nil, nil, nil, OCI_MODE) if rv == C.OCI_ERROR { return nil, ociGetError(s.c.err) } } return &OCI8Rows{s, oci8cols, false}, nil }
// exe executes a SQL statement on an Oracle server returning rowsAffected, lastInsertId and error. func (stmt *Stmt) exe(params []interface{}) (rowsAffected uint64, lastInsertId int64, err error) { stmt.mu.Lock() defer stmt.mu.Unlock() defer func() { if value := recover(); value != nil { err = errR(value) } }() stmt.log(_drv.cfg.Log.Stmt.Exe) err = stmt.checkClosed() if err != nil { return 0, 0, errE(err) } // for case of inserting and returning identity for database/sql package if _drv.sqlPkgEnv == stmt.ses.srv.env && stmt.stmtType == C.OCI_STMT_INSERT { lastIndex := strings.LastIndex(stmt.sql, ")") sqlEnd := stmt.sql[lastIndex+1 : len(stmt.sql)] sqlEnd = strings.ToUpper(sqlEnd) // add *int64 arg to capture identity if strings.Contains(sqlEnd, "RETURNING") { params[len(params)-1] = &lastInsertId } } iterations, err := stmt.bind(params) // bind parameters if err != nil { return 0, 0, errE(err) } err = stmt.setPrefetchSize() // set prefetch size if err != nil { return 0, 0, errE(err) } var mode C.ub4 // determine auto-commit state; don't auto-comit if there's an explicit user transaction occuring if stmt.cfg.IsAutoCommitting && stmt.ses.openTxs.len() == 0 { mode = C.OCI_COMMIT_ON_SUCCESS } else { mode = C.OCI_DEFAULT } // Execute statement on Oracle server r := C.OCIStmtExecute( stmt.ses.ocisvcctx, //OCISvcCtx *svchp, stmt.ocistmt, //OCIStmt *stmtp, stmt.ses.srv.env.ocierr, //OCIError *errhp, C.ub4(iterations), //ub4 iters, C.ub4(0), //ub4 rowoff, nil, //const OCISnapshot *snap_in, nil, //OCISnapshot *snap_out, mode) //ub4 mode ); if r == C.OCI_ERROR { return 0, 0, errE(stmt.ses.srv.env.ociError()) } var ub8RowsAffected C.ub8 // Get rowsAffected based on statement type switch stmt.stmtType { case C.OCI_STMT_SELECT, C.OCI_STMT_UPDATE, C.OCI_STMT_DELETE, C.OCI_STMT_INSERT: err := stmt.attr(unsafe.Pointer(&ub8RowsAffected), 8, C.OCI_ATTR_UB8_ROW_COUNT) if err != nil { return 0, 0, errE(err) } rowsAffected = uint64(ub8RowsAffected) case C.OCI_STMT_CREATE, C.OCI_STMT_DROP, C.OCI_STMT_ALTER, C.OCI_STMT_BEGIN: } if stmt.hasPtrBind { // Set any bind pointers err = stmt.setBindPtrs() if err != nil { return rowsAffected, lastInsertId, errE(err) } } return rowsAffected, lastInsertId, nil }
func (s *OCI8Stmt) Query(args []driver.Value) (rows driver.Rows, err error) { var ( freeBoundParameters func() ) if freeBoundParameters, err = s.bind(args); err != nil { return nil, err } defer freeBoundParameters() var t C.int C.OCIAttrGet( s.s, C.OCI_HTYPE_STMT, unsafe.Pointer(&t), nil, C.OCI_ATTR_STMT_TYPE, (*C.OCIError)(s.c.err)) iter := C.ub4(1) if t == C.OCI_STMT_SELECT { iter = 0 } // set the row prefetch. Only one extra row per fetch will be returned unless this is set. prefetch_size := C.ub4(s.c.attrs.Get("prefetch_rows").(int)) C.OCIAttrSet(s.s, C.OCI_HTYPE_STMT, unsafe.Pointer(&prefetch_size), 0, C.OCI_ATTR_PREFETCH_ROWS, (*C.OCIError)(s.c.err)) // if non-zero, oci will fetch rows until the memory limit or row prefetch limit is hit. // useful for memory constrained systems prefetch_memory := C.ub4(s.c.attrs.Get("prefetch_memory").(int64)) C.OCIAttrSet(s.s, C.OCI_HTYPE_STMT, unsafe.Pointer(&prefetch_memory), 0, C.OCI_ATTR_PREFETCH_MEMORY, (*C.OCIError)(s.c.err)) rv := C.OCIStmtExecute( (*C.OCISvcCtx)(s.c.svc), (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), iter, 0, nil, nil, C.OCI_DEFAULT) if rv == C.OCI_ERROR { return nil, ociGetError(s.c.err) } var rc C.ub2 C.OCIAttrGet( s.s, C.OCI_HTYPE_STMT, unsafe.Pointer(&rc), nil, C.OCI_ATTR_PARAM_COUNT, (*C.OCIError)(s.c.err)) oci8cols := make([]oci8col, int(rc)) for i := 0; i < int(rc); i++ { var p unsafe.Pointer var np *C.char var ns C.ub4 var tp C.ub2 var lp C.ub2 C.OCIParamGet( s.s, C.OCI_HTYPE_STMT, (*C.OCIError)(s.c.err), (*unsafe.Pointer)(unsafe.Pointer(&p)), C.ub4(i+1)) C.OCIAttrGet( p, C.OCI_DTYPE_PARAM, unsafe.Pointer(&tp), nil, C.OCI_ATTR_DATA_TYPE, (*C.OCIError)(s.c.err)) C.OCIAttrGet( p, C.OCI_DTYPE_PARAM, unsafe.Pointer(&np), &ns, C.OCI_ATTR_NAME, (*C.OCIError)(s.c.err)) C.OCIAttrGet( p, C.OCI_DTYPE_PARAM, unsafe.Pointer(&lp), nil, C.OCI_ATTR_DATA_SIZE, (*C.OCIError)(s.c.err)) switch tp { case C.SQLT_NUM: oci8cols[i].kind = C.SQLT_CHR default: oci8cols[i].kind = tp } oci8cols[i].name = string((*[1 << 30]byte)(unsafe.Pointer(np))[0:int(ns)]) oci8cols[i].size = int(lp) var defp *C.OCIDefine if tp == C.SQLT_CLOB || tp == C.SQLT_BLOB { rv = C.OCIDescriptorAlloc( s.c.env, &oci8cols[i].pbuf, C.OCI_DTYPE_LOB, 0, nil) if rv == C.OCI_ERROR { return nil, ociGetError(s.c.err) } rv = C.OCIDefineByPos( (*C.OCIStmt)(s.s), &defp, (*C.OCIError)(s.c.err), C.ub4(i+1), unsafe.Pointer(&oci8cols[i].pbuf), -1, oci8cols[i].kind, unsafe.Pointer(&oci8cols[i].ind), &oci8cols[i].rlen, nil, C.OCI_DEFAULT) } else { oci8cols[i].pbuf = C.malloc(C.size_t(lp) + 1) rv = C.OCIDefineByPos( (*C.OCIStmt)(s.s), &defp, (*C.OCIError)(s.c.err), C.ub4(i+1), oci8cols[i].pbuf, C.sb4(lp+1), oci8cols[i].kind, unsafe.Pointer(&oci8cols[i].ind), &oci8cols[i].rlen, nil, C.OCI_DEFAULT) } if rv == C.OCI_ERROR { return nil, ociGetError(s.c.err) } } return &OCI8Rows{s, oci8cols, false}, nil }
func (s *StatementOracle) Next() (err int) { if !s.fetchDone { s.hDefine = new(C.OCIDefine) res := C.OCIStmtExecute(s.con.driver.hService, s.hStatement, s.con.driver.hError, 0, 0, nil, nil, C.OCI_DEFAULT) if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res { fmt.Printf("Resultado OCIStmtExecute=%v\n", res) C.AuxOCIErrorGet(s.con.driver.hError) return -1 } s.fetchDone = true /* var idValue int res = C.OCIDefineByPos( s.hStatement, &s.hDefine, s.con.driver.hError, 1 /*pos* /, unsafe.Pointer(&idValue), C.sb4(unsafe.Sizeof(idValue)), C.SQLT_INT, nil, nil, nil, C.OCI_DEFAULT); if (C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res* /) { fmt.Printf( "Resultado OCIDefineByPos=%v\n", res) C.AuxOCIErrorGet( s.con.driver.hError); return -2 } var surnameValue [40]C.char res = C.OCIDefineByPos( s.hStatement, &s.hDefine, s.con.driver.hError, 2 /*pos* /, unsafe.Pointer(&surnameValue[0]), C.sb4(unsafe.Sizeof(surnameValue)), C.SQLT_STR, nil, nil, nil, C.OCI_DEFAULT); if (C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res* /) { fmt.Printf( "Resultado OCIDefineByPos=%v\n", res) C.AuxOCIErrorGet( s.con.driver.hError); return -3 } */ res = C.OCIAttrGet(unsafe.Pointer(s.hStatement), C.OCI_HTYPE_STMT, unsafe.Pointer(&s.numColumns), nil, C.OCI_ATTR_PARAM_COUNT, s.con.driver.hError) if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ { fmt.Printf("Resultado OCIAttrGet=%v\n", res) C.AuxOCIErrorGet(s.con.driver.hError) return -3 } fmt.Printf("numColumns=%v\n", s.numColumns) s.columns = make([]*ColumnOracle, 0, 50) var hColumn C.ub4 pColumn := unsafe.Pointer(&hColumn) for i := 1; i <= s.numColumns; i++ { /* get parameter for column i */ res = C.OCIParamGet(unsafe.Pointer(s.hStatement), C.OCI_HTYPE_STMT, s.con.driver.hError, &pColumn, C.ub4(i)) if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ { fmt.Printf("Resultado OCIParamGet=%v\n", res) C.AuxOCIErrorGet(s.con.driver.hError) return -4 } /* get data-type of column i */ var columnType C.ub2 pType := unsafe.Pointer(&columnType) res = C.OCIAttrGet(pColumn, C.OCI_DTYPE_PARAM, pType, nil, C.OCI_ATTR_DATA_TYPE, s.con.driver.hError) if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ { fmt.Printf("Resultado OCIParamGet=%v\n", res) C.AuxOCIErrorGet(s.con.driver.hError) return -4 } size := C.ub4(100) var column_name_tmp *C.char res = C.OCIAttrGet(pColumn, C.OCI_DTYPE_PARAM, unsafe.Pointer(&column_name_tmp), nil, C.OCI_ATTR_NAME, s.con.driver.hError) fmt.Printf("coumnName (size=%v) = %v\n", size, column_name_tmp) //column_name_tmp[size] = 0 columnName := C.GoString(column_name_tmp) var columnSize int res = C.OCIAttrGet(pColumn, C.OCI_DTYPE_PARAM, unsafe.Pointer(&columnSize), nil, C.OCI_ATTR_DATA_SIZE, s.con.driver.hError) fmt.Printf("Column:%v Name:%v Size:%v Type:%v\n", i, columnName, columnSize, columnType) switch columnType { case C.SQLT_CHR: var columnValue = make([]C.char, columnSize+1) res = C.OCIDefineByPos(s.hStatement, &s.hDefine, s.con.driver.hError, C.ub4(i), /*pos*/ unsafe.Pointer(&columnValue[0]), C.sb4(columnSize), columnType, nil, nil, nil, C.OCI_DEFAULT) if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ { fmt.Printf("Resultado OCIDefineByPos=%v\n", res) C.AuxOCIErrorGet(s.con.driver.hError) return -2 } s.columns = append(s.columns, NewColumnChrOracle(s, columnName, int(columnSize), columnValue)) case C.SQLT_NUM: var columnValue int res = C.OCIDefineByPos(s.hStatement, &s.hDefine, s.con.driver.hError, C.ub4(i), /*pos*/ unsafe.Pointer(&columnValue), C.sb4(4 /*sizeof(columnValue)*/), columnType, nil, nil, nil, C.OCI_DEFAULT) if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ { fmt.Printf("Resultado OCIDefineByPos=%v\n", res) C.AuxOCIErrorGet(s.con.driver.hError) return -2 } s.columns = append(s.columns, NewColumnNumberOracle(s, columnName, int(columnSize), columnValue)) //case C.SQLT_LNG: //case C.SQLT_RID: //case C.SQLT_DAT: //case C.SQLT_BIN: //case C.SQLT_LBI: //case C.SQLT_AFC: //case C.SQLT_REF: //case C.SQLT_CLOB: //case C.SQLT_BLOB: //case C.SQLT_BFILEE: //case C.SQLT_TIMESTAMP: //case C.SQLT_TIME_TZ: //case C.SQLT_INTERVAL_YM: //case C.SQLT_INTERVAL_DS: //case C.SQLT_TIMESTAMP_LTZ: //case C.SQLT_RDD: default: s.columns = append(s.columns, NewColumnUnknownOracle(s, columnName, int(columnSize), int(columnType))) } fmt.Printf("Next len(stmt.columns)=%v\n", len(s.columns)) } //return 0 } res := C.OCIStmtFetch2(s.hStatement, s.con.driver.hError, 1 /*nrows*/, C.OCI_FETCH_NEXT, 0, C.OCI_DEFAULT) if C.OCI_SUCCESS != res && C.OCI_NO_DATA != res { fmt.Printf("Resultado OCIStmtFetch2=%v\n", res) C.AuxOCIErrorGet(s.con.driver.hError) return -4 } else if C.OCI_NO_DATA == res { //fmt.Printf( "The result is:%v-%v\n", idValue, C.GoString(&surnameValue[0])) return 0 } return 1 }
// Open defines select-list columns. func (rset *Rset) open(stmt *Stmt, ocistmt *C.OCIStmt) error { rset.stmt = stmt rset.ocistmt = ocistmt rset.Index = -1 rset.Err = nil rset.log(_drv.cfg.Log.Rset.Open) // call log after rset.stmt is set // get the implcit select-list describe information; no server round-trip r := C.OCIStmtExecute( rset.stmt.ses.srv.ocisvcctx, //OCISvcCtx *svchp, rset.ocistmt, //OCIStmt *stmtp, rset.stmt.ses.srv.env.ocierr, //OCIError *errhp, C.ub4(1), //ub4 iters, C.ub4(0), //ub4 rowoff, nil, //const OCISnapshot *snap_in, nil, //OCISnapshot *snap_out, C.OCI_DESCRIBE_ONLY) //ub4 mode ); if r == C.OCI_ERROR { return rset.stmt.ses.srv.env.ociError() } // get the parameter count var paramCount C.ub4 err := rset.attr(unsafe.Pointer(¶mCount), 4, C.OCI_ATTR_PARAM_COUNT) if err != nil { return err } // make defines slice rset.defs = make([]def, int(paramCount)) rset.ColumnNames = make([]string, int(paramCount)) rset.Row = make([]interface{}, int(paramCount)) //fmt.Printf("rset.open (paramCount %v)\n", paramCount) // create parameters for each select-list column var gct GoColumnType for n := range rset.defs { // Create oci parameter handle; may be freed by OCIDescriptorFree() // parameter position is 1-based var ocipar *C.OCIParam r := C.OCIParamGet( unsafe.Pointer(rset.ocistmt), //const void *hndlp, C.OCI_HTYPE_STMT, //ub4 htype, rset.stmt.ses.srv.env.ocierr, //OCIError *errhp, (*unsafe.Pointer)(unsafe.Pointer(&ocipar)), //void **parmdpp, C.ub4(n+1)) //ub4 pos ); if r == C.OCI_ERROR { return rset.stmt.ses.srv.env.ociError() } // Get column size in bytes var columnSize uint32 err = rset.paramAttr(ocipar, unsafe.Pointer(&columnSize), 0, C.OCI_ATTR_DATA_SIZE) if err != nil { return err } // Get oci data type code var ociTypeCode C.ub2 err = rset.paramAttr(ocipar, unsafe.Pointer(&ociTypeCode), 0, C.OCI_ATTR_DATA_TYPE) if err != nil { return err } // Get column name var columnName *C.char err := rset.paramAttr(ocipar, unsafe.Pointer(&columnName), 0, C.OCI_ATTR_NAME) if err != nil { return err } rset.ColumnNames[n] = C.GoString(columnName) //fmt.Printf("Rset.open: ociTypeCode (%v)\n", ociTypeCode) //Log.Infof("Rset.open: ociTypeCode=%d name=%s size=%d", ociTypeCode, rset.ColumnNames[n], columnSize) //log(true, "ociTypeCode=", int(ociTypeCode), ", name=", rset.ColumnNames[n], ", size=", columnSize) switch ociTypeCode { case C.SQLT_NUM: // NUMBER // Get precision var precision C.sb2 err = rset.paramAttr(ocipar, unsafe.Pointer(&precision), 0, C.OCI_ATTR_PRECISION) if err != nil { return err } // Get scale (the number of decimal places) var numericScale C.sb1 err = rset.paramAttr(ocipar, unsafe.Pointer(&numericScale), 0, C.OCI_ATTR_SCALE) if err != nil { return err } // If the precision is nonzero and scale is -127, then it is a FLOAT; // otherwise, it's a NUMBER(precision, scale). if precision != 0 && (numericScale > 0 || numericScale == -127) { if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { if numericScale == -127 { gct = rset.stmt.cfg.Rset.float } else { gct = rset.stmt.cfg.Rset.numberFloat } } else { err = checkNumericColumn(stmt.gcts[n], rset.ColumnNames[n]) if err != nil { return err } gct = stmt.gcts[n] } err := rset.defineNumeric(n, gct) if err != nil { return err } } else { if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.numberInt } else { err = checkNumericColumn(stmt.gcts[n], rset.ColumnNames[n]) if err != nil { return err } gct = stmt.gcts[n] } err := rset.defineNumeric(n, gct) if err != nil { return err } } case C.SQLT_IBDOUBLE: // BINARY_DOUBLE if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.binaryDouble } else { err = checkNumericColumn(stmt.gcts[n], rset.ColumnNames[n]) if err != nil { return err } gct = stmt.gcts[n] } err := rset.defineNumeric(n, gct) if err != nil { return err } case C.SQLT_IBFLOAT: // BINARY_FLOAT if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.binaryFloat } else { err = checkNumericColumn(stmt.gcts[n], rset.ColumnNames[n]) if err != nil { return err } gct = stmt.gcts[n] } err := rset.defineNumeric(n, gct) if err != nil { return err } case C.SQLT_DAT, C.SQLT_TIMESTAMP, C.SQLT_TIMESTAMP_TZ, C.SQLT_TIMESTAMP_LTZ: // DATE, TIMESTAMP, TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIMEZONE if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { switch ociTypeCode { case C.SQLT_DAT: gct = rset.stmt.cfg.Rset.date case C.SQLT_TIMESTAMP: gct = rset.stmt.cfg.Rset.timestamp case C.SQLT_TIMESTAMP_TZ: gct = rset.stmt.cfg.Rset.timestampTz case C.SQLT_TIMESTAMP_LTZ: gct = rset.stmt.cfg.Rset.timestampLtz } } else { err = checkTimeColumn(stmt.gcts[n]) if err != nil { return err } gct = stmt.gcts[n] } isNullable := false if gct == OraT { isNullable = true } def := rset.getDef(defIdxTime).(*defTime) rset.defs[n] = def err = def.define(n+1, isNullable, rset) if err != nil { return err } case C.SQLT_CHR: // VARCHAR, VARCHAR2, NVARCHAR2 if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.varchar } else { err = checkStringColumn(stmt.gcts[n]) if err != nil { return err } gct = stmt.gcts[n] } err = rset.defineString(n, columnSize, gct) if err != nil { return err } case C.SQLT_AFC: //Log.Infof("rset AFC size=%d gct=%v", columnSize, gct) // CHAR, NCHAR // for char(1 char) columns, columnSize is 4 (AL32UTF8 charset) if columnSize == 1 || columnSize == 4 { if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.char1 } else { err = checkBoolOrStringColumn(stmt.gcts[n]) if err != nil { return err } gct = stmt.gcts[n] } switch gct { case B, OraB: // Interpret single char as bool isNullable := false if gct == OraB { isNullable = true } def := rset.getDef(defIdxBool).(*defBool) rset.defs[n] = def err = def.define(n+1, int(columnSize), isNullable, rset) if err != nil { return err } case S, OraS: // Interpret single char as string rset.defineString(n, columnSize, gct) } } else { // Interpret as string if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.char } else { err = checkStringColumn(stmt.gcts[n]) if err != nil { return err } gct = stmt.gcts[n] } err = rset.defineString(n, columnSize, gct) if err != nil { return err } } case C.SQLT_LNG: // LONG if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.long } else { err = checkStringColumn(stmt.gcts[n]) if err != nil { return err } gct = stmt.gcts[n] } // longBufferSize: Use a moderate default buffer size; 2GB max buffer may not be feasible on all clients err = rset.defineString(n, stmt.cfg.longBufferSize, gct) if err != nil { return err } case C.SQLT_CLOB: // CLOB, NCLOB if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.clob } else { err = checkStringColumn(stmt.gcts[n]) if err != nil { return err } gct = stmt.gcts[n] } // Get character set form var charsetForm C.ub1 err = rset.paramAttr(ocipar, unsafe.Pointer(&charsetForm), 0, C.OCI_ATTR_CHARSET_FORM) if err != nil { return err } def := rset.getDef(defIdxLob).(*defLob) rset.defs[n] = def err = def.define(n+1, charsetForm, C.SQLT_CLOB, gct, rset) if err != nil { return err } case C.SQLT_BLOB: // BLOB if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.blob } else { err = checkBinColumn(stmt.gcts[n]) if err != nil { return err } gct = stmt.gcts[n] } def := rset.getDef(defIdxLob).(*defLob) rset.defs[n] = def err = def.define(n+1, C.SQLCS_IMPLICIT, C.SQLT_BLOB, gct, rset) if err != nil { return err } case C.SQLT_BIN: // RAW if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.raw } else { err = checkBinColumn(stmt.gcts[n]) if err != nil { return err } gct = stmt.gcts[n] } isNullable := false if gct == OraBin { isNullable = true } def := rset.getDef(defIdxRaw).(*defRaw) rset.defs[n] = def err = def.define(n+1, int(columnSize), isNullable, rset) if err != nil { return err } case C.SQLT_LBI: //log(true, "LONG RAW") // LONG RAW if stmt.gcts == nil || n >= len(stmt.gcts) || stmt.gcts[n] == D { gct = rset.stmt.cfg.Rset.longRaw } else { err = checkBinColumn(stmt.gcts[n]) if err != nil { return err } gct = stmt.gcts[n] } isNullable := false if gct == OraBin { isNullable = true } def := rset.getDef(defIdxLongRaw).(*defLongRaw) rset.defs[n] = def err = def.define(n+1, rset.stmt.cfg.longRawBufferSize, isNullable, rset) if err != nil { return err } case C.SQLT_INTERVAL_YM: def := rset.getDef(defIdxIntervalYM).(*defIntervalYM) rset.defs[n] = def err = def.define(n+1, rset) if err != nil { return err } case C.SQLT_INTERVAL_DS: def := rset.getDef(defIdxIntervalDS).(*defIntervalDS) rset.defs[n] = def err = def.define(n+1, rset) if err != nil { return err } case C.SQLT_FILE: // BFILE def := rset.getDef(defIdxBfile).(*defBfile) rset.defs[n] = def err = def.define(n+1, rset) if err != nil { return err } case C.SQLT_RDD: // ROWID, UROWID def := rset.getDef(defIdxRowid).(*defRowid) rset.defs[n] = def err = def.define(n+1, rset) if err != nil { return err } break default: return errF("unsupported select-list column type (ociTypeCode: %v)", ociTypeCode) } } rset.logF(_drv.cfg.Log.Rset.OpenDefs, "%#v", rset.defs) return nil }