Example #1
0
File: rset.go Project: rjammala/ora
// 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
}
Example #2
0
// 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
}
Example #3
0
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
}
Example #4
0
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
}