gospice

package module
v8.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 6, 2026 License: Apache-2.0 Imports: 34 Imported by: 0

README

gospice

Golang SDK for Spice.ai

See Go Docs at pkg.go.dev/github.com/spiceai/gospice/v8.

For full documentation visit docs.spice.ai.

Usage

  1. Get the gospice package.
go get github.com/spiceai/gospice/v8@latest
  1. Import the package.
import "github.com/spiceai/gospice/v8"
  1. Create a SpiceClient passing in your API key. Get your free API key at spice.ai.
spice := NewSpiceClient()
defer spice.Close()
  1. Initialize the SpiceClient with spice.ai cloud.
if err := spice.Init(
    spice.WithApiKey(ApiKey),
    spice.WithSpiceCloudAddress()
); err != nil {
    panic(fmt.Errorf("error initializing SpiceClient: %w", err))
}
  1. Execute a query and get back an Apache Arrow Reader.
    reader, err := spice.Query(context.Background(), "SELECT 1")
    if err != nil {
        panic(fmt.Errorf("error querying: %w", err))
    }
    defer reader.Release()
  1. Iterate through the reader to access the records.
    for reader.Next() {
        record := reader.RecordBatch()
        defer record.Release()
        fmt.Println(record)
    }

gospice v8 supports parameterized queries using ADBC (Arrow Database Connectivity), which is the recommended approach for queries with parameters to prevent SQL injection:

// Query with a single parameter
reader, err := spice.SqlWithParams(
    context.Background(),
    "SELECT * FROM tpch.customer WHERE c_custkey > $1 LIMIT 10",
    100,
)
if err != nil {
    panic(fmt.Errorf("error querying: %w", err))
}
defer reader.Release()

for reader.Next() {
    record := reader.RecordBatch()
    defer record.Release()
    fmt.Println(record)
}

Query with multiple parameters:

reader, err := spice.SqlWithParams(
    context.Background(),
    "SELECT * FROM taxi_trips WHERE trip_distance > $1 AND fare_amount > $2 LIMIT 100",
    5.0,
    20.0,
)
if err != nil {
    panic(fmt.Errorf("error querying: %w", err))
}
defer reader.Release()

Supported parameter types with automatic type inference:

  • Integers: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64
  • Floating point: float32, float64
  • String: string
  • Boolean: bool
  • Binary: []byte
  • Null values: nil

Typed Parameters for Advanced Use Cases:

For precise control over Arrow types, use typed parameter constructors:

import "github.com/spiceai/gospice/v8"

// Explicit type control for complex scenarios
reader, err := spice.SqlWithParams(
    ctx,
    "SELECT * FROM data WHERE id = $1 AND amount = $2 AND active = $3",
    gospice.Int64Param(12345),           // Explicitly int64
    gospice.Decimal128Param(...),        // Decimal with precision
    gospice.BoolParam(true),             // Explicitly boolean
)

Available typed parameter constructors:

  • Integers: Int8Param, Int16Param, Int32Param, Int64Param, Uint8Param, Uint16Param, Uint32Param, Uint64Param
  • Floating point: Float16Param, Float32Param, Float64Param
  • Strings: StringParam, LargeStringParam
  • Binary: BinaryParam, LargeBinaryParam, FixedSizeBinaryParam
  • Boolean: BoolParam
  • Date/Time: Date32Param, Date64Param, Time32Param, Time64Param, TimestampParam, DurationParam
  • Intervals: MonthIntervalParam, DayTimeIntervalParam, MonthDayNanoIntervalParam
  • Decimals: Decimal128Param, Decimal256Param
  • Null: NullParam

Or use the generic constructors:

  • NewParam(value) - Creates a parameter with automatic type inference
  • NewTypedParam(value, arrowType) - Creates a parameter with explicit Arrow type
Using local spice runtime

Follow the quickstart guide to install and run spice locally

Initialize the SpiceClient to use local runtime connection:

if err := spice.Init(); err != nil {
    panic(fmt.Errorf("error initializing SpiceClient: %w", err))
}

Configure with a custom flight address:

if err := spice.Init(
    spice.WithFlightAddress("grpc://localhost:50052")
); err != nil {
    panic(fmt.Errorf("error initializing SpiceClient: %w", err))
}

Health Checks

gospice v8 provides health check methods to verify Spice instance status before executing queries:

// Check if Spice instance is healthy (unauthenticated)
ctx := context.Background()
if !spice.IsSpiceHealthy(ctx) {
    log.Println("Spice instance is not healthy")
    return
}

// Check if Spice Cloud is ready (requires API key)
if !spice.IsSpiceReady(ctx) {
    log.Println("Spice Cloud is not ready or API key is invalid")
    return
}
  • IsSpiceHealthy(ctx) - Calls /health endpoint (unauthenticated)
  • IsSpiceReady(ctx) - Calls /v1/ready endpoint (requires API key)

Example

Run go run . to execute a sample query and print the results to the console.

See query_test.go for examples on querying TPC-H and taxi trips datasets.

Connection retry

The SpiceClient implements connection retry mechanism (3 attempts by default). The number of attempts can be configured via SetMaxRetries:

spice := NewSpiceClient()
spice.SetMaxRetries(5) // Setting to 0 will disable retries

Retries are performed for connection and system internal errors. It is the SDK user's responsibility to properly handle other errors, for example RESOURCE_EXHAUSTED (HTTP 429).

Upgrading from v7 to v8

gospice v8 is fully backward compatible with v7. To upgrade:

go get github.com/spiceai/gospice/v8@latest
go mod tidy

Update your imports:

// Before
import "github.com/spiceai/gospice/v7"

// After
import "github.com/spiceai/gospice/v8"

What's new in v8:

  • New Sql() and SqlWithParams() methods for cleaner API (.Query() methods still work for backward compatibility)
  • IsSpiceHealthy() and IsSpiceReady() health check methods
  • Apache Arrow v18 and Go 1.24 support

See UPGRADE_V7_TO_V8.md for detailed migration guide.

Testing and Benchmarking

Running Tests

Run all tests:

go test ./...

Run tests with verbose output:

go test -v ./...

Run specific test suites:

# Local runtime tests only
go test -v -run="TestLocal"

# Cloud tests only
go test -v -run="TestCloud"

# ADBC tests only
go test -v -run="TestADBC"
Running Benchmarks

Run all benchmarks:

go test -bench=. -benchmem

Run specific benchmarks:

# Benchmark query performance
go test -bench=BenchmarkQuery -benchmem

# Benchmark parameterized queries
go test -bench=BenchmarkQueryWithParams -benchmem

# Benchmark health checks
go test -bench=BenchmarkHealthChecks -benchmem

# Benchmark client initialization
go test -bench=BenchmarkClientInitialization -benchmem

Run benchmarks with custom settings:

# Run for 10 seconds each
go test -bench=. -benchtime=10s

# Run with CPU profiling
go test -bench=. -cpuprofile=cpu.prof

# Run with memory profiling
go test -bench=. -memprofile=mem.prof

Available benchmarks:

  • BenchmarkCloudQuery - Basic query performance against Spice Cloud
  • BenchmarkCloudQueryWithParams - Parameterized query performance (Cloud)
  • BenchmarkLocalQuery - Query performance against local runtime
  • BenchmarkLocalQueryWithParams - Parameterized query performance (Local)
  • BenchmarkParameterBinding - Parameter binding overhead with varying parameter counts
  • BenchmarkClientInitialization - Client initialization overhead
  • BenchmarkHealthChecks - Health check endpoint performance
  • BenchmarkRecordProcessing - Different record processing patterns

Documentation

Index

Constants

View Source
const GO_SPICE_VERSION = "8.0.0"
View Source
const (
	MAX_MESSAGE_SIZE_BYTES = 100 * 1024 * 1024
)

Variables

This section is empty.

Functions

func FlightHeadersInterceptor

func FlightHeadersInterceptor(headers map[string]string) grpc.UnaryClientInterceptor

func GetOSRelease

func GetOSRelease() string

func GetOrCreateTracer

func GetOrCreateTracer(traceName string) trace.Tracer

GetOrCreateTracer adds a new tracer to the global tracer provider if one doesn't already exist

func GetSpiceUserAgent

func GetSpiceUserAgent() string

func RemoveNonPrintableASCII

func RemoveNonPrintableASCII(str string) string

Types

type ADBCClient

type ADBCClient struct {
	// contains filtered or unexported fields
}

ADBCClient wraps ADBC database and connection for Spice.ai

type ClientConfig

type ClientConfig struct {
	HttpUrl   string `json:"http_url,omitempty"`
	FlightUrl string `json:"flight_url,omitempty"`
}

func LoadConfig

func LoadConfig() ClientConfig

func LoadLocalConfig

func LoadLocalConfig() ClientConfig

type DatasetRefreshRequest

type DatasetRefreshRequest struct {
	RefreshSQL *string      `json:"refresh_sql,omitempty"`
	Mode       *RefreshMode `json:"refresh_mode,omitempty"`
	MaxJitter  *string      `json:"refresh_jitter_max,omitempty"`
}

type Param

type Param struct {
	Value any
	Type  arrow.DataType
}

Param represents a query parameter with an optional explicit Arrow type. If Type is nil, the type will be inferred from the Value.

func BinaryParam

func BinaryParam(value []byte) Param

BinaryParam creates a binary parameter

func BoolParam

func BoolParam(value bool) Param

BoolParam creates a boolean parameter

func Date32Param

func Date32Param(value arrow.Date32) Param

Date32Param creates a Date32 parameter

func Date64Param

func Date64Param(value arrow.Date64) Param

Date64Param creates a Date64 parameter

func DayTimeIntervalParam

func DayTimeIntervalParam(value arrow.DayTimeInterval) Param

DayTimeIntervalParam creates a DayTimeInterval parameter

func Decimal128Param

func Decimal128Param(value [16]byte, precision, scale int32) Param

Decimal128Param creates a Decimal128 parameter with specified precision and scale

func Decimal256Param

func Decimal256Param(value [32]byte, precision, scale int32) Param

Decimal256Param creates a Decimal256 parameter with specified precision and scale

func DurationParam

func DurationParam(value arrow.Duration, unit arrow.TimeUnit) Param

DurationParam creates a Duration parameter with specified unit

func FixedSizeBinaryParam

func FixedSizeBinaryParam(value []byte, byteWidth int) Param

FixedSizeBinaryParam creates a FixedSizeBinary parameter with specified byte width

func Float16Param

func Float16Param(value uint16) Param

Float16Param creates a float16 parameter

func Float32Param

func Float32Param(value float32) Param

Float32Param creates a float32 parameter

func Float64Param

func Float64Param(value float64) Param

Float64Param creates a float64 parameter

func Int8Param

func Int8Param(value int8) Param

Int8Param creates an int8 parameter

func Int16Param

func Int16Param(value int16) Param

Int16Param creates an int16 parameter

func Int32Param

func Int32Param(value int32) Param

Int32Param creates an int32 parameter

func Int64Param

func Int64Param(value int64) Param

Int64Param creates an int64 parameter

func LargeBinaryParam

func LargeBinaryParam(value []byte) Param

LargeBinaryParam creates a large binary parameter

func LargeStringParam

func LargeStringParam(value string) Param

LargeStringParam creates a large string parameter

func MonthDayNanoIntervalParam

func MonthDayNanoIntervalParam(value arrow.MonthDayNanoInterval) Param

MonthDayNanoIntervalParam creates a MonthDayNanoInterval parameter

func MonthIntervalParam

func MonthIntervalParam(value arrow.MonthInterval) Param

MonthIntervalParam creates a MonthInterval parameter

func NewParam

func NewParam(value any) Param

NewParam creates a new parameter with inferred type

func NewTypedParam

func NewTypedParam(value any, dataType arrow.DataType) Param

NewTypedParam creates a new parameter with explicit type

func NullParam

func NullParam() Param

NullParam creates a null parameter

func StringParam

func StringParam(value string) Param

StringParam creates a string parameter

func Time32Param

func Time32Param(value arrow.Time32, unit arrow.TimeUnit) Param

Time32Param creates a Time32 parameter with specified unit

func Time64Param

func Time64Param(value arrow.Time64, unit arrow.TimeUnit) Param

Time64Param creates a Time64 parameter with specified unit

func TimestampParam

func TimestampParam(value arrow.Timestamp, unit arrow.TimeUnit, timezone string) Param

TimestampParam creates a Timestamp parameter with specified unit and timezone

func Uint8Param

func Uint8Param(value uint8) Param

Uint8Param creates a uint8 parameter

func Uint16Param

func Uint16Param(value uint16) Param

Uint16Param creates a uint16 parameter

func Uint32Param

func Uint32Param(value uint32) Param

Uint32Param creates a uint32 parameter

func Uint64Param

func Uint64Param(value uint64) Param

Uint64Param creates a uint64 parameter

type RefreshMode

type RefreshMode string
const (
	RefreshModeFull   RefreshMode = "full"
	RefreshModeAppend RefreshMode = "append"
)

type SpiceClient

type SpiceClient struct {
	// contains filtered or unexported fields
}

SpiceClient is a client for Spice.ai OSS, a unified SQL query interface and portable runtime to locally materialize, accelerate, and query datasets across databases, data warehouses, and data lakes.

https://spiceai.org For documentation visit https://docs.spiceai.org/sdks/golang

func NewSpiceClient

func NewSpiceClient() *SpiceClient

NewSpiceClient creates a new SpiceClient

func NewSpiceClientWithAddress

func NewSpiceClientWithAddress(flightAddress string) *SpiceClient

func (*SpiceClient) Close

func (c *SpiceClient) Close() error

Close closes the SpiceClient and cleans up resources

func (*SpiceClient) Init

func (c *SpiceClient) Init(opts ...SpiceClientModifier) error

Init initializes the SpiceClient

func (*SpiceClient) IsSpiceHealthy

func (c *SpiceClient) IsSpiceHealthy(ctx context.Context) bool

IsSpiceHealthy checks if the Spice instance is healthy by calling the /health endpoint. This is an unauthenticated endpoint that returns 200 OK with "ok" in the body if the instance is healthy. Returns true if healthy, false otherwise.

func (*SpiceClient) IsSpiceReady

func (c *SpiceClient) IsSpiceReady(ctx context.Context) bool

IsSpiceReady checks if the Spice instance is ready to accept queries by calling the /v1/ready endpoint. For Spice Cloud, this endpoint requires authentication via API key. For local Spice instances, no API key is required. Returns "ready" in the body when ready. Returns true if ready, false otherwise.

func (*SpiceClient) Query

func (c *SpiceClient) Query(ctx context.Context, sql string) (array.RecordReader, error)

Query is deprecated. Use Sql instead. Kept for backward compatibility with v7.

func (*SpiceClient) QueryWithParams

func (c *SpiceClient) QueryWithParams(ctx context.Context, sql string, params ...any) (array.RecordReader, error)

QueryWithParams is deprecated. Use SqlWithParams instead. Kept for backward compatibility with v7.

func (*SpiceClient) RefreshDataset

func (c *SpiceClient) RefreshDataset(ctx context.Context, dataset string, opts *DatasetRefreshRequest) error

func (*SpiceClient) SetMaxRetries

func (c *SpiceClient) SetMaxRetries(maxRetries uint)

Sets the maximum number of times to retry Query and FireQuery calls. The default is 3. Setting to 0 will disable retries.

func (*SpiceClient) Sql

Sql executes a SQL query against Spice.ai and returns an Apache Arrow RecordReader For more information on Apache Arrow RecordReader visit https://godoc.org/github.com/apache/arrow/go/arrow/array#RecordReader

func (*SpiceClient) SqlWithParams

func (c *SpiceClient) SqlWithParams(ctx context.Context, sql string, params ...any) (array.RecordReader, error)

SqlWithParams executes a parameterized SQL query against Spice.ai and returns an Apache Arrow RecordReader This is the recommended method for querying with parameters to prevent SQL injection Parameters should use positional placeholders (e.g., $1, $2) in the SQL query

Parameters can be: - Simple Go values (int, string, bool, etc.) - type will be inferred - Param structs with explicit type annotation using NewTypedParam() or helper functions - Arrow types (arrow.Date32, arrow.Timestamp, etc.)

Example:

reader, err := client.SqlWithParams(ctx, "SELECT * FROM table WHERE id = $1 AND name = $2", 123, "test")
reader, err := client.SqlWithParams(ctx, "SELECT * FROM table WHERE ts = $1", TimestampParam(ts, arrow.Microsecond, "UTC"))

type SpiceClientModifier

type SpiceClientModifier func(c *SpiceClient) error

func WithApiKey

func WithApiKey(apiKey string) SpiceClientModifier

func WithFlightAddress

func WithFlightAddress(address string) SpiceClientModifier

func WithHttpAddress

func WithHttpAddress(address string) SpiceClientModifier

func WithSpiceCloudAddress

func WithSpiceCloudAddress() SpiceClientModifier

func WithUserAgent

func WithUserAgent(userAgent string) SpiceClientModifier

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL