Documentation
¶
Overview ¶
Package cel2sql provides query analysis and index recommendations
Package cel2sql converts CEL (Common Expression Language) expressions to SQL conditions. It supports multiple SQL dialects through the dialect interface, with PostgreSQL as the default.
Index ¶
- Constants
- Variables
- func Convert(ast *cel.Ast, opts ...ConvertOption) (string, error)
- type ComprehensionInfo
- type ComprehensionType
- type ConversionError
- type ConvertOption
- func WithContext(ctx context.Context) ConvertOption
- func WithDialect(d dialect.Dialect) ConvertOption
- func WithLogger(logger *slog.Logger) ConvertOption
- func WithMaxDepth(maxDepth int) ConvertOption
- func WithMaxOutputLength(maxLength int) ConvertOption
- func WithSchemas(schemas map[string]schema.Schema) ConvertOption
- type IndexRecommendation
- type Result
Constants ¶
const ( // IndexTypeBTree represents a B-tree index for efficient range queries and equality checks IndexTypeBTree = "BTREE" // IndexTypeGIN represents a GIN (Generalized Inverted Index) for JSON, arrays, and full-text search IndexTypeGIN = "GIN" // IndexTypeGIST represents a GIST (Generalized Search Tree) index IndexTypeGIST = "GIST" )
Index type constants for recommendations (kept for backward compatibility).
Variables ¶
var ( // ErrUnsupportedExpression indicates an unsupported CEL expression type ErrUnsupportedExpression = errors.New("unsupported expression type") // ErrInvalidFieldName indicates an invalid or empty field name ErrInvalidFieldName = errors.New("invalid field name") // ErrInvalidSchema indicates a problem with the provided schema ErrInvalidSchema = errors.New("invalid schema") // ErrInvalidRegexPattern indicates an invalid regex pattern ErrInvalidRegexPattern = errors.New("invalid regex pattern") // ErrMaxDepthExceeded indicates recursion depth limit exceeded ErrMaxDepthExceeded = errors.New("maximum recursion depth exceeded") // ErrMaxOutputLengthExceeded indicates output length limit exceeded ErrMaxOutputLengthExceeded = errors.New("maximum output length exceeded") // ErrInvalidComprehension indicates an invalid comprehension expression ErrInvalidComprehension = errors.New("invalid comprehension expression") // ErrMaxComprehensionDepthExceeded indicates comprehension nesting depth exceeded ErrMaxComprehensionDepthExceeded = errors.New("maximum comprehension depth exceeded") // ErrInvalidArguments indicates invalid function arguments ErrInvalidArguments = errors.New("invalid function arguments") // ErrUnsupportedOperation indicates an operation that cannot be converted to SQL ErrUnsupportedOperation = errors.New("unsupported operation") // ErrInvalidTimestampOperation indicates an invalid timestamp operation ErrInvalidTimestampOperation = errors.New("invalid timestamp operation") // ErrInvalidDuration indicates an invalid duration value ErrInvalidDuration = errors.New("invalid duration value") // ErrInvalidJSONPath indicates an invalid JSON path expression ErrInvalidJSONPath = errors.New("invalid JSON path") // ErrInvalidOperator indicates an invalid operator ErrInvalidOperator = errors.New("invalid operator") // ErrUnsupportedType indicates an unsupported type ErrUnsupportedType = errors.New("unsupported type") // ErrContextCanceled indicates the operation was cancelled via context ErrContextCanceled = errors.New("operation cancelled") // ErrInvalidByteArrayLength indicates byte array exceeds maximum length ErrInvalidByteArrayLength = errors.New("byte array exceeds maximum length") // ErrUnsupportedDialectFeature indicates a feature not supported by the selected dialect ErrUnsupportedDialectFeature = errors.New("unsupported dialect feature") )
Sentinel errors for common error conditions. These exported errors allow callers to use errors.Is() for specific error handling.
Functions ¶
func Convert ¶
func Convert(ast *cel.Ast, opts ...ConvertOption) (string, error)
Convert converts a CEL AST to a SQL WHERE clause condition. By default, PostgreSQL SQL is generated. Use WithDialect to select a different dialect.
Example without options (PostgreSQL):
sql, err := cel2sql.Convert(ast)
Example with schema information for JSON/JSONB support:
sql, err := cel2sql.Convert(ast, cel2sql.WithSchemas(schemas))
Example with a different dialect:
sql, err := cel2sql.Convert(ast, cel2sql.WithDialect(mysql.New()))
Types ¶
type ComprehensionInfo ¶
type ComprehensionInfo struct {
Type ComprehensionType
IterVar string
IndexVar string // for two-variable comprehensions
AccuVar string
HasFilter bool
IsTwoVar bool
Transform *exprpb.Expr // transform expression for map/transformList
Predicate *exprpb.Expr // predicate expression for filtering
Filter *exprpb.Expr // filter expression for map with filter
}
ComprehensionInfo holds metadata about a comprehension operation
type ComprehensionType ¶
type ComprehensionType int
ComprehensionType represents the type of comprehension operation
const ( ComprehensionAll ComprehensionType = iota // All elements satisfy condition ComprehensionExists // At least one element satisfies condition ComprehensionExistsOne // Exactly one element satisfies condition ComprehensionMap // Transform elements using expression ComprehensionFilter // Filter elements by predicate ComprehensionTransformList // Transform list elements ComprehensionTransformMap // Transform map entries ComprehensionTransformMapEntry // Transform map key-value pairs ComprehensionUnknown // Unrecognized comprehension pattern )
CEL comprehension types supported by cel2sql
func (ComprehensionType) String ¶
func (ct ComprehensionType) String() string
String returns a string representation of the comprehension type
type ConversionError ¶
type ConversionError struct {
// UserMessage is the sanitized error message safe to display to end users
UserMessage string
// InternalDetails contains detailed information for logging and debugging
// This should NEVER be exposed to end users
InternalDetails string
// WrappedErr is the underlying error, if any
WrappedErr error
}
ConversionError represents an error that occurred during CEL to SQL conversion. It provides a sanitized user-facing message while preserving detailed information for logging and debugging. This prevents information disclosure through error messages (CWE-209: Information Exposure Through Error Message).
func (*ConversionError) Error ¶
func (e *ConversionError) Error() string
Error returns the user-facing error message. This is what gets displayed when the error is returned to callers.
func (*ConversionError) Internal ¶
func (e *ConversionError) Internal() string
Internal returns the full internal details for logging purposes. This should only be used with structured logging, never displayed to users.
func (*ConversionError) Unwrap ¶
func (e *ConversionError) Unwrap() error
Unwrap returns the wrapped error for use with errors.Is and errors.As
type ConvertOption ¶
type ConvertOption func(*convertOptions)
ConvertOption is a functional option for configuring the Convert function.
func WithContext ¶
func WithContext(ctx context.Context) ConvertOption
WithContext provides a context for cancellation and timeout support. If not provided, operations will run without cancellation checks. This allows long-running conversions to be cancelled and enables timeout protection.
Example with timeout:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() sql, err := cel2sql.Convert(ast, cel2sql.WithContext(ctx))
Example with cancellation:
ctx, cancel := context.WithCancel(context.Background()) defer cancel() sql, err := cel2sql.Convert(ast, cel2sql.WithContext(ctx), cel2sql.WithSchemas(schemas))
func WithDialect ¶ added in v3.6.0
func WithDialect(d dialect.Dialect) ConvertOption
WithDialect sets the SQL dialect for conversion. If not provided, PostgreSQL is used as the default dialect.
Example:
import "github.com/spandigital/cel2sql/v3/dialect/mysql" sql, err := cel2sql.Convert(ast, cel2sql.WithDialect(mysql.New()))
func WithLogger ¶
func WithLogger(logger *slog.Logger) ConvertOption
WithLogger provides a logger for observability and debugging. If not provided, logging is disabled with zero overhead using slog.DiscardHandler.
The logger enables visibility into:
- JSON path detection decisions (table, field, operator selection)
- Comprehension type identification (all, exists, filter, map)
- Schema lookups (hits/misses, field types)
- Performance metrics (conversion duration)
- Regex pattern transformations (RE2 to POSIX)
- Operator mapping decisions
- Error contexts with full details
Example with JSON output:
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug}))
sql, err := cel2sql.Convert(ast, cel2sql.WithLogger(logger))
Example with text output:
logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) sql, err := cel2sql.Convert(ast, cel2sql.WithSchemas(schemas), cel2sql.WithLogger(logger))
func WithMaxDepth ¶
func WithMaxDepth(maxDepth int) ConvertOption
WithMaxDepth sets the maximum recursion depth for expression traversal. If not provided, defaultMaxRecursionDepth (100) is used. This protects against stack overflow from deeply nested expressions (CWE-674).
Example with custom depth:
sql, err := cel2sql.Convert(ast, cel2sql.WithMaxDepth(150))
Example with multiple options:
sql, err := cel2sql.Convert(ast,
cel2sql.WithMaxDepth(50),
cel2sql.WithContext(ctx),
cel2sql.WithSchemas(schemas))
func WithMaxOutputLength ¶
func WithMaxOutputLength(maxLength int) ConvertOption
WithMaxOutputLength sets the maximum length of generated SQL output. If not provided, defaultMaxSQLOutputLength (50000) is used. This protects against resource exhaustion from extremely large SQL queries (CWE-400).
Example with custom output length limit:
sql, err := cel2sql.Convert(ast, cel2sql.WithMaxOutputLength(100000))
Example with multiple options:
sql, err := cel2sql.Convert(ast,
cel2sql.WithMaxOutputLength(25000),
cel2sql.WithMaxDepth(50),
cel2sql.WithContext(ctx))
func WithSchemas ¶
func WithSchemas(schemas map[string]schema.Schema) ConvertOption
WithSchemas provides schema information for proper JSON/JSONB field handling. This option is required for correct SQL generation when using JSON/JSONB fields.
Example:
schemas := provider.GetSchemas() sql, err := cel2sql.Convert(ast, cel2sql.WithSchemas(schemas))
type IndexRecommendation ¶ added in v3.1.0
type IndexRecommendation struct {
// Column is the database column that should be indexed
Column string
// IndexType specifies the index type (e.g., "BTREE", "GIN", "ART", "CLUSTERING")
IndexType string
// Expression is the complete DDL statement that can be executed directly
Expression string
// Reason explains why this index is recommended and what query patterns it optimizes
Reason string
}
IndexRecommendation represents a database index recommendation based on CEL query patterns. It provides actionable guidance for optimizing query performance through appropriate indexing strategies.
func AnalyzeQuery ¶ added in v3.1.0
func AnalyzeQuery(ast *cel.Ast, opts ...ConvertOption) (string, []IndexRecommendation, error)
AnalyzeQuery converts a CEL AST to SQL and provides dialect-specific index recommendations. It analyzes the query patterns to suggest indexes that would optimize performance.
The function detects patterns that benefit from specific index types:
- JSON/JSONB path operations → GIN indexes (PostgreSQL), functional indexes (MySQL), search indexes (BigQuery)
- Array operations → GIN indexes (PostgreSQL), ART indexes (DuckDB)
- Regex matching → GIN indexes with pg_trgm (PostgreSQL), FULLTEXT indexes (MySQL)
- Comparison operations → B-tree indexes (PostgreSQL/MySQL/SQLite), ART (DuckDB), clustering (BigQuery)
Use WithDialect() to get dialect-specific index recommendations. Defaults to PostgreSQL.
Example:
sql, recommendations, err := cel2sql.AnalyzeQuery(ast,
cel2sql.WithSchemas(schemas),
cel2sql.WithDialect(mysql.New()))
if err != nil {
return err
}
// Use the SQL query
rows, err := db.Query("SELECT * FROM table WHERE " + sql)
// Apply index recommendations
for _, rec := range recommendations {
fmt.Printf("Recommendation: %s\n", rec.Reason)
fmt.Printf("Execute: %s\n\n", rec.Expression)
}
type Result ¶
type Result struct {
SQL string // The generated SQL WHERE clause with placeholders
Parameters []any // Parameter values in order ($1, $2, etc.)
}
Result represents the output of a CEL to SQL conversion with parameterized queries. It contains the SQL string with placeholders ($1, $2, etc.) and the corresponding parameter values.
func ConvertParameterized ¶
func ConvertParameterized(ast *cel.Ast, opts ...ConvertOption) (*Result, error)
ConvertParameterized converts a CEL AST to a parameterized SQL WHERE clause. Returns both the SQL string with placeholders and the parameter values. By default uses PostgreSQL ($1, $2). Use WithDialect for other placeholder styles.
Constants that are parameterized:
- String literals: 'John' → $1
- Numeric literals: 42, 3.14 → $1, $2
- Byte literals: b"data" → $1
Constants kept inline (for query plan optimization):
- TRUE, FALSE (boolean constants)
- NULL
Example:
result, err := cel2sql.ConvertParameterized(ast,
cel2sql.WithSchemas(schemas),
cel2sql.WithContext(ctx))
// result.SQL: "user.age = $1 AND user.name = $2"
// result.Parameters: []interface{}{18, "John"}
// Execute with database/sql
rows, err := db.Query("SELECT * FROM users WHERE "+result.SQL, result.Parameters...)
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package bigquery provides BigQuery type provider for CEL type system integration.
|
Package bigquery provides BigQuery type provider for CEL type system integration. |
|
Package dialect defines the interface for SQL dialect-specific code generation.
|
Package dialect defines the interface for SQL dialect-specific code generation. |
|
bigquery
Package bigquery implements the BigQuery SQL dialect for cel2sql.
|
Package bigquery implements the BigQuery SQL dialect for cel2sql. |
|
duckdb
Package duckdb implements the DuckDB SQL dialect for cel2sql.
|
Package duckdb implements the DuckDB SQL dialect for cel2sql. |
|
mysql
Package mysql implements the MySQL SQL dialect for cel2sql.
|
Package mysql implements the MySQL SQL dialect for cel2sql. |
|
postgres
Package postgres implements the PostgreSQL SQL dialect for cel2sql.
|
Package postgres implements the PostgreSQL SQL dialect for cel2sql. |
|
sqlite
Package sqlite implements the SQLite SQL dialect for cel2sql.
|
Package sqlite implements the SQLite SQL dialect for cel2sql. |
|
Package duckdb provides DuckDB type provider for CEL type system integration.
|
Package duckdb provides DuckDB type provider for CEL type system integration. |
|
examples
|
|
|
basic
command
Package main demonstrates basic usage of cel2sql with a predefined schema.
|
Package main demonstrates basic usage of cel2sql with a predefined schema. |
|
comprehensions
command
Package main demonstrates CEL comprehensions support in cel2sql with PostgreSQL integration.
|
Package main demonstrates CEL comprehensions support in cel2sql with PostgreSQL integration. |
|
context
command
Package main demonstrates context usage with cel2sql for cancellation and timeout support.
|
Package main demonstrates context usage with cel2sql for cancellation and timeout support. |
|
index_analysis
command
Package main demonstrates how to use cel2sql.AnalyzeQuery() for index recommendations
|
Package main demonstrates how to use cel2sql.AnalyzeQuery() for index recommendations |
|
load_table_schema
command
Package main demonstrates loading table schema dynamically from PostgreSQL.
|
Package main demonstrates loading table schema dynamically from PostgreSQL. |
|
logging
command
Package main demonstrates cel2sql structured logging with log/slog.
|
Package main demonstrates cel2sql structured logging with log/slog. |
|
parameterized
command
Package main demonstrates parameterized query support in cel2sql.
|
Package main demonstrates parameterized query support in cel2sql. |
|
string_extensions
command
Package main demonstrates CEL string extension functions in cel2sql
|
Package main demonstrates CEL string extension functions in cel2sql |
|
Package mysql provides MySQL type provider for CEL type system integration.
|
Package mysql provides MySQL type provider for CEL type system integration. |
|
Package pg provides PostgreSQL type provider for CEL type system integration.
|
Package pg provides PostgreSQL type provider for CEL type system integration. |
|
Package schema provides dialect-agnostic database schema types for CEL to SQL conversion.
|
Package schema provides dialect-agnostic database schema types for CEL to SQL conversion. |
|
Package sqlite provides SQLite type provider for CEL type system integration.
|
Package sqlite provides SQLite type provider for CEL type system integration. |
|
Package sqltypes provides custom SQL type definitions for CEL (Date, Time, DateTime).
|
Package sqltypes provides custom SQL type definitions for CEL (Date, Time, DateTime). |
|
Package test provides PostgreSQL schema definitions for testing.
|
Package test provides PostgreSQL schema definitions for testing. |
|
Package testcases defines shared test case types and helpers for multi-dialect testing.
|
Package testcases defines shared test case types and helpers for multi-dialect testing. |
|
Package testutil provides multi-dialect test runners and helpers.
|
Package testutil provides multi-dialect test runners and helpers. |