Documentation
¶
Overview ¶
Package gel is the official Go driver for Gel. Additionally, github.com/geldata/gel-go/cmd/edgeql-go is a code generator that generates go functions from edgeql files.
See Client for an example of typical usage.
We recommend using environment variables for connection parameters. See the client connection docs for more information.
Errors ¶
gel never returns underlying errors directly. If you are checking for things like context expiration use errors.Is or errors.As.
err := client.Query(...) if errors.Is(err, context.Canceled) { ... }
Most errors returned by the gel package will satisfy the gelerr.Error interface which has methods for introspecting.
err := client.Query(...) var gelErr gelerr.Error if errors.As(err, &gelErr) && gelErr.Category(gelcfg.NoDataError){ ... }
Datatypes ¶
The following list shows the marshal/unmarshal mapping between Gel types and go types. See also geltypes:
Gel Go --------- --------- Set []anytype array<anytype> []anytype tuple struct named tuple struct Object struct bool bool, geltypes.OptionalBool bytes []byte, geltypes.OptionalBytes str string, geltypes.OptionalStr anyenum string, geltypes.OptionalStr datetime time.Time, geltypes.OptionalDateTime cal::local_datetime geltypes.LocalDateTime, geltypes.OptionalLocalDateTime cal::local_date geltypes.LocalDate, geltypes.OptionalLocalDate cal::local_time geltypes.LocalTime, geltypes.OptionalLocalTime duration geltypes.Duration, geltypes.OptionalDuration cal::relative_duration geltypes.RelativeDuration, geltypes.OptionalRelativeDuration float32 float32, geltypes.OptionalFloat32 float64 float64, geltypes.OptionalFloat64 int16 int16, geltypes.OptionalFloat16 int32 int32, geltypes.OptionalInt16 int64 int64, geltypes.OptionalInt64 uuid geltypes.UUID, geltypes.OptionalUUID json []byte, geltypes.OptionalBytes bigint *big.Int, geltypes.OptionalBigInt decimal user defined (see Custom Marshalers)
Note that Gel's std::duration type is represented in int64 microseconds while go's time.Duration type is int64 nanoseconds. It is incorrect to cast one directly to the other.
Shape fields that are not required must use optional types for receiving query results. geltypes.Optional can be embedded to make structs optional.
Not all types listed above are valid query parameters. To pass a slice of scalar values use array in your query. Gel doesn't currently support using sets as parameters.
query := `select User filter .id in array_unpack(<array<uuid>>$1)` client.QuerySingle(ctx, query, &user, []geltypes.UUID{...})
Nested structures are also not directly allowed but you can use json instead.
By default Gel will ignore embedded structs when marshaling/unmarshaling. To treat an embedded struct's fields as part of the parent struct's fields, tag the embedded struct with `gel:"$inline"`.
type Object struct { ID geltypes.UUID } type User struct { Object `gel:"$inline"` Name string }
Custom Marshalers ¶
Interfaces for user defined marshaler/unmarshalers are documented in the github.com/geldata/gel-go/internal/marshal package.
Example (LinkProperty) ¶
Link properties are treated as fields in the linked to struct, and the @ is omitted from the field's tag.
var result []struct { Name string `gel:"name"` Friends []struct { Name string `gel:"name"` Strength geltypes.OptionalFloat64 `gel:"strength"` } `gel:"friends"` } err := client.Query( ctx, `select Person { name, friends: { name, @strength, } }`, &result, ) if err != nil { log.Fatal(err) }
Output:
Index ¶
- type Client
- func (c *Client) Close() error
- func (c *Client) EnsureConnected(ctx context.Context) error
- func (c *Client) Execute(ctx context.Context, cmd string, args ...interface{}) error
- func (c *Client) ExecuteSQL(ctx context.Context, cmd string, args ...interface{}) error
- func (c *Client) Query(ctx context.Context, cmd string, out interface{}, args ...interface{}) error
- func (c *Client) QueryJSON(ctx context.Context, cmd string, out *[]byte, args ...interface{}) error
- func (c *Client) QuerySQL(ctx context.Context, cmd string, out interface{}, args ...interface{}) error
- func (c *Client) QuerySingle(ctx context.Context, cmd string, out interface{}, args ...interface{}) error
- func (c *Client) QuerySingleJSON(ctx context.Context, cmd string, out interface{}, args ...interface{}) error
- func (c *Client) Tx(ctx context.Context, action geltypes.TxBlock) error
- func (c Client) WithConfig(cfg map[string]interface{}) *Client
- func (c Client) WithGlobals(globals map[string]interface{}) *Client
- func (c Client) WithModuleAliases(aliases ...gelcfg.ModuleAlias) *Client
- func (c Client) WithQueryOptions(opts gelcfg.QueryOptions) *Client
- func (c Client) WithQueryTag(tag string) (*Client, error)
- func (c Client) WithRetryOptions(opts gelcfg.RetryOptions) *Client
- func (c Client) WithTxOptions(opts gelcfg.TxOptions) *Client
- func (c Client) WithWarningHandler(handler gelcfg.WarningHandler) *Client
- func (c Client) WithoutConfig(key ...string) *Client
- func (c Client) WithoutGlobals(globals ...string) *Client
- func (c Client) WithoutModuleAliases(aliases ...string) *Client
- func (c Client) WithoutQueryTag() *Client
Examples ¶
- Package (LinkProperty)
- Client
- Client.Execute
- Client.ExecuteSQL
- Client.Query
- Client.QueryJSON
- Client.QuerySQL
- Client.QuerySingle
- Client.QuerySingleJSON
- Client.Tx
- Client.WithConfig
- Client.WithGlobals
- Client.WithModuleAliases
- Client.WithQueryOptions
- Client.WithQueryTag
- Client.WithRetryOptions
- Client.WithTxOptions
- Client.WithWarningHandler
- Client.WithoutConfig
- Client.WithoutGlobals
- Client.WithoutModuleAliases
- Client.WithoutQueryTag
- CreateClient
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a connection pool and is safe for concurrent use.
Example ¶
package main import ( "fmt" "log" gel "github.com/geldata/gel-go" "github.com/geldata/gel-go/geltypes" ) type User struct { ID geltypes.UUID `gel:"id"` Name string `gel:"name"` } func main() { db, err := gel.CreateClient(opts) if err != nil { log.Fatal(err) } defer db.Close() // Insert a new user. var inserted struct{ id geltypes.UUID } err = db.QuerySingle( ctx, `INSERT User { name := <str>$0 }`, &inserted, "Bob", ) if err != nil { log.Fatal(err) } // Select user. var user User err = db.QuerySingle( ctx, ` SELECT User { name } FILTER .id = <uuid>$id `, &user, map[string]any{"id": inserted.id}, ) if err != nil { log.Fatal(err) } fmt.Println(user.Name) }
Output: Bob
func CreateClient ¶
CreateClient returns a new client. The client connects lazily. Call Client.EnsureConnected to force a connection.
Instead of providing connection details directly, we recommend connecting using projects locally, and environment variables for remote instances, providing an empty gelcfg.Options struct here. Read more about the recommended ways to configure client connections.
Example ¶
client, err := gel.CreateClient(opts) if err != nil { log.Fatal(err) } var result int64 err = client.QuerySingle(ctx, `SELECT 1`, &result) if err != nil { fmt.Println(err) } fmt.Println(result)
Output: 1
func CreateClientDSN ¶
CreateClientDSN returns a new Client. We recommend using CreateClient for most use cases.
dsn is either an instance name or a DSN.
dsn := "gel://admin@localhost/main" client, err := gel.CreateClientDSN(dsn, opts)
func (*Client) Close ¶
Close closes all connections in the client. Calling Close() blocks until all acquired connections have been released, and returns an error if called more than once.
func (*Client) EnsureConnected ¶
EnsureConnected forces the client to connect if it hasn't already. This can be used to ensure that your program will fail early in the case that the configured connection parameters are not correct.
func (*Client) Execute ¶
Execute an EdgeQL command (or commands).
Example ¶
err := client.Execute(ctx, "INSERT Product") if err != nil { log.Fatal(err) }
Output:
func (*Client) ExecuteSQL ¶
ExecuteSQL executes a SQL command (or commands).
Example ¶
err := client.ExecuteSQL(ctx, `INSERT INTO "Product" DEFAULT VALUES`) if err != nil { log.Fatal(err) }
Output:
func (*Client) Query ¶
Query runs a query and returns the results.
Example ¶
var output []struct { Result int64 `gel:"result"` } err := client.Query(ctx, `SELECT {result := 2 + 2}`, &output) if err != nil { log.Fatal(err) } fmt.Print(output)
Output: [{4}]
func (*Client) QueryJSON ¶
QueryJSON runs a query and returns the results as JSON.
Example ¶
var output []byte err := client.QueryJSON(ctx, `SELECT {result := 2 + 2}`, &output) if err != nil { log.Fatal(err) } fmt.Println(string(output))
Output: [{"result" : 4}]
func (*Client) QuerySQL ¶
func (c *Client) QuerySQL(ctx context.Context, cmd string, out interface{}, args ...interface{}) error
QuerySQL runs a SQL query and returns the results.
Example ¶
var output []struct { Result int32 `gel:"result"` } err := client.QuerySQL(ctx, `SELECT 2 + 2 AS result`, &output) if err != nil { log.Fatal(err) } fmt.Println(output)
Output: [{4}]
func (*Client) QuerySingle ¶
func (c *Client) QuerySingle(ctx context.Context, cmd string, out interface{}, args ...interface{}) error
QuerySingle runs a singleton-returning query and returns its element. If the query executes successfully but doesn't return a result a gelerr.NoDataError is returned. If the out argument is an optional type the out argument will be set to missing instead of returning a NoDataError.
Example ¶
var output struct { Result int64 `gel:"result"` } err := client.QuerySingle(ctx, `SELECT {result := 2 + 2}`, &output) if err != nil { log.Fatal(err) } fmt.Print(output)
Output: {4}
func (*Client) QuerySingleJSON ¶
func (c *Client) QuerySingleJSON(ctx context.Context, cmd string, out interface{}, args ...interface{}) error
QuerySingleJSON runs a singleton-returning query. If the query executes successfully but doesn't have a result a gelerr.NoDataError is returned.
Example ¶
var output []byte err := client.QuerySingleJSON(ctx, `SELECT {result := 2 + 2}`, &output) if err != nil { log.Fatal(err) } fmt.Println(string(output))
Output: {"result" : 4}
func (*Client) Tx ¶
Tx runs action in a transaction retrying failed attempts. Queries must be executed on the geltypes.Tx that is passed to action. Queries executed on the client in a geltypes.TxBlock will not run in the transaction and will be applied immediately.
The geltypes.TxBlock may be re-run if any of the queries fail in a way that might succeed on subsequent attempts. Retries are governed by gelcfg.RetryOptions and gelcfg.RetryRule. Retry options can be set using Client.WithRetryOptions. See gelcfg.RetryRule for more details on how they work.
Example ¶
err := client.Tx(ctx, func(ctx context.Context, tx geltypes.Tx) error { return tx.Execute(ctx, "INSERT User { name := 'Don' }") }) if err != nil { log.Println(err) }
Output:
func (Client) WithConfig ¶
WithConfig returns a copy of c with configuration values set to cfg. This is equivalent to using the edgeql configure session command. For available configuration parameters refer to the config documentation.
Example ¶
configured := client.WithConfig(map[string]any{ "allow_user_specified_id": true, }) err := configured.Execute(ctx, `INSERT USER { id := <uuid>$0 }`, id) if err != nil { log.Fatal(err) }
Output:
func (Client) WithGlobals ¶
WithGlobals returns a copy of c with its global variables updated from globals.
WithGlobals does not remove variables that are not mentioned in globals. Instead use Client.WithoutGlobals.
Example ¶
configured := client.WithGlobals(map[string]any{ "used_everywhere": int64(42), }) var result int64 err := configured.QuerySingle( ctx, "SELECT GLOBAL used_everywhere", &result, ) if err != nil { log.Fatal(err) } fmt.Println(result)
Output: 42
func (Client) WithModuleAliases ¶
func (c Client) WithModuleAliases(aliases ...gelcfg.ModuleAlias) *Client
WithModuleAliases returns a copy of c with module name aliases set to aliases.
Example ¶
configured := client.WithModuleAliases( gelcfg.ModuleAlias{ Module: "math", Alias: "m", }, ) var result int64 err := configured.QuerySingle(ctx, "SELECT m::abs(-42)", &result) if err != nil { log.Fatal(err) } fmt.Println(result)
Output: 42
func (Client) WithQueryOptions ¶
func (c Client) WithQueryOptions(opts gelcfg.QueryOptions) *Client
WithQueryOptions returns a copy of c with its gelcfg.Queryoptions set to opts.
Example ¶
opts := gelcfg.NewQueryOptions().WithReadOnly(true) configured := client.WithQueryOptions(opts) err := configured.Execute(ctx, "INSERT User") fmt.Println(err)
Output: gel.DisabledCapabilityError: cannot execute data modification queries: disabled by the client
func (Client) WithQueryTag ¶ added in v1.1.0
WithQueryTag returns a copy of c with the sys::QueryStats tag set.
sys::QueryStats only records the tag from the first time a query is run. Running the query again with a different tag will not change the tag in the sys::QueryStats entry.
Example ¶
tag := "my-app/backend" configured, err := client.WithQueryTag(tag) if err != nil { log.Fatal(err) } err = configured.Execute(ctx, "SELECT User { ** }") if err != nil { log.Fatal(err) } var query string err = client.QuerySingle( ctx, ` SELECT assert_single(( SELECT sys::QueryStats FILTER .tag = <str>$0 )).query `, &query, tag, ) if err != nil { log.Fatal(err) } // sys::QueryStats reformats queries fmt.Println(query)
Output: select User { ** }
func (Client) WithRetryOptions ¶
func (c Client) WithRetryOptions(opts gelcfg.RetryOptions) *Client
WithRetryOptions returns a copy of c with the RetryOptions set to opts.
Example ¶
linearBackoff := func(n int) time.Duration { return time.Second } rule := gelcfg.NewRetryRule(). WithAttempts(5). WithBackoff(linearBackoff) opts := gelcfg.NewRetryOptions().WithDefault(rule) configured := client.WithRetryOptions(opts) err := configured.Execute( ctx, "INSERT Product { name := 'shiny and new' }", ) if err != nil { log.Fatal(err) }
Output:
func (Client) WithTxOptions ¶
WithTxOptions returns a copy of c with the gelcfg.TxOptions set to opts.
Example ¶
opts := gelcfg.NewTxOptions().WithReadOnly(true) configured := client.WithTxOptions(opts) err := configured.Tx(ctx, func(ctx context.Context, tx geltypes.Tx) error { return tx.Execute(ctx, "INSERT User") }) fmt.Println(err)
Output: gel.TransactionError: cannot execute SELECT in a read-only transaction
func (Client) WithWarningHandler ¶
func (c Client) WithWarningHandler(handler gelcfg.WarningHandler) *Client
WithWarningHandler returns a copy of c with its gelcfg.WarningHandler set to handler. If handler is nil, gelcfg.LogWarnings is used.
Example ¶
handler := func(warnings []error) error { for _, warning := range warnings { fmt.Println(warning) } return nil } configured := client.WithWarningHandler(handler) err := configured.Execute(ctx, `SELECT _warn_on_call()`) if err != nil { log.Fatal(err) }
Output: gel.QueryError: Test warning please ignore query:1:8 SELECT _warn_on_call() ^ error
func (Client) WithoutConfig ¶
WithoutConfig returns a copy of c with keys unset from the configuration.
Example ¶
configured := client.WithConfig(map[string]any{ "allow_user_specified_id": true, }) unconfigured := configured.WithoutConfig("allow_user_specified_id") err := unconfigured.Execute(ctx, `INSERT User { id := <uuid>$0 }`, id) fmt.Println(err)
Output: gel.QueryError: cannot assign to property 'id' query:1:15 INSERT User { id := <uuid>$0 } ^ consider enabling the "allow_user_specified_id" configuration parameter to allow setting custom object ids
func (Client) WithoutGlobals ¶
WithoutGlobals returns a copy of c with the specified global names unset.
Example ¶
configured := client.WithGlobals(map[string]any{ "used_everywhere": int64(42), }) unconfigured := configured.WithoutGlobals("used_everywhere") var result int64 err := unconfigured.QuerySingle( ctx, `SELECT GLOBAL used_everywhere`, &result, ) fmt.Println(err)
Output: gel.NoDataError: zero results
func (Client) WithoutModuleAliases ¶
WithoutModuleAliases returns a copy of c with aliases unset.
Example ¶
configured := client.WithModuleAliases( gelcfg.ModuleAlias{ Module: "math", Alias: "m", }, ) unconfigured := configured.WithoutModuleAliases("m") var result int64 err := unconfigured.QuerySingle(ctx, "SELECT m::abs(-42)", &result) fmt.Println(err)
Output: gel.InvalidReferenceError: function 'm::abs' does not exist query:1:8 SELECT m::abs(-42) ^ error
func (Client) WithoutQueryTag ¶ added in v1.1.0
WithoutQueryTag returns a copy of c with the sys::QueryStats tag removed.
Example ¶
tag := "my-app/api" configured, err := client.WithQueryTag(tag) if err != nil { log.Fatal(err) } unconfigured := configured.WithoutQueryTag() err = unconfigured.Execute(ctx, "SELECT Product { ** }") if err != nil { log.Fatal(err) } var queries []string err = client.Query( ctx, ` SELECT ( SELECT sys::QueryStats FILTER .tag = <str>$0 ).query `, &queries, tag, ) if err != nil { log.Fatal(err) } fmt.Println(queries)
Output: []
Directories
¶
Path | Synopsis |
---|---|
cmd
|
|
edgeql-go
edgeql-go is a tool to generate go functions from edgeql queries.
|
edgeql-go is a tool to generate go functions from edgeql queries. |
marshal
Package marshal documents marshaling interfaces.
|
Package marshal documents marshaling interfaces. |
soc
Package soc has utilities for working with sockets.
|
Package soc has utilities for working with sockets. |