Skip to content

Execute as #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (db *Db) Keyspace(keyspace string) (*gocql.KeyspaceMetadata, error) {

// Keyspaces Retrieves all the keyspace names
func (db *Db) Keyspaces() ([]string, error) {
iter := db.session.ExecuteIterSimple("SELECT keyspace_name FROM system_schema.keyspaces", gocql.One)
iter := db.session.ExecuteIter("SELECT keyspace_name FROM system_schema.keyspaces", nil)

var keyspaces []string

Expand Down
60 changes: 39 additions & 21 deletions db/db_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,33 @@ package db

import "github.com/gocql/gocql"

func (db *Db) Execute(query string, consistency gocql.Consistency, values ...interface{}) ResultIterator {
return db.session.ExecuteIter(query, consistency, values...)
type QueryOptions struct {
UserOrRole string
Consistency gocql.Consistency
}

func (db *Db) ExecuteNoResult(query string, consistency gocql.Consistency, values ...interface{}) error {
return db.session.Execute(query, consistency, values)
func NewQueryOptions() *QueryOptions {
return &QueryOptions{
Consistency: gocql.LocalOne,
}
}

type DbSession interface {
// Execute executes a prepared statement without returning row results
Execute(query string, consistency gocql.Consistency, values ...interface{}) error
func (q *QueryOptions) WithUserOrRole(userOrRole string) *QueryOptions {
q.UserOrRole = userOrRole
return q
}

// Execute executes a simple statement without returning row results
ExecuteSimple(query string, consistency gocql.Consistency, values ...interface{}) error
func (q *QueryOptions) WithConsistency(userOrRole string) *QueryOptions {
q.UserOrRole = userOrRole
return q
}

// ExecuteIter executes a prepared statement and returns iterator to the result set
ExecuteIter(query string, consistency gocql.Consistency, values ...interface{}) ResultIterator
type DbSession interface {
// Execute executes a statement without returning row results
Execute(query string, options *QueryOptions, values ...interface{}) error

// ExecuteIterSimple executes a simple statement and returns iterator to the result set
ExecuteIterSimple(query string, consistency gocql.Consistency, values ...interface{}) ResultIterator
// ExecuteIterSimple executes a statement and returns iterator to the result set
ExecuteIter(query string, options *QueryOptions, values ...interface{}) ResultIterator

//TODO: Extract metadata methods from interface into another interface
KeyspaceMetadata(keyspaceName string) (*gocql.KeyspaceMetadata, error)
Expand All @@ -40,21 +47,32 @@ type GoCqlSession struct {
ref *gocql.Session
}

func (session *GoCqlSession) Execute(query string, consistency gocql.Consistency, values ...interface{}) error {
return session.ref.Query(query).Bind(values...).Consistency(consistency).Exec()
func (db *Db) Execute(query string, options *QueryOptions, values ...interface{}) ResultIterator {
return db.session.ExecuteIter(query, options, values...)
}

func (session *GoCqlSession) ExecuteSimple(query string, consistency gocql.Consistency, values ...interface{}) error {
return session.ref.Query(query, values...).Consistency(consistency).Exec()
func (db *Db) ExecuteNoResult(query string, options* QueryOptions, values ...interface{}) error {
return db.session.Execute(query, options, values)
}

func (session *GoCqlSession) ExecuteIter(query string, consistency gocql.Consistency, values ...interface{}) ResultIterator {
return session.ref.Query(query).Bind(values...).Consistency(consistency).Iter()
func (session *GoCqlSession) Execute(query string, options *QueryOptions, values ...interface{}) error {
return session.ExecuteIter(query, options, values...).Close()
}

func (session *GoCqlSession) ExecuteIterSimple(query string, consistency gocql.Consistency, values ...interface{}) ResultIterator {
return session.ref.Query(query, values...).Consistency(consistency).Iter()
func (session *GoCqlSession) ExecuteIter(query string, options *QueryOptions, values ...interface{}) ResultIterator {
q := session.ref.Query(query, values)
if options != nil {
q.Consistency(options.Consistency)
if options.UserOrRole != "" {
q.CustomPayload(map[string][]byte {
"ProxyExecute": []byte(options.UserOrRole),
})
}
}
return session.ref.Query(query, values).Iter()
}

func (session *GoCqlSession) KeyspaceMetadata(keyspaceName string) (*gocql.KeyspaceMetadata, error) {
return session.ref.KeyspaceMetadata(keyspaceName)
}

9 changes: 4 additions & 5 deletions db/keyspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package db

import (
"fmt"
"github.com/gocql/gocql"
)

func (db *Db) CreateKeyspace(name string, dcReplicas map[string]int) (bool, error) {
func (db *Db) CreateKeyspace(name string, dcReplicas map[string]int, options *QueryOptions) (bool, error) {
// TODO: Escape keyspace datacenter names?
dcs := ""
for name, replicas := range dcReplicas {
Expand All @@ -18,15 +17,15 @@ func (db *Db) CreateKeyspace(name string, dcReplicas map[string]int) (bool, erro

query := fmt.Sprintf("CREATE KEYSPACE %s WITH REPLICATION = { 'class': 'NetworkTopologyStrategy', %s }", name, dcs)

err := db.session.ExecuteSimple(query, gocql.Any)
err := db.session.Execute(query, options)

return err == nil, err
}

func (db *Db) DropKeyspace(name string) (bool, error) {
func (db *Db) DropKeyspace(name string, options *QueryOptions) (bool, error) {
// TODO: Escape keyspace name?
query := fmt.Sprintf("DROP KEYSPACE %s", name)
err := db.session.ExecuteSimple(query, gocql.Any)
err := db.session.Execute(query, options)

return err == nil, err
}
47 changes: 31 additions & 16 deletions db/query_generators.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,24 @@ type SelectInfo struct {
OrderBy []ColumnOrder
}

type InsertInfo struct {
Keyspace string
Table string
Columns []string
QueryParams []interface{}
IfNotExists bool
TTL int
}

type DeleteInfo struct {
Keyspace string
Table string
Columns []string
QueryParams []interface{}
IfCondition map[string]interface{}
IfExists bool
}

type ColumnOrder struct {
Column string
Order string
Expand Down Expand Up @@ -74,7 +92,7 @@ func mapScan(scanner gocql.Scanner, columns []gocql.ColumnInfo) (map[string]inte
return mapped, nil
}

func (db *Db) Select(info *SelectInfo) (*types.QueryResult, error) {
func (db *Db) Select(info *SelectInfo, options *QueryOptions) (*types.QueryResult, error) {
values := make([]interface{}, 0, len(info.Columns))
whereClause := ""
for i := 0; i < len(info.Columns); i++ {
Expand Down Expand Up @@ -104,7 +122,7 @@ func (db *Db) Select(info *SelectInfo) (*types.QueryResult, error) {
}
}

iter := db.session.ExecuteIter(query, gocql.LocalOne, values...)
iter := db.session.ExecuteIter(query, options, values...)

pageState := hex.EncodeToString(iter.PageState())
columns := iter.Columns()
Expand All @@ -130,38 +148,35 @@ func (db *Db) Select(info *SelectInfo) (*types.QueryResult, error) {
}, nil
}

func (db *Db) Insert(ksName string, tableName string, columnNames []string,
queryParams []interface{}, ifNotExists bool, ttl int) (*types.ModificationResult, error) {
func (db *Db) Insert(info *InsertInfo, options *QueryOptions) (*types.ModificationResult, error) {

placeholders := "?"
for i := 1; i < len(columnNames); i++ {
for i := 1; i < len(info.Columns); i++ {
placeholders += ", ?"
}

query := fmt.Sprintf(
"INSERT INTO %s.%s (%s) VALUES (%s)",
ksName, tableName, strings.Join(columnNames, ","), placeholders)
info.Keyspace, info.Table, strings.Join(info.Columns, ","), placeholders)

if ifNotExists {
if info.IfNotExists {
query += " IF NOT EXISTS"
}

if ttl >= 0 {
if info.TTL >= 0 {
query += " USING TTL ?"
queryParams = append(queryParams, ttl)
info.QueryParams = append(info.QueryParams, info.TTL)
}

err := db.session.Execute(query, gocql.LocalOne, queryParams...)
err := db.session.Execute(query, options, info.QueryParams...)

return &types.ModificationResult{Applied: err == nil}, err
}

func (db *Db) Delete(ksName string, tableName string, columnNames []string, queryParams []interface{},
ifCondition map[string]interface{}, ifExists bool) (*types.ModificationResult, error) {

whereClause := buildWhereClause(columnNames)
query := fmt.Sprintf("DELETE FROM %s.%s WHERE %s", ksName, tableName, whereClause)
err := db.session.Execute(query, gocql.LocalOne, queryParams...)
func (db *Db) Delete(info *DeleteInfo, options *QueryOptions) (*types.ModificationResult, error) {
whereClause := buildWhereClause(info.Columns)
query := fmt.Sprintf("DELETE FROM %s.%s WHERE %s", info.Keyspace, info.Table, whereClause)
err := db.session.Execute(query, options, info.QueryParams...)
return &types.ModificationResult{Applied: err == nil}, err
}

Expand Down
23 changes: 9 additions & 14 deletions db/query_generators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ func TestDeleteGeneration(t *testing.T) {
}

for _, item := range items {
_, err := db.Delete("ks1", "tbl1", item.columnNames, item.queryParams, nil, false)
_, err := db.Delete(&DeleteInfo{
Keyspace: "ks1",
Table: "tbl1",
Columns: item.columnNames,
QueryParams: item.queryParams}, nil)
assert.Nil(t, err)
sessionMock.AssertCalled(t, "Execute", item.query, consistency, item.queryParams)
}
Expand All @@ -47,11 +51,11 @@ func TestSelectGeneration(t *testing.T) {
//items := []struct {
// columnNames []string
// values []types.OperatorAndValue
// options *types.QueryOptions
// options *types.ExecuteOptions
// orderBy []ColumnOrder
// query string
//}{
// {[]string{"a"}, []types.OperatorAndValue{{"=", 1}}, &types.QueryOptions{}, nil,
// {[]string{"a"}, []types.OperatorAndValue{{"=", 1}}, &types.ExecuteOptions{}, nil,
// "SELECT * FROM ks1.tbl1 WHERE a = ?"},
//}
//
Expand Down Expand Up @@ -81,21 +85,12 @@ type SessionMock struct {
mock.Mock
}

func (o *SessionMock) Execute(query string, consistency gocql.Consistency, values ...interface{}) error {
func (o *SessionMock) Execute(query string, options *QueryOptions, values ...interface{}) error {
args := o.Called(query, consistency, values)
return args.Error(0)
}

func (o *SessionMock) ExecuteSimple(query string, consistency gocql.Consistency, values ...interface{}) error {
args := o.Called(query, consistency, values)
return args.Error(0)
}

func (o *SessionMock) ExecuteIter(query string, consistency gocql.Consistency, values ...interface{}) ResultIterator {
return nil
}

func (o *SessionMock) ExecuteIterSimple(query string, consistency gocql.Consistency, values ...interface{}) ResultIterator {
func (o *SessionMock) ExecuteIter(query string, options *QueryOptions, values ...interface{}) ResultIterator {
return nil
}

Expand Down
39 changes: 25 additions & 14 deletions db/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,37 @@ import (
"github.com/gocql/gocql"
)

func (db *Db) CreateTable(
ksName string, name string, partitionKeys []*gocql.ColumnMetadata,
clusteringKeys []*gocql.ColumnMetadata, values []*gocql.ColumnMetadata) error {
type CreateTableInfo struct {
Keyspace string
Table string
PartitionKeys []*gocql.ColumnMetadata
ClusteringKeys []*gocql.ColumnMetadata
Values []*gocql.ColumnMetadata
}

type DropTableInfo struct {
Keyspace string
Table string
}

func (db *Db) CreateTable(info* CreateTableInfo, options *QueryOptions) (bool, error) {

columns := ""
primaryKeys := ""
clusteringOrder := ""

for _, c := range partitionKeys {
for _, c := range info.PartitionKeys {
columns += fmt.Sprintf("%s %s, ", c.Name, c.Type)
if len(primaryKeys) > 0 {
primaryKeys += ", "
}
primaryKeys += c.Name
}

if clusteringKeys != nil {
if info.ClusteringKeys != nil {
primaryKeys = fmt.Sprintf("(%s)", primaryKeys)

for _, c := range clusteringKeys {
for _, c := range info.ClusteringKeys {
columns += fmt.Sprintf("%s %s, ", c.Name, c.Type)
primaryKeys += fmt.Sprintf(", %s", c.Name)
if len(clusteringOrder) > 0 {
Expand All @@ -38,25 +49,25 @@ func (db *Db) CreateTable(
}
}

if values != nil {
for _, c := range values {
if info.Values != nil {
for _, c := range info.Values {
columns += fmt.Sprintf("%s %s, ", c.Name, c.Type)
}
}

query := fmt.Sprintf("CREATE TABLE %s.%s (%sPRIMARY KEY (%s))", ksName, name, columns, primaryKeys)
query := fmt.Sprintf("CREATE TABLE %s.%s (%sPRIMARY KEY (%s))", info.Keyspace, info.Table, columns, primaryKeys)

if clusteringOrder != "" {
query += fmt.Sprintf(" WITH CLUSTERING ORDER BY (%s)", clusteringOrder)
}

return db.session.ExecuteSimple(query, gocql.Any)
err := db.session.Execute(query, options)
return err == nil, err
}

func (db *Db) DropTable(ksName string, tableName string) (bool, error) {
func (db *Db) DropTable(info* DropTableInfo, options *QueryOptions) (bool, error) {
// TODO: Escape keyspace/table name?
query := fmt.Sprintf("DROP TABLE %s.%s", ksName, tableName)
err := db.session.ExecuteSimple(query, gocql.Any)

query := fmt.Sprintf("DROP TABLE %s.%s", info.Table, info.Keyspace)
err := db.session.Execute(query, options)
return err == nil, err
}
Loading