This is an automated email from the ASF dual-hosted git repository.

joaoreis pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra-gocql-driver.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 5fd2cdf0 Update example and test code for 2.0 release
5fd2cdf0 is described below

commit 5fd2cdf0d78d9c506cb6d883320ea28239ec7969
Author: João Reis <[email protected]>
AuthorDate: Tue Jul 15 18:19:40 2025 +0100

    Update example and test code for 2.0 release
    
    This patch updates the existing examples and tests according to the 2.0 
changes (mostly deprecations) and adds new examples for new features added in 
2.0.
    
    Patch by João Reis; reviewed by Bohdan Siryk and Lukasz Antoniak for 
CASSGO-80
---
 CHANGELOG.md                       |   1 +
 batch_test.go                      |   8 +-
 cassandra_test.go                  |   8 +-
 example_batch_test.go              |  39 +++++--
 example_dynamic_columns_test.go    |   2 +-
 example_lwt_batch_test.go          |  12 +-
 example_lwt_test.go                |  14 +--
 example_marshaler_test.go          |  10 +-
 example_setkeyspace_test.go        | 196 +++++++++++++++++++++++++++++++++
 example_structured_logging_test.go | 217 +++++++++++++++++++++++++++++++++++++
 example_test.go                    |   6 +-
 example_udt_map_test.go            |   6 +-
 example_udt_marshaler_test.go      |   2 +-
 example_udt_struct_test.go         |   6 +-
 example_udt_unmarshaler_test.go    |   3 +-
 example_vector_test.go             | 203 ++++++++++++++++++++++++++++++++++
 session_test.go                    |   4 +-
 17 files changed, 689 insertions(+), 48 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d02991cc..ec7d0861 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -34,6 +34,7 @@ and this project adheres to [Semantic 
Versioning](https://semver.org/spec/v2.0.0
 - Add Query and Batch to ObservedQuery and ObservedBatch (CASSGO-73)
 - Add way to create HostInfo objects for testing purposes (CASSGO-71)
 - Add missing Context methods on Query and Batch (CASSGO-81)
+- Update example and test code for 2.0 release (CASSGO-80)
 
 ### Changed
 
diff --git a/batch_test.go b/batch_test.go
index 7f7d0025..57eafd64 100644
--- a/batch_test.go
+++ b/batch_test.go
@@ -93,10 +93,10 @@ func TestBatch_WithNowInSeconds(t *testing.T) {
                t.Fatal(err)
        }
 
-       b := session.NewBatch(LoggedBatch)
+       b := session.Batch(LoggedBatch)
        b.WithNowInSeconds(0)
        b.Query("INSERT INTO batch_now_in_seconds (id, val) VALUES (?, ?) USING 
TTL 20", 1, "val")
-       if err := session.ExecuteBatch(b); err != nil {
+       if err := b.Exec(); err != nil {
                t.Fatal(err)
        }
 
@@ -140,10 +140,10 @@ func TestBatch_SetKeyspace(t *testing.T) {
        ids := []int{1, 2}
        texts := []string{"val1", "val2"}
 
-       b := 
session.NewBatch(LoggedBatch).SetKeyspace("gocql_keyspace_override_test")
+       b := 
session.Batch(LoggedBatch).SetKeyspace("gocql_keyspace_override_test")
        b.Query("INSERT INTO batch_keyspace(id, value) VALUES (?, ?)", ids[0], 
texts[0])
        b.Query("INSERT INTO batch_keyspace(id, value) VALUES (?, ?)", ids[1], 
texts[1])
-       err = session.ExecuteBatch(b)
+       err = b.Exec()
        if err != nil {
                t.Fatal(err)
        }
diff --git a/cassandra_test.go b/cassandra_test.go
index cb660755..bc260e44 100644
--- a/cassandra_test.go
+++ b/cassandra_test.go
@@ -3899,15 +3899,15 @@ func TestStmtCacheUsesOverriddenKeyspace(t *testing.T) {
 
        // Inserting data via Batch to ensure that batches
        // properly accounts for keyspace overriding
-       b1 := session.NewBatch(LoggedBatch)
+       b1 := session.Batch(LoggedBatch)
        b1.Query(insertQuery, 1)
-       err = session.ExecuteBatch(b1)
+       err = b1.Exec()
        require.NoError(t, err)
 
-       b2 := session.NewBatch(LoggedBatch)
+       b2 := session.Batch(LoggedBatch)
        b2.SetKeyspace("gocql_test_stmt_cache")
        b2.Query(insertQuery, 2)
-       err = session.ExecuteBatch(b2)
+       err = b2.Exec()
        require.NoError(t, err)
 
        var scannedID int
diff --git a/example_batch_test.go b/example_batch_test.go
index 9f778c84..2322a3b4 100644
--- a/example_batch_test.go
+++ b/example_batch_test.go
@@ -49,31 +49,46 @@ func Example_batch() {
 
        ctx := context.Background()
 
-       b := session.Batch(gocql.UnloggedBatch).WithContext(ctx)
+       // Example 1: Simple batch using the Query() method - recommended 
approach
+       batch := session.Batch(gocql.LoggedBatch)
+       batch.Query("INSERT INTO example.batches (pk, ck, description) VALUES 
(?, ?, ?)", 1, 2, "1.2")
+       batch.Query("INSERT INTO example.batches (pk, ck, description) VALUES 
(?, ?, ?)", 1, 3, "1.3")
+
+       err = batch.ExecContext(ctx)
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       // Example 2: Advanced batch usage with Entries for more control
+       b := session.Batch(gocql.UnloggedBatch)
        b.Entries = append(b.Entries, gocql.BatchEntry{
                Stmt:       "INSERT INTO example.batches (pk, ck, description) 
VALUES (?, ?, ?)",
-               Args:       []interface{}{1, 2, "1.2"},
+               Args:       []interface{}{1, 4, "1.4"},
                Idempotent: true,
        })
        b.Entries = append(b.Entries, gocql.BatchEntry{
                Stmt:       "INSERT INTO example.batches (pk, ck, description) 
VALUES (?, ?, ?)",
-               Args:       []interface{}{1, 3, "1.3"},
+               Args:       []interface{}{1, 5, "1.5"},
                Idempotent: true,
        })
 
-       err = b.Exec()
+       err = b.ExecContext(ctx)
        if err != nil {
                log.Fatal(err)
        }
 
-       err = b.Query("INSERT INTO example.batches (pk, ck, description) VALUES 
(?, ?, ?)", 1, 4, "1.4").
-               Query("INSERT INTO example.batches (pk, ck, description) VALUES 
(?, ?, ?)", 1, 5, "1.5").
-               Exec()
+       // Example 3: Fluent style chaining
+       err = session.Batch(gocql.LoggedBatch).
+               Query("INSERT INTO example.batches (pk, ck, description) VALUES 
(?, ?, ?)", 1, 6, "1.6").
+               Query("INSERT INTO example.batches (pk, ck, description) VALUES 
(?, ?, ?)", 1, 7, "1.7").
+               ExecContext(ctx)
        if err != nil {
                log.Fatal(err)
        }
 
-       scanner := session.Query("SELECT pk, ck, description FROM 
example.batches").Iter().Scanner()
+       // Verification: Display all inserted data
+       fmt.Println("All inserted data:")
+       scanner := session.Query("SELECT pk, ck, description FROM 
example.batches").IterContext(ctx).Scanner()
        for scanner.Next() {
                var pk, ck int32
                var description string
@@ -83,8 +98,16 @@ func Example_batch() {
                }
                fmt.Println(pk, ck, description)
        }
+
+       if err := scanner.Err(); err != nil {
+               log.Fatal(err)
+       }
+
+       // All inserted data:
        // 1 2 1.2
        // 1 3 1.3
        // 1 4 1.4
        // 1 5 1.5
+       // 1 6 1.6
+       // 1 7 1.7
 }
diff --git a/example_dynamic_columns_test.go b/example_dynamic_columns_test.go
index 984bc730..38f4c66e 100644
--- a/example_dynamic_columns_test.go
+++ b/example_dynamic_columns_test.go
@@ -56,7 +56,7 @@ func Example_dynamicColumns() {
        defer session.Close()
 
        printQuery := func(ctx context.Context, session *gocql.Session, stmt 
string, values ...interface{}) error {
-               iter := session.Query(stmt, values...).WithContext(ctx).Iter()
+               iter := session.Query(stmt, values...).IterContext(ctx)
                fmt.Println(stmt)
                w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ',
                        0)
diff --git a/example_lwt_batch_test.go b/example_lwt_batch_test.go
index c65ce961..1d0acad9 100644
--- a/example_lwt_batch_test.go
+++ b/example_lwt_batch_test.go
@@ -32,8 +32,8 @@ import (
        gocql "github.com/apache/cassandra-gocql-driver/v2"
 )
 
-// ExampleSession_MapExecuteBatchCAS demonstrates how to execute a batch 
lightweight transaction.
-func ExampleSession_MapExecuteBatchCAS() {
+// ExampleBatch_MapExecCAS demonstrates how to execute a batch lightweight 
transaction.
+func ExampleBatch_MapExecCAS() {
        /* 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));
@@ -50,13 +50,13 @@ func ExampleSession_MapExecuteBatchCAS() {
        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()
+               "pk1", "ck1", 1, "a").ExecContext(ctx)
        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()
+               "pk1", "ck2", 1, "A").ExecContext(ctx)
        if err != nil {
                log.Fatal(err)
        }
@@ -72,7 +72,7 @@ func ExampleSession_MapExecuteBatchCAS() {
                        Args: []interface{}{"B", "pk1", "ck2", ck2Version},
                })
                m := make(map[string]interface{})
-               applied, iter, err := b.WithContext(ctx).MapExecCAS(m)
+               applied, iter, err := b.MapExecCASContext(ctx, m)
                if err != nil {
                        log.Fatal(err)
                }
@@ -91,7 +91,7 @@ func ExampleSession_MapExecuteBatchCAS() {
 
        printState := func() {
                scanner := session.Query("SELECT ck, value FROM 
example.my_lwt_batch_table WHERE pk = ?", "pk1").
-                       WithContext(ctx).Iter().Scanner()
+                       IterContext(ctx).Scanner()
                for scanner.Next() {
                        var ck, value string
                        err = scanner.Scan(&ck, &value)
diff --git a/example_lwt_test.go b/example_lwt_test.go
index 17dc3c29..a7aa0a87 100644
--- a/example_lwt_test.go
+++ b/example_lwt_test.go
@@ -50,21 +50,21 @@ func ExampleQuery_MapScanCAS() {
        ctx := context.Background()
 
        err = session.Query("INSERT INTO example.my_lwt_table (pk, version, 
value) VALUES (?, ?, ?)",
-               1, 1, "a").WithContext(ctx).Exec()
+               1, 1, "a").ExecContext(ctx)
        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)
+               "b", 1, 0).MapScanCASContext(ctx, 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)
+       err = session.Query("SELECT value FROM example.my_lwt_table WHERE pk = 
?", 1).
+               ScanContext(ctx, &value)
        if err != nil {
                log.Fatal(err)
        }
@@ -72,15 +72,15 @@ func ExampleQuery_MapScanCAS() {
 
        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)
+               "b", 1, 1).MapScanCASContext(ctx, 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)
+       err = session.Query("SELECT value FROM example.my_lwt_table WHERE pk = 
?", 1).
+               ScanContext(ctx, &value2)
        if err != nil {
                log.Fatal(err)
        }
diff --git a/example_marshaler_test.go b/example_marshaler_test.go
index fce4ded0..3b6c8192 100644
--- a/example_marshaler_test.go
+++ b/example_marshaler_test.go
@@ -95,20 +95,20 @@ func Example_marshalerUnmarshaler() {
                patch: 3,
        }
        err = session.Query("INSERT INTO example.my_marshaler_table (pk, value) 
VALUES (?, ?)",
-               1, value).WithContext(ctx).Exec()
+               1, value).ExecContext(ctx)
        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)
+       err = session.Query("SELECT value FROM example.my_marshaler_table WHERE 
pk = 1").
+               ScanContext(ctx, &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)
+       err = session.Query("SELECT value FROM example.my_marshaler_table WHERE 
pk = 1").
+               ScanContext(ctx, &unmarshaledValue)
        if err != nil {
                log.Fatal(err)
        }
diff --git a/example_setkeyspace_test.go b/example_setkeyspace_test.go
new file mode 100644
index 00000000..93b9c1ca
--- /dev/null
+++ b/example_setkeyspace_test.go
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+
+package gocql_test
+
+import (
+       "context"
+       "fmt"
+       "log"
+
+       gocql "github.com/apache/cassandra-gocql-driver/v2"
+)
+
+// Example_setKeyspace demonstrates the SetKeyspace method that allows
+// specifying keyspace per query, available with Protocol 5+ (Cassandra 4.0+).
+//
+// This example shows the complete keyspace precedence hierarchy:
+// 1. Keyspace in CQL query string (keyspace.table) - HIGHEST precedence
+// 2. SetKeyspace() method - MIDDLE precedence
+// 3. Default session keyspace - LOWEST precedence
+func Example_setKeyspace() {
+       /* The example assumes the following CQL was used to setup the 
keyspaces:
+       create keyspace example with replication = { 'class' : 
'SimpleStrategy', 'replication_factor' : 1 };
+       create keyspace example2 with replication = { 'class' : 
'SimpleStrategy', 'replication_factor' : 1 };
+       create keyspace example3 with replication = { 'class' : 
'SimpleStrategy', 'replication_factor' : 1 };
+       create table example.users(id int, name text, PRIMARY KEY(id));
+       create table example2.users(id int, name text, PRIMARY KEY(id));
+       create table example3.users(id int, name text, PRIMARY KEY(id));
+       */
+       cluster := gocql.NewCluster("localhost:9042")
+       cluster.ProtoVersion = 5     // SetKeyspace requires Protocol 5+, 
available in Cassandra 4.0+
+       cluster.Keyspace = "example" // Set a default keyspace
+       session, err := cluster.CreateSession()
+       if err != nil {
+               log.Fatal(err)
+       }
+       defer session.Close()
+
+       ctx := context.Background()
+
+       // Example 1: Keyspace Precedence Hierarchy Demonstration
+       fmt.Println("Demonstrating complete keyspace precedence hierarchy:")
+       fmt.Println("1. Keyspace in CQL (keyspace.table) - HIGHEST")
+       fmt.Println("2. SetKeyspace() method - MIDDLE")
+       fmt.Println("3. Default session keyspace - LOWEST")
+       fmt.Println()
+
+       // Insert test data
+       // Default keyspace (example) - lowest precedence
+       err = session.Query("INSERT INTO users (id, name) VALUES (?, ?)").
+               Bind(1, "Alice").
+               ExecContext(ctx)
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       // SetKeyspace overrides default - middle precedence
+       err = session.Query("INSERT INTO users (id, name) VALUES (?, ?)").
+               SetKeyspace("example2").
+               Bind(1, "Bob").
+               ExecContext(ctx)
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       // Fully qualified table name - highest precedence
+       err = session.Query("INSERT INTO example3.users (id, name) VALUES (?, 
?)").
+               Bind(1, "Charlie").
+               ExecContext(ctx)
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       // Example 2: Fully qualified table names override SetKeyspace
+       fmt.Println("Example 2: Fully qualified table names take precedence 
over SetKeyspace:")
+
+       // This query sets keyspace to "example2" via SetKeyspace, but the 
fully qualified
+       // table name "example3.users" takes precedence - query will target 
example3
+       err = session.Query("INSERT INTO example3.users (id, name) VALUES (?, 
?)").
+               SetKeyspace("example2"). // This is IGNORED because CQL has 
"example3.users"
+               Bind(2, "Diana").
+               ExecContext(ctx)
+       if err != nil {
+               log.Fatal(err)
+       }
+       fmt.Println("Inserted Diana into example3.users despite 
SetKeyspace(\"example2\")")
+
+       // Verify data went to example3, not example2
+       var count int
+       iter := session.Query("SELECT COUNT(*) FROM users").
+               SetKeyspace("example2").
+               IterContext(ctx)
+       if iter.Scan(&count) {
+               fmt.Printf("Count in example2: %d (only Bob)\n", count)
+       }
+       if err := iter.Close(); err != nil {
+               log.Fatal(err)
+       }
+
+       iter = session.Query("SELECT COUNT(*) FROM users").
+               SetKeyspace("example3").
+               IterContext(ctx)
+       if iter.Scan(&count) {
+               fmt.Printf("Count in example3: %d (Charlie and Diana)\n", count)
+       }
+       if err := iter.Close(); err != nil {
+               log.Fatal(err)
+       }
+
+       // Example 3: SetKeyspace overrides default keyspace
+       fmt.Println("\nExample 3: SetKeyspace overrides default keyspace:")
+
+       // Query using default keyspace (no SetKeyspace)
+       var id int
+       var name string
+       iter = session.Query("SELECT id, name FROM users WHERE id = ?", 1).
+               IterContext(ctx) // Uses default keyspace "example"
+       if iter.Scan(&id, &name) {
+               fmt.Printf("Default keyspace (example): ID %d, Name %s\n", id, 
name)
+       }
+       if err := iter.Close(); err != nil {
+               log.Fatal(err)
+       }
+
+       // SetKeyspace overrides default
+       iter = session.Query("SELECT id, name FROM users WHERE id = ?", 1).
+               SetKeyspace("example2"). // Override default keyspace
+               IterContext(ctx)
+       if iter.Scan(&id, &name) {
+               fmt.Printf("SetKeyspace override (example2): ID %d, Name %s\n", 
id, name)
+       }
+       if err := iter.Close(); err != nil {
+               log.Fatal(err)
+       }
+
+       // Example 4: Mixed query patterns in one workflow
+       fmt.Println("\nExample 4: Using all precedence levels in one workflow:")
+
+       // Query from default keyspace
+       iter = session.Query("SELECT name FROM users WHERE id = 
1").IterContext(ctx)
+       if iter.Scan(&name) {
+               fmt.Printf("Default (example): %s\n", name)
+       }
+       iter.Close()
+
+       // Query using SetKeyspace
+       iter = session.Query("SELECT name FROM users WHERE id = 1").
+               SetKeyspace("example2").IterContext(ctx)
+       if iter.Scan(&name) {
+               fmt.Printf("SetKeyspace (example2): %s\n", name)
+       }
+       iter.Close()
+
+       // Query using fully qualified table name (ignores both default and 
SetKeyspace)
+       iter = session.Query("SELECT name FROM example3.users WHERE id = 1").
+               SetKeyspace("example2"). // This is ignored due to qualified 
table name
+               IterContext(ctx)
+       if iter.Scan(&name) {
+               fmt.Printf("Qualified name (example3): %s\n", name)
+       }
+       iter.Close()
+
+       // Demonstrating complete keyspace precedence hierarchy:
+       // 1. Keyspace in CQL (keyspace.table) - HIGHEST
+       // 2. SetKeyspace() method - MIDDLE
+       // 3. Default session keyspace - LOWEST
+       //
+       // Example 2: Fully qualified table names take precedence over 
SetKeyspace:
+       // Inserted Diana into example3.users despite SetKeyspace("example2")
+       // Count in example2: 1 (only Bob)
+       // Count in example3: 2 (Charlie and Diana)
+       //
+       // Example 3: SetKeyspace overrides default keyspace:
+       // Default keyspace (example): ID 1, Name Alice
+       // SetKeyspace override (example2): ID 1, Name Bob
+       //
+       // Example 4: Using all precedence levels in one workflow:
+       // Default (example): Alice
+       // SetKeyspace (example2): Bob
+       // Qualified name (example3): Charlie
+}
diff --git a/example_structured_logging_test.go 
b/example_structured_logging_test.go
new file mode 100644
index 00000000..c5bd3664
--- /dev/null
+++ b/example_structured_logging_test.go
@@ -0,0 +1,217 @@
+/*
+ * 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.
+ */
+
+package gocql_test
+
+import (
+       "context"
+       "log"
+       "os"
+
+       "github.com/rs/zerolog"
+       "go.uber.org/zap"
+       "go.uber.org/zap/zapcore"
+
+       gocql "github.com/apache/cassandra-gocql-driver/v2"
+       "github.com/apache/cassandra-gocql-driver/v2/gocqlzap"
+       "github.com/apache/cassandra-gocql-driver/v2/gocqlzerolog"
+)
+
+// Example_structuredLogging demonstrates the new structured logging features
+// introduced in 2.0.0. The driver now supports structured logging with proper
+// log levels and integration with popular logging libraries like Zap and 
Zerolog.
+// This example shows production-ready configurations for structured logging 
with
+// proper component separation to distinguish between application and driver 
logs.
+func Example_structuredLogging() {
+       /* 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.log_demo(id int, value text, PRIMARY KEY(id));
+       */
+
+       ctx := context.Background()
+
+       // Example 1: Using Zap logger integration
+       // Create a production Zap logger with structured JSON output and 
human-readable timestamps
+       // Production config uses JSON encoding, info level, and proper error 
handling
+       config := zap.NewProductionConfig()
+       config.EncoderConfig.TimeKey = "timestamp"
+       config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // 
Human-readable timestamp format
+
+       zapLogger, err := config.Build()
+       if err != nil {
+               log.Fatal(err)
+       }
+       defer zapLogger.Sync()
+
+       // Create base logger with service identifier
+       baseLogger := zapLogger.With(zap.String("service", "gocql-app"))
+
+       // Create application and driver loggers with component identifiers
+       appLogger := baseLogger.With(zap.String("component", "app"))
+       driverLogger := baseLogger.With(zap.String("component", "gocql-driver"))
+
+       appLogger.Info("Starting Zap structured logging example",
+               zap.String("example", "structured_logging"),
+               zap.String("logger_type", "zap"))
+
+       // Create gocql logger from driver logger
+       gocqlZapLogger := gocqlzap.NewUnnamedZapLogger(driverLogger)
+
+       zapCluster := gocql.NewCluster("localhost:9042")
+       zapCluster.Keyspace = "example"
+       zapCluster.Logger = gocqlZapLogger
+
+       zapSession, err := zapCluster.CreateSession()
+       if err != nil {
+               appLogger.Fatal("Failed to create session", zap.Error(err))
+       }
+       defer zapSession.Close()
+
+       // Perform some operations that will generate logs
+       appLogger.Info("Inserting data into database",
+               zap.String("operation", "insert"),
+               zap.Int("record_id", 1))
+
+       err = zapSession.Query("INSERT INTO example.log_demo (id, value) VALUES 
(?, ?)").
+               Bind(1, "zap logging demo").
+               ExecContext(ctx)
+       if err != nil {
+               appLogger.Error("Insert operation failed", zap.Error(err))
+               log.Fatal(err)
+       }
+
+       appLogger.Info("Querying data from database",
+               zap.String("operation", "select"),
+               zap.Int("record_id", 1))
+
+       var id int
+       var value string
+       iter := zapSession.Query("SELECT id, value FROM example.log_demo WHERE 
id = ?").
+               Bind(1).
+               IterContext(ctx)
+
+       if iter.Scan(&id, &value) {
+               // Successfully scanned the row
+       }
+       err = iter.Close()
+       if err != nil {
+               appLogger.Error("Select operation failed", zap.Error(err))
+               log.Fatal(err)
+       }
+
+       appLogger.Info("Database operation completed successfully",
+               zap.String("operation", "select"),
+               zap.Int("record_id", id),
+               zap.String("record_value", value))
+
+       // Example 2: Using Zerolog integration
+       // Create a production Zerolog logger with structured JSON output
+       // Production config includes timestamps, service info, and appropriate 
log level
+       baseZerologLogger := zerolog.New(os.Stdout).
+               Level(zerolog.InfoLevel).
+               With().
+               Timestamp().
+               Str("service", "gocql-app").
+               Logger()
+
+       // Create application logger with component identifier
+       appZerologLogger := baseZerologLogger.With().
+               Str("component", "app").
+               Logger()
+
+       // Create driver logger with component identifier
+       driverZerologLogger := baseZerologLogger.With().
+               Str("component", "gocql-driver").
+               Logger()
+
+       appZerologLogger.Info().
+               Str("example", "structured_logging").
+               Str("logger_type", "zerolog").
+               Msg("Starting Zerolog structured logging example")
+
+       // Create gocql logger from driver logger
+       gocqlZerologLogger := 
gocqlzerolog.NewUnnamedZerologLogger(driverZerologLogger)
+
+       zerologCluster := gocql.NewCluster("localhost:9042")
+       zerologCluster.Keyspace = "example"
+       zerologCluster.Logger = gocqlZerologLogger
+
+       zerologSession, err := zerologCluster.CreateSession()
+       if err != nil {
+               appZerologLogger.Fatal().Err(err).Msg("Failed to create 
session")
+       }
+       defer zerologSession.Close()
+
+       // Perform operations with Zerolog
+       appZerologLogger.Info().
+               Str("operation", "insert").
+               Int("record_id", 2).
+               Msg("Inserting data into database")
+
+       err = zerologSession.Query("INSERT INTO example.log_demo (id, value) 
VALUES (?, ?)").
+               Bind(2, "zerolog logging demo").
+               ExecContext(ctx)
+       if err != nil {
+               appZerologLogger.Error().Err(err).Msg("Insert operation failed")
+               log.Fatal(err)
+       }
+
+       appZerologLogger.Info().
+               Str("operation", "select").
+               Int("record_id", 2).
+               Msg("Querying data from database")
+
+       iter = zerologSession.Query("SELECT id, value FROM example.log_demo 
WHERE id = ?").
+               Bind(2).
+               IterContext(ctx)
+
+       if iter.Scan(&id, &value) {
+               // Successfully scanned the row
+       }
+       err = iter.Close()
+       if err != nil {
+               appZerologLogger.Error().Err(err).Msg("Select operation failed")
+               log.Fatal(err)
+       }
+
+       appZerologLogger.Info().
+               Str("operation", "select").
+               Int("record_id", id).
+               Str("record_value", value).
+               Msg("Database operation completed successfully")
+
+       // Example 1 - Zap structured logging output (JSON format):
+       // 
{"level":"info","timestamp":"2023-12-31T12:00:00.000Z","msg":"Starting Zap 
structured logging 
example","service":"gocql-app","component":"app","example":"structured_logging","logger_type":"zap"}
+       // 
{"level":"info","timestamp":"2023-12-31T12:00:00.100Z","msg":"Discovered 
protocol 
version.","service":"gocql-app","component":"gocql-driver","protocol_version":5}
+       // 
{"level":"info","timestamp":"2023-12-31T12:00:00.200Z","msg":"Control 
connection connected to 
host.","service":"gocql-app","component":"gocql-driver","host_addr":"127.0.0.1","host_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"}
+       // 
{"level":"info","timestamp":"2023-12-31T12:00:00.300Z","msg":"Refreshed 
ring.","service":"gocql-app","component":"gocql-driver","ring":"[127.0.0.1-a1b2c3d4-e5f6-7890-abcd-ef1234567890:UP]"}
+       // 
{"level":"info","timestamp":"2023-12-31T12:00:00.400Z","msg":"Session 
initialized successfully.","service":"gocql-app","component":"gocql-driver"}
+       // 
{"level":"info","timestamp":"2023-12-31T12:00:01.000Z","msg":"Inserting data 
into 
database","service":"gocql-app","component":"app","operation":"insert","record_id":1}
+       // 
{"level":"info","timestamp":"2023-12-31T12:00:02.000Z","msg":"Querying data 
from 
database","service":"gocql-app","component":"app","operation":"select","record_id":1}
+       // 
{"level":"info","timestamp":"2023-12-31T12:00:03.000Z","msg":"Database 
operation completed 
successfully","service":"gocql-app","component":"app","operation":"select","record_id":1,"record_value":"zap
 logging demo"}
+       //
+       // Example 2 - Zerolog structured logging output (JSON format):
+       // 
{"level":"info","service":"gocql-app","component":"app","example":"structured_logging","logger_type":"zerolog","time":"2023-12-31T12:00:10Z","message":"Starting
 Zerolog structured logging example"}
+       // 
{"level":"info","service":"gocql-app","component":"gocql-driver","protocol_version":5,"time":"2023-12-31T12:00:10.1Z","message":"Discovered
 protocol version."}
+       // 
{"level":"info","service":"gocql-app","component":"gocql-driver","host_addr":"127.0.0.1","host_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","time":"2023-12-31T12:00:10.2Z","message":"Control
 connection connected to host."}
+       // 
{"level":"info","service":"gocql-app","component":"gocql-driver","ring":"[127.0.0.1-a1b2c3d4-e5f6-7890-abcd-ef1234567890:UP]","time":"2023-12-31T12:00:10.3Z","message":"Refreshed
 ring."}
+       // 
{"level":"info","service":"gocql-app","component":"gocql-driver","time":"2023-12-31T12:00:10.4Z","message":"Session
 initialized successfully."}
+       // 
{"level":"info","service":"gocql-app","component":"app","operation":"insert","record_id":2,"time":"2023-12-31T12:00:11Z","message":"Inserting
 data into database"}
+       // 
{"level":"info","service":"gocql-app","component":"app","operation":"select","record_id":2,"time":"2023-12-31T12:00:12Z","message":"Querying
 data from database"}
+       // 
{"level":"info","service":"gocql-app","component":"app","operation":"select","record_id":2,"record_value":"zerolog
 logging demo","time":"2023-12-31T12:00:13Z","message":"Database operation 
completed successfully"}
+}
diff --git a/example_test.go b/example_test.go
index 0fd432ed..91725198 100644
--- a/example_test.go
+++ b/example_test.go
@@ -52,7 +52,7 @@ func Example() {
 
        // insert a tweet
        if err := session.Query(`INSERT INTO tweet (timeline, id, text) VALUES 
(?, ?, ?)`,
-               "me", gocql.TimeUUID(), "hello world").WithContext(ctx).Exec(); 
err != nil {
+               "me", gocql.TimeUUID(), "hello world").ExecContext(ctx); err != 
nil {
                log.Fatal(err)
        }
 
@@ -63,7 +63,7 @@ func Example() {
         * 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 {
+               "me").Consistency(gocql.One).ScanContext(ctx, &id, &text); err 
!= nil {
                log.Fatal(err)
        }
        fmt.Println("Tweet:", id, text)
@@ -71,7 +71,7 @@ func Example() {
 
        // list all tweets
        scanner := session.Query(`SELECT id, text FROM tweet WHERE timeline = 
?`,
-               "me").WithContext(ctx).Iter().Scanner()
+               "me").IterContext(ctx).Scanner()
        for scanner.Next() {
                err = scanner.Scan(&id, &text)
                if err != nil {
diff --git a/example_udt_map_test.go b/example_udt_map_test.go
index 099008ad..03018c31 100644
--- a/example_udt_map_test.go
+++ b/example_udt_map_test.go
@@ -56,14 +56,14 @@ func Example_userDefinedTypesMap() {
                "field_b": 42,
        }
        err = session.Query("INSERT INTO example.my_udt_table (pk, value) 
VALUES (?, ?)",
-               1, value).WithContext(ctx).Exec()
+               1, value).ExecContext(ctx)
        if err != nil {
                log.Fatal(err)
        }
 
+       // Read the UDT value back
        var readValue map[string]interface{}
-
-       err = session.Query("SELECT value FROM example.my_udt_table WHERE pk = 
1").WithContext(ctx).Scan(&readValue)
+       err = session.Query("SELECT value FROM example.my_udt_table WHERE pk = 
1").ScanContext(ctx, &readValue)
        if err != nil {
                log.Fatal(err)
        }
diff --git a/example_udt_marshaler_test.go b/example_udt_marshaler_test.go
index 3e20cacd..b2dc6acc 100644
--- a/example_udt_marshaler_test.go
+++ b/example_udt_marshaler_test.go
@@ -75,7 +75,7 @@ func ExampleUDTMarshaler() {
                fieldB: 42,
        }
        err = session.Query("INSERT INTO example.my_udt_table (pk, value) 
VALUES (?, ?)",
-               1, value).WithContext(ctx).Exec()
+               1, value).ExecContext(ctx)
        if err != nil {
                log.Fatal(err)
        }
diff --git a/example_udt_struct_test.go b/example_udt_struct_test.go
index 1038741c..1bfdc7b9 100644
--- a/example_udt_struct_test.go
+++ b/example_udt_struct_test.go
@@ -61,14 +61,14 @@ func Example_userDefinedTypesStruct() {
                FieldB: 42,
        }
        err = session.Query("INSERT INTO example.my_udt_table (pk, value) 
VALUES (?, ?)",
-               1, value).WithContext(ctx).Exec()
+               1, value).ExecContext(ctx)
        if err != nil {
                log.Fatal(err)
        }
 
+       // Read the UDT value back
        var readValue MyUDT
-
-       err = session.Query("SELECT value FROM example.my_udt_table WHERE pk = 
1").WithContext(ctx).Scan(&readValue)
+       err = session.Query("SELECT value FROM example.my_udt_table WHERE pk = 
1").ScanContext(ctx, &readValue)
        if err != nil {
                log.Fatal(err)
        }
diff --git a/example_udt_unmarshaler_test.go b/example_udt_unmarshaler_test.go
index 3467b161..2db6c611 100644
--- a/example_udt_unmarshaler_test.go
+++ b/example_udt_unmarshaler_test.go
@@ -72,8 +72,9 @@ func ExampleUDTUnmarshaler() {
 
        ctx := context.Background()
 
+       // Read the UDT value back
        var value MyUDTUnmarshaler
-       err = session.Query("SELECT value FROM example.my_udt_table WHERE pk = 
1").WithContext(ctx).Scan(&value)
+       err = session.Query("SELECT value FROM example.my_udt_table WHERE pk = 
1").ScanContext(ctx, &value)
        if err != nil {
                log.Fatal(err)
        }
diff --git a/example_vector_test.go b/example_vector_test.go
new file mode 100644
index 00000000..8e88c327
--- /dev/null
+++ b/example_vector_test.go
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+package gocql_test
+
+import (
+       "context"
+       "fmt"
+       "log"
+
+       gocql "github.com/apache/cassandra-gocql-driver/v2"
+)
+
+// Example_vector demonstrates how to work with vector search in Cassandra 
5.0+.
+// This example shows Cassandra's native vector search capabilities using ANN 
(Approximate Nearest Neighbor)
+// search with ORDER BY ... ANN OF syntax for finding similar vectors.
+// Note: Requires Cassandra 5.0+ and a SAI index on the vector column for ANN 
search.
+func Example_vector() {
+       /* 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.vectors(
+               id int,
+               item_name text,
+               embedding vector<float, 5>,
+               PRIMARY KEY(id)
+       );
+       -- Create SAI index for vector search (required for ANN)
+       CREATE INDEX IF NOT EXISTS ann_index ON example.vectors(embedding) 
USING 'sai';
+       */
+       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()
+
+       // Create the table first (if it doesn't exist)
+       err = session.Query(`CREATE TABLE IF NOT EXISTS example.vectors(
+               id int, 
+               item_name text, 
+               embedding vector<float, 5>, 
+               PRIMARY KEY(id)
+       )`).ExecContext(ctx)
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       // Create SAI index for vector search (required for ANN search)
+       fmt.Println("Creating SAI index for vector search...")
+       err = session.Query(`CREATE INDEX IF NOT EXISTS ann_index 
+               ON example.vectors(embedding) USING 'sai'`).ExecContext(ctx)
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       // Insert sample vectors representing different items
+       // These could be embeddings from ML models for products, documents, 
etc.
+       vectorData := []struct {
+               id     int
+               name   string
+               vector []float32
+       }{
+               {1, "apple", []float32{0.8, 0.2, 0.1, 0.9, 0.3}},
+               {2, "orange", []float32{0.7, 0.3, 0.2, 0.8, 0.4}},
+               {3, "banana", []float32{0.6, 0.4, 0.9, 0.2, 0.7}},
+               {4, "grape", []float32{0.9, 0.1, 0.3, 0.7, 0.5}},
+               {5, "watermelon", []float32{0.2, 0.8, 0.6, 0.4, 0.9}},
+               {6, "strawberry", []float32{0.8, 0.3, 0.2, 0.9, 0.4}},
+               {7, "pineapple", []float32{0.3, 0.7, 0.8, 0.1, 0.6}},
+               {8, "mango", []float32{0.7, 0.4, 0.5, 0.8, 0.2}},
+       }
+
+       // Insert all vectors
+       fmt.Println("Inserting sample vectors...")
+       for _, item := range vectorData {
+               err = session.Query("INSERT INTO example.vectors (id, 
item_name, embedding) VALUES (?, ?, ?)",
+                       item.id, item.name, item.vector).ExecContext(ctx)
+               if err != nil {
+                       log.Fatal(err)
+               }
+       }
+
+       // Define a query vector (e.g., searching for items similar to 
"apple-like" characteristics)
+       queryVector := []float32{0.8, 0.2, 0.1, 0.9, 0.3}
+       fmt.Printf("Searching for vectors similar to: %v\n\n", queryVector)
+
+       // Perform ANN (Approximate Nearest Neighbor) search using ORDER BY ... 
ANN OF
+       // This finds the 3 most similar vectors to our query vector
+       fmt.Println("Top 3 most similar items (using ANN search):")
+       iter := session.Query(`
+               SELECT id, item_name, embedding
+               FROM example.vectors 
+               ORDER BY embedding ANN OF ? 
+               LIMIT 3`,
+               queryVector,
+       ).IterContext(ctx)
+
+       for {
+               var id int
+               var itemName string
+               var embedding []float32
+
+               if !iter.Scan(&id, &itemName, &embedding) {
+                       break
+               }
+               fmt.Printf("  %s (ID: %d) - Vector: %v\n", itemName, id, 
embedding)
+       }
+       if err := iter.Close(); err != nil {
+               log.Fatal(err)
+       }
+
+       fmt.Println()
+
+       // Perform similarity search with a different query vector
+       queryVector2 := []float32{0.2, 0.8, 0.6, 0.4, 0.9}
+       fmt.Printf("Searching for vectors similar to: %v\n", queryVector2)
+       fmt.Println("Top 4 most similar items:")
+
+       scanner := session.Query(`
+               SELECT id, item_name, embedding
+               FROM example.vectors 
+               ORDER BY embedding ANN OF ? 
+               LIMIT 4`,
+               queryVector2,
+       ).IterContext(ctx).Scanner()
+
+       for scanner.Next() {
+               var id int
+               var itemName string
+               var embedding []float32
+
+               err = scanner.Scan(&id, &itemName, &embedding)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               fmt.Printf("  %s (ID: %d) - Vector: %v\n", itemName, id, 
embedding)
+       }
+       if err := scanner.Err(); err != nil {
+               log.Fatal(err)
+       }
+
+       fmt.Println()
+
+       // Basic vector retrieval (traditional approach)
+       fmt.Println("Basic vector retrieval by ID:")
+       var id int
+       var itemName string
+       var embedding []float32
+       iter = session.Query("SELECT id, item_name, embedding FROM 
example.vectors WHERE id = ?", 1).
+               IterContext(ctx)
+       if !iter.Scan(&id, &itemName, &embedding) {
+               log.Fatal(iter.Close())
+       }
+       fmt.Printf("  %s (ID: %d) - Vector: %v\n", itemName, id, embedding)
+
+       fmt.Println()
+
+       // Show all vectors for comparison
+       fmt.Println("All vectors in the database:")
+       allVectors := session.Query("SELECT id, item_name, embedding FROM 
example.vectors").IterContext(ctx)
+       for {
+               var id int
+               var itemName string
+               var embedding []float32
+
+               if !allVectors.Scan(&id, &itemName, &embedding) {
+                       break
+               }
+               fmt.Printf("  %s (ID: %d) - Vector: %v\n", itemName, id, 
embedding)
+       }
+       if err := allVectors.Close(); err != nil {
+               log.Fatal(err)
+       }
+
+       // Example output:
+       // Creating SAI index for vector search...
+       // Inserting sample vectors...
+       // Searching for vectors similar to: [0.8 0.2 0.1 0.9 0.3]
+       //
+       // Top 3 most similar items (using ANN search):
+       //   apple (ID: 1) - Vector: [0.8 0.2 0.1 0.9 0.3]
+       //   strawberry (ID: 6) - Vector: [0.8 0.3 0.2 0.9 0.4]
+       //   orange (ID: 2) - Vector: [0.7 0.3 0.2 0.8 0.4]
+}
diff --git a/session_test.go b/session_test.go
index 3fcb2163..3eeba22f 100644
--- a/session_test.go
+++ b/session_test.go
@@ -78,7 +78,7 @@ func TestSessionAPI(t *testing.T) {
        err := testBatch.Exec()
 
        if err != ErrNoConnections {
-               t.Fatalf("expected session.ExecuteBatch to return '%v', got 
'%v'", ErrNoConnections, err)
+               t.Fatalf("expected batch.Exec to return '%v', got '%v'", 
ErrNoConnections, err)
        }
 
        s.Close()
@@ -90,7 +90,7 @@ func TestSessionAPI(t *testing.T) {
 
        err = testBatch.Exec()
        if err != ErrSessionClosed {
-               t.Fatalf("expected session.ExecuteBatch to return '%v', got 
'%v'", ErrSessionClosed, err)
+               t.Fatalf("expected batch.Exec to return '%v', got '%v'", 
ErrSessionClosed, err)
        }
 }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to