This library implements the standard go database APIs for database/sql and database/sql/driver.
go get github.com/couchbase/go_n1ql
cd $GOPATH/src/github.com/couchbase/go_n1ql
go get ...
The test code assumes an instance of Couchbase is running on the local machine, and the beer-sample sample bucket is loaded.
From the /go_n1ql directory, run:
go test .
Start
cbq_engine ./cbq_engine -datastore=dir:../../test/json
./example
To use the go_n1ql
driver the following two imports are required
import (
"database/sql"
_ "github.com/couchbase/go_n1ql"
)
The go_n1ql
driver allows you to connect to either a standalone instance of N1QL or
a couchbase cluster endpoint.
n1ql, err := sql.Open("n1ql", "localhost:8093")
n1ql, err := sql.Open("n1ql", "http://localhost:9000/")
The driver will discover the N1QL endpoints in the cluster and connect to one of them.
Various Query options can be set by calling SetQueryParams. See example below
import go_n1ql "github.com/couchbase/go_n1ql"
ac := []byte(`[{"user": "admin:Administrator", "pass": "asdasd"}]`)
go_n1ql.SetQueryParams("creds", ac)
go_n1ql.SetQueryParams("timeout", "10s")
rows, err := n1ql.Query("select * from contacts where contacts.name = \"dave\"")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var contacts string
if err := rows.Scan(&contacts); err != nil {
log.Fatal(err)
}
log.Printf("Row returned %s : \n", contacts)
}
Note that since Couchbase is a document oriented database there are no columns. Each document in the
database is treated as a row. For queries of the form SELECT * FROM bucket
the results will be
returned in a single column. Queries where the result expression is not *
will return the results in
multiple columns.
rows, err := n1ql.Query("select personal_details, shipped_order_history from users_with_orders where doc_type=\"user_profile\" and personal_details.age = 60")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var personal, shipped string
if err := rows.Scan(&personal, &shipped); err != nil {
log.Fatal(err)
}
log.Printf("Row returned personal_details: %s shipped_order_history %s : \n", personal, shipped)
}
Positional parameters are supported by the Queryer/Execer interface and by the Statement (prepared statement) interface
stmt, err := n1ql.Prepare("select personal_details, shipped_order_history from users_with_orders where doc_type=? and personal_details.age = ?")
rows, err = stmt.Query("user_profile", 60)
if err != nil {
log.Fatal(err)
}
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var personal, shipped string
if err := rows.Scan(&personal, &shipped); err != nil {
log.Fatal(err)
}
log.Printf("Row returned personal_details: %s shipped_order_history %s : \n", personal, shipped)
}
DML queries are supported via the Execer and Statment interface. These statements are not expected to return any rows, instead the number of rows mutated/modified will be returned
result, err := n1ql.Exec("Upsert INTO contacts values (\"irish\",{\"name\":\"irish\", \"type\":\"contact\"})")
if err != nil {
log.Fatal(err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
log.Fatal(err)
}
log.Printf("Rows affected %d", rowsAffected)
stmt, err = n1ql.Prepare("Upsert INTO contacts values (?,?)")
if err != nil {
log.Fatal(err)
}
// Map Values need to be marshaled
value, _ := json.Marshal(map[string]interface{}{"name": "irish", "type": "contact"})
result, err = stmt.Exec("irish4", value)
if err != nil {
log.Fatal(err)
}
rowsAffected, err = result.RowsAffected()
if err != nil {
log.Fatal(err)
}
log.Printf("Rows affected %d", rowsAffected)
Any positional values that contain either arrays or maps or any combination thereof
need to be marshalled and passed as type []byte