mirror of https://github.com/aldy505/bob.git
feat: initial column definition types
This commit is contained in:
parent
86eb9e0935
commit
ca2d51bc7a
170
create.go
170
create.go
|
@ -5,7 +5,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aldy505/bob/util"
|
|
||||||
"github.com/lann/builder"
|
"github.com/lann/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,11 +14,13 @@ type createData struct {
|
||||||
TableName string
|
TableName string
|
||||||
IfNotExists bool
|
IfNotExists bool
|
||||||
Schema string
|
Schema string
|
||||||
Columns []string
|
Columns []ColumnDef
|
||||||
Types []string
|
}
|
||||||
Primary string
|
|
||||||
Unique string
|
type ColumnDef struct {
|
||||||
NotNull []string
|
Name string
|
||||||
|
Type string
|
||||||
|
Extras []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -41,24 +42,129 @@ func (b CreateBuilder) WithSchema(name string) CreateBuilder {
|
||||||
return builder.Set(b, "Schema", name).(CreateBuilder)
|
return builder.Set(b, "Schema", name).(CreateBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns sets the column names
|
// StringColumn creates a column with VARCHAR(255) data type.
|
||||||
func (b CreateBuilder) Columns(cols ...string) CreateBuilder {
|
// For SQLite please refer to TextColumn.
|
||||||
return builder.Set(b, "Columns", cols).(CreateBuilder)
|
func (b CreateBuilder) StringColumn(name string, extras ...string) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "VARCHAR(255)",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Types set a type for certain column
|
// TextColumn creates a column with TEXT data type
|
||||||
func (b CreateBuilder) Types(types ...string) CreateBuilder {
|
func (b CreateBuilder) TextColumn(name string, extras ...string) CreateBuilder {
|
||||||
return builder.Set(b, "Types", types).(CreateBuilder)
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "TEXT",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Primary will set that column as the primary key for a table.
|
// UUIDColumn only available for PostgreSQL
|
||||||
func (b CreateBuilder) Primary(column string) CreateBuilder {
|
func (b CreateBuilder) UUIDColumn(name string, extras ...string) CreateBuilder {
|
||||||
return builder.Set(b, "Primary", column).(CreateBuilder)
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "UUID",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unique adds an unique index to a table over the given columns.
|
// BooleanColumn only available for PostgreSQL
|
||||||
func (b CreateBuilder) Unique(column string) CreateBuilder {
|
func (b CreateBuilder) BooleanColumn(name string, extras ...string) CreateBuilder {
|
||||||
return builder.Set(b, "Unique", column).(CreateBuilder)
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "BOOLEAN",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntegerColumn only available for PostgreSQL and SQLite.
|
||||||
|
// For MySQL and MSSQL, please refer to IntColumn,
|
||||||
|
func (b CreateBuilder) IntegerColumn(name string, extras ...string) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "INTEGER",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntColumn only available for MySQL and MSSQL.
|
||||||
|
// For PostgreSQL and SQLite please refer to IntegerColumn.
|
||||||
|
func (b CreateBuilder) IntColumn(name string, extras ...string) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "INT",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b CreateBuilder) DateTimeColumn(name string, extras ...string) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "DATETIME",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b CreateBuilder) TimeStampColumn(name string, extras ...string) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "TIMESTAMP",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b CreateBuilder) TimeColumn(name string, extras ...string) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "TIME",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b CreateBuilder) DateColumn(name string, extras ...string) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "DATE",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONColumn only available for MySQL and PostgreSQL.
|
||||||
|
// For MSSQL please use AddColumn(bob.ColumnDef{Name: "name", Type: "NVARCHAR(1000)"}).
|
||||||
|
// Not supported for SQLite.
|
||||||
|
func (b CreateBuilder) JSONColumn(name string, extras ...string) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "JSON",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONBColumn only available for PostgreSQL.
|
||||||
|
// For MySQL please refer to JSONColumn.
|
||||||
|
func (b CreateBuilder) JSONBColumn(name string, extras ...string) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "JSONB",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobColumn only available for MySQL and SQLite.
|
||||||
|
// For PostgreSQL and MSSQL, please use AddColumn(bob.ColumnDef{Name: "name", Type: "BYTEA"}).
|
||||||
|
func (b CreateBuilder) BlobColumn(name string, extras ...string) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", ColumnDef{
|
||||||
|
Name: name,
|
||||||
|
Type: "BLOB",
|
||||||
|
Extras: extras,
|
||||||
|
}).(CreateBuilder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddColumn sets custom columns
|
||||||
|
func (b CreateBuilder) AddColumn(column ColumnDef) CreateBuilder {
|
||||||
|
return builder.Append(b, "Columns", column).(CreateBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToSql returns 3 variables filled out with the correct values based on bindings, etc.
|
// ToSql returns 3 variables filled out with the correct values based on bindings, etc.
|
||||||
|
@ -74,8 +180,8 @@ func (d *createData) ToSql() (sqlStr string, args []interface{}, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len(d.Columns) != len(d.Types)) && len(d.Columns) > 0 {
|
if len(d.Columns) == 0 {
|
||||||
err = errors.New("columns and types should have equal length")
|
err = errors.New("a table should at least have one column")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,30 +202,18 @@ func (d *createData) ToSql() (sqlStr string, args []interface{}, err error) {
|
||||||
|
|
||||||
var columnTypes []string
|
var columnTypes []string
|
||||||
for i := 0; i < len(d.Columns); i++ {
|
for i := 0; i < len(d.Columns); i++ {
|
||||||
columnTypes = append(columnTypes, "\""+d.Columns[i]+"\" "+d.Types[i])
|
var column []string
|
||||||
|
column = append(column, "\""+d.Columns[i].Name+"\" "+d.Columns[i].Type)
|
||||||
|
if len(d.Columns[i].Extras) > 0 {
|
||||||
|
column = append(column, strings.Join(d.Columns[i].Extras, " "))
|
||||||
|
}
|
||||||
|
columnTypes = append(columnTypes, strings.Join(column, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
sql.WriteString("(")
|
sql.WriteString("(")
|
||||||
sql.WriteString(strings.Join(columnTypes, ", "))
|
sql.WriteString(strings.Join(columnTypes, ", "))
|
||||||
sql.WriteString(");")
|
sql.WriteString(");")
|
||||||
|
|
||||||
if d.Primary != "" {
|
|
||||||
if !util.IsIn(d.Columns, d.Primary) {
|
|
||||||
err = errors.New("supplied primary column name doesn't exists on columns")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sql.WriteString(" ")
|
|
||||||
sql.WriteString("ALTER TABLE \"" + d.TableName + "\" ADD PRIMARY KEY (\"" + d.Primary + "\");")
|
|
||||||
}
|
|
||||||
|
|
||||||
if d.Unique != "" {
|
|
||||||
if !util.IsIn(d.Columns, d.Unique) {
|
|
||||||
err = errors.New("supplied unique column name doesn't exists on columns")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sql.WriteString(" ")
|
|
||||||
sql.WriteString("ALTER TABLE \"" + d.TableName + "\" ADD UNIQUE (\"" + d.Unique + "\");")
|
|
||||||
}
|
|
||||||
sqlStr = sql.String()
|
sqlStr = sql.String()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,16 @@ import (
|
||||||
|
|
||||||
func TestCreate(t *testing.T) {
|
func TestCreate(t *testing.T) {
|
||||||
t.Run("should return correct sql string with basic columns and types", func(t *testing.T) {
|
t.Run("should return correct sql string with basic columns and types", func(t *testing.T) {
|
||||||
sql, _, err := bob.CreateTable("users").Columns("name", "password", "date").Types("varchar(255)", "text", "date").ToSql()
|
sql, _, err := bob.
|
||||||
|
CreateTable("users").
|
||||||
|
StringColumn("name").
|
||||||
|
TextColumn("password").
|
||||||
|
DateColumn("date").
|
||||||
|
ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
result := "CREATE TABLE \"users\" (\"name\" varchar(255), \"password\" text, \"date\" date);"
|
result := "CREATE TABLE \"users\" (\"name\" VARCHAR(255), \"password\" TEXT, \"date\" DATE);"
|
||||||
if sql != result {
|
if sql != result {
|
||||||
t.Fatal("sql is not equal to result:", sql)
|
t.Fatal("sql is not equal to result:", sql)
|
||||||
}
|
}
|
||||||
|
@ -20,68 +25,58 @@ func TestCreate(t *testing.T) {
|
||||||
|
|
||||||
t.Run("should return correct sql with primary key and unique key", func(t *testing.T) {
|
t.Run("should return correct sql with primary key and unique key", func(t *testing.T) {
|
||||||
sql, _, err := bob.CreateTable("users").
|
sql, _, err := bob.CreateTable("users").
|
||||||
Columns("id", "name", "email", "password", "date").
|
UUIDColumn("id", "PRIMARY KEY").
|
||||||
Types("uuid", "varchar(255)", "varchar(255)", "text", "date").
|
StringColumn("name").
|
||||||
Primary("id").
|
StringColumn("email", "UNIQUE").
|
||||||
Unique("email").
|
TextColumn("password").
|
||||||
|
DateTimeColumn("date").
|
||||||
ToSql()
|
ToSql()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
result := "CREATE TABLE \"users\" (\"id\" uuid, \"name\" varchar(255), \"email\" varchar(255), \"password\" text, \"date\" date); ALTER TABLE \"users\" ADD PRIMARY KEY (\"id\"); ALTER TABLE \"users\" ADD UNIQUE (\"email\");"
|
result := "CREATE TABLE \"users\" (\"id\" UUID PRIMARY KEY, \"name\" VARCHAR(255), \"email\" VARCHAR(255) UNIQUE, \"password\" TEXT, \"date\" DATETIME);"
|
||||||
if sql != result {
|
if sql != result {
|
||||||
t.Fatal("sql is not equal to result:", sql)
|
t.Fatal("sql is not equal to result:", sql)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should be able to have a schema name", func(t *testing.T) {
|
t.Run("should be able to have a schema name", func(t *testing.T) {
|
||||||
sql, _, err := bob.CreateTable("users").WithSchema("private").Columns("name", "password", "date").Types("varchar(255)", "text", "date").ToSql()
|
sql, _, err := bob.
|
||||||
|
CreateTable("users").
|
||||||
|
WithSchema("private").
|
||||||
|
StringColumn("name").
|
||||||
|
TextColumn("password").
|
||||||
|
DateColumn("date").
|
||||||
|
ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
result := "CREATE TABLE \"private\".\"users\" (\"name\" varchar(255), \"password\" text, \"date\" date);"
|
result := "CREATE TABLE \"private\".\"users\" (\"name\" VARCHAR(255), \"password\" TEXT, \"date\" DATE);"
|
||||||
if sql != result {
|
if sql != result {
|
||||||
t.Fatal("sql is not equal to result:", sql)
|
t.Fatal("sql is not equal to result:", sql)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should emit error on unmatched column and types length", func(t *testing.T) {
|
|
||||||
_, _, err := bob.CreateTable("users").
|
|
||||||
Columns("id", "name", "email", "password", "date").
|
|
||||||
Types("uuid", "varchar(255)", "varchar(255)", "date").
|
|
||||||
ToSql()
|
|
||||||
if err.Error() != "columns and types should have equal length" {
|
|
||||||
t.Fatal("should throw an error, it didn't:", err.Error())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("should emit error on empty table name", func(t *testing.T) {
|
t.Run("should emit error on empty table name", func(t *testing.T) {
|
||||||
_, _, err := bob.CreateTable("").Columns("name").Types("text").ToSql()
|
_, _, err := bob.
|
||||||
|
CreateTable("").
|
||||||
|
StringColumn("name").
|
||||||
|
ToSql()
|
||||||
if err.Error() != "create statements must specify a table" {
|
if err.Error() != "create statements must specify a table" {
|
||||||
t.Fatal("should throw an error, it didn't:", err.Error())
|
t.Fatal("should throw an error, it didn't:", err.Error())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should emit error for primary key not in columns", func(t *testing.T) {
|
|
||||||
_, _, err := bob.CreateTable("users").Columns("name").Types("text").Primary("id").ToSql()
|
|
||||||
if err.Error() != "supplied primary column name doesn't exists on columns" {
|
|
||||||
t.Fatal("should throw an error, it didn't:", err.Error())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("should emit error for unique key not in columns", func(t *testing.T) {
|
|
||||||
_, _, err := bob.CreateTable("users").Columns("name").Types("text").Unique("id").ToSql()
|
|
||||||
if err.Error() != "supplied unique column name doesn't exists on columns" {
|
|
||||||
t.Fatal("should throw an error, it didn't:", err.Error())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("should emit create if not exists", func(t *testing.T) {
|
t.Run("should emit create if not exists", func(t *testing.T) {
|
||||||
sql, _, err := bob.CreateTableIfNotExists("users").Columns("name").Types("text").ToSql()
|
sql, _, err := bob.
|
||||||
|
CreateTableIfNotExists("users").
|
||||||
|
TextColumn("name").
|
||||||
|
ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
result := "CREATE TABLE IF NOT EXISTS \"users\" (\"name\" text);"
|
result := "CREATE TABLE IF NOT EXISTS \"users\" (\"name\" TEXT);"
|
||||||
if sql != result {
|
if sql != result {
|
||||||
t.Fatal("sql is not equal to result: ", sql)
|
t.Fatal("sql is not equal to result: ", sql)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue