func queryRow()

in xray/sql_context.go [448:517]


func queryRow(ctx context.Context, conn driver.Conn, query string, dest ...*string) error {
	var err error

	// prepare
	var stmt driver.Stmt
	if connCtx, ok := conn.(driver.ConnPrepareContext); ok {
		stmt, err = connCtx.PrepareContext(ctx, query)
	} else {
		stmt, err = conn.Prepare(query)
		if err == nil {
			select {
			default:
			case <-ctx.Done():
				stmt.Close()
				return ctx.Err()
			}
		}
	}
	if err != nil {
		return err
	}
	defer stmt.Close()

	// execute query
	var rows driver.Rows
	if queryCtx, ok := stmt.(driver.StmtQueryContext); ok {
		rows, err = queryCtx.QueryContext(ctx, []driver.NamedValue{})
	} else {
		select {
		default:
		case <-ctx.Done():
			return ctx.Err()
		}
		rows, err = stmt.Query([]driver.Value{})
	}
	if err != nil {
		return err
	}
	defer rows.Close()

	// scan
	if len(dest) != len(rows.Columns()) {
		return fmt.Errorf("xray: expected %d destination arguments in Scan, not %d", len(rows.Columns()), len(dest))
	}
	cols := make([]driver.Value, len(rows.Columns()))
	if err := rows.Next(cols); err != nil {
		return err
	}
	for i, src := range cols {
		d := dest[i]
		switch s := src.(type) {
		case string:
			*d = s
		case []byte:
			*d = string(s)
		case time.Time:
			*d = s.Format(time.RFC3339Nano)
		case int64:
			*d = strconv.FormatInt(s, 10)
		case float64:
			*d = strconv.FormatFloat(s, 'g', -1, 64)
		case bool:
			*d = strconv.FormatBool(s)
		default:
			return fmt.Errorf("sql: Scan error on column index %d, name %q: type missmatch", i, rows.Columns()[i])
		}
	}

	return nil
}