// beginRow allocates a handle for each column and fetches one row. func (rset *Rset) beginRow() (err error) { rset.log(_drv.cfg.Log.Rset.BeginRow) rset.Index++ // check is open if rset.ocistmt == nil { return errF("Rset is closed") } // allocate define descriptor handles for _, define := range rset.defs { //glog.Infof("Rset.define: ", define) rset.logF(_drv.cfg.Log.Rset.BeginRow, "%#v", define) err := define.alloc() if err != nil { return err } } // fetch one row r := C.OCIStmtFetch2( rset.ocistmt, //OCIStmt *stmthp, rset.stmt.ses.srv.env.ocierr, //OCIError *errhp, C.ub4(1), //ub4 nrows, C.OCI_FETCH_NEXT, //ub2 orientation, C.sb4(0), //sb4 fetchOffset, C.OCI_DEFAULT) //ub4 mode ); if r == C.OCI_ERROR { return rset.stmt.ses.srv.env.ociError() } else if r == C.OCI_NO_DATA { // Adjust Index so that Len() returns correct value when all rows read rset.Index-- // return io.EOF to conform with database/sql/driver return io.EOF } return nil }
// Next is called to populate the next row of data into // the provided slice. The provided slice will be the same // size as the Columns() are wide. // // The dest slice may be populated only with // a driver Value type, but excluding string. // All string values must be converted to []byte. // // Next should return io.EOF when there are no more rows. func (r *rows) Next(dest []driver.Value) error { rv := C.OCIStmtFetch2((*C.OCIStmt)(r.stmt.handle), (*C.OCIError)(r.stmt.conn.err), 1, C.OCI_FETCH_NEXT, 1, C.OCI_DEFAULT) if rv == C.OCI_ERROR { err := ociGetError(r.stmt.conn.err) fmt.Println(err) return ociGetError(r.stmt.conn.err) } if rv == C.OCI_NO_DATA { fmt.Println("no data") return io.EOF } for i := range dest { dest[i] = string(r.columns[i].raw) } return nil }
func (rc *OCI8Rows) Next(dest []driver.Value) (err error) { if rc.closed { return nil } rv := C.OCIStmtFetch2( (*C.OCIStmt)(rc.s.s), (*C.OCIError)(rc.s.c.err), 1, C.OCI_FETCH_NEXT, 0, C.OCI_DEFAULT) if rv == C.OCI_NO_DATA { return io.EOF } else if rv != C.OCI_SUCCESS && rv != C.OCI_SUCCESS_WITH_INFO { return ociGetError(rv, rc.s.c.err) } for i := range dest { // TODO: switch rc.cols[i].ind if *rc.cols[i].ind == -1 { // Null dest[i] = nil continue } else if *rc.cols[i].ind != 0 { return errors.New(fmt.Sprintf("Unknown column indicator: %d, col %s", rc.cols[i].ind, rc.cols[i].name)) } switch rc.cols[i].kind { case C.SQLT_DAT: // for test, date are return as timestamp buf := (*[1 << 30]byte)(unsafe.Pointer(rc.cols[i].pbuf))[0:*rc.cols[i].rlen] // TODO: Handle BCE dates (http://docs.oracle.com/cd/B12037_01/appdev.101/b10779/oci03typ.htm#438305) // TODO: Handle timezones (http://docs.oracle.com/cd/B12037_01/appdev.101/b10779/oci03typ.htm#443601) dest[i] = time.Date( (int(buf[0])-100)*100+(int(buf[1])-100), time.Month(int(buf[2])), int(buf[3]), int(buf[4])-1, int(buf[5])-1, int(buf[6])-1, 0, rc.s.c.location) case C.SQLT_BLOB, C.SQLT_CLOB: ptmp := unsafe.Pointer(uintptr(rc.cols[i].pbuf) + unsafe.Sizeof(unsafe.Pointer(nil))) bamt := (*C.ub4)(ptmp) ptmp = unsafe.Pointer(uintptr(rc.cols[i].pbuf) + unsafe.Sizeof(C.ub4(0)) + unsafe.Sizeof(unsafe.Pointer(nil))) b := (*[1 << 30]byte)(ptmp)[0:blobBufSize] var buf []byte again: *bamt = 0 rv = C.OCILobRead( (*C.OCISvcCtx)(rc.s.c.svc), (*C.OCIError)(rc.s.c.err), *(**C.OCILobLocator)(rc.cols[i].pbuf), bamt, 1, ptmp, C.ub4(blobBufSize), nil, nil, 0, C.SQLCS_IMPLICIT) if rv == C.OCI_NEED_DATA { buf = append(buf, b[:int(*bamt)]...) goto again } if rv != C.OCI_SUCCESS { return ociGetError(rv, rc.s.c.err) } if rc.cols[i].kind == C.SQLT_BLOB { dest[i] = append(buf, b[:int(*bamt)]...) } else { dest[i] = string(append(buf, b[:int(*bamt)]...)) } case C.SQLT_CHR, C.SQLT_AFC, C.SQLT_AVC: buf := (*[1 << 30]byte)(unsafe.Pointer(rc.cols[i].pbuf))[0:*rc.cols[i].rlen] switch { case *rc.cols[i].ind == 0: // Normal dest[i] = string(buf) case *rc.cols[i].ind == -2 || // Field longer than type (truncated) *rc.cols[i].ind > 0: // Field longer than type (truncated). Value is original length. dest[i] = string(buf) default: return errors.New(fmt.Sprintf("Unknown column indicator: %d", rc.cols[i].ind)) } case C.SQLT_BIN: // RAW buf := (*[1 << 30]byte)(unsafe.Pointer(rc.cols[i].pbuf))[0:*rc.cols[i].rlen] dest[i] = buf case C.SQLT_NUM: // NUMBER buf := (*[21]byte)(unsafe.Pointer(rc.cols[i].pbuf)) dest[i] = buf case C.SQLT_VNU: // VARNUM buf := (*[22]byte)(unsafe.Pointer(rc.cols[i].pbuf)) dest[i] = buf case C.SQLT_INT: // INT buf := (*[1 << 30]byte)(unsafe.Pointer(rc.cols[i].pbuf))[0:*rc.cols[i].rlen] dest[i] = buf case C.SQLT_LNG: // LONG buf := (*[1 << 30]byte)(unsafe.Pointer(rc.cols[i].pbuf))[0:*rc.cols[i].rlen] dest[i] = buf case C.SQLT_IBDOUBLE, C.SQLT_IBFLOAT: colsize := rc.cols[i].size buf := (*[1 << 30]byte)(unsafe.Pointer(rc.cols[i].pbuf))[0:colsize] if colsize == 4 { v := uint32(buf[3]) v |= uint32(buf[2]) << 8 v |= uint32(buf[1]) << 16 v |= uint32(buf[0]) << 24 // Don't know why bits are inverted that way, but it works if buf[0]&0x80 == 0 { v ^= 0xffffffff } else { v &= 0x7fffffff } dest[i] = math.Float32frombits(v) } else if colsize == 8 { v := uint64(buf[7]) v |= uint64(buf[6]) << 8 v |= uint64(buf[5]) << 16 v |= uint64(buf[4]) << 24 v |= uint64(buf[3]) << 32 v |= uint64(buf[2]) << 40 v |= uint64(buf[1]) << 48 v |= uint64(buf[0]) << 56 // Don't know why bits are inverted that way, but it works if buf[0]&0x80 == 0 { v ^= 0xffffffffffffffff } else { v &= 0x7fffffffffffffff } dest[i] = math.Float64frombits(v) } else { return errors.New(fmt.Sprintf("Unhandled binary float size: %d", colsize)) } case C.SQLT_TIMESTAMP: if rv := C.WrapOCIDateTimeGetDateTime( (*C.OCIEnv)(rc.s.c.env), (*C.OCIError)(rc.s.c.err), *(**C.OCIDateTime)(rc.cols[i].pbuf), ); rv.rv != C.OCI_SUCCESS { return ociGetError(rv.rv, rc.s.c.err) } else { dest[i] = time.Date( int(rv.y), time.Month(rv.m), int(rv.d), int(rv.hh), int(rv.mm), int(rv.ss), int(rv.ff), rc.s.c.location) } case C.SQLT_TIMESTAMP_TZ, C.SQLT_TIMESTAMP_LTZ: tptr := *(**C.OCIDateTime)(rc.cols[i].pbuf) rv := C.WrapOCIDateTimeGetDateTime( (*C.OCIEnv)(rc.s.c.env), (*C.OCIError)(rc.s.c.err), tptr) if rv.rv != C.OCI_SUCCESS { return ociGetError(rv.rv, rc.s.c.err) } rvz := C.WrapOCIDateTimeGetTimeZoneNameOffset( (*C.OCIEnv)(rc.s.c.env), (*C.OCIError)(rc.s.c.err), tptr) if rvz.rv != C.OCI_SUCCESS { return ociGetError(rvz.rv, rc.s.c.err) } nnn := C.GoStringN((*C.char)((unsafe.Pointer)(&rvz.zone[0])), C.int(rvz.zlen)) loc, err := time.LoadLocation(nnn) if err != nil { // TODO: reuse locations loc = time.FixedZone(nnn, int(rvz.h)*60*60+int(rvz.m)*60) } dest[i] = time.Date( int(rv.y), time.Month(rv.m), int(rv.d), int(rv.hh), int(rv.mm), int(rv.ss), int(rv.ff), loc) case C.SQLT_INTERVAL_DS: iptr := *(**C.OCIInterval)(rc.cols[i].pbuf) rv := C.WrapOCIIntervalGetDaySecond( (*C.OCIEnv)(rc.s.c.env), (*C.OCIError)(rc.s.c.err), iptr) if rv.rv != C.OCI_SUCCESS { return ociGetError(rv.rv, rc.s.c.err) } dest[i] = int64(time.Duration(rv.d)*time.Hour*24 + time.Duration(rv.hh)*time.Hour + time.Duration(rv.mm)*time.Minute + time.Duration(rv.ss)*time.Second + time.Duration(rv.ff)) case C.SQLT_INTERVAL_YM: iptr := *(**C.OCIInterval)(rc.cols[i].pbuf) rv := C.WrapOCIIntervalGetYearMonth( (*C.OCIEnv)(rc.s.c.env), (*C.OCIError)(rc.s.c.err), iptr) if rv.rv != C.OCI_SUCCESS { return ociGetError(rv.rv, rc.s.c.err) } dest[i] = int64(rv.y)*12 + int64(rv.m) default: return errors.New(fmt.Sprintf("Unhandled column type: %d", rc.cols[i].kind)) } } return 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 }