Browse Source

Merge remote-tracking branch 'upstream/master' into expose_query_info

Ben Hood 11 năm trước cách đây
mục cha
commit
80a547fbcd
3 tập tin đã thay đổi với 33 bổ sung14 xóa
  1. 11 8
      cassandra_test.go
  2. 9 2
      conn.go
  3. 13 4
      session.go

+ 11 - 8
cassandra_test.go

@@ -552,6 +552,7 @@ func TestScanCASWithNilArguments(t *testing.T) {
 	}
 }
 
+//TestStaticQueryInfo makes sure that the application can manually bind query parameters using the simplest possible static binding strategy
 func TestStaticQueryInfo(t *testing.T) {
 	session := createSession(t)
 	defer session.Close()
@@ -564,10 +565,10 @@ func TestStaticQueryInfo(t *testing.T) {
 		t.Fatalf("insert into static_query_info failed, err '%v'", err)
 	}
 
-	autobinder := func(q *QueryInfo) []interface{} {
+	autobinder := func(q *QueryInfo) ([]interface{}, error) {
 		values := make([]interface{}, 1)
 		values[0] = 113
-		return values
+		return values, nil
 	}
 
 	qry := session.Bind("SELECT id, value FROM static_query_info WHERE id = ?", autobinder)
@@ -599,7 +600,7 @@ type ClusteredKeyValue struct {
 	Value   string
 }
 
-func (kv *ClusteredKeyValue) Bind(q *QueryInfo) []interface{} {
+func (kv *ClusteredKeyValue) Bind(q *QueryInfo) ([]interface{}, error) {
 	values := make([]interface{}, len(q.args))
 
 	for i, info := range q.args {
@@ -609,7 +610,7 @@ func (kv *ClusteredKeyValue) Bind(q *QueryInfo) []interface{} {
 		values[i] = field.Addr().Interface()
 	}
 
-	return values
+	return values, nil
 }
 
 func upcaseInitial(str string) string {
@@ -619,6 +620,7 @@ func upcaseInitial(str string) string {
 	return ""
 }
 
+//TestBoundQueryInfo makes sure that the application can manually bind query parameters using the query meta data supplied at runtime
 func TestBoundQueryInfo(t *testing.T) {
 
 	session := createSession(t)
@@ -657,6 +659,7 @@ func TestBoundQueryInfo(t *testing.T) {
 
 }
 
+//TestBatchQueryInfo makes sure that the application can manually bind query parameters when executing in a batch
 func TestBatchQueryInfo(t *testing.T) {
 
 	if *flagProto == 1 {
@@ -670,12 +673,12 @@ func TestBatchQueryInfo(t *testing.T) {
 		t.Fatalf("failed to create table with error '%v'", err)
 	}
 
-	write := func(q *QueryInfo) []interface{} {
+	write := func(q *QueryInfo) ([]interface{}, error) {
 		values := make([]interface{}, 3)
 		values[0] = 4000
 		values[1] = 5000
 		values[2] = "bar"
-		return values
+		return values, nil
 	}
 
 	batch := session.NewBatch(LoggedBatch)
@@ -685,11 +688,11 @@ func TestBatchQueryInfo(t *testing.T) {
 		t.Fatalf("batch insert into batch_query_info failed, err '%v'", err)
 	}
 
-	read := func(q *QueryInfo) []interface{} {
+	read := func(q *QueryInfo) ([]interface{}, error) {
 		values := make([]interface{}, 2)
 		values[0] = 4000
 		values[1] = 5000
-		return values
+		return values, nil
 	}
 
 	qry := session.Bind("SELECT id, cluster, value FROM batch_query_info WHERE id = ? and cluster = ?", read)

+ 9 - 2
conn.go

@@ -370,7 +370,10 @@ func (c *Conn) executeQuery(qry *Query) *Iter {
 		if qry.binding == nil {
 			values = qry.values
 		} else {
-			values = qry.binding(info)
+			values, err = qry.binding(info)
+			if err != nil {
+				return &Iter{err: err}
+			}
 		}
 
 		if len(values) != len(info.args) {
@@ -491,7 +494,10 @@ func (c *Conn) executeBatch(batch *Batch) error {
 			if entry.binding == nil {
 				args = entry.Args
 			} else {
-				args = entry.binding(info)
+				args, err = entry.binding(info)
+				if err != nil {
+					return err
+				}
 			}
 
 			if len(args) != len(info.args) {
@@ -640,6 +646,7 @@ func (c *Conn) setKeepalive(d time.Duration) error {
 	return nil
 }
 
+// QueryInfo represents the meta data associated with a prepared CQL statement.
 type QueryInfo struct {
 	id   []byte
 	args []ColumnInfo

+ 13 - 4
session.go

@@ -90,7 +90,13 @@ func (s *Session) Query(stmt string, values ...interface{}) *Query {
 	return qry
 }
 
-func (s *Session) Bind(stmt string, b func(q *QueryInfo) []interface{}) *Query {
+// Bind generates a new query object based on the query statement passed in.
+// The query is automatically prepared if it has not previously been executed.
+// The binding callback allows the application to define which query argument
+// values will be marshalled as part of the query execution.
+// During execution, the meta data of the prepared query will be routed to the
+// binding callback, which is responsible for producing the query argument values.
+func (s *Session) Bind(stmt string, b func(q *QueryInfo) ([]interface{}, error)) *Query {
 	s.mu.RLock()
 	qry := &Query{stmt: stmt, binding: b, cons: s.cons,
 		session: s, pageSize: s.pageSize, trace: s.trace,
@@ -193,7 +199,7 @@ type Query struct {
 	trace     Tracer
 	session   *Session
 	rt        RetryPolicy
-	binding   func(q *QueryInfo) []interface{}
+	binding   func(q *QueryInfo) ([]interface{}, error)
 }
 
 // Consistency sets the consistency level for this query. If no consistency
@@ -405,7 +411,10 @@ func (b *Batch) Query(stmt string, args ...interface{}) {
 	b.Entries = append(b.Entries, BatchEntry{Stmt: stmt, Args: args})
 }
 
-func (b *Batch) Bind(stmt string, bind func(q *QueryInfo) []interface{}) {
+// Bind adds the query to the batch operation and correlates it with a binding callback
+// that will be invoked when the batch is executed. The binding callback allows the application
+// to define which query argument values will be marshalled as part of the batch execution.
+func (b *Batch) Bind(stmt string, bind func(q *QueryInfo) ([]interface{}, error)) {
 	b.Entries = append(b.Entries, BatchEntry{Stmt: stmt, binding: bind})
 }
 
@@ -431,7 +440,7 @@ const (
 type BatchEntry struct {
 	Stmt    string
 	Args    []interface{}
-	binding func(q *QueryInfo) []interface{}
+	binding func(q *QueryInfo) ([]interface{}, error)
 }
 
 type Consistency int