EdgeDB Go Driver

Package edgedb is the official Go EdgeDB driver. https://www.edgedb.com

Typical usage looks like this:

  1. package main
  2. import (
  3. "context"
  4. "log"
  5. "github.com/edgedb/edgedb-go"
  6. )
  7. func main() {
  8. ctx := context.Background()
  9. client, err := edgedb.CreateClient(ctx, edgedb.Options{})
  10. if err != nil {
  11. log.Fatal(err)
  12. }
  13. defer client.Close()
  14. var (
  15. age int64 = 21
  16. users []struct {
  17. ID edgedb.UUID `edgedb:"id"`
  18. Name string `edgedb:"name"`
  19. }
  20. )
  21. query := "SELECT User{name} FILTER .age = <int64>$0"
  22. err = client.Query(ctx, query, &users, age)
  23. ...
  24. }

You can also connect to a database using a DSN:

  1. url := "edgedb://edgedb@localhost/edgedb"
  2. client, err := edgedb.CreateClientDSN(ctx, url, opts)

Or you can use Option fields.

  1. opts := edgedb.Options{
  2. Database: "edgedb",
  3. User: "edgedb",
  4. Concurrency: 4,
  5. }
  6. client, err := edgedb.CreateClient(ctx, opts)

# Errors

edgedb never returns underlying errors directly. If you are checking for things like context expiration use errors.Is() or errors.As().

  1. err := client.Query(...)
  2. if errors.Is(err, context.Canceled) { ... }

Most errors returned by the edgedb package will satisfy the edgedb.Error interface which has methods for introspecting.

  1. err := client.Query(...)
  2. var edbErr edgedb.Error
  3. if errors.As(err, &edbErr) && edbErr.Category(edgedb.NoDataError){
  4. ...
  5. }

# Datatypes

The following list shows the marshal/unmarshal mapping between EdgeDB types and go types:

  1. EdgeDB Go
  2. --------- ---------
  3. Set []anytype
  4. array<anytype> []anytype
  5. tuple struct
  6. named tuple struct
  7. Object struct
  8. bool bool, edgedb.OptionalBool
  9. bytes []byte, edgedb.OptionalBytes
  10. str string, edgedb.OptionalStr
  11. anyenum string, edgedb.OptionalStr
  12. datetime time.Time, edgedb.OptionalDateTime
  13. cal::local_datetime edgedb.LocalDateTime,
  14. edgedb.OptionalLocalDateTime
  15. cal::local_date edgedb.LocalDate, edgedb.OptionalLocalDate
  16. cal::local_time edgedb.LocalTime, edgedb.OptionalLocalTime
  17. duration time.Duration, edgedb.OptionalDuration
  18. cal::relative_duraation edgedb.RelativeDuration,
  19. edgedb.OptionalRelativeDuration
  20. float32 float32, edgedb.OptionalFloat32
  21. float64 float64, edgedb.OptionalFloat64
  22. int16 int16, edgedb.OptionalFloat16
  23. int32 int32, edgedb.OptionalInt16
  24. int64 int64, edgedb.OptionalInt64
  25. uuid edgedb.UUID, edgedb.OptionalUUID
  26. json []byte, edgedb.OptionalBytes
  27. bigint *big.Int, edgedb.OptionalBigInt
  28. decimal user defined (see Custom Marshalers)

Shape fields that are not required must use optional types for receiving query results. The edgedb.Optional struct can be embedded to make structs optional.

  1. type User Struct {
  2. edgedb.Optional
  3. Email string `edgedb:"email"`
  4. }
  5. var result User
  6. err := client.QuerySingle(ctx, `SELECT User { email } LIMIT 0`, $result)
  7. fmt.Println(result.Missing())
  8. // Output: true
  9. err := client.QuerySingle(ctx, `SELECT User { email } LIMIT 1`, $result)
  10. fmt.Println(result.Missing())
  11. // Output: false

# Custom Marshalers

Interfaces for user defined marshaler/unmarshalers are documented in the internal/marshal package.

Usage Example

  1. package edgedb_test
  2. import (
  3. "context"
  4. "fmt"
  5. "log"
  6. "time"
  7. "github.com/edgedb/edgedb-go"
  8. )
  9. type User struct {
  10. ID edgedb.UUID `edgedb:"id"`
  11. Name string `edgedb:"name"`
  12. DOB time.Time `edgedb:"dob"`
  13. }
  14. func Example() {
  15. opts := edgedb.Options{Concurrency: 4}
  16. ctx := context.Background()
  17. db, err := edgedb.CreateClientDSN(ctx, "edgedb://edgedb@localhost/test", opts)
  18. if err != nil {
  19. log.Fatal(err)
  20. }
  21. defer db.Close()
  22. // create a user object type.
  23. err = db.Execute(ctx, `
  24. CREATE TYPE User {
  25. CREATE REQUIRED PROPERTY name -> str;
  26. CREATE PROPERTY dob -> datetime;
  27. }
  28. `)
  29. if err != nil {
  30. log.Fatal(err)
  31. }
  32. // Insert a new user.
  33. var inserted struct{ id edgedb.UUID }
  34. err = db.QuerySingle(ctx, `
  35. INSERT User {
  36. name := <str>$0,
  37. dob := <datetime>$1
  38. }
  39. `, &inserted, "Bob", time.Date(1984, 3, 1, 0, 0, 0, 0, time.UTC))
  40. if err != nil {
  41. log.Fatal(err)
  42. }
  43. // Select users.
  44. var users []User
  45. args := map[string]interface{}{"name": "Bob"}
  46. query := "SELECT User {name, dob} FILTER .name = <str>$name"
  47. err = db.Query(ctx, query, &users, args)
  48. if err != nil {
  49. log.Fatal(err)
  50. }
  51. fmt.Println(users)
  52. }