Giter Club home page Giter Club logo

crud's Introduction

CRUD

A minimalistic relational database library for Go.

Table of Contents

Install

$ go get github.com/azer/crud/v2

Initialize

import (
  "github.com/azer/crud/v2"
  _ "github.com/go-sql-driver/mysql"
)

var DB *crud.DB

func init () {
  var err error
  DB, err = crud.Connect("mysql", os.Getenv("DATABASE_URL"))
  err = DB.Ping()
}

Define

type User struct {
  Id int `sql:"auto-increment primary-key"`
  FirstName string
  LastName string
  ProfileId int
}

type Profile struct {
  Id int `sql:"auto-increment primary-key"`
  Bio string `sql:"text"`
}

CRUD will automatically convert column names from "FirstName" (CamelCase) to "first_name" (snake_case) for you. You can still choose custom names though;

type Post struct {
  Slug string `sql:"name=slug_id varchar(255) primary-key required"`
}

If no primary key is specified, CRUD will look for a field named "Id" with int type, and set it as auto-incrementing primary-key field.

Create & Drop Tables

CreateTables takes list of structs and makes sure they exist in the database.

err := DB.CreateTables(User{}, Profile{})

err := DB.DropTables(User{}, Profile{})
Reset Tables

Shortcut for dropping and creating tables.

err := DB.ResetTables(User{}, Profile{})
SQL Options

CRUD tries to be smart about figuring out the best SQL options for your structs, and lets you choose manually, too. For example;

type Tweet struct {
 Text string `sql:"varchar(140) required name=tweet"`
}

Above example sets the type of the Text column as varchar(140), makes it required (NOT NULL) and changes the column name as tweet.

Here is the list of the options that you can pass;

  • Types: int, bigint, varchar, text, date, time, timestamp
  • auto-increment / autoincrement / auto_increment
  • primary-key / primarykey / primary_key
  • required
  • default='?'
  • name=?
  • table-name=?

If you'd like a struct field to be ignored by CRUD, choose - as options:

type Foo struct {
 IgnoreMe string `sql:"-"`
}

Create

Simply pass a struct. It can be pointer or not.

user := &User{1, "Foo", "Bar", 1}
err := DB.Create(user)

CreateAndRead

Create a row, and read it back from the DB. The values of the struct you passed get resetted to whatever the corresponding DB row has. In the other words, CreateAndRead creates, and reads. So you got fields generated by the DB scanned to your struct, like ID.

Make sure passing a pointer.

user := User{
  FirstName:"Foo"
}

err := DB.CreateAndRead(&user)

user.Id
// => 123

Read

You can read single/multiple rows, or custom values, with the Read method.

Reading a single row:

Pass your struct's pointer, and a query;

user := &User{}
err := DB.Read(user, "SELECT * FROM users WHERE id = ?", 1)
// => SELECT * FROM users WHERE id = 1

fmt.Println(user.Name)
// => Foo
Reading multiple rows:
users := []*User{}

err := DB.Read(&users, "SELECT * FROM users")
// => SELECT * FROM users

fmt.Println(len(users))
// => 10
Scanning to custom values:
names := []string{}
err := DB.Read(&names, "SELECT name FROM users")
name := ""
err := DB.Read(&name, "SELECT name FROM users WHERE id=1")
totalUsers := 0
err := DB.Read(&totalUsers, "SELECT COUNT(id) FROM users"

Update

Updates matching row in database, returns sql.ErrNoRows nothing matched.

user := &User{}
err := DB.Read(user, "SELECT * FROM users WHERE id = ?", 1)

user.Name = "Yolo"
err := DB.Update(user)

Delete

Deletes matching row in database, returns sql.ErrNoRows nothing matched.

err := DB.Delete(&User{
  Id: 1
})

Contexts

Use WithContext method to get a DB client with context. Here is an example;

db := DB.WithContext(context.Background())

Transactions

Use Begin method of a crud.DB instance to create a new transaction. Each transaction will provide you following methods;

  • Commit
  • Rollback
  • Exec
  • Query
  • Create
  • CreateAndRead
  • Read
  • Update
  • Delete
tx, err := DB.Begin(context.Background())

err := tx.Create(&User{
  Name: "yolo"
})

err := tx.Delete(&User{
  Id: 123
})

err := tx.Commit()

CRUD generates an ID for each transaction, and uses that for logging queries and the state of the transactions. You can override transaction IDs in some use cases such as having same IDs and ID field keys with your Rest framework generating request IDs;

tx.Id = requestId
tx.IdKey = "requestId"

Logs

If you want to see crud's internal logs, specify crud in the LOG environment variable when you run your app. For example;

$ LOG=crud go run myapp.go

Custom Queries

result, err := DB.Query("DROP DATABASE yolo") // or .Exec

Running Tests

DATABASE_URL="?" go test ./...

What's Missing?

  • Hooks: I'm not sure if this is needed, but worths to consider.
  • Foreign Keys: *
  • Make UTF-8 Default: Looks like the default charset is not UTF8.

LICENSE

MIT License

crud's People

Contributors

ashishmohite avatar skatsuta avatar thomshutt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

crud's Issues

panic: near "AUTO_INCREMENT": syntax error

package main

import (
	"fmt"
	"github.com/azer/crud"
 
		_ "github.com/mattn/go-sqlite3"
 
)

type User struct {
	Id        int `sql:"primary_key auto_increment "`
	FirstName string
	LastName  string
}

func main() {
	DB, err := crud.Connect("sqlite3","test.db")  // os.Getenv("DATABASE_URL")
	if err != nil {
		panic(err)
	}

	if err := DB.CreateTables(User{}); err != nil {
		panic(err)
	}

	azer := User{
		FirstName: "Azer",
		LastName:  "Koculu",
	}

	if err := DB.Create(&azer); err != nil {
		panic(err)
	}

	copy := User{}
	if err := DB.Read(&copy, "WHERE first_name='Azer'"); err != nil {
		panic(err)
	}

	fmt.Println(copy.Id)
}

auto-increment / autoincrement / auto_increment all fail with panic: near "AUTO_INCREMENT": syntax error
primary_key works fine but when insert another record fail with panic: UNIQUE constraint failed: user.id

Custom queries are ignored if they begin with `select` rather than `SELECT`

Given

const sqlFindTweets = "select tweets.* from tweets left join sent using (id) where sent.id is null"
err = db.Read(&tweets, sqlFindTweets)                                   

With select -

{ "time":"2016-01-11 16:29:33.806763777 +0100 CET", "package":"crud", "level":"INFO", "msg":"SELECT * FROM tweets select tweets.* from tweets left join sent using (id) where sent.id is null" }

With SELECT -

{ "time":"2016-01-11 16:29:17.760972918 +0100 CET", "package":"crud", "level":"INFO", "msg":"SELECT tweets.* from tweets left join sent using (id) where sent.id is null" }

I can live with this but it might be worth calling out specifically in the documentation.

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.