This commit is contained in:
Michał Matczuk
2017-07-28 10:18:38 +02:00
parent 3b3c7087d2
commit 41bb8def2a
12 changed files with 247 additions and 132 deletions

View File

@@ -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 Lt(column string) Cmp {
return Cmp{
op: lt,
@@ -69,6 +74,7 @@ func Lt(column string) Cmp {
}
}
// LtNamed produces column<? with a custom parameter name.
func LtNamed(column, name string) Cmp {
return Cmp{
op: lt,
@@ -77,6 +83,7 @@ func LtNamed(column, name string) Cmp {
}
}
// LtOrEq produces column<=?.
func LtOrEq(column string) Cmp {
return Cmp{
op: leq,
@@ -85,6 +92,7 @@ func LtOrEq(column string) Cmp {
}
}
// LtOrEqNamed produces column<=? with a custom parameter name.
func LtOrEqNamed(column, name string) Cmp {
return Cmp{
op: leq,
@@ -93,6 +101,7 @@ func LtOrEqNamed(column, name string) Cmp {
}
}
// Gt 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,

View File

@@ -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

4
qb/doc.go Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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