### Install gocql with go get Source: https://pkg.go.dev/github.com/gocql/gocql Install the gocql package using the go get command. This is the standard installation method for Go modules. ```bash go get github.com/gocql/gocql ``` -------------------------------- ### MapScanCAS example Source: https://pkg.go.dev/github.com/gocql/gocql Demonstrates executing a single-statement lightweight transaction with MapScanCAS. Assumes a keyspace and table are set up as described in the comment. Shows the output of the example. ```go package main import ( "context" "fmt" "log" gocql "github.com/gocql/gocql" ) func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create table example.my_lwt_table(pk int, version int, value text, PRIMARY KEY(pk)); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.ProtoVersion = 4 session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() ctx := context.Background() err = session.Query("INSERT INTO example.my_lwt_table (pk, version, value) VALUES (?, ?, ?)", 1, 1, "a").WithContext(ctx).Exec() if err != nil { log.Fatal(err) } m := make(map[string]interface{}) applied, err := session.Query("UPDATE example.my_lwt_table SET value = ? WHERE pk = ? IF version = ?", "b", 1, 0).WithContext(ctx).MapScanCAS(m) if err != nil { log.Fatal(err) } fmt.Println(applied, m) var value string err = session.Query("SELECT value FROM example.my_lwt_table WHERE pk = ?", 1).WithContext(ctx). Scan(&value) if err != nil { log.Fatal(err) } fmt.Println(value) m = make(map[string]interface{}) applied, err = session.Query("UPDATE example.my_lwt_table SET value = ? WHERE pk = ? IF version = ?", "b", 1, 1).WithContext(ctx).MapScanCAS(m) if err != nil { log.Fatal(err) } fmt.Println(applied, m) var value2 string err = session.Query("SELECT value FROM example.my_lwt_table WHERE pk = ?", 1).WithContext(ctx). Scan(&value2) if err != nil { log.Fatal(err) } fmt.Println(value2) // false map[version:1] // a // true map[] // b } ``` ```text Output: ``` -------------------------------- ### ExampleUDTMarshaler implementation Source: https://pkg.go.dev/github.com/gocql/gocql Complete example demonstrating how to implement the UDTMarshaler interface. It defines a MyUDTMarshaler struct with MarshalUDT method and inserts a UDT value into a Cassandra table. The example assumes a specific CQL setup with keyspace 'example', type 'my_udt', and table 'my_udt_table'. ```go /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Content before git sha 34fdeebefcbf183ed7f916f931aa0586fdaa1b40 * Copyright (c) 2016, The Gocql authors, * provided under the BSD-3-Clause License. * See the NOTICE file distributed with this work for additional information. */ package main import ( "context" "log" gocql "github.com/gocql/gocql" ) // MyUDTMarshaler implements UDTMarshaler. type MyUDTMarshaler struct { fieldA string fieldB int32 } // MarshalUDT marshals the selected field to bytes. func (m MyUDTMarshaler) MarshalUDT(name string, info gocql.TypeInfo) ([]byte, error) { switch name { case "field_a": return gocql.Marshal(info, m.fieldA) case "field_b": return gocql.Marshal(info, m.fieldB) default: // If you want to be strict and return error un unknown field, you can do so here instead. // Returning nil, nil will set the value of unknown fields to null, which might be handy if you want // to be forward-compatible when a new field is added to the UDT. return nil, nil } } // ExampleUDTMarshaler demonstrates how to implement a UDTMarshaler. func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create type example.my_udt (field_a text, field_b int); create table example.my_udt_table(pk int, value frozen, PRIMARY KEY(pk)); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.ProtoVersion = 4 session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() ctx := context.Background() value := MyUDTMarshaler{ fieldA: "a value", fieldB: 42, } err = session.Query("INSERT INTO example.my_udt_table (pk, value) VALUES (?, ?)", 1, value).WithContext(ctx).Exec() if err != nil { log.Fatal(err) } } ``` -------------------------------- ### Query Cassandra with gocql and print results Source: https://pkg.go.dev/github.com/gocql/gocql This example connects to a Cassandra cluster, runs three SELECT queries, and prints the results with column names and types. It assumes a keyspace 'example' with tables 'table1' and 'table2' as described in the CQL comments. The output shows the query results with column types and values. ```go package main import ( "context" "fmt" "log" "os" "reflect" "text/tabwriter" gocql "github.com/gocql/gocql" ) func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create table example.table1(pk text, ck int, value1 text, value2 int, PRIMARY KEY(pk, ck)); insert into example.table1 (pk, ck, value1, value2) values ('a', 1, 'b', 2); insert into example.table1 (pk, ck, value1, value2) values ('c', 3, 'd', 4); insert into example.table1 (pk, ck, value1, value2) values ('c', 5, null, null); create table example.table2(pk int, value1 timestamp, PRIMARY KEY(pk)); insert into example.table2 (pk, value1) values (1, '2020-01-02 03:04:05'); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.ProtoVersion = 4 session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() printQuery := func(ctx context.Context, session *gocql.Session, stmt string, values ...interface{}) error { iter := session.Query(stmt, values...).WithContext(ctx).Iter() fmt.Println(stmt) w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) for i, columnInfo := range iter.Columns() { if i > 0 { fmt.Fprint(w, "\t| ") } fmt.Fprintf(w, "%s (%s)", columnInfo.Name, columnInfo.TypeInfo) } for { rd, err := iter.RowData() if err != nil { return err } if !iter.Scan(rd.Values...) { break } fmt.Fprint(w, "\n") for i, val := range rd.Values { if i > 0 { fmt.Fprint(w, "\t| ") } fmt.Fprint(w, reflect.Indirect(reflect.ValueOf(val)).Interface()) } } fmt.Fprint(w, "\n") w.Flush() fmt.Println() return iter.Close() } ctx := context.Background() err = printQuery(ctx, session, "SELECT * FROM table1") if err != nil { log.Fatal(err) } err = printQuery(ctx, session, "SELECT value2, pk, ck FROM table1") if err != nil { log.Fatal(err) } err = printQuery(ctx, session, "SELECT * FROM table2") if err != nil { log.Fatal(err) } // SELECT * FROM table1 // pk (varchar) | ck (int) | value1 (varchar) | value2 (int) // a | 1 | b | 2 // c | 3 | d | 4 // c | 5 | | 0 // // SELECT value2, pk, ck FROM table1 // value2 (int) | pk (varchar) | ck (int) // 2 | a | 1 // 4 | c | 3 // 0 | c | 5 // // SELECT * FROM table2 // pk (int) | value1 (timestamp) // 1 | 2020-01-02 03:04:05 +0000 UTC } ``` -------------------------------- ### gocql UDT Struct Example Source: https://pkg.go.dev/github.com/gocql/gocql Complete example showing how to use a user-defined type as a struct with gocql. It assumes a keyspace with a UDT and table created via the CQL statements in the comment. The example inserts a MyUDT value and then selects it back, printing the fields. ```go /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Content before git sha 34fdeebefcbf183ed7f916f931aa0586fdaa1b40 * Copyright (c) 2016, The Gocql authors, * provided under the BSD-3-Clause License. * See the NOTICE file distributed with this work for additional information. */ package main import ( "context" "fmt" "log" gocql "github.com/gocql/gocql" ) type MyUDT struct { FieldA string `cql:"field_a"` FieldB int32 `cql:"field_b"` } // Example_userDefinedTypesStruct demonstrates how to work with user-defined types as structs. // See also examples for UDTMarshaler and UDTUnmarshaler if you need more control/better performance. func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create type example.my_udt (field_a text, field_b int); create table example.my_udt_table(pk int, value frozen, PRIMARY KEY(pk)); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.ProtoVersion = 4 session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() ctx := context.Background() value := MyUDT{ FieldA: "a value", FieldB: 42, } err = session.Query("INSERT INTO example.my_udt_table (pk, value) VALUES (?, ?)", 1, value).WithContext(ctx).Exec() if err != nil { log.Fatal(err) } var readValue MyUDT err = session.Query("SELECT value FROM example.my_udt_table WHERE pk = 1").WithContext(ctx).Scan(&readValue) if err != nil { log.Fatal(err) } fmt.Println(readValue.FieldA) fmt.Println(readValue.FieldB) // a value // 42 } ``` -------------------------------- ### SimpleRetryPolicy usage examples Source: https://pkg.go.dev/github.com/gocql/gocql Examples of assigning the retry policy to a cluster and to a query. ```go //Assign to the cluster cluster.RetryPolicy = &gocql.SimpleRetryPolicy{NumRetries: 3} //Assign to a query query.RetryPolicy(&gocql.SimpleRetryPolicy{NumRetries: 1}) ``` -------------------------------- ### ExampleSession_MapExecuteBatchCAS demonstrates batch lightweight transaction Source: https://pkg.go.dev/github.com/gocql/gocql Full example showing how to execute a batch lightweight transaction using MapExecuteBatchCAS. It assumes a keyspace and table are set up with the provided CQL. The example inserts initial rows, then executes a batch with conditional updates, printing the applied status and scanned results. ```go package main import ( "context" "fmt" "log" gocql "github.com/gocql/gocql" ) func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create table example.my_lwt_batch_table(pk text, ck text, version int, value text, PRIMARY KEY(pk, ck)); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.ProtoVersion = 4 session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() ctx := context.Background() err = session.Query("INSERT INTO example.my_lwt_batch_table (pk, ck, version, value) VALUES (?, ?, ?, ?)", "pk1", "ck1", 1, "a").WithContext(ctx).Exec() if err != nil { log.Fatal(err) } err = session.Query("INSERT INTO example.my_lwt_batch_table (pk, ck, version, value) VALUES (?, ?, ?, ?)", "pk1", "ck2", 1, "A").WithContext(ctx).Exec() if err != nil { log.Fatal(err) } executeBatch := func(ck2Version int) { b := session.NewBatch(gocql.LoggedBatch) b.Entries = append(b.Entries, gocql.BatchEntry{ Stmt: "UPDATE my_lwt_batch_table SET value=? WHERE pk=? AND ck=? IF version=?", Args: []interface{}{"b", "pk1", "ck1", 1}, }) b.Entries = append(b.Entries, gocql.BatchEntry{ Stmt: "UPDATE my_lwt_batch_table SET value=? WHERE pk=? AND ck=? IF version=?", Args: []interface{}{"B", "pk1", "ck2", ck2Version}, }) m := make(map[string]interface{}) applied, iter, err := session.MapExecuteBatchCAS(b.WithContext(ctx), m) if err != nil { log.Fatal(err) } fmt.Println(applied, m) m = make(map[string]interface{}) for iter.MapScan(m) { fmt.Println(m) m = make(map[string]interface{}) } if err := iter.Close(); err != nil { log.Fatal(err) } } printState := func() { scanner := session.Query("SELECT ck, value FROM example.my_lwt_batch_table WHERE pk = ?", "pk1"). WithContext(ctx).Iter().Scanner() for scanner.Next() { var ck, value string err = scanner.Scan(&ck, &value) if err != nil { log.Fatal(err) } fmt.Println(ck, value) } if err := scanner.Err(); err != nil { log.Fatal(err) } } executeBatch(0) printState() executeBatch(1) printState() // false map[ck:ck1 pk:pk1 version:1] // map[[applied]:false ck:ck2 pk:pk1 version:1] // ck1 a // ck2 A // true map[] // ck1 b // ck2 B } ``` -------------------------------- ### Query.Release method signature and example Source: https://pkg.go.dev/github.com/gocql/gocql Releases a query back into a pool of queries. Released Queries cannot be reused. The example shows creating a query, executing it, and releasing it. ```go func (q *Query) Release() ``` ```go qry := session.Query("SELECT * FROM my_table") qry.Exec() qry.Release() ``` -------------------------------- ### Example: Handle Null Values with Scanner Source: https://pkg.go.dev/github.com/gocql/gocql Shows how to scan rows into a *string pointer to distinguish null from empty string. Assumes a keyspace 'example' with table 'stringvals' containing rows with null, empty, and 'hello' values. Outputs 'Row 1 is null', 'Row 2 is ""', and 'Row 3 is "hello"'. ```go package main import ( "fmt" "log" gocql "github.com/gocql/gocql" ) func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create table example.stringvals(id int, value text, PRIMARY KEY(id)); insert into example.stringvals (id, value) values (1, null); insert into example.stringvals (id, value) values (2, ''); insert into example.stringvals (id, value) values (3, 'hello'); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() scanner := session.Query(`SELECT id, value FROM stringvals`).Iter().Scanner() for scanner.Next() { var ( id int32 val *string ) err := scanner.Scan(&id, &val) if err != nil { log.Fatal(err) } if val != nil { fmt.Printf("Row %d is %q\n", id, *val) } else { fmt.Printf("Row %d is null\n", id) } } err = scanner.Err() if err != nil { log.Fatal(err) } // Row 1 is null // Row 2 is "" // Row 3 is "hello" } ``` -------------------------------- ### Example: Implementing UDTMarshaler Source: https://pkg.go.dev/github.com/gocql/gocql ExampleUDTMarshaler demonstrates how to implement a UDTMarshaler. It shows how to marshal UDT fields to bytes and insert them into a Cassandra table. ```APIDOC ## Example: Implementing UDTMarshaler ### Description ExampleUDTMarshaler demonstrates how to implement a UDTMarshaler. It shows how to marshal UDT fields to bytes and insert them into a Cassandra table. ### Example Code ```go /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Content before git sha 34fdeebefcbf183ed7f916f931aa0586fdaa1b40 * Copyright (c) 2016, The Gocql authors, * provided under the BSD-3-Clause License. * See the NOTICE file distributed with this work for additional information. */ package main import ( "context" "log" gocql "github.com/gocql/gocql" ) // MyUDTMarshaler implements UDTMarshaler. type MyUDTMarshaler struct { fieldA string fieldB int32 } // MarshalUDT marshals the selected field to bytes. func (m MyUDTMarshaler) MarshalUDT(name string, info gocql.TypeInfo) ([]byte, error) { switch name { case "field_a": return gocql.Marshal(info, m.fieldA) case "field_b": return gocql.Marshal(info, m.fieldB) default: // If you want to be strict and return error un unknown field, you can do so here instead. // Returning nil, nil will set the value of unknown fields to null, which might be handy if you want // to be forward-compatible when a new field is added to the UDT. return nil, nil } } // ExampleUDTMarshaler demonstrates how to implement a UDTMarshaler. func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create type example.my_udt (field_a text, field_b int); create table example.my_udt_table(pk int, value frozen, PRIMARY KEY(pk)); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.ProtoVersion = 4 session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() ctx := context.Background() value := MyUDTMarshaler{ fieldA: "a value", fieldB: 42, } err = session.Query("INSERT INTO example.my_udt_table (pk, value) VALUES (?, ?)", 1, value).WithContext(ctx).Exec() if err != nil { log.Fatal(err) } } ``` ### Output (No output is shown in the source.) ``` -------------------------------- ### Basic gocql example: connect, insert, query, and scan Source: https://pkg.go.dev/github.com/gocql/gocql Shows how to connect to a Cassandra cluster, insert a tweet, query with a secondary index, and iterate over results using a scanner. Assumes a keyspace and table are set up as described in the comments. ```go package main import ( "context" "fmt" "log" gocql "github.com/gocql/gocql" ) func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create table example.tweet(timeline text, id UUID, text text, PRIMARY KEY(id)); create index on example.tweet(timeline); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.Consistency = gocql.Quorum // connect to the cluster session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() ctx := context.Background() // insert a tweet if err := session.Query(`INSERT INTO tweet (timeline, id, text) VALUES (?, ?, ?)`, "me", gocql.TimeUUID(), "hello world").WithContext(ctx).Exec(); err != nil { log.Fatal(err) } var id gocql.UUID var text string /* Search for a specific set of records whose 'timeline' column matches * the value 'me'. The secondary index that we created earlier will be * used for optimizing the search */ if err := session.Query(`SELECT id, text FROM tweet WHERE timeline = ? LIMIT 1`, "me").WithContext(ctx).Consistency(gocql.One).Scan(&id, &text); err != nil { log.Fatal(err) } fmt.Println("Tweet:", id, text) fmt.Println() // list all tweets scanner := session.Query(`SELECT id, text FROM tweet WHERE timeline = ?`, "me").WithContext(ctx).Iter().Scanner() for scanner.Next() { err = scanner.Scan(&id, &text) if err != nil { log.Fatal(err) } fmt.Println("Tweet:", id, text) } // scanner.Err() closes the iterator, so scanner nor iter should be used afterwards. if err := scanner.Err(); err != nil { log.Fatal(err) } // Tweet: cad53821-3731-11eb-971c-708bcdaada84 hello world // // Tweet: cad53821-3731-11eb-971c-708bcdaada84 hello world // Tweet: d577ab85-3731-11eb-81eb-708bcdaada84 hello world } ``` -------------------------------- ### gocql batch example: execute a batch of statements Source: https://pkg.go.dev/github.com/gocql/gocql Demonstrates how to create and execute an unlogged batch of INSERT statements using gocql. Assumes a keyspace and table are set up as described in the comments. ```go package main import ( "context" "fmt" "log" gocql "github.com/gocql/gocql" ) func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create table example.batches(pk int, ck int, description text, PRIMARY KEY(pk, ck)); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.ProtoVersion = 4 session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() ctx := context.Background() b := session.NewBatch(gocql.UnloggedBatch).WithContext(ctx) b.Entries = append(b.Entries, gocql.BatchEntry{ Stmt: "INSERT INTO example.batches (pk, ck, description) VALUES (?, ?, ?)", Args: []interface{}{1, 2, "1.2"}, Idempotent: true, }) b.Entries = append(b.Entries, gocql.BatchEntry{ Stmt: "INSERT INTO example.batches (pk, ck, description) VALUES (?, ?, ?)", Args: []interface{}{1, 3, "1.3"}, Idempotent: true, }) err = session.ExecuteBatch(b) if err != nil { log.Fatal(err) } scanner := session.Query("SELECT pk, ck, description FROM example.batches").Iter().Scanner() for scanner.Next() { var pk, ck int32 var description string err = scanner.Scan(&pk, &ck, &description) if err != nil { log.Fatal(err) } fmt.Println(pk, ck, description) } // 1 2 1.2 // 1 3 1.3 } ``` -------------------------------- ### Correct keyspace configuration before session creation Source: https://pkg.go.dev/github.com/gocql/gocql Example of correct usage: set the cluster.Keyspace before creating the session. This is the only way to define the default keyspace. ```go cluster := gocql.NewCluster("192.168.1.1", "192.168.1.2", "192.168.1.3") cluster.Keyspace = "example" ... session, err := cluster.CreateSession() ``` -------------------------------- ### ConstantReconnectionPolicy usage example Source: https://pkg.go.dev/github.com/gocql/gocql Example of setting a constant reconnection policy on a cluster with 10 max retries and an 8-second interval. ```go cluster.ReconnectionPolicy = &gocql.ConstantReconnectionPolicy{MaxRetries: 10, Interval: 8 * time.Second} ``` -------------------------------- ### Example: Manual Paging with PageState Source: https://pkg.go.dev/github.com/gocql/gocql Demonstrates manual paging using PageSize and PageState. Uses ProtoVersion 4 and PageSize(2) for demonstration; default page size is 5000. Output shows page state byte slices and row order. ```go package main import ( "fmt" "log" gocql "github.com/gocql/gocql" ) func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create table example.itoa(id int, description text, PRIMARY KEY(id)); insert into example.itoa (id, description) values (1, 'one'); insert into example.itoa (id, description) values (2, 'two'); insert into example.itoa (id, description) values (3, 'three'); insert into example.itoa (id, description) values (4, 'four'); insert into example.itoa (id, description) values (5, 'five'); insert into example.itoa (id, description) values (6, 'six'); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.ProtoVersion = 4 session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() var pageState []byte for { // We use PageSize(2) for the sake of example, use larger values in production (default is 5000) for performance // reasons. iter := session.Query(`SELECT id, description FROM itoa`).PageSize(2).PageState(pageState).Iter() nextPageState := iter.PageState() scanner := iter.Scanner() for scanner.Next() { var ( id int description string ) err = scanner.Scan(&id, &description) if err != nil { log.Fatal(err) } fmt.Println(id, description) } err = scanner.Err() if err != nil { log.Fatal(err) } fmt.Printf("next page state: %+v\n", nextPageState) if len(nextPageState) == 0 { break } pageState = nextPageState } // 5 five // 1 one // next page state: [4 0 0 0 1 0 240 127 255 255 253 0] // 2 two // 4 four // next page state: [4 0 0 0 4 0 240 127 255 255 251 0] // 6 six // 3 three // next page state: [4 0 0 0 3 0 240 127 255 255 249 0] // next page state: [] } ``` -------------------------------- ### Consistency.String method signature Source: https://pkg.go.dev/github.com/gocql/gocql Method to get string representation of Consistency. ```go func (c Consistency) String() string ``` -------------------------------- ### Configure TLS with SslOptions and EnableHostVerification Source: https://pkg.go.dev/github.com/gocql/gocql Example of setting SslOptions with EnableHostVerification set to true. Note that SslOptions is insecure by default, so you need to set EnableHostVerification to true if no Config is set. ```go cluster := gocql.NewCluster("192.168.1.1", "192.168.1.2", "192.168.1.3") cluster.SslOpts = &gocql.SslOptions{ EnableHostVerification: true, } session, err := cluster.CreateSession() if err != nil { return err } defer session.Close() ``` -------------------------------- ### ExampleUDTUnmarshaler implementation Source: https://pkg.go.dev/github.com/gocql/gocql Full example of implementing a UDTUnmarshaler. It assumes a keyspace with a UDT and table as described in the comment. It queries a row and prints the unmarshaled fields, expecting 'a value' and '42'. ```go /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Content before git sha 34fdeebefcbf183ed7f916f931aa0586fdaa1b40 * Copyright (c) 2016, The Gocql authors, * provided under the BSD-3-Clause License. * See the NOTICE file distributed with this work for additional information. */ package main import ( "context" "fmt" "log" gocql "github.com/gocql/gocql" ) // MyUDTUnmarshaler implements UDTUnmarshaler. type MyUDTUnmarshaler struct { fieldA string fieldB int32 } // UnmarshalUDT unmarshals the field identified by name into MyUDTUnmarshaler. func (m *MyUDTUnmarshaler) UnmarshalUDT(name string, info gocql.TypeInfo, data []byte) error { switch name { case "field_a": return gocql.Unmarshal(info, data, &m.fieldA) case "field_b": return gocql.Unmarshal(info, data, &m.fieldB) default: // If you want to be strict and return error un unknown field, you can do so here instead. // Returning nil will ignore unknown fields, which might be handy if you want // to be forward-compatible when a new field is added to the UDT. return nil } } // ExampleUDTUnmarshaler demonstrates how to implement a UDTUnmarshaler. func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create type example.my_udt (field_a text, field_b int); create table example.my_udt_table(pk int, value frozen, PRIMARY KEY(pk)); insert into example.my_udt_table (pk, value) values (1, {field_a: 'a value', field_b: 42}); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.ProtoVersion = 4 session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() ctx := context.Background() var value MyUDTUnmarshaler err = session.Query("SELECT value FROM example.my_udt_table WHERE pk = 1").WithContext(ctx).Scan(&value) if err != nil { log.Fatal(err) } fmt.Println(value.fieldA) fmt.Println(value.fieldB) // a value // 42 } ``` -------------------------------- ### Iterating with MapScan using a new map each iteration Source: https://pkg.go.dev/github.com/gocql/gocql Example of using MapScan in a loop. A new map is created for each row, and the loop breaks when MapScan returns false. The example prints the 'fullname' field if present. ```go iter := session.Query(`SELECT * FROM mytable`).Iter() for { // New map each iteration row := make(map[string]interface{}) if !iter.MapScan(row) { break } // Do things with row if fullname, ok := row["fullname"]; ok { fmt.Printf("Full Name: %s\n", fullname) } } ``` -------------------------------- ### func (c *Cache) Get(key string) (value interface{}, ok bool) Source: https://pkg.go.dev/github.com/gocql/gocql/internal/lru Get looks up a key's value from the cache. ```APIDOC ## func (c *Cache) Get(key string) (value interface{}, ok bool) ### Description Get looks up a key's value from the cache. ### Parameters - **key** (string) - The key to look up. ### Returns - **value** (interface{}) - The value associated with the key, if present. - **ok** (bool) - True if the key was found, false otherwise. ``` -------------------------------- ### Implement Marshaler and Unmarshaler for custom version type Source: https://pkg.go.dev/github.com/gocql/gocql Complete Go program showing how to implement gocql.Marshaler and gocql.Unmarshaler for a custom type representing a version number stored as a string. It includes setup for a Cassandra cluster, inserting and selecting data, and demonstrates distinguishing between null and zero values. ```go /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Content before git sha 34fdeebefcbf183ed7f916f931aa0586fdaa1b40 * Copyright (c) 2016, The Gocql authors, * provided under the BSD-3-Clause License. * See the NOTICE file distributed with this work for additional information. */ package main import ( "context" "fmt" "log" "strconv" "strings" gocql "github.com/gocql/gocql" ) // MyMarshaler implements Marshaler and Unmarshaler. // It represents a version number stored as string. type MyMarshaler struct { major, minor, patch int } func (m MyMarshaler) MarshalCQL(info gocql.TypeInfo) ([]byte, error) { return gocql.Marshal(info, fmt.Sprintf("%d.%d.%d", m.major, m.minor, m.patch)) } func (m *MyMarshaler) UnmarshalCQL(info gocql.TypeInfo, data []byte) error { var s string err := gocql.Unmarshal(info, data, &s) if err != nil { return err } parts := strings.SplitN(s, ".", 3) if len(parts) != 3 { return fmt.Errorf("parse version %q: %d parts instead of 3", s, len(parts)) } major, err := strconv.Atoi(parts[0]) if err != nil { return fmt.Errorf("parse version %q major number: %v", s, err) } minor, err := strconv.Atoi(parts[1]) if err != nil { return fmt.Errorf("parse version %q minor number: %v", s, err) } patch, err := strconv.Atoi(parts[2]) if err != nil { return fmt.Errorf("parse version %q patch number: %v", s, err) } m.major = major m.minor = minor m.patch = patch return nil } // Example_marshalerUnmarshaler demonstrates how to implement a Marshaler and Unmarshaler. func main() { /* The example assumes the following CQL was used to setup the keyspace: create keyspace example with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; create table example.my_marshaler_table(pk int, value text, PRIMARY KEY(pk)); */ cluster := gocql.NewCluster("localhost:9042") cluster.Keyspace = "example" cluster.ProtoVersion = 4 session, err := cluster.CreateSession() if err != nil { log.Fatal(err) } defer session.Close() ctx := context.Background() value := MyMarshaler{ major: 1, minor: 2, patch: 3, } err = session.Query("INSERT INTO example.my_marshaler_table (pk, value) VALUES (?, ?)", 1, value).WithContext(ctx).Exec() if err != nil { log.Fatal(err) } var stringValue string err = session.Query("SELECT value FROM example.my_marshaler_table WHERE pk = 1").WithContext(ctx). Scan(&stringValue) if err != nil { log.Fatal(err) } fmt.Println(stringValue) var unmarshaledValue MyMarshaler err = session.Query("SELECT value FROM example.my_marshaler_table WHERE pk = 1").WithContext(ctx). Scan(&unmarshaledValue) if err != nil { log.Fatal(err) } fmt.Println(unmarshaledValue) // 1.2.3 // {1 2 3} } ``` -------------------------------- ### Token-aware routing requires parameterized partition key Source: https://pkg.go.dev/github.com/gocql/gocql Shows that token-aware routing only works when all partition key columns are query parameters. The first example with a literal value is not token-aware; the second with parameters is. ```go session.Query("select value from mytable where pk1 = 'abc' AND pk2 = ?", "def") ``` ```go session.Query("select value from mytable where pk1 = ? AND pk2 = ?", "abc", "def") ``` -------------------------------- ### Use PasswordAuthenticator for username/password authentication Source: https://pkg.go.dev/github.com/gocql/gocql Set ClusterConfig.Authenticator to gocql.PasswordAuthenticator to use username/password authentication. The example shows creating a cluster, setting the authenticator, and creating a session. ```go cluster := gocql.NewCluster("192.168.1.1", "192.168.1.2", "192.168.1.3") cluster.Authenticator = gocql.PasswordAuthenticator{ Username: "user", Password: "password" } session, err := cluster.CreateSession() if err != nil { return err } defer session.Close() ``` -------------------------------- ### Incorrect usage with 'use' statement Source: https://pkg.go.dev/github.com/gocql/gocql Example of incorrect usage: attempting to execute a 'use' statement after session creation. This will result in an error from the session.Query line. ```go cluster := gocql.NewCluster("192.168.1.1", "192.168.1.2", "192.168.1.3") cluster.Keyspace = "example" ... session, err := cluster.CreateSession() if err = session.Query("use example2").Exec(); err != nil { log.Fatal(err) } ``` -------------------------------- ### Iterating with MapScan using pointers in the map Source: https://pkg.go.dev/github.com/gocql/gocql Example of using MapScan with pointers to custom types and standard types. The map is populated with pointers before each call, and the loop breaks when MapScan returns false. ```go var fullName FullName // Implements gocql.Unmarshaler and gocql.Marshaler interfaces var address net.IP var age int iter := session.Query(`SELECT * FROM scan_map_table`).Iter() for { // New map each iteration row := map[string]interface{}{ "fullname": &fullName, "age": &age, "address": &address, } if !iter.MapScan(row) { break } fmt.Printf("First: %s Age: %d Address: %q\n", fullName.FirstName, age, address) } ``` -------------------------------- ### Customize cluster options (Keyspace, Consistency, ProtoVersion) Source: https://pkg.go.dev/github.com/gocql/gocql After creating a cluster configuration, you can customize options such as Keyspace, Consistency, and ProtoVersion. The driver tries to auto-detect the protocol version if not set, but setting it explicitly is recommended during cluster upgrades. ```go cluster.Keyspace = "example" cluster.Consistency = gocql.Quorum cluster.ProtoVersion = 4 ``` -------------------------------- ### Query.String method signature Source: https://pkg.go.dev/github.com/gocql/gocql Implements the stringer interface. ```go func (q Query) String() string ```