Permalink
Browse files

fix query composite builder, add GetBetween, more query tests

  • Loading branch information...
1 parent f63f556 commit e452bb275a7dfc06e30cf85f869aa120b4ef0ac1 @carloscm committed May 12, 2012
Showing with 364 additions and 49 deletions.
  1. +2 −2 README.md
  2. +13 −1 schema-test.txt
  3. +2 −2 src/gossie/connection.go
  4. +9 −0 src/gossie/mapping.go
  5. +35 −7 src/gossie/query.go
  6. +301 −35 src/gossie/query_test.go
  7. +2 −2 src/gossie/schema_test.go
View
@@ -42,7 +42,7 @@ Launch a Cassandra instance in localhost:9160, create a keyspace named TestGossi
### Import
-Gossie uses the Go 1.0 packaging conventions. Import Gossie into your code like this:
+Gossie follows the Go 1.0 packaging conventions. Import Gossie into your code like this:
```Go
import (
@@ -105,7 +105,7 @@ err = pool.Writer().Insert("Timeline", row).Run()
When calling NewMapping() you can tag your struct fiels with `name`, `type` and `skip`. The `name` field tag will change the column name to its value when the field it appears on is (un)marhsaled to/from a Cassandra row column. The `type` field tag allows to override the default type Go<->Cassandra type mapping used by Gossie for the field it appears on. If `skip:"true"` is present the field will be ignored by Gossie.
-The tags `kind`, `cf`, `key`, `cols` and `value` can be used in any field in the struct to document a mapping. `kind` is optional and can have a value of `sparse` (the default) or `compact`. See [CQL3.0](http://www.datastax.com/dev/blog/whats-new-in-cql-3-0) for more information. `cf` is the column family name. `key` is the field name in the struct that stores the Cassandra row key value. `cols` is optional and it is a list of struct fiels that build up the composite column name, if there is any. `value` is the field that stores the column value for compact storage rows, and it is ignored in sparse storage rows.
+The tags `mapping`, `cf`, `key`, `cols` and `value` can be used in any field in the struct to document a mapping. `mapping` is optional and can have a value of `sparse` (the default) or `compact`. See [CQL3.0](http://www.datastax.com/dev/blog/whats-new-in-cql-3-0) for more information. `cf` is the column family name. `key` is the field name in the struct that stores the Cassandra row key value. `cols` is optional and it is a list of struct fiels that build up the composite column name, if there is any. `value` is the field that stores the column value for compact storage rows, and it is ignored in sparse storage rows.
### Query and Result
View
@@ -29,12 +29,24 @@ create column family Composite with
default_validation_class = BytesType
;
-create column family Reasonable with
+create column family ReasonableZero with
+ comparator = AsciiType and
+ key_validation_class = UTF8Type and
+ default_validation_class = BytesType
+;
+
+create column family ReasonableOne with
comparator = 'CompositeType(LongType,AsciiType)' and
key_validation_class = UTF8Type and
default_validation_class = BytesType
;
+create column family ReasonableTwo with
+ comparator = 'CompositeType(LongType,LongType,AsciiType)' and
+ key_validation_class = UTF8Type and
+ default_validation_class = BytesType
+;
+
create column family Timeseries with
comparator = 'CompositeType(TimeUUIDType(reversed=true),AsciiType)' and
key_validation_class = UTF8Type and
View
@@ -3,13 +3,13 @@ package gossie
import (
"errors"
"fmt"
+ "github.com/carloscm/gossie/src/cassandra"
+ "github.com/pomack/thrift4go/lib/go/src/thrift"
"math/rand"
"net"
"strconv"
"strings"
"time"
- "github.com/carloscm/gossie/src/cassandra"
- "github.com/pomack/thrift4go/lib/go/src/thrift"
)
/*
View
@@ -19,8 +19,10 @@ type Mapping interface {
// Cf returns the column family name
Cf() string
+ // MarshalKey marshals the passed key value into a []byte
MarshalKey(key interface{}) ([]byte, error)
+ // MarshalComponent marshals the passed component value at the position into a []byte
MarshalComponent(component interface{}, position int) ([]byte, error)
// Map converts a Go object compatible with this Mapping into a Row
@@ -35,9 +37,16 @@ var (
EndAtLimit = errors.New("No more results found but reached the limit")
)
+// RowProvider abstracts the details of reading a series of columns from a Cassandra row
type RowProvider interface {
+
+ // Key returns the row key
Key() []byte
+
+ // NextColumn returns the next column in the row, and advances the column pointer
NextColumn() (*Column, error)
+
+ // Rewind moves back the column pointer one position
Rewind()
}
View
@@ -10,8 +10,6 @@ todo:
autopaging?
- "start slice from here"
-
Search() and interface(s) for indexed get
multiget
@@ -44,6 +42,10 @@ type Query interface {
// comparator and you only specify the key and zero or more comparator
// components the Result will allow you to iterate over the entire row.
Get(key interface{}, components ...interface{}) (Result, error)
+
+ // GetBetween is like Get, but the last two passed components values are
+ // used as the last values for the slice Start and End composite values.
+ GetBetween(key interface{}, components ...interface{}) (Result, error)
}
// Result reads Query results into Go objects, internally buffering them.
@@ -92,7 +94,19 @@ func (q *query) Get(key interface{}, components ...interface{}) (Result, error)
reader.ConsistencyLevel(q.consistencyLevel)
}
- return &result{keyB, reader, q.mapping, q.limit, components, nil, 0}, nil
+ return &result{keyB, reader, q.mapping, q.limit, components, nil, 0, nil}, nil
+}
+
+func (q *query) GetBetween(key interface{}, components ...interface{}) (Result, error) {
+ if len(components) < 2 {
+ return nil, errors.New("GetBetween requires at least 2 component values")
+ }
+ r, err := q.Get(key, components[:len(components)-1]...)
+ if err != nil {
+ return nil, err
+ }
+ r.(*result).between = components[len(components)-1]
+ return r, nil
}
type result struct {
@@ -103,26 +117,40 @@ type result struct {
components []interface{}
row *Row
position int
+ between interface{}
}
func (r *result) Key() []byte {
return r.key
}
func (r *result) buildFixedSlice() error {
+ start := make([]byte, 0)
+ end := make([]byte, 0)
if len(r.components) > 0 {
- start := make([]byte, 0)
- end := make([]byte, 0)
+ last := len(r.components) - 1
for i, c := range r.components {
b, err := r.mapping.MarshalComponent(c, i)
if err != nil {
return err
}
start = append(start, packComposite(b, eocEquals)...)
- end = append(end, packComposite(b, eocGreater)...)
+ if i == last {
+ if r.between != nil {
+ b, err := r.mapping.MarshalComponent(r.between, i)
+ if err != nil {
+ return err
+ }
+ end = append(end, packComposite(b, eocEquals)...)
+ } else {
+ end = append(end, packComposite(b, eocGreater)...)
+ }
+ } else {
+ end = append(end, packComposite(b, eocEquals)...)
+ }
}
- r.reader.Slice(&Slice{Start: start, End: end, Count: r.limit})
}
+ r.reader.Slice(&Slice{Start: start, End: end, Count: r.limit})
return nil
}
Oops, something went wrong.

0 comments on commit e452bb2

Please sign in to comment.