Example #1
0
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
}
Example #2
0
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
}
Example #3
0
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
}