/** * CQL Minus - cqlminus * * This file is licensed under the Affero General Public License version 3 or * later. See the COPYING file. * * @author Paolo Lulli * @copyright Paolo Lulli 2026 */ package db import ( "cqlminus/internal/config" "fmt" "time" "github.com/gocql/gocql" ) // Config holds the connection settings loaded from the JSON config file. func Connect(cfg *config.Config) (*gocql.Session, error) { cluster := gocql.NewCluster(cfg.Endpoint) cluster.Keyspace = cfg.Keyspace cluster.Consistency = gocql.LocalQuorum cluster.Timeout = 10 * time.Second if cfg.Username != "" { cluster.Authenticator = gocql.PasswordAuthenticator{ Username: cfg.Username, Password: cfg.Password, } } if cfg.TlsCertificate != "" { cluster.SslOpts = buildSslOptions(cfg) } session, err := cluster.CreateSession() if err != nil { return nil, fmt.Errorf("connecting to cassandra: %w", err) } return session, nil } // QueryResult holds column names and row data returned from a CQL query. type QueryResult struct { Columns []string Rows [][]string } func RunQuery(session *gocql.Session, query string) (*QueryResult, error) { iter := session.Query(query).Iter() columns := iter.Columns() colNames := make([]string, len(columns)) for i, c := range columns { colNames[i] = c.Name } result := &QueryResult{Columns: colNames} row := make(map[string]interface{}) for iter.MapScan(row) { strRow := make([]string, len(colNames)) for i, name := range colNames { strRow[i] = formatValue(row[name]) } result.Rows = append(result.Rows, strRow) row = make(map[string]interface{}) } if err := iter.Close(); err != nil { return nil, fmt.Errorf("query error: %w", err) } return result, nil }