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"
|
||||
"strings"
|
||||
|
||||
"github.com/aldy505/bob/util"
|
||||
"github.com/lann/builder"
|
||||
)
|
||||
|
||||
|
@ -15,11 +14,13 @@ type createData struct {
|
|||
TableName string
|
||||
IfNotExists bool
|
||||
Schema string
|
||||
Columns []string
|
||||
Types []string
|
||||
Primary string
|
||||
Unique string
|
||||
NotNull []string
|
||||
Columns []ColumnDef
|
||||
}
|
||||
|
||||
type ColumnDef struct {
|
||||
Name string
|
||||
Type string
|
||||
Extras []string
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -41,24 +42,129 @@ func (b CreateBuilder) WithSchema(name string) CreateBuilder {
|
|||
return builder.Set(b, "Schema", name).(CreateBuilder)
|
||||
}
|
||||
|
||||
// Columns sets the column names
|
||||
func (b CreateBuilder) Columns(cols ...string) CreateBuilder {
|
||||
return builder.Set(b, "Columns", cols).(CreateBuilder)
|
||||
// StringColumn creates a column with VARCHAR(255) data type.
|
||||
// For SQLite please refer to TextColumn.
|
||||
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
|
||||
func (b CreateBuilder) Types(types ...string) CreateBuilder {
|
||||
return builder.Set(b, "Types", types).(CreateBuilder)
|
||||
// TextColumn creates a column with TEXT data type
|
||||
func (b CreateBuilder) TextColumn(name string, extras ...string) 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.
|
||||
func (b CreateBuilder) Primary(column string) CreateBuilder {
|
||||
return builder.Set(b, "Primary", column).(CreateBuilder)
|
||||
// UUIDColumn only available for PostgreSQL
|
||||
func (b CreateBuilder) UUIDColumn(name string, extras ...string) 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.
|
||||
func (b CreateBuilder) Unique(column string) CreateBuilder {
|
||||
return builder.Set(b, "Unique", column).(CreateBuilder)
|
||||
// BooleanColumn only available for PostgreSQL
|
||||
func (b CreateBuilder) BooleanColumn(name string, extras ...string) 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.
|
||||
|
@ -74,8 +180,8 @@ func (d *createData) ToSql() (sqlStr string, args []interface{}, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
if (len(d.Columns) != len(d.Types)) && len(d.Columns) > 0 {
|
||||
err = errors.New("columns and types should have equal length")
|
||||
if len(d.Columns) == 0 {
|
||||
err = errors.New("a table should at least have one column")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -96,30 +202,18 @@ func (d *createData) ToSql() (sqlStr string, args []interface{}, err error) {
|
|||
|
||||
var columnTypes []string
|
||||
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(strings.Join(columnTypes, ", "))
|
||||
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()
|
||||
return
|
||||
}
|
||||
|
|
|
@ -8,11 +8,16 @@ import (
|
|||
|
||||
func TestCreate(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 {
|
||||
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 {
|
||||
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) {
|
||||
sql, _, err := bob.CreateTable("users").
|
||||
Columns("id", "name", "email", "password", "date").
|
||||
Types("uuid", "varchar(255)", "varchar(255)", "text", "date").
|
||||
Primary("id").
|
||||
Unique("email").
|
||||
UUIDColumn("id", "PRIMARY KEY").
|
||||
StringColumn("name").
|
||||
StringColumn("email", "UNIQUE").
|
||||
TextColumn("password").
|
||||
DateTimeColumn("date").
|
||||
ToSql()
|
||||
|
||||
if err != nil {
|
||||
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 {
|
||||
t.Fatal("sql is not equal to result:", sql)
|
||||
}
|
||||
})
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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) {
|
||||
_, _, err := bob.CreateTable("").Columns("name").Types("text").ToSql()
|
||||
_, _, err := bob.
|
||||
CreateTable("").
|
||||
StringColumn("name").
|
||||
ToSql()
|
||||
if err.Error() != "create statements must specify a table" {
|
||||
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) {
|
||||
sql, _, err := bob.CreateTableIfNotExists("users").Columns("name").Types("text").ToSql()
|
||||
sql, _, err := bob.
|
||||
CreateTableIfNotExists("users").
|
||||
TextColumn("name").
|
||||
ToSql()
|
||||
if err != nil {
|
||||
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 {
|
||||
t.Fatal("sql is not equal to result: ", sql)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue