Giter Club home page Giter Club logo

query's Introduction

query

query โ€“ A Go SQL query package

Abusing language features for fun and profit, query provides a different take for querying SQL databases in Go keeping SQL front and centre, but using language constructs to generate the SQL.

Introduction

query provides a set of helper functions to assist with querying a SQL database. The caller is able to prepare SQL queries through defining a Go struct which doubles as the scan target when retrieving a SQL result set. The results may then be transformed into the application domain model in a type-safe manner, or the original query struct can be used by the application using the Ident function. This reduces the load on the developer to have to define a query, define SQL-safe variables to scan into, and convert the results into a usable model by combining the first and second operation.

Examples

Find One

type User struct {
    ID   int
    Name string
}

func FindUser(ctx context.Context, db *sql.DB, userID int) (User, error) {
    type users struct {
        query.Conditions `q:"id = $1"`
        ID               int
        Name             string
    }
    return query.One(ctx, db, func(row users) User {
        return User{ID: row.ID, Name: row.Name}
    }, userID)
}

Find Many

type User struct {
    ID   int
    Name string
}

func FindUsers(ctx context.Context, db *sql.DB, limit, offset int) ([]User, error) {
    type users struct {
        query.Limit  `q:"$1"`
        query.Offset `q:"$2"`
        ID           int
        Name         string
    }
    return query.All(ctx, db, func(row users) User {
        return User{ID: row.ID, Name: row.Name}
    }, limit, offset)
}

Has Many

type User struct {
    ID        int
    Name      string
    Addresses []Address
}

type Address struct {
    ID    int
    City  string
    State string
}

func FindUser(ctx context.Context, db *sql.DB, userID int) (User, error) {
    return query.One(ctx, db, func(u userQuery) User {
        user := User{
            ID:        u.ID,
            Name:      u.Name,
            Addresses: make([]Address, len(u.Addresses)),
        }
        for i, addr := range u.Addresses {
            user.Addresses[i] = Address{
                ID:    addr.ID,
                City:  addr.City,
                State: addr.State,
            }
        }
        return user
    }, userID)
}

type usersQuery struct {
    query.Table `q:"users"`

    ID        int
    Name      string

    Addresses []struct {
        ID    int
        City  string
        State string
    } `q:"users.address_id = addresses.id"`
}

type userQuery struct {
    query.Conditions `q:"users.id = $1"`
    usersQuery
}

Options

While query works with standard database/sql database/transaction handles, additional features can be unlocked by opening the database using query's Open function. The following options are available:

Namer

The Namer configuration open allows the caller to specify an object that implements the Namer interface to provide custom query naming rules. This allows customization for databases that do not match the default standard namer conventions used by query.

Logger

The Logger holds a function that accepts a query and arguments which is called when a query is executed. This can be used to help with debugging or to keep tabs on what queries are being executed.

Example

db, err := query.Open("sqlite3", "myfile.db", &query.Options{
    Namer: myNamer,
    Logger: func(query string, args []any) {
        fmt.Println(query, args)
    },
})

Example Queries

Basic Select

type users struct {
    ID   int            `q:"id"`
    Name sql.NullString `q:"name"`
}
// SELECT id, name FROM users

Select With Attributes

type users struct {
    query.Table      `q:"user"`
    query.Conditions `q:"id = ?"`
    query.GroupBy    `q:"id, name"`
    query.OrderBy    `q:"name DESC"`
    query.Limit      `q:"10"`
    query.Offset     `q:"?"`

    ID   int            `q:"id"`
    Name sql.NullString `q:"name"`
}
// SELECT id, name FROM user WHERE id = ?
//   GROUP BY id, name ORDER BY name DESC
//   LIMIT 10 OFFSET ?

Count Query

type users struct {
    Count int `q:"COUNT(*)"`
}
// SELECT COUNT(*) FROM users

Composition

type usersQuery struct {
    query.Table `q:"users"`

    ID   int
    Name string
}

type usersByIDQuery struct {
    query.Conditions `q:"id = ?"`
    usersQuery
}
// SELECT id, name FROM users WHERE id = ?

Inner Join

type usersQuery struct {
    query.Table `q:"users"`

    ID        int
    Name      string
    Addresses struct {
        City string
    } `q:"users.address_id = addresses.id`
}
// SELECT users.id, users.name, addresses.city FROM users INNER JOIN addresses ON users.address_id = addresses.id

Left Join

type usersQuery struct {
    query.Table `q:"users"`

    ID        int
    Name      string
    Addresses struct {
        query.LeftJoin

        City sql.NullString
    } `q:"users.address_id = addresses.id`
}
// SELECT users.id, users.name, addresses.city FROM users LEFT JOIN addresses ON users.address_id = addresses.id

Has Many Join

type usersQuery struct {
    query.Table `q:"users"`

    ID        int
    Name      string
    Addresses []struct {
        City string
    } `q:"users.address_id = addresses.id`
}
// SELECT users.id, users.name, addresses.city FROM users INNER JOIN addresses ON users.address_id = addresses.id

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.