<commit_before>package couchbase

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"time"
)

// ViewRow represents a single result from a view.
//
// Doc is present only if include_docs was set on the request.
type ViewRow struct {
	ID    string
	Key   interface{}
	Value interface{}
	Doc   *interface{}
}

// A ViewError is a node-specific error indicating a partial failure
// within a view result.
type ViewError struct {
	From   string
	Reason string
}

func (ve ViewError) Error() string {
	return "Node: " + ve.From + ", reason: " + ve.Reason
}

// ViewResult holds the entire result set from a view request,
// including the rows and the errors.
type ViewResult struct {
	TotalRows int `json:"total_rows"`
	Rows      []ViewRow
	Errors    []ViewError
}

func (b *Bucket) randomBaseURL() (*url.URL, error) {
	nodes := []Node{}
	for _, n := range b.Nodes() {
		if n.Status == "healthy" && n.CouchAPIBase != "" {
			nodes = append(nodes, n)
		}
	}
	if len(nodes) == 0 {
		return nil, errors.New("no available couch rest URLs")
	}
	nodeNo := rand.Intn(len(nodes))
	node := nodes[nodeNo]
	u, err := ParseURL(node.CouchAPIBase)
	if err != nil {
		return nil, fmt.Errorf("config error: Bucket %q node #%d CouchAPIBase=%q: %v",
			b.Name, nodeNo, node.CouchAPIBase, err)
	} else if b.pool != nil {
		u.User = b.pool.client.BaseURL.User
	}
	return u, err
}

// DocID is the document ID type for the startkey_docid parameter in
// views.
type DocID string

func qParam(k, v string) string {
	format := `"%s"`
	switch k {
	case "startkey_docid","endkey_docid","stale":
		format = "%s"
	}
	return fmt.Sprintf(format, v)
}

// ViewURL constructs a URL for a view with the given ddoc, view name,
// and parameters.
func (b *Bucket) ViewURL(ddoc, name string,
	params map[string]interface{}) (string, error) {
	u, err := b.randomBaseURL()
	if err != nil {
		return "", err
	}

	values := url.Values{}
	for k, v := range params {
		switch t := v.(type) {
		case DocID:
			values[k] = []string{string(t)}
		case string:
			values[k] = []string{qParam(k, t)}
		case int:
			values[k] = []string{fmt.Sprintf(`%d`, t)}
		case bool:
			values[k] = []string{fmt.Sprintf(`%v`, t)}
		default:
			b, err := json.Marshal(v)
			if err != nil {
				return "", fmt.Errorf("unsupported value-type %T in Query, "+
					"json encoder said %v", t, err)<commit_msg>Running go fmt<commit_after>package couchbase

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"time"
)

// ViewRow represents a single result from a view.
//
// Doc is present only if include_docs was set on the request.
type ViewRow struct {
	ID    string
	Key   interface{}
	Value interface{}
	Doc   *interface{}
}

// A ViewError is a node-specific error indicating a partial failure
// within a view result.
type ViewError struct {
	From   string
	Reason string
}

func (ve ViewError) Error() string {
	return "Node: " + ve.From + ", reason: " + ve.Reason
}

// ViewResult holds the entire result set from a view request,
// including the rows and the errors.
type ViewResult struct {
	TotalRows int `json:"total_rows"`
	Rows      []ViewRow
	Errors    []ViewError
}

func (b *Bucket) randomBaseURL() (*url.URL, error) {
	nodes := []Node{}
	for _, n := range b.Nodes() {
		if n.Status == "healthy" && n.CouchAPIBase != "" {
			nodes = append(nodes, n)
		}
	}
	if len(nodes) == 0 {
		return nil, errors.New("no available couch rest URLs")
	}
	nodeNo := rand.Intn(len(nodes))
	node := nodes[nodeNo]
	u, err := ParseURL(node.CouchAPIBase)
	if err != nil {
		return nil, fmt.Errorf("config error: Bucket %q node #%d CouchAPIBase=%q: %v",
			b.Name, nodeNo, node.CouchAPIBase, err)
	} else if b.pool != nil {
		u.User = b.pool.client.BaseURL.User
	}
	return u, err
}

// DocID is the document ID type for the startkey_docid parameter in
// views.
type DocID string

func qParam(k, v string) string {
	format := `"%s"`
	switch k {
	case "startkey_docid", "endkey_docid", "stale":
		format = "%s"
	}
	return fmt.Sprintf(format, v)
}

// ViewURL constructs a URL for a view with the given ddoc, view name,
// and parameters.
func (b *Bucket) ViewURL(ddoc, name string,
	params map[string]interface{}) (string, error) {
	u, err := b.randomBaseURL()
	if err != nil {
		return "", err
	}

	values := url.Values{}
	for k, v := range params {
		switch t := v.(type) {
		case DocID:
			values[k] = []string{string(t)}
		case string:
			values[k] = []string{qParam(k, t)}
		case int:
			values[k] = []string{fmt.Sprintf(`%d`, t)}
		case bool:
			values[k] = []string{fmt.Sprintf(`%v`, t)}
		default:
			b, err := json.Marshal(v)
			if err != nil {
				return "", fmt.Errorf("unsupported value-type %T in Query, "+
					"json encoder said %v", t, err)
{'fraction_non_alphanumeric': 0.15068205666316895, 'fraction_numerical': 0.0004197271773347324, 'mean_word_length': 3.4007386888273317, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7598321', 'n_tokens_mistral': 1789, 'n_tokens_neox': 1713, 'n_words': 547}