From 41bb8def2a608b61c6962005f28cc0cb5f6e2af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Matczuk?= Date: Fri, 28 Jul 2017 10:18:38 +0200 Subject: [PATCH] qb: doc --- README.md | 89 +++++++++++++++++------------- doc.go | 35 +----------- example_test.go | 141 ++++++++++++++++++++++++++++++++++-------------- qb/cmp.go | 16 ++++++ qb/delete.go | 10 +++- qb/doc.go | 4 ++ qb/insert.go | 9 +++- qb/qb.go | 2 +- qb/select.go | 23 ++++++-- qb/update.go | 19 ++++--- queryx.go | 26 ++++++--- queryx_test.go | 5 +- 12 files changed, 247 insertions(+), 132 deletions(-) create mode 100644 qb/doc.go diff --git a/README.md b/README.md index 027d224..3f5b6cf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # gocqlx [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/scylladb/gocqlx) [![Go Report Card](https://goreportcard.com/badge/github.com/scylladb/gocqlx)](https://goreportcard.com/report/github.com/scylladb/gocqlx) [![Build Status](https://travis-ci.org/scylladb/gocqlx.svg?branch=master)](https://travis-ci.org/scylladb/gocqlx) -Package `gocqlx` is a `gocql` extension, similar to what `sqlx` is to `database/sql`. +Package `gocqlx` is a Scylla / Cassandra productivity toolkit for `gocql`, it's +similar to what `sqlx` is to `database/sql`. It contains wrappers over `gocql` types that provide convenience methods which are useful in the development of database driven applications. Under the @@ -12,43 +13,59 @@ hood it uses `sqlx/reflectx` package so `sqlx` models will also work with `gocql ## Features -Read all rows into a slice. +Fast, boilerplate free and flexible `SELECTS`, `INSERTS`, `UPDATES` and `DELETES`. ```go -var v []*Item -if err := gocqlx.Select(&v, session.Query(`SELECT * FROM items WHERE id = ?`, id)); err != nil { - log.Fatal("select failed", err) +type Person struct { + FirstName string // no need to add `db:"first_name"` etc. + LastName string + Email []string +} + +p := &Person{ + "Patricia", + "Citizen", + []string{"patricia.citzen@gocqlx_test.com"}, +} + +// Insert +{ + q := Query(qb.Insert("person").Columns("first_name", "last_name", "email").ToCql()) + if err := q.BindStruct(p); err != nil { + t.Fatal("bind:", err) + } + mustExec(q.Query) +} + +// Update +{ + p.Email = append(p.Email, "patricia1.citzen@gocqlx_test.com") + + q := Query(qb.Update("person").Set("email").Where(qb.Eq("first_name"), qb.Eq("last_name")).ToCql()) + if err := q.BindStruct(p); err != nil { + t.Fatal("bind:", err) + } + mustExec(q.Query) +} + +// Select +{ + q := Query(qb.Select("person").Where(qb.In("first_name")).ToCql()) + m := map[string]interface{}{ + "first_name": []string{"Patricia", "John"}, + } + if err := q.BindMap(m); err != nil { + t.Fatal("bind:", err) + } + + var people []Person + if err := gocqlx.Select(&people, q.Query); err != nil { + t.Fatal(err) + } + t.Log(people) + + // [{Patricia Citizen [patricia.citzen@gocqlx_test.com patricia1.citzen@gocqlx_test.com]} {John Doe [johndoeDNE@gmail.net]}] } ``` -Read a single row into a struct. - -```go -var v Item -if err := gocqlx.Get(&v, session.Query(`SELECT * FROM items WHERE id = ?`, id)); err != nil { - log.Fatal("get failed", err) -} -``` - -Bind named query parameters from a struct or map. - -```go -stmt, names, err := gocqlx.CompileNamedQuery([]byte("INSERT INTO items (id, name) VALUES (:id, :name)")) -if err != nil { - t.Fatal("compile:", err) -} -q := gocqlx.Queryx{ - Query: session.Query(stmt), - Names: names, -} -if err := q.BindStruct(&Item{"id", "name"}); err != nil { - t.Fatal("bind:", err) -} -if err := q.Query.Exec(); err != nil { - log.Fatal("get failed", err) -} -``` - -## Example - -See [example test](https://github.com/scylladb/gocqlx/blob/master/example_test.go). +For more details see [example test](https://github.com/scylladb/gocqlx/blob/master/example_test.go). diff --git a/doc.go b/doc.go index e7d64bf..e411ae0 100644 --- a/doc.go +++ b/doc.go @@ -1,38 +1,7 @@ -// Package gocqlx is a gocql extension, similar to what sqlx is to database/sql. +// Package gocqlx is a Scylla / Cassandra productivity toolkit for `gocql`, it's +// similar to what `sqlx` is to `database/sql`. // // It contains wrappers over gocql types that provide convenience methods which // are useful in the development of database driven applications. Under the // hood it uses sqlx/reflectx package so sqlx models will also work with gocqlx. -// -// Example, read all rows into a slice -// -// var v []*Item -// if err := gocqlx.Select(&v, session.Query(`SELECT * FROM items WHERE id = ?`, id)); err != nil { -// log.Fatal("select failed", err) -// } -// -// Example, read a single row into a struct -// -// var v Item -// if err := gocqlx.Get(&v, session.Query(`SELECT * FROM items WHERE id = ?`, id)); err != nil { -// log.Fatal("get failed", err) -// } -// -// Example, bind named query parameters from a struct or map -// -// stmt, names, err := gocqlx.CompileNamedQuery([]byte("INSERT INTO items (id, name) VALUES (:id, :name)")) -// if err != nil { -// t.Fatal("compile:", err) -// } -// q := gocqlx.Queryx{ -// Query: session.Query(stmt), -// Names: names, -// } -// if err := q.BindStruct(&Item{"id", "name"}); err != nil { -// t.Fatal("bind:", err) -// } -// if err := q.Query.Exec(); err != nil { -// log.Fatal("get failed", err) -// } -// package gocqlx diff --git a/example_test.go b/example_test.go index 403b2c6..50553f4 100644 --- a/example_test.go +++ b/example_test.go @@ -3,11 +3,11 @@ package gocqlx_test import ( - "fmt" "testing" "github.com/gocql/gocql" "github.com/scylladb/gocqlx" + "github.com/scylladb/gocqlx/qb" ) var personSchema = ` @@ -27,7 +27,7 @@ CREATE TABLE gocqlx_test.place ( )` // Field names are converted to camel case by default, no need to add -// `db:"first_name"`, if you want to disable a filed add `db:"-"` tag +// `db:"first_name"`, if you want to disable a filed add `db:"-"` tag. type Person struct { FirstName string LastName string @@ -46,13 +46,15 @@ func TestExample(t *testing.T) { mustExec := func(q *gocql.Query) { if err := q.Exec(); err != nil { - t.Fatal("insert:", q, err) + t.Fatal("query:", q, err) } } - // Fill person table + // Fill person table. { - mustExec(session.Query(personSchema)) + if err := createTable(session, personSchema); err != nil { + t.Fatal("create table:", err) + } q := session.Query("INSERT INTO gocqlx_test.person (first_name, last_name, email) VALUES (?, ?, ?)") mustExec(q.Bind("Jason", "Moiron", []string{"jmoiron@jmoiron.net"})) @@ -60,9 +62,11 @@ func TestExample(t *testing.T) { q.Release() } - // Fill place table + // Fill place table. { - mustExec(session.Query(placeSchema)) + if err := createTable(session, placeSchema); err != nil { + t.Fatal("create table:", err) + } q := session.Query("INSERT INTO gocqlx_test.place (country, city, code) VALUES (?, ?, ?)") mustExec(q.Bind("United States", "New York", 1)) @@ -71,72 +75,131 @@ func TestExample(t *testing.T) { q.Release() } - // Query the database, storing results in a []Person (wrapped in []interface{}) + // Query the database, storing results in a []Person (wrapped in []interface{}). { - people := []Person{} + var people []Person if err := gocqlx.Select(&people, session.Query("SELECT * FROM person")); err != nil { t.Fatal("select:", err) } + t.Log(people) - fmt.Printf("%#v\n%#v\n", people[0], people[1]) - // gocqlx_test.Person{FirstName:"John", LastName:"Doe", Email:[]string{"johndoeDNE@gmail.net"}} - // gocqlx_test.Person{FirstName:"Jason", LastName:"Moiron", Email:[]string{"jmoiron@jmoiron.net"}} + // [{John Doe [johndoeDNE@gmail.net]} {Jason Moiron [jmoiron@jmoiron.net]}] } - // Get a single result, a la QueryRow + // Get a single result. { var jason Person if err := gocqlx.Get(&jason, session.Query("SELECT * FROM person WHERE first_name=?", "Jason")); err != nil { t.Fatal("get:", err) } - fmt.Printf("%#v\n", jason) - // gocqlx_test.Person{FirstName:"Jason", LastName:"Moiron", Email:[]string{"jmoiron@jmoiron.net"}} + t.Log(jason) + + // Jason Moiron [jmoiron@jmoiron.net]} } - // Loop through rows using only one struct + // Loop through rows using only one struct. { var place Place iter := gocqlx.Iter(session.Query("SELECT * FROM place")) for iter.StructScan(&place) { - fmt.Printf("%#v\n", place) + t.Log(place) } if err := iter.Close(); err != nil { t.Fatal("iter:", err) } iter.ReleaseQuery() - // gocqlx_test.Place{Country:"Hong Kong", City:"", TelCode:852} - // gocqlx_test.Place{Country:"United States", City:"New York", TelCode:1} - // gocqlx_test.Place{Country:"Singapore", City:"", TelCode:65} + + // {Hong Kong 852} + // {United States New York 1} + // {Singapore 65} } - // Named queries, using `:name` as the bindvar + // Query builder, using DSL to build queries, using `:name` as the bindvar. { + // helper function for creating session queries + Query := gocqlx.SessionQuery(session) + + p := &Person{ + "Patricia", + "Citizen", + []string{"patricia.citzen@gocqlx_test.com"}, + } + + // Insert + { + q := Query(qb.Insert("person").Columns("first_name", "last_name", "email").ToCql()) + if err := q.BindStruct(p); err != nil { + t.Fatal("bind:", err) + } + mustExec(q.Query) + } + + // Update + { + p.Email = append(p.Email, "patricia1.citzen@gocqlx_test.com") + + q := Query(qb.Update("person").Set("email").Where(qb.Eq("first_name"), qb.Eq("last_name")).ToCql()) + if err := q.BindStruct(p); err != nil { + t.Fatal("bind:", err) + } + mustExec(q.Query) + } + + // Select + { + q := Query(qb.Select("person").Where(qb.In("first_name")).ToCql()) + m := map[string]interface{}{ + "first_name": []string{"Patricia", "John"}, + } + if err := q.BindMap(m); err != nil { + t.Fatal("bind:", err) + } + + var people []Person + if err := gocqlx.Select(&people, q.Query); err != nil { + t.Fatal("select:", err) + } + t.Log(people) + + // [{Patricia Citizen [patricia.citzen@gocqlx_test.com patricia1.citzen@gocqlx_test.com]} {John Doe [johndoeDNE@gmail.net]}] + } + } + + // Named queries, using `:name` as the bindvar. + { + // compile query to valid gocqlx query and list of named parameters stmt, names, err := gocqlx.CompileNamedQuery([]byte("INSERT INTO person (first_name, last_name, email) VALUES (:first_name, :last_name, :email)")) if err != nil { t.Fatal("compile:", err) } + q := gocqlx.Query(session.Query(stmt), names) - q := gocqlx.Queryx{ - Query: session.Query(stmt), - Names: names, + // bind named parameters from a struct + { + p := &Person{ + "Jane", + "Citizen", + []string{"jane.citzen@gocqlx_test.com"}, + } + + if err := q.BindStruct(p); err != nil { + t.Fatal("bind:", err) + } + mustExec(q.Query) } - if err := q.BindStruct(&Person{ - "Jane", - "Citizen", - []string{"jane.citzen@gocqlx_test.com"}, - }); err != nil { - t.Fatal("bind:", err) - } - mustExec(q.Query) + // bind named parameters from a map + { + m := map[string]interface{}{ + "first_name": "Bin", + "last_name": "Smuth", + "email": []string{"bensmith@allblacks.nz"}, + } - if err := q.BindMap(map[string]interface{}{ - "first_name": "Bin", - "last_name": "Smuth", - "email": []string{"bensmith@allblacks.nz"}, - }); err != nil { - t.Fatal("bind:", err) + if err := q.BindMap(m); err != nil { + t.Fatal("bind:", err) + } + mustExec(q.Query) } - mustExec(q.Query) } } diff --git a/qb/cmp.go b/qb/cmp.go index e1b8c7c..3c7f21e 100644 --- a/qb/cmp.go +++ b/qb/cmp.go @@ -2,6 +2,7 @@ package qb import "bytes" +// op specifies Cmd operation type. type op byte const ( @@ -14,6 +15,7 @@ const ( cnt ) +// Cmp if a filtering comparator that is used in WHERE and IF clauses. type Cmp struct { op op column string @@ -45,6 +47,7 @@ func (cmp Cmp) writeCql(cql *bytes.Buffer) string { return cmp.name } +// Eq produces column=?. func Eq(column string) Cmp { return Cmp{ op: eq, @@ -53,6 +56,7 @@ func Eq(column string) Cmp { } } +// EqNamed produces column=? with a custom parameter name. func EqNamed(column, name string) Cmp { return Cmp{ op: eq, @@ -61,6 +65,7 @@ func EqNamed(column, name string) Cmp { } } +// Lt produces column?. func Gt(column string) Cmp { return Cmp{ op: gt, @@ -101,6 +110,7 @@ func Gt(column string) Cmp { } } +// GtNamed produces column>? with a custom parameter name. func GtNamed(column, name string) Cmp { return Cmp{ op: gt, @@ -109,6 +119,7 @@ func GtNamed(column, name string) Cmp { } } +// GtOrEq produces column>=?. func GtOrEq(column string) Cmp { return Cmp{ op: geq, @@ -117,6 +128,7 @@ func GtOrEq(column string) Cmp { } } +// GtOrEqNamed produces column>=? with a custom parameter name. func GtOrEqNamed(column, name string) Cmp { return Cmp{ op: geq, @@ -125,6 +137,7 @@ func GtOrEqNamed(column, name string) Cmp { } } +// In produces column IN ?. func In(column string) Cmp { return Cmp{ op: in, @@ -133,6 +146,7 @@ func In(column string) Cmp { } } +// InNamed produces column IN ? with a custom parameter name. func InNamed(column, name string) Cmp { return Cmp{ op: in, @@ -141,6 +155,7 @@ func InNamed(column, name string) Cmp { } } +// Contains produces column CONTAINS ?. func Contains(column string) Cmp { return Cmp{ op: cnt, @@ -149,6 +164,7 @@ func Contains(column string) Cmp { } } +// ContainsNamed produces column CONTAINS ? with a custom parameter name. func ContainsNamed(column, name string) Cmp { return Cmp{ op: cnt, diff --git a/qb/delete.go b/qb/delete.go index 45ab123..21c92e1 100644 --- a/qb/delete.go +++ b/qb/delete.go @@ -1,13 +1,14 @@ package qb // DELETE reference: -// http://docs.datastax.com/en/dse/5.1/cql/cql/cql_reference/cql_commands/cqlDelete.html +// https://cassandra.apache.org/doc/latest/cql/dml.html#delete import ( "bytes" "time" ) +// DeleteBuilder builds CQL DELETE statements. type DeleteBuilder struct { table string columns columns @@ -24,6 +25,7 @@ func Delete(table string) *DeleteBuilder { } } +// ToCql builds the query into a CQL string and named args. func (b *DeleteBuilder) ToCql() (stmt string, names []string) { cql := bytes.Buffer{} @@ -61,21 +63,27 @@ func (b *DeleteBuilder) Columns(columns ...string) *DeleteBuilder { return b } +// Timestamp sets a USING TIMESTAMP clause on the query. func (b *DeleteBuilder) Timestamp(t time.Time) *DeleteBuilder { b.using.timestamp = t return b } +// Where adds an expression to the WHERE clause of the query. Expressions are +// ANDed together in the generated CQL. func (b *DeleteBuilder) Where(w ...Cmp) *DeleteBuilder { b.where = append(b.where, w...) return b } +// If adds an expression to the IF clause of the query. Expressions are ANDed +// together in the generated CQL. func (b *DeleteBuilder) If(w ...Cmp) *DeleteBuilder { b._if = append(b._if, w...) return b } +// Existing sets a IF EXISTS clause on the query. func (b *DeleteBuilder) Existing() *DeleteBuilder { b.exists = true return b diff --git a/qb/doc.go b/qb/doc.go new file mode 100644 index 0000000..ee4b830 --- /dev/null +++ b/qb/doc.go @@ -0,0 +1,4 @@ +// Package qb provides CQL (Scylla / Cassandra query language) query builders. +// The builders create CQL statement and a list of named parameters that can +// later be bound using github.com/scylladb/gocqlx. +package qb diff --git a/qb/insert.go b/qb/insert.go index 2b31bb6..86a98a3 100644 --- a/qb/insert.go +++ b/qb/insert.go @@ -1,13 +1,14 @@ package qb // INSERT reference: -// http://docs.datastax.com/en/dse/5.1/cql/cql/cql_reference/cql_commands/cqlInsert.html +// https://cassandra.apache.org/doc/latest/cql/dml.html#insert import ( "bytes" "time" ) +// InsertBuilder builds CQL INSERT statements. type InsertBuilder struct { table string columns columns @@ -22,6 +23,7 @@ func Insert(table string) *InsertBuilder { } } +// ToCql builds the query into a CQL string and named args. func (b *InsertBuilder) ToCql() (stmt string, names []string) { cql := bytes.Buffer{} @@ -49,26 +51,31 @@ func (b *InsertBuilder) ToCql() (stmt string, names []string) { return } +// Into sets the INTO clause of the query. func (b *InsertBuilder) Into(table string) *InsertBuilder { b.table = table return b } +// Columns adds insert columns to the query. func (b *InsertBuilder) Columns(columns ...string) *InsertBuilder { b.columns = append(b.columns, columns...) return b } +// Unique sets a IF NOT EXISTS clause on the query. func (b *InsertBuilder) Unique() *InsertBuilder { b.unique = true return b } +// Timestamp sets a USING TIMESTAMP clause on the query. func (b *InsertBuilder) Timestamp(t time.Time) *InsertBuilder { b.using.timestamp = t return b } +// TTL sets a USING TTL clause on the query. func (b *InsertBuilder) TTL(d time.Duration) *InsertBuilder { b.using.ttl = d return b diff --git a/qb/qb.go b/qb/qb.go index 00f690a..ed05c7c 100644 --- a/qb/qb.go +++ b/qb/qb.go @@ -4,4 +4,4 @@ package qb type Builder interface { // ToCql builds the query into a CQL string and named args. ToCql() (stmt string, names []string) -} \ No newline at end of file +} diff --git a/qb/select.go b/qb/select.go index 7e3c03f..7721a72 100644 --- a/qb/select.go +++ b/qb/select.go @@ -1,20 +1,24 @@ package qb // SELECT reference: -// http://docs.datastax.com/en/dse/5.1/cql/cql/cql_reference/cql_commands/cqlSelect.html +// https://cassandra.apache.org/doc/latest/cql/dml.html#select import ( "bytes" "fmt" ) +// Order specifies sorting order. type Order bool const ( - ASC Order = true - DESC = false + // ASC is ascending order + ASC Order = true + // DESC is descending order + DESC = false ) +// SelectBuilder builds CQL SELECT statements. type SelectBuilder struct { table string columns columns @@ -35,6 +39,7 @@ func Select(table string) *SelectBuilder { } } +// ToCql builds the query into a CQL string and named args. func (b *SelectBuilder) ToCql() (stmt string, names []string) { cql := bytes.Buffer{} @@ -100,16 +105,20 @@ func (b *SelectBuilder) From(table string) *SelectBuilder { return b } +// Columns adds result columns to the query. func (b *SelectBuilder) Columns(columns ...string) *SelectBuilder { b.columns = append(b.columns, columns...) return b } -func (b *SelectBuilder) Distinct(columns... string) *SelectBuilder { +// Distinct sets DISTINCT clause on the query. +func (b *SelectBuilder) Distinct(columns ...string) *SelectBuilder { b.distinct = append(b.distinct, columns...) return b } +// Where adds an expression to the WHERE clause of the query. Expressions are +// ANDed together in the generated CQL. func (b *SelectBuilder) Where(w ...Cmp) *SelectBuilder { b.where = append(b.where, w...) return b @@ -117,26 +126,30 @@ func (b *SelectBuilder) Where(w ...Cmp) *SelectBuilder { // GroupBy sets GROUP BY clause on the query. Columns must be a primary key, // this will automatically add the the columns as first selectors. -func (b *SelectBuilder) GroupBy(columns... string) *SelectBuilder { +func (b *SelectBuilder) GroupBy(columns ...string) *SelectBuilder { b.groupBy = append(b.groupBy, columns...) return b } +// OrderBy sets ORDER BY clause on the query. func (b *SelectBuilder) OrderBy(column string, o Order) *SelectBuilder { b.orderBy, b.order = column, o return b } +// Limit sets a LIMIT clause on the query. func (b *SelectBuilder) Limit(limit uint) *SelectBuilder { b.limit = limit return b } +// LimitPerPartition sets a PER PARTITION LIMIT clause on the query. func (b *SelectBuilder) LimitPerPartition(limit uint) *SelectBuilder { b.limitPerPartition = limit return b } +// AllowFiltering sets a ALLOW FILTERING clause on the query. func (b *SelectBuilder) AllowFiltering() *SelectBuilder { b.allowFiltering = true return b diff --git a/qb/update.go b/qb/update.go index 14c3294..4fd433c 100644 --- a/qb/update.go +++ b/qb/update.go @@ -1,16 +1,14 @@ package qb +// UPDATE reference: +// https://cassandra.apache.org/doc/latest/cql/dml.html#update + import ( "bytes" -) - -// UPDATE reference: -// http://docs.datastax.com/en/dse/5.1/cql/cql/cql_reference/cql_commands/cqlUpdate.html - -import ( "time" ) +// UpdateBuilder builds CQL UPDATE statements. type UpdateBuilder struct { table string using using @@ -27,6 +25,7 @@ func Update(table string) *UpdateBuilder { } } +// ToCql builds the query into a CQL string and named args. func (b *UpdateBuilder) ToCql() (stmt string, names []string) { cql := bytes.Buffer{} @@ -64,31 +63,39 @@ func (b *UpdateBuilder) Table(table string) *UpdateBuilder { return b } +// Timestamp sets a USING TIMESTAMP clause on the query. func (b *UpdateBuilder) Timestamp(t time.Time) *UpdateBuilder { b.using.timestamp = t return b } +// TTL sets a USING TTL clause on the query. func (b *UpdateBuilder) TTL(d time.Duration) *UpdateBuilder { b.using.ttl = d return b } +// Set adds SET clauses to the query. func (b *UpdateBuilder) Set(columns ...string) *UpdateBuilder { b.columns = append(b.columns, columns...) return b } +// Where adds an expression to the WHERE clause of the query. Expressions are +// ANDed together in the generated CQL. func (b *UpdateBuilder) Where(w ...Cmp) *UpdateBuilder { b.where = append(b.where, w...) return b } +// If adds an expression to the IF clause of the query. Expressions are ANDed +// together in the generated CQL. func (b *UpdateBuilder) If(w ...Cmp) *UpdateBuilder { b._if = append(b._if, w...) return b } +// Existing sets a IF EXISTS clause on the query. func (b *UpdateBuilder) Existing() *UpdateBuilder { b.exists = true return b diff --git a/queryx.go b/queryx.go index 557aff0..d7e7da0 100644 --- a/queryx.go +++ b/queryx.go @@ -82,14 +82,18 @@ type Queryx struct { Mapper *reflectx.Mapper } +// Query creates a new Queryx from gocql.Query using a default mapper. +func Query(q *gocql.Query, names []string) Queryx { + return Queryx{ + Query: q, + Names: names, + Mapper: DefaultMapper, + } +} + // BindStruct binds query named parameters using mapper. func (q Queryx) BindStruct(arg interface{}) error { - m := q.Mapper - if m == nil { - m = DefaultMapper - } - - arglist, err := bindStructArgs(q.Names, arg, m) + arglist, err := bindStructArgs(q.Names, arg, q.Mapper) if err != nil { return err } @@ -144,3 +148,13 @@ func bindMapArgs(names []string, arg map[string]interface{}) ([]interface{}, err } return arglist, nil } + +// QueryFunc creates Queryx from qb.Builder.ToCql() output. +type QueryFunc func(stmt string, names []string) Queryx + +// SessionQuery creates QueryFunc that's session aware. +func SessionQuery(session *gocql.Session) QueryFunc { + return func(stmt string, names []string) Queryx { + return Query(session.Query(stmt), names) + } +} diff --git a/queryx_test.go b/queryx_test.go index 7b9afa7..3130219 100644 --- a/queryx_test.go +++ b/queryx_test.go @@ -101,10 +101,7 @@ func TestBindStruct(t *testing.T) { } func BenchmarkBindStruct(b *testing.B) { - q := Queryx{ - Query: &gocql.Query{}, - Names: []string{"name", "age", "first", "last"}, - } + q := Query(&gocql.Query{}, []string{"name", "age", "first", "last"}) type t struct { Name string Age int