gocassa

package module
v0.0.0-...-8cd751c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 12, 2015 License: MIT Imports: 13 Imported by: 0

README

gocassa

GoDoc Build Status

Gocassa is a high-level library on top of gocql.

Compared to gocql it provides query building, adds data binding, and provides easy-to-use "recipe" tables for common query use-cases. Unlike cqlc, it does not use code generation.

For docs, see: https://godoc.org/github.com/hailocab/gocassa

Table types

Gocassa provides multiple table types with their own unique interfaces:

  • a raw CQL table called simply Table - this lets you do pretty much any query imaginable
  • and a number of single purpose 'recipe' tables (Map, Multimap, TimeSeries, MultiTimeSeries), which aims to help the user by having a simplified interface tailored to a given common query use case
Table
package main

import(
    "fmt"
    "time"
    
    "github.com/hailocab/gocassa"
)

type Sale struct {
    Id          string
    CustomerId  string
    SellerId    string
    Price       int
    Created     time.Time
}

func main() {
    keySpace, err := gocassa.ConnectToKeySpace("test", []string{"127.0.0.1"}, "", "")
    if err != nil {
        panic(err)
    }
    salesTable := keySpace.Table("sale", Sale{}, gocassa.Keys{
        PartitionKeys: []string{"Id"},
    })

    err = salesTable.Set(Sale{
        Id: "sale-1",
        CustomerId: "customer-1",
        SellerId: "seller-1",
        Price: 42,
        Created: time.Now(),
    }).Run()
    if err != nil {
        panic(err)
    }

    result := Sale{}
    if err := salesTable.Where(gocassa.Eq("Id", "sale-1")).ReadOne(&result).Run(); err != nil {
        panic(err)
    }
    fmt.Println(result)
}

link to this example

MapTable

MapTable provides only very simple CRUD functionality:

    // …
    salesTable := keySpace.MapTable("sale", "Id", Sale{})
    result := Sale{}
    salesTable.Read("sale-1", &result).Run()
}

link to this example

Read, Set, Update, and Delete all happen by "Id".

MultimapTable

MultimapTable can list rows filtered by equality of a single field (eg. list sales based on their sellerId):

    salesTable := keySpace.MultimapTable("sale", "SellerId", "Id", Sale{})
    // …
    results := []Sale{}
    err := salesTable.List("seller-1", nil, 0, &results).Run()

link to this example

For examples on how to do pagination or Update with this table, refer to the example (linked under code snippet).

TimeSeriesTable

TimeSeriesTable provides an interface to list rows within a time interval:

    salesTable := keySpace.TimeSeriesTable("sale", "Created", "Id", Sale{})
    //...
    results := []Sale{}
    err := salesTable.List(yesterdayTime, todayTime, &results).Run()
MultiTimeSeriesTable

MultiTimeSeriesTable is like a cross between MultimapTable and TimeSeriesTable. It can list rows within a time interval, and filtered by equality of a single field. The following lists sales in a time interval, by a certain seller:

    salesTable := keySpace.MultiTimeSeriesTable("sale", "SellerId", "Created", "Id", Sale{})
    //...
    results := []Sale{}
    err := salesTable.List("seller-1", yesterdayTime, todayTime, &results).Run()

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Connection

type Connection interface {
	CreateKeySpace(name string) error
	DropKeySpace(name string) error
	KeySpace(name string) KeySpace
}

Connection exists because one can not connect to a keyspace if it does not exist, thus having a Create on KeySpace is not possible. Use ConnectToKeySpace to acquire an instance of KeySpace without getting a Connection.

func Connect

func Connect(nodeIps []string, username, password string) (Connection, error)

Connect to a cluster.

func NewConnection

func NewConnection(q QueryExecutor) Connection

NewConnection creates a Connection with a custom query executor. This is mostly useful for testing/mocking purposes. Use `Connect` if you just want to talk to Cassandra.

type Counter

type Counter int

type Filter

type Filter interface {
	// Updates does a partial update. Use this if you don't want to overwrite your whole row, but you want to modify fields atomically.
	Update(m map[string]interface{}) Op // Probably this is danger zone (can't be implemented efficiently) on a selectuinb with more than 1 document
	// Delete all rows matching the filter.
	Delete() Op
	// Read the results. Make sure you pass in a pointer to a slice.
	Read(pointerToASlice interface{}) Op
	// Read one result. Make sure you pass in a pointer.
	ReadOne(pointer interface{}) Op
}

Filter is a subset of a Table, filtered by Relations. You can do writes or reads on a filter.

type KeySpace

type KeySpace interface {
	MapTable(tableName, id string, row interface{}) MapTable
	MultimapTable(tableName, fieldToIndexBy, uniqueKey string, row interface{}) MultimapTable
	TimeSeriesTable(tableName, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) TimeSeriesTable
	MultiTimeSeriesTable(tableName, fieldToIndexByField, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) MultiTimeSeriesTable
	Table(tableName string, row interface{}, keys Keys) Table
	// DebugMode enables/disables debug mode depending on the value of the input boolean.
	// When DebugMode is enabled, all built CQL statements are printe to stdout.
	DebugMode(bool)
	// Name returns the keyspace name as in C*
	Name() string
	// Tables returns the name of all configured column families in this keyspace
	Tables() ([]string, error)
	// Exists returns whether the specified column family exists within the keyspace
	Exists(string) (bool, error)
}

KeySpace is used to obtain tables from.

func ConnectToKeySpace

func ConnectToKeySpace(keySpace string, nodeIps []string, username, password string) (KeySpace, error)

Connect to a certain keyspace directly. Same as using Connect().KeySpace(keySpaceName)

func NewMockKeySpace

func NewMockKeySpace() KeySpace

type Keys

type Keys struct {
	PartitionKeys     []string
	ClusteringColumns []string
}

Keys is used with the raw CQL Table type. It is implicit when using recipe tables.

type MapTable

type MapTable interface {
	Set(v interface{}) Op
	Update(id interface{}, m map[string]interface{}) Op
	Delete(id interface{}) Op
	Read(id, pointer interface{}) Op
	MultiRead(ids []interface{}, pointerToASlice interface{}) Op
	WithOptions(Options) MapTable
	TableChanger
}

MapTable gives you basic CRUD functionality. If you need fancier ways to query your data set have a look at the other tables.

type MockFilter

type MockFilter struct {
	// contains filtered or unexported fields
}

MockFilter implements the Filter interface and works with MockTable.

func (*MockFilter) Delete

func (f *MockFilter) Delete() Op

func (*MockFilter) Read

func (q *MockFilter) Read(out interface{}) Op

func (*MockFilter) ReadOne

func (q *MockFilter) ReadOne(out interface{}) Op

func (*MockFilter) Update

func (f *MockFilter) Update(m map[string]interface{}) Op

func (*MockFilter) UpdateWithOptions

func (f *MockFilter) UpdateWithOptions(m map[string]interface{}, options Options) Op

type MockTable

type MockTable struct {
	// contains filtered or unexported fields
}

MockTable implements the Table interface and stores rows in-memory.

func (*MockTable) Create

func (t *MockTable) Create() error

func (*MockTable) CreateStatement

func (t *MockTable) CreateStatement() (string, error)

func (*MockTable) Name

func (t *MockTable) Name() string

func (*MockTable) Recreate

func (t *MockTable) Recreate() error

func (*MockTable) Set

func (t *MockTable) Set(i interface{}) Op

func (*MockTable) SetWithOptions

func (t *MockTable) SetWithOptions(i interface{}, options Options) Op

func (*MockTable) Where

func (t *MockTable) Where(relations ...Relation) Filter

func (*MockTable) WithOptions

func (t *MockTable) WithOptions(o Options) Table

type Modifier

type Modifier struct {
	// contains filtered or unexported fields
}

func CounterIncrement

func CounterIncrement(value int) Modifier

CounterIncrement increments the value of the counter with the given value. Negative value results in decrementing.

func ListAppend

func ListAppend(value interface{}) Modifier

ListAppend appends a value to the end of the list

func ListPrepend

func ListPrepend(value interface{}) Modifier

ListPrepend prepends a value to the front of the list

func ListRemove

func ListRemove(value interface{}) Modifier

ListRemove removes all elements from a list having a particular value

func ListSetAtIndex

func ListSetAtIndex(index int, value interface{}) Modifier

ListSetAtIndex sets the list element at a given index to a given value

func MapSetField

func MapSetField(key, value interface{}) Modifier

MapSetField updates the map with the given key and value

func MapSetFields

func MapSetFields(fields map[string]interface{}) Modifier

MapSetFields updates the map with keys and values in the given map

type MultiTimeSeriesTable

type MultiTimeSeriesTable interface {
	// timeField and idField must be present
	Set(v interface{}) Op
	Update(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}) Op
	Delete(v interface{}, timeStamp time.Time, id interface{}) Op
	Read(v interface{}, timeStamp time.Time, id, pointer interface{}) Op
	List(v interface{}, start, end time.Time, pointerToASlice interface{}) Op
	WithOptions(Options) MultiTimeSeriesTable
	TableChanger
}

MultiTimeSeriesTable is a cross between TimeSeries and Multimap tables.

type MultimapTable

type MultimapTable interface {
	Set(v interface{}) Op
	Update(v, id interface{}, m map[string]interface{}) Op
	Delete(v, id interface{}) Op
	DeleteAll(v interface{}) Op
	List(v, startId interface{}, limit int, pointerToASlice interface{}) Op
	Read(v, id, pointer interface{}) Op
	MultiRead(v interface{}, ids []interface{}, pointerToASlice interface{}) Op
	WithOptions(Options) MultimapTable
	TableChanger
}

MultimapTable lets you list rows based on a field equality, eg. 'list all sales where seller id = v'.

type Op

type Op interface {
	// Run the operation.
	Run() error
	// You do not need this in 95% of the use cases, use Run!
	// Using atomic batched writes (logged batches in Cassandra terminology) comes at a high performance cost!
	RunAtomically() error
	// Add an other Op to this one.
	Add(...Op) Op
	// WithOptions lets you specify `Op` level `Options`.
	// The `Op` level Options and the `Table` level `Options` will be merged in a way that Op level takes precedence.
	// All queries in an `Op` will have the specified `Options`.
	// When using Add(), the existing options are preserved.
	// For example:
	//
	//    op1.WithOptions(Options{Limit:3}).Add(op2.WithOptions(Options{Limit:2})) // op1 has a limit of 3, op2 has a limit of 2
	//    op1.WithOptions(Options{Limit:3}).Add(op2).WithOptions(Options{Limit:2}) // op1 and op2 both have a limit of 2
	//
	WithOptions(Options) Op
}

Op is returned by both read and write methods, you have to run them explicitly to take effect. It represents one or more operations.

type Options

type Options struct {
	// TTL specifies a duration over which data is valid. It will be truncated to second precision upon statement
	// execution.
	TTL time.Duration
	// Limit query result set
	Limit int
	// TableName
	TableName string
}

Options can contain table or statement specific options. The reason for this is because statement specific (TTL, Limit) options make sense as table level options (eg. have default TTL for every Update without specifying it all the time)

func (Options) Merge

func (o Options) Merge(neu Options) Options

Returns a new Options which is a right biased merge of the two initial Options.

type QueryExecutor

type QueryExecutor interface {
	// Query executes a query and returns the results
	Query(stmt string, params ...interface{}) ([]map[string]interface{}, error)
	// Execute executes a DML query
	Execute(stmt string, params ...interface{}) error
	// ExecuteAtomically executs multiple DML queries with a logged batch
	ExecuteAtomically(stmt []string, params [][]interface{}) error
}

QueryExecutor actually executes the queries - this is mostly useful for testing/mocking purposes, ignore this otherwise. This library is using github.com/gocql/gocql as the query executor by default.

type Relation

type Relation struct {
	// contains filtered or unexported fields
}

func Eq

func Eq(key string, term interface{}) Relation

func GT

func GT(key string, term interface{}) Relation

func GTE

func GTE(key string, term interface{}) Relation

func In

func In(key string, terms ...interface{}) Relation

func LT

func LT(key string, term interface{}) Relation

func LTE

func LTE(key string, term interface{}) Relation

type RowNotFoundError

type RowNotFoundError struct {
	// contains filtered or unexported fields
}

RowNotFoundError is returned by Reads if the Row is not found.

func (RowNotFoundError) Error

func (r RowNotFoundError) Error() string

type Table

type Table interface {
	// Set Inserts, or Replaces your row with the supplied struct. Be aware that what is not in your struct
	// will be deleted. To only overwrite some of the fields, use Query.Update.
	Set(v interface{}) Op
	// Where accepts a bunch of realtions and returns a filter. See the documentation for Relation and Filter to understand what that means.
	Where(relations ...Relation) Filter // Because we provide selections
	// Name returns the underlying table name, as stored in C*
	WithOptions(Options) Table
	TableChanger
}

Table is the only non-recipe table, it is the "raw CQL table", it lets you do pretty much whatever you want with the downside that you have to know what you are doing - eg. you have to know what queries can you make on a certain partition key - clustering column combination.

type TableChanger

type TableChanger interface {
	// Create creates the table in the keySpace, but only if it does not exist already.
	// If the table already exists, it returns an error.
	Create() error
	// CreateStatement returns you the CQL query which can be used to create the tably manually in cqlsh
	CreateStatement() (string, error)
	// Recreate drops the table if exists and creates it again.
	// This is useful for test purposes only.
	Recreate() error
	// Name returns the name of the table, as in C*
	Name() string
}

Danger zone! Do not use this interface unless you really know what you are doing

type TimeSeriesTable

type TimeSeriesTable interface {
	// timeField and idField must be present
	Set(v interface{}) Op
	Update(timeStamp time.Time, id interface{}, m map[string]interface{}) Op
	Delete(timeStamp time.Time, id interface{}) Op
	Read(timeStamp time.Time, id, pointer interface{}) Op
	List(start, end time.Time, pointerToASlice interface{}) Op
	WithOptions(Options) TimeSeriesTable
	TableChanger
}

TimeSeriesTable lets you list rows which have a field value between two date ranges.

Directories

Path Synopsis
examples
This package provides some punk-rock reflection which is not in the stdlib.
This package provides some punk-rock reflection which is not in the stdlib.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL