kin

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 3, 2024 License: MIT Imports: 11 Imported by: 0

README

Kin

CircleCI Go Report Card Documentation Coverage Status

Kin is very experimental - don't use it for anything real!

Kin is an opinionated, PostgreSQL-specific database driver that places an emphasis on writing SQL and explicit mappings to database tables. It gives users the control to write their own SQL queries, uses simple patterns that focus on control.

This means that kin isn't for everyone! It's certainly not a full-featured ORM in the mold of Gorm or Ruby's ActiveRecord. Instead, Kin smoothes out the rough edges and gives better error handling to SQL packages already built into Go.

Finally, support for running migrations is built in.

Getting Started

Installing kin is as simple as running:

go get github.com/jmataya/kin

Next, define your models, connect to the database, and you're off to the races!

package main

import (
        "database/sql"
        "fmt"
        "time"

        "github.com/jmataya/kin"
)

// User is a representation of a table called "users" with columns
// id (int), name (text), attributes (jsonb), is_active (bool), and
// created_at (timestamp).
type User struct {
	ID         int                    `db:"id"`
	Name       string                 `db:"name"`
	Attributes map[string]interface{} `db:"attributes"`
	IsActive   bool                   `db:"is_active"`
	CreatedAt  time.Time              `db:"created_at"`
}

func (u User) TableName() string {
	return "users"
}

func main() {
        // Connect with a raw Postgres URL.
        dbStr := "postgresql://localhost:5432/kin_test?user=kin"
        db, _ := sql.Open("postgres", dbStr)
        defer db.Close()
        
        // For most operations, Kin leverages SQL.
        queryStr := "SELECT * FROM users WHERE id = $1"
        id := 1
        
        // Output a single result into the user struct defined above.
		user, err := kin.NewQuery[User](db).Raw(queryStr, id).One()
        if err != nil {
                panic(err)
        }
        
        // Print the result.
        fmt.Printf("User: %+v\n", user)
}

Developing

You will need a database in order to run tests. Create a Postgres instance and put the database URL into a .env file in the root of the project. It should look something like this:

DATABASE_URL=postgresql://localhost:5432/kin_test?user=kin

Next, you can run tests with:

go test

Author

Jeff Mataya (jeff@jeffmataya.com)

License

MIT

Documentation

Overview

Package kin implements a delcarative query manager for PostgreSQL.

Overview

Kin is an opinionated, PostgeSQL-specific query driver that places an emphasis on writing SQL and explicit mappings to query tables. Instead of relying on reflection or other conventions, it gives users the control to write their own SQL queries, uses simple patterns that focus on control.

This means that kin probably isn't for everyone! It's certainly not a full-featured ORM in the mold of Gorm or Ruby's ActiveRecord. Instead, Kin smoothes out the rough edges and gives better error handling to SQL packages already built into Go.

Finally, support for running migrations is built in.

Getting Started

Installing kin is as simple as running:

go get github.com/jmataya/kin

Next, define your models, connect to the query, and you're off to the races!

	package main

	import (
		"fmt"
		"time"

		"github.com/jmataya/kin"
	)

	// user is a representation of a table called "users" with columns
	// id (int), name (text), attributes (jsonb), is_active (bool), and
  // created_at (timestamp).
	type user struct {
		ID         int
		Name       string
		Attributes map[string]interface{}
		IsActive   bool
		CreatedAt  time.Time
	}

	// Columns defines the mapping between query columns, their type,
	// and the model. It's used internally by kin to wire everything up.
	func (u *user) Columns() []FieldBuilder {
		return []FieldBuilder{
			IntField("id", &u.ID),
			StringField("name", &u.Name),
			JSONField("attributes", &u.Attributes),
			BoolField("is_active", &u.IsActive),
			TimeField("created_at", &u.CreatedAt),
		}
	}

	func main() {
		// Connect with a raw Postges URL.
		dbStr := "postgresql://localhost:5432/kin_test?user=kin"
		db, _ := kin.NewConnection(dbStr)
		defer db.Close()

		// For most operations, Kin leverages SQL.
		queryStr := "SELECT * FROM users WHERE id = $1"
		id := 1

		// Output a single result into the user struct defined above.
		u := new(user)
		err := db.Statement(queryStr, id).OneAndExtract(u)
		if err != nil {
			panic(err)
		}

		// Print the result.
		fmt.Printf("User: %+v\n", u)
	}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BuildFn

type BuildFn func(builder Model) error

BuildFn takes a Builder and initializes its values.

type DatabaseConnection

type DatabaseConnection interface {
	Prepare(string) (*sql.Stmt, error)
}

type Migrator

type Migrator struct {
	// contains filtered or unexported fields
}

Migrator is a structure used for running query migrations.

func NewMigrator

func NewMigrator(db *sql.DB) (*Migrator, error)

NewMigrator creates a new Migrator around an existing DB connection.

func NewMigratorConnection

func NewMigratorConnection(dbURL string) (*Migrator, error)

NewMigratorConnection initialized a DB connection and uses it to power migrations.

func (Migrator) Close

func (m Migrator) Close() error

Close terminates the DB connection. Once this occurs there can be no future migrations with this object.

func (Migrator) Migrate

func (m Migrator) Migrate(folderPath string) error

Migrate runs a series of query migrations.

type Model

type Model interface {
	// TableName returns the name of the table that this model maps to.
	TableName() string
}

Model is a data structure that can be used to construct a query insert or update.

type Query

type Query[T Model] interface {
	// Get runs a select and returns all results.
	Get(table string) ([]*T, error)

	// Insert adds a record and returns the result.
	Insert(model T) (*T, error)

	// Raw generates a new statement to be executed at a later time.
	Raw(stmt string, params ...interface{}) *Statement[T]
}

Query is an interface for generating query queries. It supports a few common and simple querying operations and then allows the user to solve more complex problems using SQL.

func NewQuery

func NewQuery[T Model](db DatabaseConnection) Query[T]

NewQuery creates a new wrapper around an existing DB connection.

type Result

type Result struct {
	Columns []string
	Rows    []*RowResult
}

Result contains the results of a query query.

type RowResult

type RowResult struct {
	Columns []string
	Data    map[string]interface{}
	// contains filtered or unexported fields
}

RowResult contains the results of a single row in a query result set.

func (*RowResult) Err

func (rr *RowResult) Err() error

Err returns any aggregrated errors.

func (*RowResult) ExtractBool

func (rr *RowResult) ExtractBool(column string) bool

ExtractBool gets the value in the dataset and returns a boolean. If the value can't be extracted, it stores an error on the result and prevents further extraction from occurring.

func (*RowResult) ExtractDecimal

func (rr *RowResult) ExtractDecimal(column string) float64

ExtractDecimal gets the value in the dataset and returns an integer. If the value can't be extracted, it stores an error on the result and prevents further extraction from occurring.

func (*RowResult) ExtractInt

func (rr *RowResult) ExtractInt(column string) int

ExtractInt gets the value in the dataset and returns an integer. If the value can't be extracted, it stores an error on the result and prevents further extraction from occurring.

func (*RowResult) ExtractJSON

func (rr *RowResult) ExtractJSON(column string, out interface{})

ExtractJSON gets a JSON value from the dataset and unmarshals it into an interface passed by the caller.

func (*RowResult) ExtractString

func (rr *RowResult) ExtractString(column string) string

ExtractString gets the value in the dataset and returns a string. If the value can't be extracted, it stores an error on the result and prevents further extraction from occurring.

func (*RowResult) ExtractTime

func (rr *RowResult) ExtractTime(column string) time.Time

ExtractTime gets the value in the dataset and returns a time.Time. If the value can't be extracted, it stores an error on the result and prevents further extraction from occurring.

type Statement

type Statement[T Model] struct {
	// contains filtered or unexported fields
}

Statement is a SQL statement that has yet to be executed.

func (Statement[T]) Many

func (s Statement[T]) Many() ([]*T, error)

func (Statement[T]) One

func (s Statement[T]) One() (*T, error)

One executes the query and updates the model with the result.

func (Statement[T]) Run

func (s Statement[T]) Run() (*Result, error)

Run executes the query and returns the results.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL