From 49d6a5a6e738f4d1b4f07c8d747273d32d8bff5c Mon Sep 17 00:00:00 2001 From: Mesut GENEZ Date: Wed, 5 Jun 2024 22:53:41 +0300 Subject: [PATCH] distinct, isnull and having added --- README.md | 26 ++-- builder.go | 231 +++++++++++++++++++++++++++++++++ builder_test.go | 338 ++++++++++++++++++++++++++++++++++++++++++++++++ example/main.go | 32 +++-- sql.go | 151 --------------------- sql_test.go | 211 ------------------------------ 6 files changed, 603 insertions(+), 386 deletions(-) create mode 100644 builder.go create mode 100644 builder_test.go delete mode 100644 sql.go delete mode 100644 sql_test.go diff --git a/README.md b/README.md index 8adfff0..e6f00aa 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,12 @@ var gb GoBuilder ```go // all columns -gb.Select("users").Where("id","=","1").Sql() +gb.Select("users").Where("id","=","1").ToSql() // filter columns gb.Select("users", "firstname", "lastname", "create_date"). Where("id", "=", "1"). - Sql() + ToSql() ``` ```sql Result: SELECT * FROM users WHERE id = '1' @@ -28,7 +28,7 @@ Result: SELECT firstname,lastname,create_date FROM users WHERE id = '1' gb.Select("users"). Where("id", "=", "1"). OrWhere("email", "=", "loremipsum@lrmpsm.com"). - Sql() + ToSql() ``` ```sql Result: SELECT * FROM users WHERE id='1' OR email='loremipsum@lrmpsm.com' @@ -38,7 +38,7 @@ Result: SELECT * FROM users WHERE id='1' OR email='loremipsum@lrmpsm.com' gb.Select("users as u", "u.firstname", "u.lastname", "a.address"). Join("INNER", "address as a", "a.user_id=u.id"). Where("u.email", "=", "loremipsum@lrmpsm.com"). - Sql() + ToSql() ``` ```sql Result: SELECT u.firstname,u.lastname,a.address FROM users as u INNER JOIN address as a ON a.user_id=u.id WHERE u.email='loremipsum@lrmpsm.com' @@ -48,7 +48,7 @@ Result: SELECT u.firstname,u.lastname,a.address FROM users as u INNER JOIN addre gb.Select("users"). Where("id", "=", "1"). Between("create_date", "2021-01-01", "2021-03-16"). - Sql() + ToSql() ``` ```sql Result: SELECT * FROM users WHERE id='1' AND create_date BETWEEN '2021-01-01' AND '2021-03-16' @@ -59,7 +59,7 @@ gb.Select("users"). Where("id", "=", "1"). Between("create_date", "2021-01-01", "2021-03-16"). Limit(1, 5). - Sql() + ToSql() ``` ```sql Result: SELECT * FROM users WHERE id='1' AND create_date BETWEEN '2021-01-01' AND '2021-03-16' LIMIT 1,5 @@ -70,7 +70,7 @@ gb.Select("users"). Where("id", "=", "1"). Between("create_date", "2021-01-01", "2021-03-16"). GroupBy("lastname"). - Sql() + ToSql() ``` ```sql Result: SELECT * FROM users WHERE id='1' AND create_date BETWEEN '2021-01-01' AND '2021-03-16' GROUP BY lastname @@ -82,15 +82,15 @@ gb.Select("users"). Between("create_date", "2021-01-01", "2021-03-16"). GroupBy("lastname"). OrderBy("id", "DESC"). - Sql() + ToSql() ``` ```sql Result: SELECT * FROM users WHERE id='1' AND create_date BETWEEN '2021-01-01' AND '2021-03-16' GROUP BY lastname ORDER BY id DESC ``` ### union ```go -s1 := gb.Select("users").Where("lastname", "=", "lorem").Sql() -s2 := gb.Select("users").Where("lastname", "=", "ipsum").Union(s1).Sql() +s1 := gb.Select("users").Where("lastname", "=", "lorem").ToSql() +s2 := gb.Select("users").Where("lastname", "=", "ipsum").Union(s1).ToSql() ``` ```sql Result: SELECT * FROM users WHERE lastname='ipsum' UNION SELECT * FROM users WHERE lastname='lorem' @@ -102,7 +102,7 @@ args := map[string]string{ "firstname": "Lorem", "lastname": "IPSUM", } -gb.Insert("users", args).Sql() +gb.Insert("users", args).ToSql() ``` ```sql Result : INSERT INTO users (lastname,firstname) VALUES ('Lorem','IPSUM') @@ -114,7 +114,7 @@ args := map[string]string{ "firstname": "Lorem", "lastname": "IPSUM", } -gb.Update("users", args).Where("email", "=", "loremipsum@lrmpsm.com").Sql() +gb.Update("users", args).Where("email", "=", "loremipsum@lrmpsm.com").ToSql() ``` ```sql Result: UPDATE users SET firstname='Lorem', lastname='IPSUM' WHERE email='loremipsum@lrmpsm.com' @@ -122,7 +122,7 @@ Result: UPDATE users SET firstname='Lorem', lastname='IPSUM' WHERE email='loremi ## Delete ```go -gb.Delete("users").Where("email", "=", "loremipsum@lrmpsm.com").Sql() +gb.Delete("users").Where("email", "=", "loremipsum@lrmpsm.com").ToSql() ``` ```sql Result: DELETE FROM users WHERE email='loremipsum@lrmpsm.com' diff --git a/builder.go b/builder.go new file mode 100644 index 0000000..e2c3eb6 --- /dev/null +++ b/builder.go @@ -0,0 +1,231 @@ +package gobuilder + +import ( + "fmt" + "strings" + + "golang.org/x/exp/maps" +) + +type GoBuilder struct { + sql string +} + +func (gb *GoBuilder) Select(table string, columns ...string) *GoBuilder { + if len(columns) == 0 { + columns = append(columns, "*") + } + gb.sql = fmt.Sprintf("SELECT %v FROM %v", strings.Join(columns, ", "), table) + return gb +} + +func (gb *GoBuilder) SelectDistinct(table string, columns ...string) *GoBuilder { + if len(columns) == 0 { + columns = append(columns, "*") + } + gb.sql = fmt.Sprintf("SELECT DISTINCT %v FROM %v", strings.Join(columns, ", "), table) + return gb +} + +func (gb *GoBuilder) Insert(table string, args map[string]any) *GoBuilder { + if len(args) != 0 { + keys := maps.Keys(args) + var values []string + for _, v := range maps.Values(args) { + values = append(values, fmt.Sprintf("'%v'", v)) + } + gb.sql = fmt.Sprintf("INSERT INTO %v (%v) VALUES (%v)", table, strings.Join(keys, ", "), strings.Join(values, ", ")) + } + return gb +} + +func (gb *GoBuilder) Update(table string, args map[string]any) *GoBuilder { + if len(args) != 0 { + var setClauses []string + for key, value := range args { + setClauses = append(setClauses, fmt.Sprintf("%v = '%v'", key, value)) + } + gb.sql = fmt.Sprintf("UPDATE %v SET %v", table, strings.Join(setClauses, ", ")) + } + return gb +} + +func (gb *GoBuilder) Delete(table string) *GoBuilder { + gb.sql = fmt.Sprintf("DELETE FROM %v", table) + return gb +} + +func (gb *GoBuilder) Where(key, opt string, val any) *GoBuilder { + return gb.where("AND", key, opt, val) +} + +func (gb *GoBuilder) OrWhere(key, opt string, val any) *GoBuilder { + return gb.where("OR", key, opt, val) +} + +func (gb *GoBuilder) where(OP, key, opt string, val any) *GoBuilder { + var clause string + + switch v := val.(type) { + case int, int64, float32, float64: + clause = fmt.Sprintf("%v %v %v", key, opt, v) + case *GoBuilder: + clause = fmt.Sprintf("%v %v (%v)", key, opt, v.ToSql()) + default: + clause = fmt.Sprintf("%v %v '%v'", key, opt, v) + } + + if strings.Contains(gb.sql, "WHERE") { + gb.sql = fmt.Sprintf("%v %v %v", gb.sql, OP, clause) + } else { + gb.sql = fmt.Sprintf("%v WHERE %v", gb.sql, clause) + } + return gb +} + +func (gb *GoBuilder) In(column string, args ...any) *GoBuilder { + return gb.in("AND", column, args...) +} + +func (gb *GoBuilder) OrIn(column string, args ...any) *GoBuilder { + return gb.in("OR", column, args...) +} + +func (gb *GoBuilder) in(OP, column string, args ...any) *GoBuilder { + if len(args) > 0 { + var values []string + for _, arg := range args { + switch v := arg.(type) { + case int, int64, float32, float64: + values = append(values, fmt.Sprintf("%v", v)) + default: + values = append(values, fmt.Sprintf("'%v'", v)) + } + } + clause := fmt.Sprintf("%v IN (%v)", column, strings.Join(values, ", ")) + if strings.Contains(gb.sql, "WHERE") { + gb.sql = fmt.Sprintf("%v %v %v", gb.sql, OP, clause) + } else { + gb.sql = fmt.Sprintf("%v WHERE %v", gb.sql, clause) + } + } + return gb +} + +func (gb *GoBuilder) Between(column string, args ...any) *GoBuilder { + return gb.between("AND", column, args...) +} + +func (gb *GoBuilder) OrBetween(column string, args ...any) *GoBuilder { + return gb.between("OR", column, args...) +} + +func (gb *GoBuilder) between(OP, column string, args ...any) *GoBuilder { + if len(args) == 2 { + var clause string + switch args[0].(type) { + case int, int64, float32, float64: + clause = fmt.Sprintf("%v BETWEEN %v AND %v", column, args[0], args[1]) + default: + clause = fmt.Sprintf("%v BETWEEN '%v' AND '%v'", column, args[0], args[1]) + } + if strings.Contains(gb.sql, "WHERE") { + gb.sql = fmt.Sprintf("%v %v %v", gb.sql, OP, clause) + } else { + gb.sql = fmt.Sprintf("%v WHERE %v", gb.sql, clause) + } + } + return gb +} + +func (gb *GoBuilder) IsNull(column string) *GoBuilder { + clause := fmt.Sprintf("%v IS NULL", column) + if strings.Contains(gb.sql, "WHERE") { + gb.sql = fmt.Sprintf("%v AND %v", gb.sql, clause) + } else { + gb.sql = fmt.Sprintf("%v WHERE %v", gb.sql, clause) + } + return gb +} + +func (gb *GoBuilder) OrIsNull(column string) *GoBuilder { + clause := fmt.Sprintf("%v IS NULL", column) + if strings.Contains(gb.sql, "WHERE") { + gb.sql = fmt.Sprintf("%v OR %v", gb.sql, clause) + } else { + gb.sql = fmt.Sprintf("%v WHERE %v", gb.sql, clause) + } + return gb +} + +func (gb *GoBuilder) IsNotNull(column string) *GoBuilder { + clause := fmt.Sprintf("%v IS NOT NULL", column) + if strings.Contains(gb.sql, "WHERE") { + gb.sql = fmt.Sprintf("%v AND %v", gb.sql, clause) + } else { + gb.sql = fmt.Sprintf("%v WHERE %v", gb.sql, clause) + } + return gb +} + +func (gb *GoBuilder) OrIsNotNull(column string) *GoBuilder { + clause := fmt.Sprintf("%v IS NOT NULL", column) + if strings.Contains(gb.sql, "WHERE") { + gb.sql = fmt.Sprintf("%v OR %v", gb.sql, clause) + } else { + gb.sql = fmt.Sprintf("%v WHERE %v", gb.sql, clause) + } + return gb +} + +func (gb *GoBuilder) Having(condition string) *GoBuilder { + if strings.Contains(gb.sql, "HAVING") { + gb.sql = fmt.Sprintf("%v AND %v", gb.sql, condition) + } else { + gb.sql = fmt.Sprintf("%v HAVING %v", gb.sql, condition) + } + return gb +} + +func (gb *GoBuilder) OrHaving(condition string) *GoBuilder { + if strings.Contains(gb.sql, "HAVING") { + gb.sql = fmt.Sprintf("%v OR %v", gb.sql, condition) + } else { + gb.sql = fmt.Sprintf("%v HAVING %v", gb.sql, condition) + } + return gb +} + +func (gb *GoBuilder) Join(joinType, table, onCondition string) *GoBuilder { + gb.sql = fmt.Sprintf("%v %v JOIN %v ON %v", gb.sql, joinType, table, onCondition) + return gb +} + +func (gb *GoBuilder) Limit(start, limit int) *GoBuilder { + gb.sql = fmt.Sprintf("%v LIMIT %v, %v", gb.sql, start, limit) + return gb +} + +func (gb *GoBuilder) GroupBy(columns ...string) *GoBuilder { + gb.sql = fmt.Sprintf("%v GROUP BY %v", gb.sql, strings.Join(columns, ", ")) + return gb +} + +func (gb *GoBuilder) OrderBy(columns ...string) *GoBuilder { + gb.sql = fmt.Sprintf("%v ORDER BY %v ASC", gb.sql, strings.Join(columns, ", ")) + return gb +} + +func (gb *GoBuilder) OrderByDesc(columns ...string) *GoBuilder { + gb.sql = fmt.Sprintf("%v ORDER BY %v DESC", gb.sql, strings.Join(columns, ", ")) + return gb +} + +func (gb *GoBuilder) Union(sql string) *GoBuilder { + gb.sql = fmt.Sprintf("%v UNION %v", gb.sql, sql) + return gb +} + +func (gb *GoBuilder) ToSql() string { + return gb.sql +} diff --git a/builder_test.go b/builder_test.go new file mode 100644 index 0000000..a5ea1d1 --- /dev/null +++ b/builder_test.go @@ -0,0 +1,338 @@ +package gobuilder + +import ( + "reflect" + "testing" +) + +var ( + got string + expected string + s GoBuilder +) + +func TestSql_Select(t *testing.T) { + s.sql = "" + expected = "SELECT * FROM users" + got = s.Select("users").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Select_With_Columns(t *testing.T) { + s.sql = "" + expected = "SELECT firstname, lastname FROM users" + got = s.Select("users", "firstname", "lastname").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Distinct(t *testing.T) { + expected = "SELECT DISTINCT name, age FROM users" + got = s.SelectDistinct("users", "name", "age").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Insert(t *testing.T) { + s.sql = "" + insert := map[string]any{"firstname": "Mesut", "lastname": "GENEZ"} + expected = "INSERT INTO users (firstname, lastname) VALUES ('Mesut', 'GENEZ')" + got = s.Insert("users", insert).ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Update(t *testing.T) { + s.sql = "" + // sometimes it may not pass the test because the map is unordered + expected = "UPDATE users SET firstname = 'Mesut', lastname = 'GENEZ'" + got = s.Update("users", map[string]any{"firstname": "Mesut", "lastname": "GENEZ"}).ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Delete(t *testing.T) { + s.sql = "" + expected = "DELETE FROM users" + got = s.Delete("users").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Where(t *testing.T) { + s.sql = "" + expected = " WHERE firstname = 'Mesut'" + got = s.Where("firstname", "=", "Mesut").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_WhereWithInt(t *testing.T) { + s.sql = "" + expected = " WHERE id = 55" + got = s.Where("id", "=", 55).ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_WhereWithFloat(t *testing.T) { + s.sql = "" + expected = " WHERE amount = 55.5" + got = s.Where("amount", "=", 55.5).ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Where_With_And(t *testing.T) { + s.sql = "" + expected = " WHERE firstname = 'Mesut' AND lastname = 'GENEZ'" + got = s.Where("firstname", "=", "Mesut").Where("lastname", "=", "GENEZ").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrWhere(t *testing.T) { + s.sql = "" + expected = " WHERE firstname = 'Mesut'" + got = s.OrWhere("firstname", "=", "Mesut").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrWhere_With_And(t *testing.T) { + s.sql = "" + expected = " WHERE firstname = 'Mesut' OR lastname = 'GENEZ'" + got = s.OrWhere("firstname", "=", "Mesut").OrWhere("lastname", "=", "GENEZ").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_In(t *testing.T) { + s.sql = "" + expected = " WHERE firstname IN ('Mesut')" + got = s.In("firstname", "Mesut").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_InWithInt(t *testing.T) { + s.sql = "" + expected = " WHERE id IN (12, 34, 55)" + got = s.In("id", 12, 34, 55).ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_InAnd(t *testing.T) { + s.sql = "" + expected = " WHERE firstname IN ('Mesut') AND lastname IN ('GENEZ')" + got = s.In("firstname", "Mesut").In("lastname", "GENEZ").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrIn(t *testing.T) { + s.sql = "" + expected = " WHERE firstname IN ('Mesut')" + got = s.OrIn("firstname", "Mesut").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrInAnd(t *testing.T) { + s.sql = "" + expected = " WHERE firstname IN ('Mesut', 'GENEZ') OR lastname IN ('GENEZ')" + got = s.OrIn("firstname", "Mesut", "GENEZ").OrIn("lastname", "GENEZ").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Between(t *testing.T) { + s.sql = "" + expected = " WHERE firstname BETWEEN 'Mesut' AND 'GENEZ'" + got = s.Between("firstname", "Mesut", "GENEZ").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_BetweenWithInt(t *testing.T) { + s.sql = "" + expected = " WHERE id BETWEEN 12 AND 55" + got = s.Between("id", 12, 55).ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_BetweenWithWhere(t *testing.T) { + s.sql = "" + expected = " WHERE firstname BETWEEN 'Mesut' AND 'GENEZ' AND lastname BETWEEN 'Mesut' AND 'GENEZ'" + got = s.Between("firstname", "Mesut", "GENEZ").Between("lastname", "Mesut", "GENEZ").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrBetween(t *testing.T) { + s.sql = "" + expected = " WHERE firstname BETWEEN 'Mesut' AND 'GENEZ'" + got = s.OrBetween("firstname", "Mesut", "GENEZ").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrBetweenWithWhere(t *testing.T) { + s.sql = "" + expected = " WHERE firstname BETWEEN 'Mesut' AND 'GENEZ' OR lastname BETWEEN 'Mesut' AND 'GENEZ'" + got = s.OrBetween("firstname", "Mesut", "GENEZ").OrBetween("lastname", "Mesut", "GENEZ").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_IsNull(t *testing.T) { + expected = "SELECT * FROM users WHERE age = 30 AND name IS NULL" + got = s.Select("users").Where("age", "=", 30).IsNull("name").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_IsNotNull(t *testing.T) { + expected = "SELECT * FROM users WHERE age = 30 AND name IS NOT NULL" + got = s.Select("users").Where("age", "=", 30).IsNotNull("name").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Having(t *testing.T) { + expected = "SELECT * FROM orders GROUP BY user_id HAVING COUNT(*) > 1" + got = s.Select("orders").GroupBy("user_id").Having("COUNT(*) > 1").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrHaving(t *testing.T) { + expected = "SELECT * FROM orders GROUP BY user_id HAVING COUNT(*) > 1 OR COUNT(*) < 5" + got = s.Select("orders").GroupBy("user_id").OrHaving("COUNT(*) > 1").OrHaving("COUNT(*) < 5").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Join(t *testing.T) { + s.sql = "" + expected = " INNER JOIN users ON roles" + got = s.Join("INNER", "users", "roles").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Limit(t *testing.T) { + s.sql = "" + expected = " LIMIT 1, 5" + got = s.Limit(1, 5).ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Group(t *testing.T) { + s.sql = "" + expected = " GROUP BY firstname" + got = s.GroupBy("firstname").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_GroupMultiple(t *testing.T) { + s.sql = "" + expected = " GROUP BY firstname, lastname, email" + got = s.GroupBy("firstname", "lastname", "email").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrderBy(t *testing.T) { + s.sql = "" + expected = " ORDER BY firstname ASC" + got = s.OrderBy("firstname").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrderByMultiple(t *testing.T) { + s.sql = "" + expected = " ORDER BY firstname, lastname ASC" + got = s.OrderBy("firstname", "lastname").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrderByDesc(t *testing.T) { + s.sql = "" + expected = " ORDER BY firstname DESC" + got = s.OrderByDesc("firstname").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_OrderByDescMultiple(t *testing.T) { + s.sql = "" + expected = " ORDER BY firstname, lastname DESC" + got = s.OrderByDesc("firstname", "lastname").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_Union(t *testing.T) { + s.sql = "" + expected = " UNION select * from companies" + got = s.Union("select * from companies").ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} + +func TestSql_SubQuery(t *testing.T) { + mainBuilder := &GoBuilder{} + subBuilder := &GoBuilder{} + + subBuilder.Select("users", "id").Where("age", ">", 30) + mainBuilder.Select("orders", "order_id", "user_id").Where("user_id", "IN", subBuilder) + + expected = "SELECT order_id, user_id FROM orders WHERE user_id IN (SELECT id FROM users WHERE age > 30)" + got = mainBuilder.ToSql() + if !reflect.DeepEqual(expected, got) { + t.Errorf("expected = %v, got %v", expected, got) + } +} diff --git a/example/main.go b/example/main.go index 916f043..57cb5c3 100644 --- a/example/main.go +++ b/example/main.go @@ -13,56 +13,66 @@ var ( func main() { - sql = gb.Select("users").Where("id", "=", "1").Sql() + sql = gb.Select("users").Where("id", "=", "1").ToSql() fmt.Printf("All Columns: \n%s\n", sql) sql = gb.Select("users", "firstname", "lastname", "create_date"). Where("id", "=", "1"). - Sql() + ToSql() fmt.Printf("Filter Columns: \n%s\n", sql) sql = gb.Select("users"). Where("id", "=", "1"). OrWhere("email", "=", "loremipsum@lrmpsm.com"). - Sql() + ToSql() fmt.Printf("Where Or Where: \n%s\n", sql) sql = gb.Select("users as u", "u.firstname", "u.lastname", "a.address"). Join("INNER", "address as a", "a.user_id=u.id"). Where("u.email", "=", "loremipsum@lrmpsm.com"). - Sql() + ToSql() fmt.Printf("Join: \n%s\n", sql) sql = gb.Select("users"). Where("id", "=", "1"). Between("create_date", "2021-01-01", "2021-03-16"). - Sql() + ToSql() fmt.Printf("Between: \n%s\n", sql) sql = gb.Select("users"). Where("id", "=", "1"). Between("create_date", "2021-01-01", "2021-03-16"). Limit(1, 5). - Sql() + ToSql() fmt.Printf("Limit: \n%s\n", sql) sql = gb.Select("users"). Where("id", "=", "1"). Between("create_date", "2021-01-01", "2021-03-16"). GroupBy("lastname"). - Sql() + ToSql() fmt.Printf("Group By: \n%s\n", sql) sql = gb.Select("users"). Where("id", "=", "1"). Between("create_date", "2021-01-01", "2021-03-16"). GroupBy("lastname"). - OrderBy("id", "DESC"). - Sql() + OrderBy("id"). + ToSql() fmt.Printf("Order By: \n%s\n", sql) - sql = gb.Select("users").Where("lastname", "=", "lorem").Sql() - sql = gb.Select("users").Where("lastname", "=", "ipsum").Union(sql).Sql() + sql = gb.Select("users").Where("lastname", "=", "lorem").ToSql() + sql = gb.Select("users").Where("lastname", "=", "ipsum").Union(sql).ToSql() fmt.Printf("Union: \n%s\n", sql) + // example subquery + mainBuilder := &query.GoBuilder{} + subBuilder := &query.GoBuilder{} + + subBuilder.Select("users", "id").Where("age", ">", 30) + mainBuilder.Select("orders", "order_id", "user_id").Where("user_id", "IN", subBuilder) + + fmt.Println(mainBuilder.ToSql()) + // SELECT order_id, user_id FROM orders WHERE user_id IN (SELECT id FROM users WHERE age > '30') + } diff --git a/sql.go b/sql.go deleted file mode 100644 index 012116b..0000000 --- a/sql.go +++ /dev/null @@ -1,151 +0,0 @@ -package gobuilder - -import ( - "fmt" - "strings" - - "golang.org/x/exp/maps" -) - -type GoBuilder struct { - sql string -} - -func (gb *GoBuilder) Select(table string, columns ...string) *GoBuilder { - if len(columns) == 0 { - columns = append(columns, "*") - } - gb.sql = fmt.Sprintf("SELECT %v FROM %v", strings.Join(columns, ","), table) - return gb -} - -func (gb *GoBuilder) Insert(table string, args map[string]string) *GoBuilder { - if len(args) != 0 { - keys := maps.Keys(args) - values := "" - for _, v := range maps.Values(args) { - values += fmt.Sprintf("'%v',", v) - } - values = strings.Trim(values, ",") - gb.sql = fmt.Sprintf("INSERT INTO %v (%v) VALUES (%v)", table, strings.Join(keys, ","), values) - } - return gb -} - -func (gb *GoBuilder) Update(table string, args map[string]string) *GoBuilder { - if len(args) != 0 { - set := "" - for _, key := range maps.Keys(args) { - set += fmt.Sprintf("%v='%v', ", key, args[key]) - } - set = strings.Trim(set, ", ") - gb.sql = fmt.Sprintf("UPDATE %v SET %v", table, set) - } - return gb -} - -func (gb *GoBuilder) Delete(table string) *GoBuilder { - gb.sql = fmt.Sprintf("DELETE FROM %v", table) - return gb -} - -func (gb *GoBuilder) Where(key, opt, val string) *GoBuilder { - if strings.Contains(gb.sql, "WHERE") { - gb.sql = fmt.Sprintf("%v AND %v%v'%v'", gb.sql, key, opt, val) - } else { - gb.sql = fmt.Sprintf("%v WHERE %v%v'%v'", gb.sql, key, opt, val) - } - return gb -} - -func (gb *GoBuilder) OrWhere(key, opt, val string) *GoBuilder { - if strings.Contains(gb.sql, "WHERE") { - gb.sql = fmt.Sprintf("%v OR %v%v'%v'", gb.sql, key, opt, val) - } else { - gb.sql = fmt.Sprintf("%v WHERE %v%v'%v'", gb.sql, key, opt, val) - } - return gb -} - -func (gb *GoBuilder) In(column string, args ...string) *GoBuilder { - if len(args) > 0 { - var values string - for _, v := range args { - values += fmt.Sprintf("'%v', ", v) - } - values = fmt.Sprintf("(%v)", strings.Trim(values, ", ")) - if strings.Contains(gb.sql, "WHERE") { - gb.sql = fmt.Sprintf("%v AND %v", gb.sql, values) - } else { - gb.sql = fmt.Sprintf("%v WHERE %v IN %v", gb.sql, column, values) - } - } - return gb -} - -func (gb *GoBuilder) OrIn(column string, args ...string) *GoBuilder { - if len(args) > 0 { - var values string - for _, v := range args { - values += fmt.Sprintf("'%v', ", v) - } - values = fmt.Sprintf("(%v)", strings.Trim(values, ", ")) - if strings.Contains(gb.sql, "WHERE") { - gb.sql = fmt.Sprintf("%v OR %v", gb.sql, values) - } else { - gb.sql = fmt.Sprintf("%v WHERE %v IN %v", gb.sql, column, values) - } - } - return gb -} - -func (gb *GoBuilder) Between(column string, vals ...string) *GoBuilder { - if len(vals) == 2 { - if strings.Contains(gb.sql, "WHERE") { - gb.sql = fmt.Sprintf("%v AND %v BETWEEN '%v' AND '%v'", gb.sql, column, vals[0], vals[1]) - } else { - gb.sql = fmt.Sprintf("%v WHERE %v BETWEEN '%v' AND '%v'", gb.sql, column, vals[0], vals[1]) - } - } - return gb -} - -func (gb *GoBuilder) OrBetween(column string, vals ...string) *GoBuilder { - if len(vals) == 2 { - if strings.Contains(gb.sql, "WHERE") { - gb.sql = fmt.Sprintf("%v OR %v BETWEEN '%v' AND '%v'", gb.sql, column, vals[0], vals[1]) - } else { - gb.sql = fmt.Sprintf("%v WHERE %v BETWEEN '%v' AND '%v'", gb.sql, column, vals[0], vals[1]) - } - } - return gb -} - -func (gb *GoBuilder) Join(joinName, table, equal string) *GoBuilder { - gb.sql = fmt.Sprintf("%v %v JOIN %v ON %v", gb.sql, joinName, table, equal) - return gb -} - -func (gb *GoBuilder) Limit(start, limit int) *GoBuilder { - gb.sql = fmt.Sprintf("%v LIMIT %v,%v", gb.sql, start, limit) - return gb -} - -func (gb *GoBuilder) GroupBy(column string) *GoBuilder { - gb.sql = fmt.Sprintf("%v GROUP BY %v", gb.sql, column) - return gb -} - -func (gb *GoBuilder) OrderBy(column, sortName string) *GoBuilder { - gb.sql = fmt.Sprintf("%v ORDER BY %v %v", gb.sql, column, sortName) - return gb -} - -func (gb *GoBuilder) Union(sql string) *GoBuilder { - gb.sql = gb.sql + " UNION " + sql - return gb -} - -func (gb *GoBuilder) Sql() string { - return gb.sql -} diff --git a/sql_test.go b/sql_test.go deleted file mode 100644 index 08cc692..0000000 --- a/sql_test.go +++ /dev/null @@ -1,211 +0,0 @@ -package gobuilder - -import ( - "reflect" - "testing" -) - -var ( - got string - expected string - s GoBuilder -) - -func TestSql_Select(t *testing.T) { - s.sql = "" - expected = "SELECT * FROM users" - got = s.Select("users").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Select_With_Columns(t *testing.T) { - s.sql = "" - expected = "SELECT firstname,lastname FROM users" - got = s.Select("users", "firstname", "lastname").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Insert(t *testing.T) { - s.sql = "" - insert := map[string]string{"firstname": "Mesut", "lastname": "GENEZ"} - expected = "INSERT INTO users (firstname,lastname) VALUES ('Mesut','GENEZ')" - got = s.Insert("users", insert).Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Update(t *testing.T) { - s.sql = "" - expected = "UPDATE users SET firstname='Mesut', lastname='GENEZ'" - got = s.Update("users", map[string]string{"firstname": "Mesut", "lastname": "GENEZ"}).Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Delete(t *testing.T) { - s.sql = "" - expected = "DELETE FROM users" - got = s.Delete("users").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Where(t *testing.T) { - s.sql = "" - expected = " WHERE firstname='Mesut'" - got = s.Where("firstname", "=", "Mesut").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Where_With_And(t *testing.T) { - s.sql = "" - expected = " WHERE firstname='Mesut' AND lastname='GENEZ'" - got = s.Where("firstname", "=", "Mesut").Where("lastname", "=", "GENEZ").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_OrWhere(t *testing.T) { - s.sql = "" - expected = " WHERE firstname='Mesut'" - got = s.OrWhere("firstname", "=", "Mesut").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_OrWhere_With_And(t *testing.T) { - s.sql = "" - expected = " WHERE firstname='Mesut' OR lastname='GENEZ'" - got = s.OrWhere("firstname", "=", "Mesut").OrWhere("lastname", "=", "GENEZ").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_In(t *testing.T) { - s.sql = "" - expected = " WHERE firstname IN ('Mesut')" - got = s.In("firstname", "Mesut").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_InAnd(t *testing.T) { - s.sql = "" - expected = " WHERE firstname IN ('Mesut') AND ('GENEZ')" - got = s.In("firstname", "Mesut").In("lastname", "GENEZ").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_OrIn(t *testing.T) { - s.sql = "" - expected = " WHERE firstname IN ('Mesut')" - got = s.OrIn("firstname", "Mesut").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_OrInAnd(t *testing.T) { - s.sql = "" - expected = " WHERE firstname IN ('Mesut') OR ('GENEZ')" - got = s.OrIn("firstname", "Mesut").OrIn("lastname", "GENEZ").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Between(t *testing.T) { - s.sql = "" - expected = " WHERE firstname BETWEEN 'Mesut' AND 'GENEZ'" - got = s.Between("firstname", "Mesut", "GENEZ").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_BetweenWithWhere(t *testing.T) { - s.sql = "" - expected = " WHERE firstname BETWEEN 'Mesut' AND 'GENEZ' AND lastname BETWEEN 'Mesut' AND 'GENEZ'" - got = s.Between("firstname", "Mesut", "GENEZ").Between("lastname", "Mesut", "GENEZ").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_OrBetween(t *testing.T) { - s.sql = "" - expected = " WHERE firstname BETWEEN 'Mesut' AND 'GENEZ'" - got = s.OrBetween("firstname", "Mesut", "GENEZ").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_OrBetweenWithWhere(t *testing.T) { - s.sql = "" - expected = " WHERE firstname BETWEEN 'Mesut' AND 'GENEZ' OR lastname BETWEEN 'Mesut' AND 'GENEZ'" - got = s.OrBetween("firstname", "Mesut", "GENEZ").OrBetween("lastname", "Mesut", "GENEZ").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Join(t *testing.T) { - s.sql = "" - expected = " INNER JOIN users ON roles" - got = s.Join("INNER", "users", "roles").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Limit(t *testing.T) { - s.sql = "" - expected = " LIMIT 1,5" - got = s.Limit(1, 5).Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Group(t *testing.T) { - s.sql = "" - expected = " GROUP BY firstname" - got = s.GroupBy("firstname").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Order(t *testing.T) { - s.sql = "" - expected = " ORDER BY firstname ASC" - got = s.OrderBy("firstname", "ASC").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -} - -func TestSql_Union(t *testing.T) { - s.sql = "" - expected = " UNION select * from companies" - got = s.Union("select * from companies").Sql() - if !reflect.DeepEqual(expected, got) { - t.Errorf("expected = %v, got %v", expected, got) - } -}