package std import ( "context" "fmt" "github.com/ClickHouse/clickhouse-go/v2" ) func DynamicExample() error { ctx := context.Background() conn, err := GetStdOpenDBConnection(clickhouse.Native, nil, nil, nil) if err != nil { return err } if !CheckMinServerVersion(conn, 25, 6, 0) { fmt.Print("unsupported clickhouse version for Dynamic type") return nil } _, err = conn.ExecContext(ctx, "SET allow_experimental_dynamic_type = 1") if err != nil { return err } _, err = conn.ExecContext(ctx, "SET output_format_native_use_flattened_dynamic_and_json_serialization = 1") if err != nil { return err } defer func() { conn.Exec("DROP TABLE go_dynamic_example") }() _, err = conn.ExecContext(ctx, "DROP TABLE IF EXISTS go_dynamic_example") if err != nil { return err } _, err = conn.ExecContext(ctx, ` CREATE TABLE go_dynamic_example ( c Dynamic ) ENGINE = Memory `) if err != nil { return err } tx, err := conn.BeginTx(ctx, nil) if err != nil { return err } batch, err := tx.PrepareContext(ctx, "INSERT INTO go_dynamic_example (c)") if err != nil { return err } if _, err = batch.ExecContext(ctx, true); err != nil { return err } if _, err = batch.ExecContext(ctx, int64(42)); err != nil { return err } if _, err = batch.ExecContext(ctx, "example"); err != nil { return err } if _, err = batch.ExecContext(ctx, clickhouse.NewDynamic("example dynamic")); err != nil { return err } if _, err = batch.ExecContext(ctx, clickhouse.NewDynamicWithType("example dynamic with specific type", "String")); err != nil { return err } if _, err = batch.ExecContext(ctx, nil); err != nil { return err } if err = tx.Commit(); err != nil { return err } // Switch on Go Type rows, err := conn.QueryContext(ctx, "SELECT c FROM go_dynamic_example") if err != nil { return err } for i := 0; rows.Next(); i++ { var row clickhouse.Dynamic err := rows.Scan(&row) if err != nil { return fmt.Errorf("failed to scan row index %d: %w", i, err) } switch row.Any().(type) { case bool: fmt.Printf("row at index %d is Bool: %v\n", i, row.Any()) case int64: fmt.Printf("row at index %d is Int64: %v\n", i, row.Any()) case string: fmt.Printf("row at index %d is String: %v\n", i, row.Any()) case nil: fmt.Printf("row at index %d is NULL\n", i) } } // Switch on ClickHouse Type rows, err = conn.QueryContext(ctx, "SELECT c FROM go_dynamic_example") if err != nil { return err } for i := 0; rows.Next(); i++ { var row clickhouse.Dynamic err := rows.Scan(&row) if err != nil { return fmt.Errorf("failed to scan row index %d: %w", i, err) } switch row.Type() { case "Bool": fmt.Printf("row at index %d is bool: %v\n", i, row.Any()) case "Int64": fmt.Printf("row at index %d is int64: %v\n", i, row.Any()) case "String": fmt.Printf("row at index %d is string: %v\n", i, row.Any()) case "": fmt.Printf("row at index %d is nil\n", i) } } return nil }