DEV Community

Wang Zuo
Wang Zuo

Posted on

Queryx: An Open-Source Golang ORM with Automatic Schema Management

Github link: https://github.com/swiftcarrot/queryx

Installation:

curl -sf https://raw.githubusercontent.com/swiftcarrot/queryx/main/install.sh  | sh
Enter fullscreen mode Exit fullscreen mode

schema.hcl

Queryx uses schema.hcl to describe the database. The following example defines database environments and models:

database "db" {
  adapter = "postgresql"

  config "development" {
    url = "postgres://postgres:postgres@localhost:5432/blog_development?sslmode=disable"
  }

  config "production" {
    url = env("DATABASE_URL")
  }

  generator "client-golang" {}

  model "Post" {
    column "title" {
      type = string
    }
    column "content" {
      type = text
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Run the queryx db:create command to create a PostgreSQL database, and then run queryx db:migrate to automatically create the database migration files and database structure. Queryx’s database schema management is built upon Atlas.

CRUD

Running queryx g generates corresponding ORM code in the db directory. The generated code generates Go types based on the database schema and has no other third-party dependencies except for the lib/pq driver. We hope that the automatically generated code is concise and readable.

Below are some sample code for CRUD operations:

// Create
newPost := c.ChangePost().SetTitle("post title")
post, err := c.QueryPost().Create(newPost)

// Read
post, err := c.QueryPost().Find(1)
posts, err := c.QueryPost().Where(c.PostTitle.EQ("post title")).All()

// Update
updatePost := c.ChangePost().SetTitle("new post title")
err := post.Update(updatePost)
updated, err := c.QueryPost().Where(c.PostTitle.EQ("post title")).UpdateAll(updatePost)

// Delete
err := post.Delete()
deleted, err := c.QueryPost().Where(c.PostTitle.EQ("post title")).DeleteAll()
Enter fullscreen mode Exit fullscreen mode

Relationships

Relationships between models, including belongs_to, has_one, and has_many, can also be declared in schema.hcl. For example:

model "User" {
  belongs_to "group" {}

  column "name" {
    type = string
  }
}

model "Group" {
  has_many "users" {}

  column "name" {
    type = string
  }
}
Enter fullscreen mode Exit fullscreen mode

After declaring the relationship, you can use the generated preload method to avoid n+1 queries. For example:

users, err := c.QueryUser().PreloadGroup().All()
// users[0].Groups

groups, err := c.QueryGroup().PreloadUsers().All()
// groups[0].User
Enter fullscreen mode Exit fullscreen mode

If you are familiar with Rails, you will find that Queryx references many design concepts from ActiveRecord. We hope to replicate the development experience of ActiveRecord. For more queryx usages, please refer to the README documentation, and feel free to discuss in the issue, discussion, and reply. Queryx is currently in beta (v0), and many features are still under development such as MySQL support. We hope to continue to improve the development experience in future versions.

Top comments (0)