mirror of https://github.com/aldy505/bob.git
commit
6402e24423
|
@ -1,26 +0,0 @@
|
|||
name: Build test
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
build-test:
|
||||
name: Build test
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
go-version: [1.15.x, 1.16.x, 1.17.x]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Run go vet
|
||||
run: go vet
|
||||
|
||||
- name: Test
|
||||
run: go test -v -race -covermode=atomic -failfast
|
|
@ -3,21 +3,24 @@ name: Test and coverage
|
|||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
check:
|
||||
name: Check
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17.x
|
||||
|
||||
- name: Vet check
|
||||
run: go vet -v
|
||||
|
||||
- name: Run coverage
|
||||
run: go test -v -race -coverprofile=coverage.out -covermode=atomic -failfast
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v1
|
||||
uses: codecov/codecov-action@v1
|
||||
|
|
71
README.md
71
README.md
|
@ -1,18 +1,51 @@
|
|||
# Bob - SQL Query Builder
|
||||
|
||||
[![Go Reference](https://pkg.go.dev/badge/github.com/aldy505/bob.svg)](https://pkg.go.dev/github.com/aldy505/bob) [![Go Report Card](https://goreportcard.com/badge/github.com/aldy505/bob)](https://goreportcard.com/report/github.com/aldy505/bob) ![GitHub](https://img.shields.io/github/license/aldy505/bob) [![CodeFactor](https://www.codefactor.io/repository/github/aldy505/bob/badge)](https://www.codefactor.io/repository/github/aldy505/bob) [![codecov](https://codecov.io/gh/aldy505/bob/branch/master/graph/badge.svg?token=Noeexg5xEJ)](https://codecov.io/gh/aldy505/bob) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/9b78970127c74c1a923533e05f65848d)](https://www.codacy.com/gh/aldy505/bob/dashboard?utm_source=github.com&utm_medium=referral&utm_content=aldy505/bob&utm_campaign=Badge_Grade) [![Build test](https://github.com/aldy505/bob/actions/workflows/build.yml/badge.svg)](https://github.com/aldy505/bob/actions/workflows/build.yml) [![Test and coverage](https://github.com/aldy505/bob/actions/workflows/coverage.yml/badge.svg)](https://github.com/aldy505/bob/actions/workflows/coverage.yml)
|
||||
[![Go Reference](pkg-go-dev-badge)](pkg-go-dev-link)
|
||||
[![Go Report Card](go-report-badge)](go-report-link)
|
||||
![GitHub](license-badge)
|
||||
[![CodeFactor](codefactor-badge)](codefactor-link)
|
||||
[![codecov](codecov-badge)](codecov-link)
|
||||
[![Codacy Badge](codacy-badge)](codacy-link)
|
||||
[![Test and coverage](actions-badge)](actions-link)
|
||||
|
||||
Think of this as an extension of [Squirrel](https://github.com/Masterminds/squirrel) with functionability like [Knex](https://knexjs.org/). 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.
|
||||
Bob is an SQL builder library initially made as an extension for [Squirrel](squirrel-url)
|
||||
with functionality like [Knex](knex-url) (from the Node.js world). Squirrel itself
|
||||
doesn't provide other types of queries for creating a table, upsert,
|
||||
and some other things. Bob is meant to fill those gaps.
|
||||
|
||||
Oh, and of course, heavily inspired by [Bob the Builder](https://en.wikipedia.org/wiki/Bob_the_Builder).
|
||||
The different between Bob and Squirrel is that Bob is solely a query builder.
|
||||
The users have to execute and manage the SQL connection themself.
|
||||
Meaning there are no ExecWith() function implemented on Bob, as you can
|
||||
find it on Squirrel.
|
||||
|
||||
The purpose of an SQL query builder is to prevent any typo or mistypes
|
||||
on the SQL queries. Although also with that reason, Bob might not always
|
||||
have the right query for you, depending on what you are doing with the
|
||||
SQL query. It might sometimes be better for you to write the SQL query
|
||||
yourself, if your problem is specific and needs some micro-tweaks.
|
||||
|
||||
With that being said, I hope you enjoy using Bob and consider starring or
|
||||
reporting any issues regarding the usage of Bob in your projects.
|
||||
|
||||
Oh, and of course, heavily inspired by [Bob the Builder](bob-wikipedia).
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
import "github.com/aldy505/bob"
|
||||
```
|
||||
|
||||
## Usage
|
||||
Like any other Go projects when you're using Go modules, just put that
|
||||
text right there on the top of your projects, do `go mod tidy` and
|
||||
you are good to go.
|
||||
|
||||
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.
|
||||
Either way, I'm not 100% confident enough to say that this thing is
|
||||
production ready. But, the way I see it, it's good enough to be used
|
||||
on a production-level applications. In fact, I'm using it on one of my
|
||||
current projects that's getting around 100-200 hits per day.
|
||||
|
||||
If you have any feature request or improvement ideas for the project,
|
||||
please kindly open an issue
|
||||
|
||||
### Create a table
|
||||
|
||||
|
@ -177,7 +210,7 @@ func main() {
|
|||
Key("email").
|
||||
Replace("age", 40).
|
||||
ToSql()
|
||||
|
||||
|
||||
// One more time, for MSSQL / SQL Server.
|
||||
sql, args, err = bob.
|
||||
Upsert("users", bob.MSSQL).
|
||||
|
@ -276,7 +309,7 @@ func main() {
|
|||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
_, err = db.Query(context.Background(), inventoryQuery[i])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -299,13 +332,6 @@ func main() {
|
|||
* `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 [ExecWith](https://pkg.go.dev/github.com/Masterminds/squirrel?utm_source=godoc#ExecWith)
|
||||
* `bob.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.
|
||||
|
@ -313,3 +339,20 @@ Contributions are always welcome! As long as you add a test for your changes.
|
|||
## License
|
||||
|
||||
Bob is licensed under [MIT license](./LICENSE)
|
||||
|
||||
[squirrel-url]: https://github.com/Masterminds/squirrel
|
||||
[knex-url]: https://knexjs.org/
|
||||
[bob-wikipedia]: https://en.wikipedia.org/wiki/Bob_the_Builder
|
||||
[pkg-go-dev-badge]: https://pkg.go.dev/badge/github.com/aldy505/bob.svg
|
||||
[pkg-go-dev-link]: https://pkg.go.dev/github.com/aldy505/bob
|
||||
[go-report-badge]: https://goreportcard.com/badge/github.com/aldy505/bob
|
||||
[go-report-link]: https://goreportcard.com/report/github.com/aldy505/bob
|
||||
[license-badge]: https://img.shields.io/github/license/aldy505/bob
|
||||
[codefactor-link]: https://www.codefactor.io/repository/github/aldy505/bob
|
||||
[codefactor-badge]: https://www.codefactor.io/repository/github/aldy505/bob/badge
|
||||
[codecov-badge]: https://codecov.io/gh/aldy505/bob/branch/master/graph/badge.svg?token=Noeexg5xEJ
|
||||
[codecov-link]: https://codecov.io/gh/aldy505/bob
|
||||
[codacy-badge]: https://app.codacy.com/project/badge/Grade/9b78970127c74c1a923533e05f65848d
|
||||
[codacy-link]: https://www.codacy.com/gh/aldy505/bob/dashboard?utm_source=github.com&utm_medium=referral&utm_content=aldy505/bob&utm_campaign=Badge_Grade
|
||||
[actions-badge]: https://github.com/aldy505/bob/actions/workflows/coverage.yml/badge.svg
|
||||
[actions-link]: https://github.com/aldy505/bob/actions/workflows/coverage.yml
|
||||
|
|
23
bob.go
23
bob.go
|
@ -1,3 +1,26 @@
|
|||
// Bob is an SQL builder library initially made as an extension for Squirrel
|
||||
// with functionality like Knex (from the Node.js world). Squirrel itself
|
||||
// doesn't provide other types of queries for creating a table, upsert,
|
||||
// and some other things. Bob is meant to fill those gaps.
|
||||
//
|
||||
// The different between Bob and Squirrel is that Bob is solely a query builder.
|
||||
// The users have to execute and manage the SQL connection themself.
|
||||
// Meaning there are no ExecWith() function implemented on Bob, as you can
|
||||
// find it on Squirrel.
|
||||
//
|
||||
// The purpose of an SQL query builder is to prevent any typo or mistypes
|
||||
// on the SQL queries. Although also with that reason, Bob might not always
|
||||
// have the right query for you, depending on what you are doing with the
|
||||
// SQL query. It might sometimes be better for you to write the SQL query
|
||||
// yourself, if your problem is specific and needs some micro-tweaks.
|
||||
//
|
||||
// With that being said, I hope you enjoy using Bob and consider starring or
|
||||
// reporting any issues regarding the usage of Bob in your projects.
|
||||
//
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2021-present Reinaldy Rafli and Bob collaborators
|
||||
//
|
||||
package bob
|
||||
|
||||
import (
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
package bob_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aldy505/bob"
|
||||
)
|
||||
|
||||
func ExampleCreateIndex() {
|
||||
sql, _, err := bob.
|
||||
CreateIndex("idx_email").
|
||||
On("users").
|
||||
Unique().
|
||||
Columns(bob.IndexColumn{Name: "email", Collate: "DEFAULT", Extras: []string{"ASC"}}).
|
||||
ToSql()
|
||||
if err != nil {
|
||||
fmt.Printf("Handle this error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Print(sql)
|
||||
// Output: CREATE UNIQUE INDEX idx_email ON users (email COLLATE DEFAULT ASC);
|
||||
}
|
||||
|
||||
func ExampleHasTable() {
|
||||
sql, args, err := bob.HasTable("users").ToSql()
|
||||
if err != nil {
|
||||
fmt.Printf("Handle this error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("sql: %s, args: %v", sql, args)
|
||||
// Output: sql: SELECT * FROM information_schema.tables WHERE table_name = ? AND table_schema = current_schema();, args: [users]
|
||||
}
|
||||
|
||||
func ExampleHasColumn() {
|
||||
sql, args, err := bob.HasColumn("email").HasTable("users").ToSql()
|
||||
if err != nil {
|
||||
fmt.Printf("Handle this error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("sql: %s, args: %v", sql, args)
|
||||
// Output: sql: SELECT * FROM information_schema.columns WHERE table_name = ? AND column_name = ? AND table_schema = current_schema();, args: [users email]
|
||||
}
|
||||
|
||||
func ExampleDropTable() {
|
||||
sql, _, err := bob.DropTable("users").Cascade().ToSql()
|
||||
if err != nil {
|
||||
fmt.Printf("Handle this error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(sql)
|
||||
// Output: DROP TABLE "users" CASCADE;
|
||||
}
|
||||
|
||||
func ExampleDropTableIfExists() {
|
||||
sql, _, err := bob.DropTableIfExists("users").ToSql()
|
||||
if err != nil {
|
||||
fmt.Printf("Handle this error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(sql)
|
||||
// Output: DROP TABLE IF EXISTS "users";
|
||||
}
|
||||
|
||||
func ExampleTruncate() {
|
||||
sql, _, err := bob.Truncate("users").ToSql()
|
||||
if err != nil {
|
||||
fmt.Printf("Handle this error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(sql)
|
||||
// Output: TRUNCATE "users";
|
||||
}
|
||||
|
||||
func ExampleRenameTable() {
|
||||
sql, _, err := bob.RenameTable("users", "people").ToSql()
|
||||
if err != nil {
|
||||
fmt.Printf("Handle this error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(sql)
|
||||
// Output: RENAME TABLE "users" TO "people";
|
||||
}
|
||||
|
||||
func ExampleUpsert() {
|
||||
// Example for MYSQL
|
||||
mysql, myArgs, 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).
|
||||
ToSql()
|
||||
if err != nil {
|
||||
fmt.Printf("Handle this error: %v", err)
|
||||
}
|
||||
|
||||
// Another example for PostgreSQL
|
||||
pgsql, pgArgs, err := bob.
|
||||
Upsert("users", bob.PostgreSQL).
|
||||
Columns("name", "email", "age").
|
||||
Values("Billy Urtha", "billu@something.com", 30).
|
||||
Key("email").
|
||||
Replace("age", 40).
|
||||
ToSql()
|
||||
if err != nil {
|
||||
fmt.Printf("Handle this error: %v", err)
|
||||
}
|
||||
|
||||
// One more time, for MSSQL / SQL Server.
|
||||
mssql, msArgs, 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).
|
||||
ToSql()
|
||||
if err != nil {
|
||||
fmt.Printf("Handle this error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("MySQL: %s, %v\n", mysql, myArgs)
|
||||
fmt.Printf("PostgreSQL: %s, %v\n", pgsql, pgArgs)
|
||||
fmt.Printf("MSSQL: %s, %v\n", mssql, msArgs)
|
||||
// Output:
|
||||
// MySQL: INSERT INTO "users" ("name", "email", "age") VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE "age" = ?;, [Thomas Mueler tmueler@something.com 25 25]
|
||||
// PostgreSQL: INSERT INTO "users" ("name", "email", "age") VALUES ($1, $2, $3) ON CONFLICT ("email") DO UPDATE SET "age" = $4;, [Billy Urtha billu@something.com 30 40]
|
||||
// MSSQL: IF NOT EXISTS (SELECT * FROM "users" WHERE "email" = @p1) INSERT INTO "users" ("name", "email", "age") VALUES (@p2, @p3, @p4) ELSE UPDATE "users" SET "age" = @p5 WHERE "email" = @p6;, [georgee@something.com George Rust georgee@something.com 19 18 georgee@something.com]
|
||||
}
|
Loading…
Reference in New Issue