Documentation
¶
Overview ¶
Package query owns the analytics read path. HTTP and MCP adapters call this package instead of constructing ClickHouse SQL settings themselves, so tenant isolation and query limits stay in one place.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrEmptySQL is returned before ClickHouse is touched when the request // body doesn't carry a query. ErrEmptySQL = errors.New("sql is required") // ErrRowLimitExceeded is used by the web playground sink to stop rendering // before a huge result set is buffered in memory. ErrRowLimitExceeded = errors.New("row limit exceeded") // ErrSettingsNotAllowed is returned when user SQL carries its own SETTINGS // clause. The readonly user runs with readonly=2 so the app can attach // per-request settings (additional_table_filters, resource limits); that // same mode lets a user-supplied SETTINGS clause OVERRIDE those settings, // including the tenant-isolation filter. We reject such queries rather than // let a query silently widen its own scope. Query settings are the server's // to control, not the caller's. ErrSettingsNotAllowed = errors.New("SETTINGS clause is not allowed in queries") )
Functions ¶
This section is empty.
Types ¶
type Column ¶
type Column struct {
Name string `json:"name"`
Type string `json:"type"`
Description string `json:"description,omitempty"`
}
Column describes one query output or schema column. Description is only populated on the schema surface (curated, keyed by column name); query result columns leave it empty and omitempty keeps it off the wire there.
type Executor ¶
type Executor struct {
MaxExecutionTime int
MaxMemoryUsage uint64
MaxResultRows uint64
// contains filtered or unexported fields
}
Executor runs user SQL through the readonly ClickHouse pool with project filters and bounded resource settings.
func NewExecutor ¶
NewExecutor builds an executor over the readonly ClickHouse pool. database is usually "analytics". The public allowlist exposes only the curated events/persons/sessions surface; filterNames holds the hidden physical tables those views read so tenant isolation still anchors to real storage.
func (*Executor) Collect ¶
func (e *Executor) Collect(ctx context.Context, projectID, sqlText string, maxRows int) (Result, error)
Collect runs a query and buffers up to maxRows rows for the web playground.
func (*Executor) StreamJSON ¶
func (e *Executor) StreamJSON(ctx context.Context, projectID, sqlText string, w io.Writer) (Stats, error)
StreamJSON writes the API response envelope incrementally:
{"columns":[...],"rows":[...],"stats":{...}}
Rows are emitted as arrays in column order. The caller must set status and Content-Type before calling if it wants headers written early.
type Querier ¶
type Querier interface {
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
}
Querier is the subset of *sql.DB the executor needs. Tests use it to assert the original request context reaches the ClickHouse driver call.
type Result ¶
Result is the bounded in-memory shape used by the web playground. The API route streams instead.
type Schema ¶
type Schema struct {
Tables []SchemaTable `json:"tables"`
}
Schema is the public catalog exposed by /api/v1/.../schema and MCP. It is derived from the executor's table allowlist and enriched with curated descriptions so an agent (or human) can build effective queries without guessing what each table and column means.
type SchemaProvider ¶
type SchemaProvider struct {
// contains filtered or unexported fields
}
SchemaProvider reads ClickHouse metadata for the allowlisted query tables.
func NewSchemaProvider ¶
func NewSchemaProvider(db Querier, exec *Executor) *SchemaProvider