godb is a simple Go query builder and struct mapper, not a full-featured ORM. godb does not manage relationships.
Initially, godb was a learning project. The goal was to improve my Go skills by doing some useful things. But more and more features have been added and godb has become a serious project that can be used by others.
godb is a project that is still young and evolving. The API is almost stable, but it can still change slightly from one version to another. Each new version is associated with a tag, so it is possible to target a particular one if necessary.
Features
Queries builder.
Mapping between structs and tables (or views).
Mapping with nested structs.
Execution of custom SELECT, INSERT, UPDATE and DELETE queries with structs and slices.
Optional execution of SELECT queries with an iterator to limit memory consumption if needed (e.g. batches).
Execution of raw queries, mapping rows to structs.
Optimistic Locking
SQL queries and durations logs.
Two adjustable prepared statements caches (with/without transaction).
RETURNING support for PostgreSQL.
OUTPUT support for SQL Server.
Optional common db errors handling for backend databases.(db.UseErrorParser())
Define your own logger (should have Println(...) method)
Define model struct name to db table naming with db.SetDefaultTableNamer(yourFn). Supported types are: Plural,Snake,SnakePlural. You can also define TableName() string method to for your struct and return whatever table name will be.
BlackListing or WhiteListing columns for struct based inserts and updates.
Could by used with
SQLite
PostgreSQL
MySQL / MariaDB
MS SQL Server
other compatible database if you write an adapter.
I made tests of godb on differents architectures and operating systems : OSX, Windows, Linux, ARM (Cortex A7) and Intel x64.
The current version of godb is compatible from Go 1.13 to 1.17. Older versions through 1.10 to 1.12 are supported by the v1.0.14 tag .
Documentation
There are three forms of documentation :
This README with the example presented below, which gives an overview of what godb allows.
The tests in dbtests/common, which are run on the different databases supported.
Install the required driver (see tests). You cas use multiple databases if needed.
Of course you can also use a dependency management tool like dep.
Running Tests
godb tests use GoConvey and at least SQLite :
go get github.com/smartystreets/goconvey
go get github.com/mattn/go-sqlite3
To run tests, go into the godb directory and executes go test ./...
SQLite tests are done with in memory database, it's fast. You can run tests with others databases, see below.
With the exception of SQLite, all drivers are pure Go code, and does not require external dependencies.
Test with PostgreSQL
Install the driver and set the GODB_POSTGRESQL environment variable with the PostgreSQL connection string.
go get github.com/lib/pq
GODB_POSTGRESQL="your connection string" go test ./...
Test with MySQL / MariaDB
Install the driver and set the GODB_MYSQL environment variable with the MySQL connection string.
go get github.com/go-sql-driver/mysql
GODB_MYSQL="your connection string" go test ./...
Test with MS SQL Server
Install the driver and set the GODB_MSSQL environment variable with the SQL Server connection string.
go get github.com/denisenkom/go-mssqldb
GODB_MSSQL="your connection string" go test ./...
Test all with Docker
Using Docker you can test with SQLite, PostgreSQL, MariaDB and SQL Server with the testallwithdocker.sh shell script.
SQL Server is greedy, on OSX allow at least 4Go to Docker.
Example
The example below illustrates the main features of godb.
You can copy the code into an example.go file and run it. You need to create the database and the books table as explained in the code.
package main
import (
"database/sql""fmt""time""github.com/samonzeweb/godb""github.com/samonzeweb/godb/adapters/sqlite""log""os"
)
/* To run this example, initialize a SQLite3 DB called 'library.db' and add a 'books' table like this : create table books ( id integer not null primary key autoincrement, title text not null, author text not null, published date not null);*/// Struct and its mappingtypeBookstruct {
Idint`db:"id,key,auto"`Titlestring`db:"title"`Authorstring`db:"author"`Published time.Time`db:"published"`
}
// Optional, default if the struct name (Book)func (*Book) TableName() string {
return"books"
}
// See "group by" exampletypeCountByAuthorstruct {
Authorstring`db:"author"`Countint`db:"count"`
}
funcmain() {
// Examples fixturesvarauthorTolkien="J.R.R. tolkien"varbookTheHobbit=Book{
Title: "The Hobbit",
Author: authorTolkien,
Published: time.Date(1937, 9, 21, 0, 0, 0, 0, time.UTC),
}
varbookTheFellowshipOfTheRing=Book{
Title: "The Fellowship of the Ring",
Author: authorTolkien,
Published: time.Date(1954, 7, 29, 0, 0, 0, 0, time.UTC),
}
varbookTheTwoTowers=Book{
Title: "The Two Towers",
Author: authorTolkien,
Published: time.Date(1954, 11, 11, 0, 0, 0, 0, time.UTC),
}
varbookTheReturnOfTheKing=Book{
Title: "The Return of the King",
Author: authorTolkien,
Published: time.Date(1955, 10, 20, 0, 0, 0, 0, time.UTC),
}
varsetTheLordOfTheRing= []Book{
bookTheFellowshipOfTheRing,
bookTheTwoTowers,
bookTheReturnOfTheKing,
}
// Connect to the DBdb, err:=godb.Open(sqlite.Adapter, "./library.db")
panicIfErr(err)
// OPTIONAL: Set logger to show SQL execution logsdb.SetLogger(log.New(os.Stderr, "", 0))
// OPTIONAL: Set default table name building style from struct's name(if active struct doesn't have TableName() method)db.SetDefaultTableNamer(tablenamer.Plural())
// Single insert (id will be updated)err=db.Insert(&bookTheHobbit).Do()
panicIfErr(err)
// Multiple insert// Warning : BulkInsert only update ids with PostgreSQL and SQL Server!err=db.BulkInsert(&setTheLordOfTheRing).Do()
panicIfErr(err)
// Countcount, err:=db.SelectFrom("books").Count()
panicIfErr(err)
fmt.Println("Books count : ", count)
// Custom selectcountByAuthor:=make([]CountByAuthor, 0, 0)
err=db.SelectFrom("books").
Columns("author", "count(*) as count").
GroupBy("author").
Having("count(*) > 3").
Do(&countByAuthor)
fmt.Println("Count by authors : ", countByAuthor)
// Select single objectsingleBook:=Book{}
err=db.Select(&singleBook).
Where("title = ?", bookTheHobbit.Title).
Do()
iferr==sql.ErrNoRows {
// sql.ErrNoRows is only returned when the target is a single instancefmt.Println("Book not found !")
} else {
panicIfErr(err)
}
// Select single record valuesauthorName:=""title:=""err=db.SelectFrom("books").
Where("title = ?", bookTheHobbit.Title).
Columns("author", "title").
Scanx(&authorName, &title)
iferr==sql.ErrNoRows {
// sql.ErrNoRows is only returned when the target is a single instancefmt.Println("Book not found !")
} else {
panicIfErr(err)
}
// Select multiple objectsmultipleBooks:=make([]Book, 0, 0)
err=db.Select(&multipleBooks).Do()
panicIfErr(err)
fmt.Println("Books found : ", len(multipleBooks))
// Iteratoriter, err:=db.SelectFrom("books").
Columns("id", "title", "author", "published").
DoWithIterator()
panicIfErr(err)
foriter.Next() {
book:=Book{}
err:=iter.Scan(&book)
panicIfErr(err)
fmt.Println(book)
}
panicIfErr(iter.Err())
panicIfErr(iter.Close())
// Raw querysubQuery:=godb.NewSQLBuffer(0, 0). // sizes are indicativeWrite("select author ").
Write("from books ").
WriteCondition(godb.Q("where title = ?", bookTheHobbit.Title))
queryBuffer:=godb.NewSQLBuffer(64, 0).
Write("select * ").
Write("from books ").
Write("where author in (").
Append(subQuery).
Write(")")
panicIfErr(queryBuffer.Err())
books:=make([]Book, 0, 0)
err=db.RawSQL(queryBuffer.SQL(), queryBuffer.Arguments()...).Do(&books)
panicIfErr(err)
fmt.Printf("Raw query found %d books\n", len(books))
// Update and transactionserr=db.Begin()
panicIfErr(err)
updated, err:=db.UpdateTable("books").Set("author", "Tolkien").Do()
panicIfErr(err)
fmt.Println("Books updated : ", updated)
bookTheHobbit.Author="Tolkien"err=db.Update(&bookTheHobbit).Do()
panicIfErr(err)
fmt.Println("Books updated : ", updated)
err=db.Rollback()
panicIfErr(err)
// Deletedeleted, err:=db.Delete(&bookTheHobbit).Do()
panicIfErr(err)
fmt.Println("Books deleted : ", deleted)
deleted, err=db.DeleteFrom("books").
WhereQ(godb.Or(
godb.Q("author = ?", authorTolkien),
godb.Q("author = ?", "Georged Orwell"),
)).
Do()
panicIfErr(err)
fmt.Println("Books deleted : ", deleted)
// Byeerr=db.Close()
panicIfErr(err)
}
// It's just an example, what did you expect ? (never do that in real code)funcpanicIfErr(errerror) {
iferr!=nil {
panic(err)
}
}
Licence
Released under the MIT License, see LICENSE.txt for more informations.
samonzeweb/godb
godb - a Go query builder and struct mapper
godb is a simple Go query builder and struct mapper, not a full-featured ORM. godb does not manage relationships.
Initially, godb was a learning project. The goal was to improve my Go skills by doing some useful things. But more and more features have been added and godb has become a serious project that can be used by others.
godb is a project that is still young and evolving. The API is almost stable, but it can still change slightly from one version to another. Each new version is associated with a tag, so it is possible to target a particular one if necessary.
Features
RETURNING
support for PostgreSQL.OUTPUT
support for SQL Server.db.UseErrorParser()
)Println(...)
method)db.SetDefaultTableNamer(yourFn)
. Supported types are: Plural,Snake,SnakePlural. You can also defineTableName() string
method to for your struct and return whatever table name will be.I made tests of godb on differents architectures and operating systems : OSX, Windows, Linux, ARM (Cortex A7) and Intel x64.
The current version of godb is compatible from Go 1.13 to 1.17. Older versions through 1.10 to 1.12 are supported by the v1.0.14 tag .
Documentation
There are three forms of documentation :
dbtests/common
, which are run on the different databases supported.Install
Install the required driver (see tests). You cas use multiple databases if needed.
Of course you can also use a dependency management tool like
dep
.Running Tests
godb tests use GoConvey and at least SQLite :
To run tests, go into the godb directory and executes
go test ./...
SQLite tests are done with in memory database, it's fast. You can run tests with others databases, see below.
With the exception of SQLite, all drivers are pure Go code, and does not require external dependencies.
Test with PostgreSQL
Install the driver and set the
GODB_POSTGRESQL
environment variable with the PostgreSQL connection string.Test with MySQL / MariaDB
Install the driver and set the
GODB_MYSQL
environment variable with the MySQL connection string.Test with MS SQL Server
Install the driver and set the
GODB_MSSQL
environment variable with the SQL Server connection string.Test all with Docker
Using Docker you can test with SQLite, PostgreSQL, MariaDB and SQL Server with the
testallwithdocker.sh
shell script.SQL Server is greedy, on OSX allow at least 4Go to Docker.
Example
The example below illustrates the main features of godb.
You can copy the code into an
example.go
file and run it. You need to create the database and thebooks
table as explained in the code.Licence
Released under the MIT License, see LICENSE.txt for more informations.