func (cursor *Cursor) prep() (err error) { var isc_status [20]C.ISC_STATUS if err = cursor.check(); err != nil { return } if err = cursor.connection.check(); err != nil { return } C.isc_dsql_describe(&isc_status[0], &cursor.stmt, 1, cursor.o_sqlda) if err = fbErrorCheck(&isc_status); err != nil { return } cols := cursor.o_sqlda.sqld var offset C.ISC_SHORT = 0 for count := C.ISC_SHORT(0); count < cols; count++ { ovar := C.sqlda_sqlvar(cursor.o_sqlda, count) length, alignment := ovar.sqllen, ovar.sqllen dtp := ovar.sqltype & ^1 if dtp == C.SQL_TEXT { alignment = 1 } else if dtp == C.SQL_VARYING { length += C.SHORT_SIZE alignment = C.SHORT_SIZE } offset = fbAlign(offset, alignment) ovar.sqldata = (*C.ISC_SCHAR)(unsafe.Pointer((uintptr(unsafe.Pointer(cursor.o_buffer)) + uintptr(offset)))) offset += length offset = fbAlign(offset, C.SHORT_SIZE) ovar.sqlind = (*C.ISC_SHORT)(unsafe.Pointer(uintptr(unsafe.Pointer(cursor.o_buffer)) + uintptr(offset))) offset += C.SHORT_SIZE } return }
func fieldsFromSqlda(sqlda *C.XSQLDA, lowercaseNames bool) []*Field { cols := sqlda.sqld if cols == 0 { return nil } ary := make([]*Field, cols) for count := C.ISC_SHORT(0); count < cols; count++ { var field Field sqlvar := C.sqlda_sqlvar(sqlda, count) dtp := sqlvar.sqltype & ^1 if sqlvar.aliasname_length > 0 { field.Name = C.GoStringN((*C.char)(unsafe.Pointer(&sqlvar.aliasname[0])), C.int(sqlvar.aliasname_length)) } else { field.Name = C.GoStringN((*C.char)(unsafe.Pointer(&sqlvar.sqlname[0])), C.int(sqlvar.sqlname_length)) } if lowercaseNames && !hasLowercase(field.Name) { field.Name = strings.ToLower(field.Name) } field.TypeCode = int(sqlvar.sqltype & ^1) field.SqlType = sqlTypeFromCode(dtp, sqlvar.sqlsubtype) field.SqlSubtype = int(sqlvar.sqlsubtype) field.DisplaySize = int(sqlvar.sqllen) if dtp == C.SQL_VARYING { field.InternalSize = int(sqlvar.sqllen + C.SHORT_SIZE) } else { field.InternalSize = int(sqlvar.sqllen) } field.Precision = precisionFromSqlvar(sqlvar) field.Scale = int(sqlvar.sqlscale) field.Nullable = (sqlvar.sqltype & 1) != 0 ary[count] = &field } return ary }
func (cursor *Cursor) Fetch(row interface{}) (err error) { const SQLCODE_NOMORE = 100 var isc_status [20]C.ISC_STATUS if err = cursor.prep(); err != nil { return } if err = cursor.connection.check(); err != nil { return } if cursor.eof { err = &Error{Message: "Cursor is past end of data."} return } // fetch one row if C.isc_dsql_fetch(&isc_status[0], &cursor.stmt, 1, cursor.o_sqlda) == SQLCODE_NOMORE { cursor.eof = true err = io.EOF return } if err = fbErrorCheck(&isc_status); err != nil { return } // create result tuple cols := cursor.o_sqlda.sqld ary := make([]interface{}, cols) // set result value for each column for count := C.ISC_SHORT(0); count < cols; count++ { var val interface{} // sqlvar := &cursor.o_sqlda.sqlvar[count] sqlvar := C.sqlda_sqlvar(cursor.o_sqlda, count) dtp := sqlvar.sqltype & ^1 // check if column is null if (sqlvar.sqltype&1 != 0) && (*sqlvar.sqlind < 0) { val = nil } else { // set column value to result tuple switch dtp { case C.SQL_TEXT: val = C.GoStringN((*C.char)(unsafe.Pointer(sqlvar.sqldata)), C.int(sqlvar.sqllen)) case C.SQL_SHORT: sval := *(*C.short)(unsafe.Pointer(sqlvar.sqldata)) if sqlvar.sqlscale < 0 { ratio := C.short(1) for scnt := C.ISC_SHORT(0); scnt > sqlvar.sqlscale; scnt-- { ratio *= 10 } dval := sval / ratio val = dval } else { val = int16(sval) } } } ary[count] = val } switch row := row.(type) { case *[]interface{}: *row = ary } return }