Exemple #1
0
// Scan parses the values of the current result row (set using Result.Next)
// into the given arguments.
func (r *Result) Scan(args ...interface{}) os.Error {
	if len(args) != r.ncols {
		return os.NewError(fmt.Sprintf("incorrect argument count for Result.Scan: have %d want %d", len(args), r.ncols))
	}

	for i, v := range args {
		if int(C.PQgetisnull(r.res, C.int(r.currRow), C.int(i))) == 1 {
			continue
		}
		val := C.GoString(C.PQgetvalue(r.res, C.int(r.currRow), C.int(i)))
		switch v := v.(type) {
		case *[]byte:
			if !strings.HasPrefix(val, "\\x") {
				return argErr(i, "[]byte", "invalid byte string format")
			}
			buf, err := hex.DecodeString(val[2:])
			if err != nil {
				return argErr(i, "[]byte", err.String())
			}
			*v = buf
		case *string:
			*v = val
		case *bool:
			*v = val == "t"
		case *int:
			x, err := strconv.Atoi(val)
			if err != nil {
				return argErr(i, "int", err.String())
			}
			*v = x
		case *int64:
			x, err := strconv.Atoi64(val)
			if err != nil {
				return argErr(i, "int64", err.String())
			}
			*v = x
		case *float32:
			x, err := strconv.Atof32(val)
			if err != nil {
				return argErr(i, "float32", err.String())
			}
			*v = x
		case *float64:
			x, err := strconv.Atof64(val)
			if err != nil {
				return argErr(i, "float64", err.String())
			}
			*v = x
		case *time.Time:
			x, _, err := ParseTimestamp(val)
			if err != nil {
				return argErr(i, "time.Time", err.String())
			}
			*v = *x
		default:
			return os.NewError("unsupported type in Scan: " + reflect.TypeOf(v).String())
		}
	}
	return nil
}
Exemple #2
0
func (r *libpqRows) Next(dest []driver.Value) error {
	if r.currRow >= r.nrows {
		return io.EOF
	}
	currRow := C.int(r.currRow)
	r.currRow++

	for i := 0; i < len(dest); i++ {
		ci := C.int(i)

		// check for NULL
		if int(C.PQgetisnull(r.res, currRow, ci)) == 1 {
			dest[i] = nil
			continue
		}

		var err error
		val := C.GoString(C.PQgetvalue(r.res, currRow, ci))
		switch vtype := int(C.PQftype(r.res, ci)); vtype {
		case r.s.c.oids.Bytea:
			if !strings.HasPrefix(val, `\x`) {
				return errors.New("libpq: invalid byte string format")
			}
			dest[i], err = hex.DecodeString(val[2:])
			if err != nil {
				return errors.New(fmt.Sprint("libpq: could not decode hex string: %s", err))
			}
		case r.s.c.oids.Date:
			dest[i], err = time.Parse("2006-01-02", val)
			if err != nil {
				return errors.New(fmt.Sprint("libpq: could not parse DATE %s: %s", val, err))
			}
		case r.s.c.oids.Timestamp:
			dest[i], err = time.Parse("2006-01-02 15:04:05", val)
			if err != nil {
				return errors.New(fmt.Sprint("libpq: could not parse TIMESTAMP %s: %s", val, err))
			}
		case r.s.c.oids.TimestampTz:
			dest[i], err = time.Parse(timeFormat, val)
			if err != nil {
				return errors.New(fmt.Sprint("libpq: could not parse TIMESTAMP WITH TIME ZONE %s: %s", val, err))
			}
		case r.s.c.oids.Time:
			dest[i], err = time.Parse("15:04:05", val)
			if err != nil {
				return errors.New(fmt.Sprint("libpq: could not parse TIME %s: %s", val, err))
			}
		case r.s.c.oids.TimeTz:
			dest[i], err = time.Parse("15:04:05-07", val)
			if err != nil {
				return errors.New(fmt.Sprint("libpq: could not parse TIME WITH TIME ZONE %s: %s", val, err))
			}
		default:
			dest[i] = val
		}
	}

	return nil
}
Exemple #3
0
func (r *driverRows) Next(dest []driver.Value) error {
	r.currRow++
	if r.currRow >= r.nrows {
		return io.EOF
	}

	for i := 0; i < len(dest); i++ {
		if int(C.PQgetisnull(r.res, C.int(r.currRow), C.int(i))) == 1 {
			dest[i] = nil
			continue
		}
		val := C.GoString(C.PQgetvalue(r.res, C.int(r.currRow), C.int(i)))
		switch vtype := uint(C.PQftype(r.res, C.int(i))); vtype {
		case BOOLOID:
			if val == "t" {
				dest[i] = "true"
			} else {
				dest[i] = "false"
			}
		case BYTEAOID:
			if !strings.HasPrefix(val, "\\x") {
				return argErr(i, "[]byte", "invalid byte string format")
			}
			buf, err := hex.DecodeString(val[2:])
			if err != nil {
				return argErr(i, "[]byte", err.Error())
			}
			dest[i] = buf
		case CHAROID, BPCHAROID, VARCHAROID, TEXTOID,
			INT2OID, INT4OID, INT8OID, OIDOID, XIDOID,
			FLOAT8OID, FLOAT4OID,
			DATEOID, TIMEOID, TIMESTAMPOID, TIMESTAMPTZOID, INTERVALOID, TIMETZOID,
			NUMERICOID:
			dest[i] = val
		default:
			return errors.New(fmt.Sprintf("unsupported type oid: %d", vtype))
		}
	}
	return nil
}
Exemple #4
0
func next(r *PgRows, dest []driver.Value) error {
	if r.cur >= int(C.PQntuples(r.result)) {
		return io.EOF
	}

	// TODO: cache oids
	// TODO: extendibility
	for i := 0; i < len(dest); i++ {
		if 0 == int(C.PQgetisnull(r.result, C.int(r.cur), C.int(i))) {
			oid := int(C.PQftype(r.result, C.int(i)))
			data := C.PQgetvalue(r.result, C.int(r.cur), C.int(i))
			length := C.PQgetlength(r.result, C.int(r.cur), C.int(i))
			var err error
			dest[i], err = typecast(oid, data, length, r)
			if err != nil {
				return err
			}
		} else {
			dest[i] = nil
		}
	}
	r.cur++
	return nil
}