2021-12-10 09:44:15 +00:00
|
|
|
// 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
|
|
|
|
//
|
2021-06-24 07:43:28 +00:00
|
|
|
package bob
|
|
|
|
|
2021-07-21 08:59:53 +00:00
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
"github.com/lann/builder"
|
|
|
|
)
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// ErrEmptyTable is a common database/sql error if a table is empty or no rows is returned by the query.
|
2021-07-21 08:59:53 +00:00
|
|
|
var ErrEmptyTable = errors.New("sql: no rows in result set")
|
2021-07-31 04:48:40 +00:00
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// ErrEmptyTable is a common pgx error if a table is empty or no rows is returned by the query.
|
2021-07-21 08:59:53 +00:00
|
|
|
var ErrEmptyTablePgx = errors.New("no rows in result set")
|
2021-07-31 04:48:40 +00:00
|
|
|
|
2021-07-25 04:41:39 +00:00
|
|
|
// ErrDialectNotSupported tells you whether the dialect is supported or not.
|
|
|
|
var ErrDialectNotSupported = errors.New("provided database dialect is not supported")
|
|
|
|
|
|
|
|
const (
|
2021-07-31 04:44:21 +00:00
|
|
|
MySQL int = iota
|
|
|
|
PostgreSQL
|
|
|
|
SQLite
|
|
|
|
MSSQL
|
2021-07-25 04:41:39 +00:00
|
|
|
)
|
2021-06-24 07:43:28 +00:00
|
|
|
|
2021-06-26 02:57:08 +00:00
|
|
|
// BobBuilderType is the type for BobBuilder
|
2021-06-24 07:43:28 +00:00
|
|
|
type BobBuilderType builder.Builder
|
|
|
|
|
2021-07-09 06:41:34 +00:00
|
|
|
// BobBuilder interface wraps the ToSql method
|
2021-06-24 07:43:28 +00:00
|
|
|
type BobBuilder interface {
|
2021-07-09 06:41:34 +00:00
|
|
|
ToSql() (string, []interface{}, error)
|
2021-06-24 07:43:28 +00:00
|
|
|
}
|
|
|
|
|
2021-06-26 02:57:08 +00:00
|
|
|
// CreateTable creates a table with CreateBuilder interface
|
2021-06-24 07:43:28 +00:00
|
|
|
func (b BobBuilderType) CreateTable(table string) CreateBuilder {
|
2021-07-31 04:17:48 +00:00
|
|
|
return CreateBuilder(b).name(table)
|
2021-06-24 07:43:28 +00:00
|
|
|
}
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// CreateTableIfNotExists creates a table with CreateBuilder interface, if the table doesn't exists.
|
2021-07-09 06:39:30 +00:00
|
|
|
func (b BobBuilderType) CreateTableIfNotExists(table string) CreateBuilder {
|
2021-07-31 04:17:48 +00:00
|
|
|
return CreateBuilder(b).name(table).ifNotExists()
|
2021-07-09 06:39:30 +00:00
|
|
|
}
|
|
|
|
|
2021-11-09 05:16:10 +00:00
|
|
|
// CreateIndex creates an index with CreateIndexBuilder interface.
|
|
|
|
func (b BobBuilderType) CreateIndex(name string) IndexBuilder {
|
|
|
|
return IndexBuilder(b).name(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateIndexIfNotExists creates an index with CreateIndexBuilder interface, if the index doesn't exists.
|
|
|
|
func (b BobBuilderType) CreateIndexIfNotExists(name string) IndexBuilder {
|
|
|
|
return IndexBuilder(b).name(name).ifNotExists()
|
|
|
|
}
|
|
|
|
|
2021-06-26 02:57:08 +00:00
|
|
|
// HasTable checks if a table exists with HasBuilder interface
|
2021-06-25 17:04:41 +00:00
|
|
|
func (b BobBuilderType) HasTable(table string) HasBuilder {
|
|
|
|
return HasBuilder(b).HasTable(table)
|
|
|
|
}
|
|
|
|
|
2021-06-26 02:57:08 +00:00
|
|
|
// HasColumn checks if a column exists with HasBuilder interface
|
2021-06-25 17:04:41 +00:00
|
|
|
func (b BobBuilderType) HasColumn(column string) HasBuilder {
|
|
|
|
return HasBuilder(b).HasColumn(column)
|
|
|
|
}
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// DropTable drops (delete contents & remove) a table from the database.
|
2021-07-24 18:35:12 +00:00
|
|
|
func (b BobBuilderType) DropTable(table string) DropBuilder {
|
2021-07-31 04:17:48 +00:00
|
|
|
return DropBuilder(b).dropTable(table)
|
2021-07-24 18:35:12 +00:00
|
|
|
}
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// DropTable drops (delete contents & remove) a table from the database if the table exists.
|
2021-07-24 18:35:12 +00:00
|
|
|
func (b BobBuilderType) DropTableIfExists(table string) DropBuilder {
|
2021-07-31 04:17:48 +00:00
|
|
|
return DropBuilder(b).dropTable(table).ifExists()
|
2021-07-24 18:35:12 +00:00
|
|
|
}
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// RenameTable simply renames an exisisting table.
|
2021-07-24 18:35:12 +00:00
|
|
|
func (b BobBuilderType) RenameTable(from, to string) RenameBuilder {
|
2021-07-31 04:17:48 +00:00
|
|
|
return RenameBuilder(b).from(from).to(to)
|
2021-07-24 18:35:12 +00:00
|
|
|
}
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// Truncate performs TRUNCATE function. It deletes all contents from a table but not deleting the table.
|
2021-07-24 18:35:12 +00:00
|
|
|
func (b BobBuilderType) Truncate(table string) TruncateBuilder {
|
2021-07-31 04:17:48 +00:00
|
|
|
return TruncateBuilder(b).truncate(table)
|
2021-07-24 18:35:12 +00:00
|
|
|
}
|
|
|
|
|
2021-07-25 04:41:39 +00:00
|
|
|
func (b BobBuilderType) Upsert(table string, dialect int) UpsertBuilder {
|
2021-07-31 04:27:31 +00:00
|
|
|
return UpsertBuilder(b).dialect(dialect).into(table)
|
2021-07-25 04:41:39 +00:00
|
|
|
}
|
|
|
|
|
2021-11-10 05:27:55 +00:00
|
|
|
func (b BobBuilderType) DropColumn(table, column string) AlterBuilder {
|
|
|
|
return AlterBuilder(b).whatToAlter(alterDropColumn).tableName(table).firstKey(column)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b BobBuilderType) DropConstraint(table, constraint string) AlterBuilder {
|
|
|
|
return AlterBuilder(b).whatToAlter(alterDropConstraint).tableName(table).firstKey(constraint)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b BobBuilderType) RenameColumn(table, from, to string) AlterBuilder {
|
|
|
|
return AlterBuilder(b).whatToAlter(alterRenameColumn).tableName(table).firstKey(from).secondKey(to)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b BobBuilderType) RenameConstraint(table, from, to string) AlterBuilder {
|
|
|
|
return AlterBuilder(b).whatToAlter(alterRenameConstraint).tableName(table).firstKey(from).secondKey(to)
|
|
|
|
}
|
|
|
|
|
2021-06-26 02:57:08 +00:00
|
|
|
// BobStmtBuilder is the parent builder for BobBuilderType
|
2021-06-24 07:43:28 +00:00
|
|
|
var BobStmtBuilder = BobBuilderType(builder.EmptyBuilder)
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// CreateTable creates a table with CreateBuilder interface.
|
2021-07-31 04:44:21 +00:00
|
|
|
// Refer to README for available column definition types.
|
|
|
|
//
|
|
|
|
// // 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 README.
|
|
|
|
// 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
|
|
|
|
// }
|
2021-06-24 07:43:28 +00:00
|
|
|
func CreateTable(table string) CreateBuilder {
|
|
|
|
return BobStmtBuilder.CreateTable(table)
|
|
|
|
}
|
2021-06-25 17:04:41 +00:00
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// CreateTableIfNotExists creates a table with CreateBuilder interface, if the table doesn't exists.
|
2021-07-09 06:39:30 +00:00
|
|
|
func CreateTableIfNotExists(table string) CreateBuilder {
|
|
|
|
return BobStmtBuilder.CreateTableIfNotExists(table)
|
|
|
|
}
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// HasTable checks if a table exists with HasBuilder interface.
|
2021-06-25 17:04:41 +00:00
|
|
|
func HasTable(table string) HasBuilder {
|
|
|
|
return BobStmtBuilder.HasTable(table)
|
|
|
|
}
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// HasColumn checks if a column exists with HasBuilder interface.
|
2021-06-25 17:04:41 +00:00
|
|
|
func HasColumn(col string) HasBuilder {
|
|
|
|
return BobStmtBuilder.HasColumn(col)
|
|
|
|
}
|
2021-07-24 18:35:12 +00:00
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// DropTable drops (delete contents & remove) a table from the database.
|
2021-07-24 18:35:12 +00:00
|
|
|
func DropTable(table string) DropBuilder {
|
|
|
|
return BobStmtBuilder.DropTable(table)
|
|
|
|
}
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// DropTable drops (delete contents & remove) a table from the database if the table exists.
|
2021-07-24 18:35:12 +00:00
|
|
|
func DropTableIfExists(table string) DropBuilder {
|
|
|
|
return BobStmtBuilder.DropTableIfExists(table)
|
|
|
|
}
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// RenameTable simply renames an exisisting table.
|
2021-07-24 18:35:12 +00:00
|
|
|
func RenameTable(from, to string) RenameBuilder {
|
|
|
|
return BobStmtBuilder.RenameTable(from, to)
|
|
|
|
}
|
|
|
|
|
2021-07-24 18:47:02 +00:00
|
|
|
// Truncate performs TRUNCATE function. It deletes all contents from a table but not deleting the table.
|
2021-07-24 18:35:12 +00:00
|
|
|
func Truncate(table string) TruncateBuilder {
|
|
|
|
return BobStmtBuilder.Truncate(table)
|
2021-07-25 04:41:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Upsert performs a UPSERT query with specified database dialect.
|
|
|
|
// Supported database includes MySQL, PostgreSQL, SQLite and MSSQL.
|
2021-07-31 04:44:21 +00:00
|
|
|
//
|
|
|
|
// // MySQL example:
|
|
|
|
// 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()
|
2021-07-31 04:48:40 +00:00
|
|
|
//
|
2021-07-31 04:44:21 +00:00
|
|
|
// // 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()
|
2021-07-31 04:48:40 +00:00
|
|
|
//
|
2021-07-31 04:44:21 +00:00
|
|
|
// // 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()
|
2021-07-25 04:41:39 +00:00
|
|
|
func Upsert(table string, dialect int) UpsertBuilder {
|
|
|
|
return BobStmtBuilder.Upsert(table, dialect)
|
2021-07-31 04:48:40 +00:00
|
|
|
}
|
2021-11-09 05:16:10 +00:00
|
|
|
|
|
|
|
// CreateIndex creates an index with CreateIndexBuilder interface.
|
|
|
|
func CreateIndex(name string) IndexBuilder {
|
|
|
|
return BobStmtBuilder.CreateIndex(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateIndexIfNotExists creates an index with CreateIndexBuilder interface, if the index doesn't exists.
|
|
|
|
func CreateIndexIfNotExists(name string) IndexBuilder {
|
|
|
|
return BobStmtBuilder.CreateIndexIfNotExists(name)
|
2021-11-09 05:16:31 +00:00
|
|
|
}
|
2021-11-10 05:27:55 +00:00
|
|
|
|
|
|
|
func DropColumn(table, column string) AlterBuilder {
|
|
|
|
return BobStmtBuilder.DropColumn(table, column)
|
|
|
|
}
|
|
|
|
|
|
|
|
func DropConstraint(table, constraint string) AlterBuilder {
|
|
|
|
return BobStmtBuilder.DropConstraint(table, constraint)
|
|
|
|
}
|
|
|
|
|
|
|
|
func RenameColumn(table, from, to string) AlterBuilder {
|
|
|
|
return BobStmtBuilder.RenameColumn(table, from, to)
|
|
|
|
}
|
|
|
|
|
|
|
|
func RenameConstraint(table, from, to string) AlterBuilder {
|
|
|
|
return BobStmtBuilder.RenameConstraint(table, from, to)
|
|
|
|
}
|