Skip to content

Commit

Permalink
Added routing key computation (with override) to Query
Browse files Browse the repository at this point in the history
- Added routingKeyInfo(string) function to Session which is a cached calculation of the query
value indexes to routing key indexes with type info
- Added RoutingKey([]byte) function to Query which sets the routing key bytes for the query
- Added GetRoutingKey() []byte which returns the routing key for the query; if the routing
key is not set explicitly with RoutingKey([]byte) then the routing key is constructed using
the routing key info retrieved from Session
  • Loading branch information
justinretailnext committed Mar 27, 2015
1 parent 730396a commit d1eb335
Show file tree
Hide file tree
Showing 4 changed files with 300 additions and 37 deletions.
62 changes: 62 additions & 0 deletions cassandra_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1704,3 +1704,65 @@ func TestKeyspaceMetadata(t *testing.T) {
t.Errorf("Expected column index named 'index_metadata' but was '%s'", thirdColumn.Index.Name)
}
}

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

if err := createTable(session, "CREATE TABLE test_single_routing_key (first_id int, second_id int, PRIMARY KEY (first_id, second_id))"); err != nil {
t.Fatalf("failed to create table with error '%v'", err)
}
if err := createTable(session, "CREATE TABLE test_composite_routing_key (first_id int, second_id int, PRIMARY KEY ((first_id,second_id)))"); err != nil {
t.Fatalf("failed to create table with error '%v'", err)
}

routingKeyInfo := session.routingKeyInfo("SELECT * FROM test_single_routing_key WHERE second_id=? AND first_id=?")
if routingKeyInfo == nil {
t.Fatal("Expected routing key info, but was nil")
}
if len(routingKeyInfo.indexes) != 1 {
t.Fatalf("Expected routing key indexes length to be 1 but was %d", len(routingKeyInfo.indexes))
}
if routingKeyInfo.indexes[0] != 1 {
t.Errorf("Expected routing key index[0] to be 1 but was %d", routingKeyInfo.indexes[0])
}
query := session.Query("SELECT * FROM test_single_routing_key WHERE second_id=? AND first_id=?", 1, 2)
routingKey := query.GetRoutingKey()
expectedRoutingKey := []byte{0, 0, 0, 2}
if !reflect.DeepEqual(expectedRoutingKey, routingKey) {
t.Errorf("Expected routing key %v but was %v", expectedRoutingKey, routingKey)
}

// verify the cache is working
session.routingKeyInfo("SELECT * FROM test_single_routing_key WHERE second_id=? AND first_id=?")
cacheSize := session.routingKeyInfoCache.lru.Len()
if cacheSize != 1 {
t.Errorf("Expected cache size to be 1 but was %d", cacheSize)
}

routingKeyInfo = session.routingKeyInfo("SELECT * FROM test_composite_routing_key WHERE second_id=? AND first_id=?")
if routingKeyInfo == nil {
t.Fatal("Expected routing key info, but was nil")
}
if len(routingKeyInfo.indexes) != 2 {
t.Fatalf("Expected routing key indexes length to be 2 but was %d", len(routingKeyInfo.indexes))
}
if routingKeyInfo.indexes[0] != 1 {
t.Errorf("Expected routing key index[0] to be 1 but was %d", routingKeyInfo.indexes[0])
}
if routingKeyInfo.indexes[1] != 0 {
t.Errorf("Expected routing key index[1] to be 0 but was %d", routingKeyInfo.indexes[1])
}
query = session.Query("SELECT * FROM test_composite_routing_key WHERE second_id=? AND first_id=?", 1, 2)
routingKey = query.GetRoutingKey()
expectedRoutingKey = []byte{0, 4, 0, 0, 0, 2, 0, 0, 4, 0, 0, 0, 1, 0}
if !reflect.DeepEqual(expectedRoutingKey, routingKey) {
t.Errorf("Expected routing key %v but was %v", expectedRoutingKey, routingKey)
}

// verify the cache is working
cacheSize = session.routingKeyInfoCache.lru.Len()
if cacheSize != 2 {
t.Errorf("Expected cache size to be 2 but was %d", cacheSize)
}
}
60 changes: 31 additions & 29 deletions cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,40 +55,42 @@ type DiscoveryConfig struct {
// behavior to fit the most common use cases. Applications that requre a
// different setup must implement their own cluster.
type ClusterConfig struct {
Hosts []string // addresses for the initial connections
CQLVersion string // CQL version (default: 3.0.0)
ProtoVersion int // version of the native protocol (default: 2)
Timeout time.Duration // connection timeout (default: 600ms)
Port int // port (default: 9042)
Keyspace string // initial keyspace (optional)
NumConns int // number of connections per host (default: 2)
NumStreams int // number of streams per connection (default: max per protocol, either 128 or 32768)
Consistency Consistency // default consistency level (default: Quorum)
Compressor Compressor // compression algorithm (default: nil)
Authenticator Authenticator // authenticator (default: nil)
RetryPolicy RetryPolicy // Default retry policy to use for queries (default: 0)
SocketKeepalive time.Duration // The keepalive period to use, enabled if > 0 (default: 0)
ConnPoolType NewPoolFunc // The function used to create the connection pool for the session (default: NewSimplePool)
DiscoverHosts bool // If set, gocql will attempt to automatically discover other members of the Cassandra cluster (default: false)
MaxPreparedStmts int // Sets the maximum cache size for prepared statements globally for gocql (default: 1000)
PageSize int // Default page size to use for created sessions (default: 0)
Discovery DiscoveryConfig
SslOpts *SslOptions
Hosts []string // addresses for the initial connections
CQLVersion string // CQL version (default: 3.0.0)
ProtoVersion int // version of the native protocol (default: 2)
Timeout time.Duration // connection timeout (default: 600ms)
Port int // port (default: 9042)
Keyspace string // initial keyspace (optional)
NumConns int // number of connections per host (default: 2)
NumStreams int // number of streams per connection (default: max per protocol, either 128 or 32768)
Consistency Consistency // default consistency level (default: Quorum)
Compressor Compressor // compression algorithm (default: nil)
Authenticator Authenticator // authenticator (default: nil)
RetryPolicy RetryPolicy // Default retry policy to use for queries (default: 0)
SocketKeepalive time.Duration // The keepalive period to use, enabled if > 0 (default: 0)
ConnPoolType NewPoolFunc // The function used to create the connection pool for the session (default: NewSimplePool)
DiscoverHosts bool // If set, gocql will attempt to automatically discover other members of the Cassandra cluster (default: false)
MaxPreparedStmts int // Sets the maximum cache size for prepared statements globally for gocql (default: 1000)
MaxRoutingKeyInfo int // Sets the maximum cache size for query info about statements for each session (default: 1000)
PageSize int // Default page size to use for created sessions (default: 0)
Discovery DiscoveryConfig
SslOpts *SslOptions
}

// NewCluster generates a new config for the default cluster implementation.
func NewCluster(hosts ...string) *ClusterConfig {
cfg := &ClusterConfig{
Hosts: hosts,
CQLVersion: "3.0.0",
ProtoVersion: 2,
Timeout: 600 * time.Millisecond,
Port: 9042,
NumConns: 2,
Consistency: Quorum,
ConnPoolType: NewSimplePool,
DiscoverHosts: false,
MaxPreparedStmts: defaultMaxPreparedStmts,
Hosts: hosts,
CQLVersion: "3.0.0",
ProtoVersion: 2,
Timeout: 600 * time.Millisecond,
Port: 9042,
NumConns: 2,
Consistency: Quorum,
ConnPoolType: NewSimplePool,
DiscoverHosts: false,
MaxPreparedStmts: defaultMaxPreparedStmts,
MaxRoutingKeyInfo: 1000,
}
return cfg
}
Expand Down
9 changes: 9 additions & 0 deletions metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ func getKeyspaceMetadata(
`,
keyspaceName,
)
// Set a routing key to avoid GetRoutingKey from computing the routing key
// TODO use a separate connection (pool) for system keyspace queries.
query.RoutingKey([]byte{})

keyspace := &KeyspaceMetadata{Name: keyspaceName}
var strategyOptionsJSON []byte
Expand Down Expand Up @@ -375,6 +378,9 @@ func getTableMetadata(
`,
keyspaceName,
)
// Set a routing key to avoid GetRoutingKey from computing the routing key
// TODO use a separate connection (pool) for system keyspace queries.
query.RoutingKey([]byte{})
iter := query.Iter()

tables := []TableMetadata{}
Expand Down Expand Up @@ -511,6 +517,9 @@ func getColumnMetadata(
var indexOptionsJSON []byte

query := session.Query(stmt, keyspaceName)
// Set a routing key to avoid GetRoutingKey from computing the routing key
// TODO use a separate connection (pool) for system keyspace queries.
query.RoutingKey([]byte{})
iter := query.Iter()

for scan(iter, &column, &indexOptionsJSON) {
Expand Down
Loading

0 comments on commit d1eb335

Please sign in to comment.