Reinaldy Rafli
2f066ace06
feat: create index method |
||
---|---|---|
.github | ||
.gitignore | ||
LICENSE | ||
README.md | ||
bob.go | ||
create_index.go | ||
create_index_test.go | ||
create_table.go | ||
create_table_test.go | ||
drop.go | ||
drop_test.go | ||
go.mod | ||
go.sum | ||
has.go | ||
has_test.go | ||
internal.go | ||
placeholder.go | ||
placeholder_test.go | ||
rename.go | ||
rename_test.go | ||
truncate.go | ||
truncate_test.go | ||
upsert.go | ||
upsert_test.go |
README.md
Bob - SQL Query Builder
Think of this as an extension of Squirrel with functionability like Knex. I still use Squirrel for other types of queries (insert, select, and all that), but I needed some SQL builder for create table and some other stuffs. Including database creation & upsert.
Oh, and of course, heavily inspired by Bob the Builder.
import "github.com/aldy505/bob"
Usage
It's not ready for large-scale production yet (although I've already using it on one of my projects). But, the API is probably close to how you'd do things on Squirrel.
Create a table
import "github.com/aldy505/bob"
func main() {
// Note that CREATE TABLE doesn't returns args params.
sql, _, err := bob.
CreateTable("tableName").
// The first parameter is the column's name.
// The second parameters and so on forth are extras.
StringColumn("id", "NOT NULL", "PRIMARY KEY", "AUTOINCREMENT").
StringColumn("email", "NOT NULL", "UNIQUE").
// See the list of available column definition types through pkg.go.dev or scroll down below.
TextColumn("password").
// Or add your custom type.
AddColumn(bob.ColumnDef{Name: "tableName", Type: "customType", Extras: []string{"NOT NULL"}}).
ToSql()
if err != nil {
// handle your error
}
}
Available column definition types (please be aware that some only works on certain database):
StringColumn()
- Default toVARCHAR(255)
TextColumn()
- Default toTEXT
UUIDColumn()
- Defaults toUUID
BooleanColumn()
- Defaults toBOOLEAN
IntegerColumn()
- Defaults toINTEGER
. Postgres and SQLite only.IntColumn()
- Defaults toINT
. MySQL and MSSQL only.RealColumn()
- Defaults toREAL
. Postgres, MSSQL, and SQLite only.FloatColumn()
- Defaults toFLOAT
. Postgres and SQLite only.DateTimeColumn()
- Defaults toDATETIME
.TimeStampColumn()
- Defaults toTIMESTAMP
.TimeColumn()
- Defaults toTIME
.DateColumn()
- Defaults toDATE
.JSONColumn()
- Dafults toJSON
. MySQL and Postgres only.JSONBColumn()
- Defaults toJSONB
. Postgres only.BlobColumn()
- Defaults toBLOB
. MySQL and SQLite only.
For any other types, please use AddColumn()
.
Another builder of bob.CreateTableIfNotExists()
is also available.
Check if a table exists
func main() {
sql, args, err := bob.HasTable("users").ToSql()
if err != nil {
log.Fatal(err)
}
}
Check if a column exists
func main() {
sql, args, err := bob.HasColumn("email").ToSql()
if err != nil {
log.Fatal(err)
}
}
Drop table
func main() {
sql, _, err := bob.DropTable("users").ToSql()
if err != nil {
log.Fatal(err)
}
// sql = "DROP TABLE users;"
sql, _, err = bob.DropTableIfExists("users").ToSql()
if err != nil {
log.Fatal(err)
}
// sql = "DROP TABLE IF EXISTS users;"
sql, _, err = bob.DropTable("users").Cascade().ToSql()
if err != nil {
log.Fatal(err)
}
// sql = "DROP TABLE users CASCADE;"
sql, _, err = bob.DropTable("users").Restrict().ToSql()
if err != nil {
log.Fatal(err)
}
// sql = "DROP TABLE users RESTRICT;"
}
Truncate table
func main() {
sql, _, err := bob.Truncate("users").ToSql()
if err != nil {
log.Fatal(err)
}
}
Rename table
func main() {
sql, _, err := bob.RenameTable("users", "people").ToSql()
if err != nil {
log.Fatal(err)
}
}
Upsert
func main() {
sql, args, err := bob.
// Notice that you should give database dialect on the second params.
// Available database dialect are MySQL, PostgreSQL, SQLite, and MSSQL.
Upsert("users", bob.MySQL).
Columns("name", "email", "age").
// You could do multiple Values() call, but I'd suggest to not do it.
// Because this is an upsert function, not an insert one.
Values("Thomas Mueler", "tmueler@something.com", 25).
Replace("age", 25).
PlaceholderFormat(bob.Question).
ToSql()
// Another example for PostgreSQL
sql, args, err = bob.
Upsert("users", bob.PostgreSQL).
Columns("name", "email", "age").
Values("Billy Urtha", "billu@something.com", 30).
Key("email").
Replace("age", 40).
PlaceholderFormat(bob.Dollar).
ToSql()
// One more time, for MSSQL / SQL Server.
sql, args, err = bob.
Upsert("users", bob.MSSQL).
Columns("name", "email", "age").
Values("George Rust", "georgee@something.com", 19).
Key("email", "georgee@something.com").
Replace("age", 18).
PlaceholderFormat(bob.AtP).
ToSql()
}
Placeholder format / Dialect
Default placeholder is a question mark (MySQL-like). If you want to change it, simply use something like this:
func main() {
// Option 1
sql, args, err := bob.HasTable("users").PlaceholderFormat(bob.Dollar).ToSql()
if err != nil {
log.Fatal(err)
}
// Option 2
sql, args, err = bob.HasTable("users").ToSql()
if err != nil {
log.Fatal(err)
}
correctPlaceholder := bob.ReplacePlaceholder(sql, bob.Dollar)
}
Available placeholder formats:
bob.Question
-INSERT INTO "users" (name) VALUES (?)
bob.Dollar
-INSERT INTO "users" (name) VALUES ($1)
bob.Colon
-INSERT INTO "users" (name) VALUES (:1)
bob.AtP
-INSERT INTO "users" (name) VALUES (@p1)
With pgx (PostgreSQL)
import (
"context"
"log"
"strings"
"github.com/aldy505/bob"
"github.com/jackc/pgx/v4"
)
func main() {
db := pgx.Connect()
// Check if a table is exists
sql, args, err = bob.HasTable("users").PlaceholderFormat(bob.Dollar).ToSql()
if err != nil {
log.Fatal(err)
}
var hasTableUsers bool
err = db.QueryRow(context.Background(), sql, args...).Scan(&hasTableUsers)
if err != nil {
if err == bob.ErrEmptyTablePg {
hasTableUsers = false
} else {
log.Fatal(err)
}
}
if !hasTableUsers {
// Create "users" table
sql, _, err := bob.
CreateTable("users").
IntegerColumn("id", "PRIMARY KEY", "SERIAL").
StringColumn("name", "NOT NULL").
TextColumn("password", "NOT NULL").
DateColumn("created_at").
ToSql()
if err != nil {
log.Fatal(err)
}
_, err = db.Query(context.Background(), splitQuery[i])
if err != nil {
log.Fatal(err)
}
// Create another table, this time with CREATE TABLE IF NOT EXISTS
sql, _, err := bob.
CreateTableIfNotExists("inventory").
UUIDColumn("id", "PRIMARY KEY").
IntegerColumn("userID", "FOREIGN KEY REFERENCES users(id)").
JSONColumn("items").
IntegerColumn("quantity").
ToSql()
if err != nil {
log.Fatal(err)
}
_, err = db.Query(context.Background(), inventoryQuery[i])
if err != nil {
log.Fatal(err)
}
}
}
Features
bob.CreateTable(tableName)
- Basic SQL create tablebob.CreateTableIfNotExists(tableName)
- Create table if not existsbob.HasTable(tableName)
- Checks if column exists (return error if false, check example above for error handling)bob.HasColumn(columnName)
- Check if a column exists on current tablebob.DropTable(tableName)
- Drop a table (drop table "users"
)bob.DropTableIfExists(tableName)
- Drop a table if exists (drop table if exists "users"
)bob.RenameTable(currentTable, desiredName)
- Rename a table (rename table "users" to "people"
)bob.Truncate(tableName)
- Truncate a table (truncate "users"
)bob.Upsert(tableName, dialect)
- UPSERT function (insert into "users" ("name", "email") values (?, ?) on duplicate key update email = ?
)
TODO
Meaning these are some ideas for the future development of Bob.
bob.ExecWith()
- Just like Squirrel's ExecWithbob.Count(tableName, columnName)
- Count query (select count("active") from "users"
)
Contributing
Contributions are always welcome! As long as you add a test for your changes.
License
Bob is licensed under MIT license