Skip to content

Go Quickstart

Terminal window
go get github.com/iamtelescope/flyql/golang
package main
import (
"fmt"
flyql "github.com/iamtelescope/flyql/golang"
)
func main() {
result, err := flyql.Parse("status = 200 and active")
if err != nil {
panic(err)
}
fmt.Printf("Parsed: %+v\n", result.Root)
}

Parse returns a *ParseResult with a Root node representing the AST.

Use a generator to turn the AST into a WHERE clause. Each database dialect has its own generator with dialect-specific column types.

package main
import (
"fmt"
flyql "github.com/iamtelescope/flyql/golang"
"github.com/iamtelescope/flyql/golang/generators/clickhouse"
)
func main() {
result, err := flyql.Parse("status >= 400 and host like 'prod%'")
if err != nil {
panic(err)
}
columns := map[string]*clickhouse.Column{
"status": clickhouse.NewColumn(clickhouse.ColumnDef{Name: "status", Type: "UInt32"}),
"host": clickhouse.NewColumn(clickhouse.ColumnDef{Name: "host", Type: "String"}),
}
sql, err := clickhouse.ToSQLWhere(result.Root, columns)
if err != nil {
panic(err)
}
fmt.Println(sql)
}

PostgreSQL and StarRocks generators follow the same pattern — import from generators/postgresql or generators/starrocks instead.

Evaluate a query against a data record without generating SQL:

package main
import (
"fmt"
"github.com/iamtelescope/flyql/golang/matcher"
)
func main() {
data := map[string]any{
"status": 200,
"active": true,
"host": "prod-api-01",
}
matches, err := matcher.Match("status = 200 and active", data)
if err != nil {
panic(err)
}
fmt.Printf("Matches: %v\n", matches) // true
}

Parse a columns expression into structured data with segments, transformers, and aliases. The second argument is a Capabilities struct that controls which features are enabled. Transformers are disabled by default.

package main
import (
"fmt"
"github.com/iamtelescope/flyql/golang/columns"
)
func main() {
// Parse basic columns (transformers disabled by default)
parsed, err := columns.Parse("message, status", columns.Capabilities{})
if err != nil {
panic(err)
}
for _, col := range parsed {
fmt.Printf("%s (display: %q, segments: %v)\n", col.Name, col.DisplayName, col.Segments)
}
// Enable transformers via capabilities
caps := columns.Capabilities{Transformers: true}
withTransforms, err := columns.Parse("message|chars(25) as msg, status", caps)
if err != nil {
panic(err)
}
fmt.Println(withTransforms[0].Transformers)
// Or serialize directly to JSON for API responses
jsonBytes, _ := columns.ParseToJSON("message, status|upper", caps)
fmt.Println(string(jsonBytes))
}

Use $name and $1 placeholders, then resolve them at runtime with BindParams():

package main
import (
"fmt"
flyql "github.com/iamtelescope/flyql/golang"
"github.com/iamtelescope/flyql/golang/generators/clickhouse"
)
func main() {
// Parse a query with parameter placeholders
result, err := flyql.Parse(`status = $code and env in [$env, 'staging']`)
if err != nil {
panic(err)
}
// Bind concrete values to the parameters
if err := flyql.BindParams(result.Root, map[string]any{
"code": 200,
"env": "prod",
}); err != nil {
panic(err)
}
// Generate SQL
columns := map[string]*clickhouse.Column{
"status": clickhouse.NewColumn(clickhouse.ColumnDef{Name: "status", Type: "Int32"}),
"env": clickhouse.NewColumn(clickhouse.ColumnDef{Name: "env", Type: "String"}),
}
sql, err := clickhouse.ToSQLWhere(result.Root, columns)
if err != nil {
panic(err)
}
fmt.Println(sql)
// (status = 200 AND env IN ('prod', 'staging'))
}

See Parameters for the full reference.

Parse a query with transformers and generate SQL:

package main
import (
"fmt"
flyql "github.com/iamtelescope/flyql/golang"
clickhousegen "github.com/iamtelescope/flyql/golang/generators/clickhouse"
)
func main() {
result, _ := flyql.Parse("message|upper = 'ERROR'")
columns := map[string]*clickhousegen.Column{
"message": clickhousegen.NewColumn(clickhousegen.ColumnDef{Name: "message", Type: "String"}),
}
sql, _ := clickhousegen.ToSQLWhere(result.Root, columns)
fmt.Println(sql) // equals(upper(message), 'ERROR')
}

See Transformers for the full syntax reference.