Skip to content

Commit

Permalink
support named query values (apache#971)
Browse files Browse the repository at this point in the history
Add NamedValue to support naming query values
  • Loading branch information
Zariel authored Sep 10, 2017
1 parent 605a5e0 commit 2badfed
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 17 deletions.
22 changes: 22 additions & 0 deletions cassandra_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2695,3 +2695,25 @@ func TestUnsetColBatch(t *testing.T) {
t.Fatalf("expected id, my_int to be 1, got %v and %v", id, mInt)
}
}

func TestQuery_NamedValues(t *testing.T) {
session := createSession(t)
defer session.Close()

if session.cfg.ProtoVersion < 3 {
t.Skip("named Values are not supported in protocol < 3")
}

if err := createTable(session, "CREATE TABLE gocql_test.named_query(id int, value text, PRIMARY KEY (id))"); err != nil {
t.Fatal(err)
}

err := session.Query("INSERT INTO gocql_test.named_query(id, value) VALUES(:id, :value)", NamedValue("id", 1), NamedValue("value", "i am a value")).Exec()
if err != nil {
t.Fatal(err)
}
var value string
if err := session.Query("SELECT VALUE from gocql_test.named_query WHERE id = :id", NamedValue("id", 1)).Scan(&value); err != nil {
t.Fatal(err)
}
}
45 changes: 28 additions & 17 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,26 @@ func (c *Conn) prepareStatement(ctx context.Context, stmt string, tracer Tracer)
return flight.preparedStatment, flight.err
}

func marshalQueryValue(typ TypeInfo, value interface{}, dst *queryValues) error {
if named, ok := value.(*namedValue); ok {
dst.name = named.name
value = named.value
}

if _, ok := value.(unsetColumn); !ok {
val, err := Marshal(typ, value)
if err != nil {
return err
}

dst.value = val
} else {
dst.isUnset = true
}

return nil
}

func (c *Conn) executeQuery(qry *Query) *Iter {
params := queryParams{
consistency: qry.cons,
Expand Down Expand Up @@ -809,17 +829,12 @@ func (c *Conn) executeQuery(qry *Query) *Iter {

params.values = make([]queryValues, len(values))
for i := 0; i < len(values); i++ {
val, err := Marshal(info.request.columns[i].TypeInfo, values[i])
if err != nil {
return &Iter{err: err}
}

v := &params.values[i]
v.value = val
if _, ok := values[i].(unsetColumn); ok {
v.isUnset = true
value := values[i]
typ := info.request.columns[i].TypeInfo
if err := marshalQueryValue(typ, value, v); err != nil {
return &Iter{err: err}
}
// TODO: handle query binding names
}

params.skipMeta = !(c.session.cfg.DisableSkipMetadata || qry.disableSkipMetadata)
Expand Down Expand Up @@ -1009,16 +1024,12 @@ func (c *Conn) executeBatch(batch *Batch) *Iter {
b.values = make([]queryValues, info.request.actualColCount)

for j := 0; j < info.request.actualColCount; j++ {
val, err := Marshal(info.request.columns[j].TypeInfo, values[j])
if err != nil {
v := &b.values[j]
value := values[j]
typ := info.request.columns[j].TypeInfo
if err := marshalQueryValue(typ, value, v); err != nil {
return &Iter{err: err}
}

b.values[j].value = val
if _, ok := values[j].(unsetColumn); ok {
b.values[j].isUnset = true
}
// TODO: add names
}
} else {
b.statement = entry.Stmt
Expand Down
13 changes: 13 additions & 0 deletions frame.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ type unsetColumn struct{}

var UnsetValue = unsetColumn{}

type namedValue struct {
name string
value interface{}
}

// NamedValue produce a value which will bind to the named parameter in a query
func NamedValue(name string, value interface{}) interface{} {
return &namedValue{
name: name,
value: value,
}
}

const (
protoDirectionMask = 0x80
protoVersionMask = 0x7F
Expand Down

0 comments on commit 2badfed

Please sign in to comment.