zoobzio December 18, 2025 Edit this page

Quickstart

Requirements

Go 1.24 or later.

Installation

go get github.com/zoobz-io/soy

Basic Usage

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/jmoiron/sqlx"
    _ "github.com/lib/pq"
    "github.com/zoobz-io/astql/pkg/postgres"
    "github.com/zoobz-io/soy"
)

// Define your model with struct tags
type User struct {
    ID    int    `db:"id" type:"serial" constraints:"primary key"`
    Email string `db:"email" type:"text" constraints:"not null unique"`
    Name  string `db:"name" type:"text"`
    Age   int    `db:"age" type:"int"`
}

func main() {
    // Connect to PostgreSQL
    db, err := sqlx.Connect("postgres", "postgres://localhost/mydb?sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // Create soy instance with PostgreSQL provider
    users, err := soy.New[User](db, "users", postgres.New())
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Insert a user
    newUser := &User{Email: "alice@example.com", Name: "Alice", Age: 30}
    created, err := users.Insert().Exec(ctx, newUser)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Created user: %d\n", created.ID)

    // Query by email
    found, err := users.Select().
        Where("email", "=", "email_param").
        Exec(ctx, map[string]any{"email_param": "alice@example.com"})
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Found: %s\n", found.Name)

    // Update the user
    updated, err := users.Modify().
        Set("age", "new_age").
        Where("id", "=", "user_id").
        Exec(ctx, map[string]any{"new_age": 31, "user_id": created.ID})
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Updated age: %d\n", updated.Age)

    // Query all users
    all, err := users.Query().
        OrderBy("name", "asc").
        Exec(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Total users: %d\n", len(all))
}

What's Happening

  1. New[User](db, "users", postgres.New()) inspects the struct tags and builds a schema with the PostgreSQL provider
  2. Insert().Build().Exec() generates an INSERT with RETURNING
  3. Select().Where().Exec() generates a SELECT with named parameters
  4. Modify().Set().Where().Exec() generates an UPDATE (WHERE required)
  5. Query().OrderBy().Exec() generates a SELECT returning multiple rows

Other Databases

Soy supports multiple databases through ASTQL providers:

import (
    "github.com/zoobz-io/astql/pkg/postgres"
    "github.com/zoobz-io/astql/pkg/mariadb"
    "github.com/zoobz-io/astql/pkg/sqlite"
    "github.com/zoobz-io/astql/pkg/mssql"
)

users, err := soy.New[User](db, "users", mariadb.New()) // MariaDB
users, err := soy.New[User](db, "users", sqlite.New()) // SQLite
users, err := soy.New[User](db, "users", mssql.New())  // MSSQL

Struct Tags

Soy uses struct tags to define the schema:

TagPurposeExample
dbColumn namedb:"email"
typeSQL column typetype:"text", type:"int", type:"serial"
constraintsColumn constraintsconstraints:"primary key", constraints:"not null unique"
defaultDefault valuedefault:"now()"
checkCheck constraintcheck:"age >= 0"
indexCreate indexindex:"true"
referencesForeign keyreferences:"users(id)"

Next Steps