gendry alternatives and similar packages
Based on the "Database" category.
Alternatively, view gendry alternatives based on common mentions on social networks and blogs.
-
tidb
TiDB is an open-source, cloud-native, distributed, MySQL-Compatible database for elastic scale and real-time analytics. Try AI-powered Chat2Query free at : https://tidbcloud.com/free-trial -
cockroach
CockroachDB - the open source, cloud-native distributed SQL database. -
Milvus
A cloud-native vector database, storage for next generation AI applications -
vitess
Vitess is a database clustering system for horizontal scaling of MySQL. -
TinyGo
Go compiler for small places. Microcontrollers, WebAssembly (WASM/WASI), and command-line tools. Based on LLVM. -
groupcache
groupcache is a caching and cache-filling library, intended as a replacement for memcached in many cases. -
VictoriaMetrics
VictoriaMetrics: fast, cost-effective monitoring solution and time series database -
go-cache
An in-memory key:value store/cache (similar to Memcached) library for Go, suitable for single-machine applications. -
immudb
immudb - immutable database based on zero trust, SQL/Key-Value/Document model, tamperproof, data change history -
bytebase
Database DevOps and CI/CD for Developer, DBA and Platform Engineering team. -
rosedb
Lightweight, fast and reliable key/value storage engine based on Bitcask. -
pREST
PostgreSQL ➕ REST, low-code, simplify and accelerate development, ⚡ instant, realtime, high-performance on any Postgres application, existing or new -
buntdb
BuntDB is an embeddable, in-memory key/value database for Go with custom indexing and geospatial support -
xo
Command line tool to generate idiomatic Go code for SQL databases supporting PostgreSQL, MySQL, SQLite, Oracle, and Microsoft SQL Server -
nutsdb
A simple, fast, embeddable, persistent key/value store written in pure Go. It supports fully serializable transactions and many data structures such as list, set, sorted set. -
tiedot
A rudimentary implementation of a basic document (NoSQL) database in Go -
LinDB
LinDB is a scalable, high performance, high availability distributed time series database. -
cache2go
Concurrency-safe Go caching library with expiration capabilities and access counters -
GCache
An in-memory cache library for golang. It supports multiple eviction policies: LRU, LFU, ARC -
gocraft/dbr (database records)
Additions to Go's database/sql for super fast performance and convenience. -
fastcache
Fast thread-safe inmemory cache for big number of entries in Go. Minimizes GC overhead -
CovenantSQL
A decentralized, trusted, high performance, SQL database with blockchain features -
lotusdb
Most advanced key-value store written in Go, extremely fast, compatible with LSM tree and B+ tree, optimization of badger and bbolt.
Clean code begins in your IDE with SonarLint
Do you think we are missing an alternative of gendry or a related project?
Popular Comparisons
README
Gendry
gendry is a Go library that helps you operate database. Based on go-sql-driver/mysql
, it provides a series of simple but useful tools to prepare parameters for calling methods in standard library database/sql
.
The name gendry comes from the role in the hottest drama The Game of Throne
, in which Gendry is not only the bastardy of the late king Robert Baratheon but also a skilled blacksmith. Like the one in drama, this library also forge something which is called SQL
.
gendry consists of three isolated parts, and you can use each one of them partially:
Translation
- [中文](translation/zhcn/README.md)
Manager
manager is used for initializing database connection pool(i.e sql.DB
),
you can set almost all parameters for those mysql driver supported.For example, initializing a database connection pool:
var db *sql.DB
var err error
db, err = manager
.New(dbName, user, password, host)
.Set(
manager.SetCharset("utf8"),
manager.SetAllowCleartextPasswords(true),
manager.SetInterpolateParams(true),
manager.SetTimeout(1 * time.Second),
manager.SetReadTimeout(1 * time.Second)
).Port(3302).Open(true)
In fact, all things manager does is just for concatting the dataSourceName
the format of a dataSourceName
is:
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
manager is based on go-mysql-driver/mysql
, and if you don't know some of the manager.SetXXX series functions, see it on mysql driver's github home page.And for more details see [manager's doc](manager/README.md)
Builder
builder as its name says, is for building sql. Writing sql manually is intuitive but somewhat difficult to maintain.And for where in
, if you have huge amount of elements in the in
set, it's very hard to write.
builder isn't an ORM, in fact one of the most important reasons we create Gendry is we don't like ORM. So Gendry just provides some simple APIs to help you building sqls:
where := map[string]interface{}{
"city": []string{"beijing", "shanghai"},
// The in operator can be omitted by default,
// which is equivalent to:
// "city in": []string{"beijing", "shanghai"},
"score": 5,
"age >": 35,
"address": builder.IsNotNull,
"_or": []map[string]interface{}{
{
"x1": 11,
"x2 >=": 45,
},
{
"x3": "234",
"x4 <>": "tx2",
},
},
"_orderby": "bonus desc",
"_groupby": "department",
}
table := "some_table"
selectFields := []string{"name", "age", "sex"}
cond, values, err := builder.BuildSelect(table, where, selectFields)
//cond = SELECT name,age,sex FROM some_table WHERE (((x1=? AND x2>=?) OR (x3=? AND x4!=?)) AND score=? AND city IN (?,?) AND age>? AND address IS NOT NULL) GROUP BY department ORDER BY bonus DESC
//values = []interface{}{11, 45, "234", "tx2", 5, "beijing", "shanghai", 35}
rows, err := db.Query(cond, values...)
In the where
param, automatically add 'in' operator by value type(reflect.Slice).
where := map[string]interface{}{
"city": []string{"beijing", "shanghai"},
}
the same as
where := map[string]interface{}{
"city in": []string{"beijing", "shanghai"},
}
And, the library provide a useful API for executing aggregate queries like count, sum, max, min, avg
where := map[string]interface{}{
"score > ": 100,
"city": []interface{}{"Beijing", "Shijiazhuang", }
}
// AggregateSum, AggregateMax, AggregateMin, AggregateCount, AggregateAvg are supported
result, err := AggregateQuery(ctx, db, "tableName", where, AggregateSum("age"))
sumAge := result.Int64()
result, err = AggregateQuery(ctx, db, "tableName", where, AggregateCount("*"))
numberOfRecords := result.Int64()
result, err = AggregateQuery(ctx, db, "tableName", where, AggregateAvg("score"))
averageScore := result.Float64()
If you want to clear the zero value in the where map, you can use builder.OmitEmpty
where := map[string]interface{}{
"score": 0,
"age >": 35,
}
finalWhere := builder.OmitEmpty(where, []string{"score", "age"})
// finalWhere = map[string]interface{}{"age >": 35}
// support: Bool, Array, String, Float32, Float64, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Map, Slice, Interface, Struct
For complex queries, NamedQuery
may be helpful:
cond, vals, err := builder.NamedQuery("select * from tb where name={{name}} and id in (select uid from anothertable where score in {{m_score}})", map[string]interface{}{
"name": "caibirdme",
"m_score": []float64{3.0, 5.8, 7.9},
})
assert.Equal("select * from tb where name=? and id in (select uid from anothertable where score in (?,?,?))", cond)
assert.Equal([]interface{}{"caibirdme", 3.0, 5.8, 7.9}, vals)
slice type can be expanded automatically according to its length, thus these sqls are very convenient for DBA to review.
For critical system, this is recommended
For more detail, see [builder's doc](builder/README.md) or just use godoc
Scanner For each response from mysql, you want to map it with your well-defined structure. Scanner provides a very easy API to do this, it's based on reflection:
standard library
type Person struct {
Name string
Age int
}
rows, err := db.Query("SELECT age as m_age, name from g_xxx where xxx")
defer rows.Close()
var students []Person
for rows.Next() {
var student Person
rows.Scan(student.Age, student.Name)
students = append(students, student)
}
using scanner
type Person struct {
Name string `ddb:"name"`
Age int `ddb:"m_age"`
}
rows, err := db.Query("SELECT age as m_age, name from g_xxx where xxx")
defer rows.Close()
var students []Person
scanner.Scan(rows, &students)
Types which implement the interface
type ByteUnmarshaler interface {
UnmarshalByte(data []byte) error
}
will take over the corresponding unmarshal work.
type human struct {
Age int `ddb:"ag"`
Extra *extraInfo `ddb:"ext"`
}
type extraInfo struct {
Hobbies []string `json:"hobbies"`
LuckyNumber int `json:"ln"`
}
func (ext *extraInfo) UnmarshalByte(data []byte) error {
return json.Unmarshal(data, ext)
}
//if the type of ext column in a table is varchar(stored legal json string) or json(mysql5.7)
var student human
err := scanner.Scan(rows, &student)
// ...
The extra tag of the struct will be used by scanner resolve data from response.The default tag name is ddb:"tagname"
, but you can specify your own such as:
scanner.SetTagName("json")
type Person struct {
Name string `json:"name"`
Age int `json:"m_age"`
}
// ...
var student Person
scanner.Scan(rows, &student)
scanner.SetTagName is a global setting and it can be invoked only once
ScanMap
rows, _ := db.Query("select name, age as m_age from person")
result, err := scanner.ScanMap(rows)
for _, record := range result {
fmt.Println(record["name"], record["m_age"])
}
ScanMap scans data from rows and returns a []map[string]interface{}
int, float, string type may be stored as []uint8 by mysql driver, ScanMap just copy those value into the map. If you're sure that there's no binary data type in your mysql table(in most cases, this is true), you can use ScanMapDecode instead which will convert []uint8 to int, float64 or string
For more detail, see [scanner's doc](scanner/README.md)
PS:
- Don't forget close rows if you don't use ScanXXXClose
- The second parameter of Scan must be a reference
Tools Besides APIs above, Gendry provide a CLI tool to help generating codes.
*Note that all licence references and agreements mentioned in the gendry README section above
are relevant to that project's source code only.