From 5cac8a346256f03eb70abf6d77cc05b76cd4fc7a Mon Sep 17 00:00:00 2001 From: Yoshihiro Misawa Date: Fri, 1 Jun 2018 18:14:41 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E7=94=9F=E6=88=90=E6=99=82=E3=81=AE?= =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=81=AB=E3=81=84=E3=81=8F=E3=81=A4?= =?UTF-8?q?=E3=81=8B=E3=81=AE=E3=83=A1=E3=82=BD=E3=83=83=E3=83=89=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E3=81=99=E3=82=8B=20(#47)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * implement ErrBuilderNotSupported * fix doc * implement ErrRecordNotFound and ErrFoundMultipleRecords * implement Session * generate QueryOne, Count, Query and Exec methods * upgrade mysql to 5.7 * fix wrong method * golang 1.10.2 * update new format * rename variable name in Count method * fix fixture tests * fix Usage * add TestNewSession * export package from Gopkg.lock * remove lines --- Dockerfile | 2 +- Gopkg.lock | 21 +- Gopkg.toml | 14 +- builder/errors.go | 21 ++ cmd/sqlabble/fixtures/foo/bar/bar_want.go | 81 ++++++ .../fixtures/foo/bar/baz/article_want.go | 81 ++++++ .../fixtures/foo/bar/baz/comment_want.go | 81 ++++++ .../fixtures/foo/bar/baz/post_want.go | 81 ++++++ .../fixtures/foo/bar/baz/qux/null_want.go | 81 ++++++ cmd/sqlabble/fixtures/foo/foo_want.go | 239 ++++++++++++++++++ cmd/sqlabble/generator/converter.go | 86 ++++++- cmd/sqlabble/main.go | 2 +- codeship-services.yml | 2 +- docker-compose.yml | 2 +- errors.go | 37 +++ sqlabble.go | 30 +++ sqlabble_test.go | 77 ++++++ 17 files changed, 922 insertions(+), 16 deletions(-) create mode 100644 builder/errors.go create mode 100644 errors.go diff --git a/Dockerfile b/Dockerfile index 6903432..dccc211 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.8 +FROM golang:1.10.2 WORKDIR /go/src/github.com/sqlabble/sqlabble RUN go get -u \ diff --git a/Gopkg.lock b/Gopkg.lock index 2eabbb2..0d11ee5 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -5,13 +5,16 @@ name = "github.com/go-sql-driver/mysql" packages = ["."] revision = "a0583e0143b1624142adab07e0e97fe106d99561" - version = "v1.3" + version = "v1.3.0" [[projects]] branch = "master" name = "github.com/mattn/go-zglob" - packages = [".","fastwalk"] - revision = "95345c4e1c0ebc9d16a3284177f09360f4d20fab" + packages = [ + ".", + "fastwalk" + ] + revision = "9960a25705902198f55789b9b689a686682798b5" [[projects]] branch = "master" @@ -23,17 +26,21 @@ branch = "master" name = "github.com/sergi/go-diff" packages = ["diffmatchpatch"] - revision = "feef008d51ad2b3778f85d387ccf91735543008d" + revision = "da645544ed44df016359bd4c0e3dc60ee3a0da43" [[projects]] branch = "master" name = "golang.org/x/tools" - packages = ["go/ast/astutil","imports"] - revision = "c853fd576988aeebd3665f6224972f1379960013" + packages = [ + "go/ast/astutil", + "imports", + "internal/fastwalk" + ] + revision = "a5b4c53f6e8bdcafa95a94671bf2d1203365858b" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "5eed09f20a723e6014e9618a08ed025f23197f759dedd8a75beb1c4eaf1608c2" + inputs-digest = "98850a5b538295838cc7788ee22d8412ec013170e48009b2d9671fb19cecbd21" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 194cd87..e614318 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -49,8 +49,18 @@ ## what source location any dependent projects specify. # source = "https://github.com/myfork/package.git" +[[constraint]] + branch = "master" + name = "golang.org/x/tools" + +[[constraint]] + branch = "master" + name = "github.com/mattn/go-zglob" +[[constraint]] + branch = "master" + name = "github.com/minodisk/caseconv" -[[dependencies]] +[[constraint]] branch = "master" - name = "golang.org/x/tools" + name = "github.com/sergi/go-diff" diff --git a/builder/errors.go b/builder/errors.go new file mode 100644 index 0000000..7eebd71 --- /dev/null +++ b/builder/errors.go @@ -0,0 +1,21 @@ +package builder + +import ( + "fmt" +) + +// ErrBuilderNotSupported builder not supported error +type ErrBuilderNotSupported struct { + builderName string +} + +func (err ErrBuilderNotSupported) Error() string { + return fmt.Sprintf("%s builder not supported", err.builderName) +} + +// NewErrBuilderNotSupported create an ErrBuilderNotSupported instance +func NewErrBuilderNotSupported(builderName string) ErrBuilderNotSupported { + return ErrBuilderNotSupported{ + builderName: builderName, + } +} diff --git a/cmd/sqlabble/fixtures/foo/bar/bar_want.go b/cmd/sqlabble/fixtures/foo/bar/bar_want.go index c823dff..c377128 100644 --- a/cmd/sqlabble/fixtures/foo/bar/bar_want.go +++ b/cmd/sqlabble/fixtures/foo/bar/bar_want.go @@ -1,13 +1,16 @@ +// Code generated by sqlabble, DO NOT EDIT. package bar import ( "database/sql" "strings" + "github.com/sqlabble/sqlabble" "github.com/sqlabble/sqlabble/cmd/sqlabble/fixtures/foo" "github.com/sqlabble/sqlabble/stmt" ) +// ArticleDB Article table type ArticleDB struct { Table stmt.Table TableAlias stmt.TableAlias @@ -20,6 +23,7 @@ type ArticleDB struct { Author foo.UserDB } +// NewArticleDB Create a/an ArticleDB func NewArticleDB(aliases ...string) ArticleDB { alias := strings.Join(aliases, ".") if alias == "" { @@ -38,6 +42,7 @@ func NewArticleDB(aliases ...string) ArticleDB { } } +// Register - func (a ArticleDB) Register(mapper map[string]interface{}, dist *Article, aliases ...string) { mapper[strings.Join(append(aliases, "PostID"), ".")] = &dist.PostID mapper[strings.Join(append(aliases, "Body"), ".")] = &dist.Body @@ -45,6 +50,7 @@ func (a ArticleDB) Register(mapper map[string]interface{}, dist *Article, aliase a.Author.Register(mapper, &dist.Author, append(aliases, "Author")...) } +// Columns - func (a ArticleDB) Columns() []stmt.Column { return []stmt.Column{ a.PostIDColumn, @@ -53,6 +59,7 @@ func (a ArticleDB) Columns() []stmt.Column { } } +// ColumnAliases - func (a ArticleDB) ColumnAliases() []stmt.ColumnAlias { aliases := []stmt.ColumnAlias{ a.PostIDColumnAlias, @@ -63,6 +70,7 @@ func (a ArticleDB) ColumnAliases() []stmt.ColumnAlias { return aliases } +// Selectors - func (a ArticleDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { as := a.ColumnAliases() is := make([]stmt.ValOrColOrAliasOrFuncOrSubOrFormula, len(as)) @@ -72,6 +80,7 @@ func (a ArticleDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { return is } +// Map - func (a ArticleDB) Map(rows *sql.Rows) ([]Article, error) { cols, err := rows.Columns() if err != nil { @@ -93,3 +102,75 @@ func (a ArticleDB) Map(rows *sql.Rows) ([]Article, error) { } return dist, nil } + +// QueryOne Select single record +func (a ArticleDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Article, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return Article{}, err + } + ms, err := a.Map(rows) + if err != nil { + return Article{}, err + } + if len(ms) == 0 { + return Article{}, sqlabble.NewErrRecordNotFound(a.Table.Name) + } + if len(ms) > 1 { + return Article{}, sqlabble.NewErrFoundMultipleRecords(a.Table.Name) + } + return ms[0], nil +} + +// Count count records +func (a ArticleDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperation) (int64, error) { + var query string + var values []interface{} + + fc := sqlabble.Select(sqlabble.Count(sqlabble.Wildcard)).From(a.Table) + if op != nil { + query, values = sess.Builder.Build(fc.Where(op)) + } else { + query, values = sess.Builder.Build(fc) + } + rows, err := sess.Query(query, values...) + if err != nil { + return 0, err + } + + var count int64 + for rows.Next() { + err := rows.Scan(&count) + if err != nil { + return 0, err + } + } + + return count, nil +} + +// Query select some records +func (a ArticleDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Article, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return []Article{}, err + } + ms, err := a.Map(rows) + if err != nil { + return []Article{}, err + } + + return ms, nil +} + +// Exec execute a query +func (a ArticleDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(s) + result, err := sess.Exec(query, values...) + if err != nil { + return nil, err + } + return result, nil +} diff --git a/cmd/sqlabble/fixtures/foo/bar/baz/article_want.go b/cmd/sqlabble/fixtures/foo/bar/baz/article_want.go index a211e0a..88f25e3 100644 --- a/cmd/sqlabble/fixtures/foo/bar/baz/article_want.go +++ b/cmd/sqlabble/fixtures/foo/bar/baz/article_want.go @@ -1,12 +1,15 @@ +// Code generated by sqlabble, DO NOT EDIT. package baz import ( "database/sql" "strings" + "github.com/sqlabble/sqlabble" "github.com/sqlabble/sqlabble/stmt" ) +// ArticleDB Article table type ArticleDB struct { Table stmt.Table TableAlias stmt.TableAlias @@ -18,6 +21,7 @@ type ArticleDB struct { BodyColumnAlias stmt.ColumnAlias } +// NewArticleDB Create a/an ArticleDB func NewArticleDB(aliases ...string) ArticleDB { alias := strings.Join(aliases, ".") if alias == "" { @@ -35,12 +39,14 @@ func NewArticleDB(aliases ...string) ArticleDB { } } +// Register - func (a ArticleDB) Register(mapper map[string]interface{}, dist *Article, aliases ...string) { mapper[strings.Join(append(aliases, "ArticleID"), ".")] = &dist.ArticleID mapper[strings.Join(append(aliases, "Subject"), ".")] = &dist.Subject mapper[strings.Join(append(aliases, "Body"), ".")] = &dist.Body } +// Columns - func (a ArticleDB) Columns() []stmt.Column { return []stmt.Column{ a.ArticleIDColumn, @@ -49,6 +55,7 @@ func (a ArticleDB) Columns() []stmt.Column { } } +// ColumnAliases - func (a ArticleDB) ColumnAliases() []stmt.ColumnAlias { aliases := []stmt.ColumnAlias{ a.ArticleIDColumnAlias, @@ -58,6 +65,7 @@ func (a ArticleDB) ColumnAliases() []stmt.ColumnAlias { return aliases } +// Selectors - func (a ArticleDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { as := a.ColumnAliases() is := make([]stmt.ValOrColOrAliasOrFuncOrSubOrFormula, len(as)) @@ -67,6 +75,7 @@ func (a ArticleDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { return is } +// Map - func (a ArticleDB) Map(rows *sql.Rows) ([]Article, error) { cols, err := rows.Columns() if err != nil { @@ -88,3 +97,75 @@ func (a ArticleDB) Map(rows *sql.Rows) ([]Article, error) { } return dist, nil } + +// QueryOne Select single record +func (a ArticleDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Article, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return Article{}, err + } + ms, err := a.Map(rows) + if err != nil { + return Article{}, err + } + if len(ms) == 0 { + return Article{}, sqlabble.NewErrRecordNotFound(a.Table.Name) + } + if len(ms) > 1 { + return Article{}, sqlabble.NewErrFoundMultipleRecords(a.Table.Name) + } + return ms[0], nil +} + +// Count count records +func (a ArticleDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperation) (int64, error) { + var query string + var values []interface{} + + fc := sqlabble.Select(sqlabble.Count(sqlabble.Wildcard)).From(a.Table) + if op != nil { + query, values = sess.Builder.Build(fc.Where(op)) + } else { + query, values = sess.Builder.Build(fc) + } + rows, err := sess.Query(query, values...) + if err != nil { + return 0, err + } + + var count int64 + for rows.Next() { + err := rows.Scan(&count) + if err != nil { + return 0, err + } + } + + return count, nil +} + +// Query select some records +func (a ArticleDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Article, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return []Article{}, err + } + ms, err := a.Map(rows) + if err != nil { + return []Article{}, err + } + + return ms, nil +} + +// Exec execute a query +func (a ArticleDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(s) + result, err := sess.Exec(query, values...) + if err != nil { + return nil, err + } + return result, nil +} diff --git a/cmd/sqlabble/fixtures/foo/bar/baz/comment_want.go b/cmd/sqlabble/fixtures/foo/bar/baz/comment_want.go index 6f3c12e..178f31e 100644 --- a/cmd/sqlabble/fixtures/foo/bar/baz/comment_want.go +++ b/cmd/sqlabble/fixtures/foo/bar/baz/comment_want.go @@ -1,12 +1,15 @@ +// Code generated by sqlabble, DO NOT EDIT. package baz import ( "database/sql" "strings" + "github.com/sqlabble/sqlabble" "github.com/sqlabble/sqlabble/stmt" ) +// CommentDB Comment table type CommentDB struct { Table stmt.Table TableAlias stmt.TableAlias @@ -17,6 +20,7 @@ type CommentDB struct { Article ArticleDB } +// NewCommentDB Create a/an CommentDB func NewCommentDB(aliases ...string) CommentDB { alias := strings.Join(aliases, ".") if alias == "" { @@ -33,12 +37,14 @@ func NewCommentDB(aliases ...string) CommentDB { } } +// Register - func (c CommentDB) Register(mapper map[string]interface{}, dist *Comment, aliases ...string) { mapper[strings.Join(append(aliases, "CommentID"), ".")] = &dist.CommentID mapper[strings.Join(append(aliases, "ArticleID"), ".")] = &dist.ArticleID c.Article.Register(mapper, &dist.Article, append(aliases, "Article")...) } +// Columns - func (c CommentDB) Columns() []stmt.Column { return []stmt.Column{ c.CommentIDColumn, @@ -46,6 +52,7 @@ func (c CommentDB) Columns() []stmt.Column { } } +// ColumnAliases - func (c CommentDB) ColumnAliases() []stmt.ColumnAlias { aliases := []stmt.ColumnAlias{ c.CommentIDColumnAlias, @@ -55,6 +62,7 @@ func (c CommentDB) ColumnAliases() []stmt.ColumnAlias { return aliases } +// Selectors - func (c CommentDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { as := c.ColumnAliases() is := make([]stmt.ValOrColOrAliasOrFuncOrSubOrFormula, len(as)) @@ -64,6 +72,7 @@ func (c CommentDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { return is } +// Map - func (c CommentDB) Map(rows *sql.Rows) ([]Comment, error) { cols, err := rows.Columns() if err != nil { @@ -85,3 +94,75 @@ func (c CommentDB) Map(rows *sql.Rows) ([]Comment, error) { } return dist, nil } + +// QueryOne Select single record +func (c CommentDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Comment, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return Comment{}, err + } + ms, err := c.Map(rows) + if err != nil { + return Comment{}, err + } + if len(ms) == 0 { + return Comment{}, sqlabble.NewErrRecordNotFound(c.Table.Name) + } + if len(ms) > 1 { + return Comment{}, sqlabble.NewErrFoundMultipleRecords(c.Table.Name) + } + return ms[0], nil +} + +// Count count records +func (c CommentDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperation) (int64, error) { + var query string + var values []interface{} + + fc := sqlabble.Select(sqlabble.Count(sqlabble.Wildcard)).From(c.Table) + if op != nil { + query, values = sess.Builder.Build(fc.Where(op)) + } else { + query, values = sess.Builder.Build(fc) + } + rows, err := sess.Query(query, values...) + if err != nil { + return 0, err + } + + var count int64 + for rows.Next() { + err := rows.Scan(&count) + if err != nil { + return 0, err + } + } + + return count, nil +} + +// Query select some records +func (c CommentDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Comment, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return []Comment{}, err + } + ms, err := c.Map(rows) + if err != nil { + return []Comment{}, err + } + + return ms, nil +} + +// Exec execute a query +func (c CommentDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(s) + result, err := sess.Exec(query, values...) + if err != nil { + return nil, err + } + return result, nil +} diff --git a/cmd/sqlabble/fixtures/foo/bar/baz/post_want.go b/cmd/sqlabble/fixtures/foo/bar/baz/post_want.go index 02a2a5e..1570093 100644 --- a/cmd/sqlabble/fixtures/foo/bar/baz/post_want.go +++ b/cmd/sqlabble/fixtures/foo/bar/baz/post_want.go @@ -1,12 +1,15 @@ +// Code generated by sqlabble, DO NOT EDIT. package baz import ( "database/sql" "strings" + "github.com/sqlabble/sqlabble" "github.com/sqlabble/sqlabble/stmt" ) +// PostDB Post table type PostDB struct { Table stmt.Table TableAlias stmt.TableAlias @@ -17,6 +20,7 @@ type PostDB struct { Article ArticleDB } +// NewPostDB Create a/an PostDB func NewPostDB(aliases ...string) PostDB { alias := strings.Join(aliases, ".") if alias == "" { @@ -33,12 +37,14 @@ func NewPostDB(aliases ...string) PostDB { } } +// Register - func (p PostDB) Register(mapper map[string]interface{}, dist *Post, aliases ...string) { mapper[strings.Join(append(aliases, "PostID"), ".")] = &dist.PostID mapper[strings.Join(append(aliases, "ArticleID"), ".")] = &dist.ArticleID p.Article.Register(mapper, &dist.Article, append(aliases, "Article")...) } +// Columns - func (p PostDB) Columns() []stmt.Column { return []stmt.Column{ p.PostIDColumn, @@ -46,6 +52,7 @@ func (p PostDB) Columns() []stmt.Column { } } +// ColumnAliases - func (p PostDB) ColumnAliases() []stmt.ColumnAlias { aliases := []stmt.ColumnAlias{ p.PostIDColumnAlias, @@ -55,6 +62,7 @@ func (p PostDB) ColumnAliases() []stmt.ColumnAlias { return aliases } +// Selectors - func (p PostDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { as := p.ColumnAliases() is := make([]stmt.ValOrColOrAliasOrFuncOrSubOrFormula, len(as)) @@ -64,6 +72,7 @@ func (p PostDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { return is } +// Map - func (p PostDB) Map(rows *sql.Rows) ([]Post, error) { cols, err := rows.Columns() if err != nil { @@ -85,3 +94,75 @@ func (p PostDB) Map(rows *sql.Rows) ([]Post, error) { } return dist, nil } + +// QueryOne Select single record +func (p PostDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Post, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return Post{}, err + } + ms, err := p.Map(rows) + if err != nil { + return Post{}, err + } + if len(ms) == 0 { + return Post{}, sqlabble.NewErrRecordNotFound(p.Table.Name) + } + if len(ms) > 1 { + return Post{}, sqlabble.NewErrFoundMultipleRecords(p.Table.Name) + } + return ms[0], nil +} + +// Count count records +func (p PostDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperation) (int64, error) { + var query string + var values []interface{} + + fc := sqlabble.Select(sqlabble.Count(sqlabble.Wildcard)).From(p.Table) + if op != nil { + query, values = sess.Builder.Build(fc.Where(op)) + } else { + query, values = sess.Builder.Build(fc) + } + rows, err := sess.Query(query, values...) + if err != nil { + return 0, err + } + + var count int64 + for rows.Next() { + err := rows.Scan(&count) + if err != nil { + return 0, err + } + } + + return count, nil +} + +// Query select some records +func (p PostDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Post, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return []Post{}, err + } + ms, err := p.Map(rows) + if err != nil { + return []Post{}, err + } + + return ms, nil +} + +// Exec execute a query +func (p PostDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(s) + result, err := sess.Exec(query, values...) + if err != nil { + return nil, err + } + return result, nil +} diff --git a/cmd/sqlabble/fixtures/foo/bar/baz/qux/null_want.go b/cmd/sqlabble/fixtures/foo/bar/baz/qux/null_want.go index 3eee1e0..eb50a92 100644 --- a/cmd/sqlabble/fixtures/foo/bar/baz/qux/null_want.go +++ b/cmd/sqlabble/fixtures/foo/bar/baz/qux/null_want.go @@ -1,12 +1,15 @@ +// Code generated by sqlabble, DO NOT EDIT. package qux import ( "database/sql" "strings" + "github.com/sqlabble/sqlabble" "github.com/sqlabble/sqlabble/stmt" ) +// ArticleDB Article table type ArticleDB struct { Table stmt.Table TableAlias stmt.TableAlias @@ -20,6 +23,7 @@ type ArticleDB struct { StringColumnAlias stmt.ColumnAlias } +// NewArticleDB Create a/an ArticleDB func NewArticleDB(aliases ...string) ArticleDB { alias := strings.Join(aliases, ".") if alias == "" { @@ -39,6 +43,7 @@ func NewArticleDB(aliases ...string) ArticleDB { } } +// Register - func (a ArticleDB) Register(mapper map[string]interface{}, dist *Article, aliases ...string) { mapper[strings.Join(append(aliases, "Bool"), ".")] = &dist.Bool mapper[strings.Join(append(aliases, "Float64"), ".")] = &dist.Float64 @@ -46,6 +51,7 @@ func (a ArticleDB) Register(mapper map[string]interface{}, dist *Article, aliase mapper[strings.Join(append(aliases, "String"), ".")] = &dist.String } +// Columns - func (a ArticleDB) Columns() []stmt.Column { return []stmt.Column{ a.BoolColumn, @@ -55,6 +61,7 @@ func (a ArticleDB) Columns() []stmt.Column { } } +// ColumnAliases - func (a ArticleDB) ColumnAliases() []stmt.ColumnAlias { aliases := []stmt.ColumnAlias{ a.BoolColumnAlias, @@ -65,6 +72,7 @@ func (a ArticleDB) ColumnAliases() []stmt.ColumnAlias { return aliases } +// Selectors - func (a ArticleDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { as := a.ColumnAliases() is := make([]stmt.ValOrColOrAliasOrFuncOrSubOrFormula, len(as)) @@ -74,6 +82,7 @@ func (a ArticleDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { return is } +// Map - func (a ArticleDB) Map(rows *sql.Rows) ([]Article, error) { cols, err := rows.Columns() if err != nil { @@ -95,3 +104,75 @@ func (a ArticleDB) Map(rows *sql.Rows) ([]Article, error) { } return dist, nil } + +// QueryOne Select single record +func (a ArticleDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Article, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return Article{}, err + } + ms, err := a.Map(rows) + if err != nil { + return Article{}, err + } + if len(ms) == 0 { + return Article{}, sqlabble.NewErrRecordNotFound(a.Table.Name) + } + if len(ms) > 1 { + return Article{}, sqlabble.NewErrFoundMultipleRecords(a.Table.Name) + } + return ms[0], nil +} + +// Count count records +func (a ArticleDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperation) (int64, error) { + var query string + var values []interface{} + + fc := sqlabble.Select(sqlabble.Count(sqlabble.Wildcard)).From(a.Table) + if op != nil { + query, values = sess.Builder.Build(fc.Where(op)) + } else { + query, values = sess.Builder.Build(fc) + } + rows, err := sess.Query(query, values...) + if err != nil { + return 0, err + } + + var count int64 + for rows.Next() { + err := rows.Scan(&count) + if err != nil { + return 0, err + } + } + + return count, nil +} + +// Query select some records +func (a ArticleDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Article, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return []Article{}, err + } + ms, err := a.Map(rows) + if err != nil { + return []Article{}, err + } + + return ms, nil +} + +// Exec execute a query +func (a ArticleDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(s) + result, err := sess.Exec(query, values...) + if err != nil { + return nil, err + } + return result, nil +} diff --git a/cmd/sqlabble/fixtures/foo/foo_want.go b/cmd/sqlabble/fixtures/foo/foo_want.go index 95403d7..878bcb5 100644 --- a/cmd/sqlabble/fixtures/foo/foo_want.go +++ b/cmd/sqlabble/fixtures/foo/foo_want.go @@ -1,12 +1,15 @@ +// Code generated by sqlabble, DO NOT EDIT. package foo import ( "database/sql" "strings" + "github.com/sqlabble/sqlabble" "github.com/sqlabble/sqlabble/stmt" ) +// UserDB User table type UserDB struct { Table stmt.Table TableAlias stmt.TableAlias @@ -19,6 +22,7 @@ type UserDB struct { Prof ProfileDB } +// NewUserDB Create a/an UserDB func NewUserDB(aliases ...string) UserDB { alias := strings.Join(aliases, ".") if alias == "" { @@ -37,6 +41,7 @@ func NewUserDB(aliases ...string) UserDB { } } +// Register - func (u UserDB) Register(mapper map[string]interface{}, dist *User, aliases ...string) { mapper[strings.Join(append(aliases, "UserID"), ".")] = &dist.UserID mapper[strings.Join(append(aliases, "Name"), ".")] = &dist.Name @@ -45,6 +50,7 @@ func (u UserDB) Register(mapper map[string]interface{}, dist *User, aliases ...s mapper[strings.Join(append(aliases, "NumFriends"), ".")] = &dist.NumFriends } +// Columns - func (u UserDB) Columns() []stmt.Column { return []stmt.Column{ u.UserIDColumn, @@ -53,6 +59,7 @@ func (u UserDB) Columns() []stmt.Column { } } +// ColumnAliases - func (u UserDB) ColumnAliases() []stmt.ColumnAlias { aliases := []stmt.ColumnAlias{ u.UserIDColumnAlias, @@ -63,6 +70,7 @@ func (u UserDB) ColumnAliases() []stmt.ColumnAlias { return aliases } +// Selectors - func (u UserDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { as := u.ColumnAliases() is := make([]stmt.ValOrColOrAliasOrFuncOrSubOrFormula, len(as)) @@ -72,6 +80,7 @@ func (u UserDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { return is } +// Map - func (u UserDB) Map(rows *sql.Rows) ([]User, error) { cols, err := rows.Columns() if err != nil { @@ -94,6 +103,79 @@ func (u UserDB) Map(rows *sql.Rows) ([]User, error) { return dist, nil } +// QueryOne Select single record +func (u UserDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (User, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return User{}, err + } + ms, err := u.Map(rows) + if err != nil { + return User{}, err + } + if len(ms) == 0 { + return User{}, sqlabble.NewErrRecordNotFound(u.Table.Name) + } + if len(ms) > 1 { + return User{}, sqlabble.NewErrFoundMultipleRecords(u.Table.Name) + } + return ms[0], nil +} + +// Count count records +func (u UserDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperation) (int64, error) { + var query string + var values []interface{} + + fc := sqlabble.Select(sqlabble.Count(sqlabble.Wildcard)).From(u.Table) + if op != nil { + query, values = sess.Builder.Build(fc.Where(op)) + } else { + query, values = sess.Builder.Build(fc) + } + rows, err := sess.Query(query, values...) + if err != nil { + return 0, err + } + + var count int64 + for rows.Next() { + err := rows.Scan(&count) + if err != nil { + return 0, err + } + } + + return count, nil +} + +// Query select some records +func (u UserDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]User, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return []User{}, err + } + ms, err := u.Map(rows) + if err != nil { + return []User{}, err + } + + return ms, nil +} + +// Exec execute a query +func (u UserDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(s) + result, err := sess.Exec(query, values...) + if err != nil { + return nil, err + } + return result, nil +} + +// ProfileDB Profile table type ProfileDB struct { Table stmt.Table TableAlias stmt.TableAlias @@ -105,6 +187,7 @@ type ProfileDB struct { UserIDColumnAlias stmt.ColumnAlias } +// NewProfileDB Create a/an ProfileDB func NewProfileDB(aliases ...string) ProfileDB { alias := strings.Join(aliases, ".") if alias == "" { @@ -122,12 +205,14 @@ func NewProfileDB(aliases ...string) ProfileDB { } } +// Register - func (p ProfileDB) Register(mapper map[string]interface{}, dist *Profile, aliases ...string) { mapper[strings.Join(append(aliases, "ProfileID"), ".")] = &dist.ProfileID mapper[strings.Join(append(aliases, "Body"), ".")] = &dist.Body mapper[strings.Join(append(aliases, "UserID"), ".")] = &dist.UserID } +// Columns - func (p ProfileDB) Columns() []stmt.Column { return []stmt.Column{ p.ProfileIDColumn, @@ -136,6 +221,7 @@ func (p ProfileDB) Columns() []stmt.Column { } } +// ColumnAliases - func (p ProfileDB) ColumnAliases() []stmt.ColumnAlias { aliases := []stmt.ColumnAlias{ p.ProfileIDColumnAlias, @@ -145,6 +231,7 @@ func (p ProfileDB) ColumnAliases() []stmt.ColumnAlias { return aliases } +// Selectors - func (p ProfileDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { as := p.ColumnAliases() is := make([]stmt.ValOrColOrAliasOrFuncOrSubOrFormula, len(as)) @@ -154,6 +241,7 @@ func (p ProfileDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { return is } +// Map - func (p ProfileDB) Map(rows *sql.Rows) ([]Profile, error) { cols, err := rows.Columns() if err != nil { @@ -176,6 +264,79 @@ func (p ProfileDB) Map(rows *sql.Rows) ([]Profile, error) { return dist, nil } +// QueryOne Select single record +func (p ProfileDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Profile, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return Profile{}, err + } + ms, err := p.Map(rows) + if err != nil { + return Profile{}, err + } + if len(ms) == 0 { + return Profile{}, sqlabble.NewErrRecordNotFound(p.Table.Name) + } + if len(ms) > 1 { + return Profile{}, sqlabble.NewErrFoundMultipleRecords(p.Table.Name) + } + return ms[0], nil +} + +// Count count records +func (p ProfileDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperation) (int64, error) { + var query string + var values []interface{} + + fc := sqlabble.Select(sqlabble.Count(sqlabble.Wildcard)).From(p.Table) + if op != nil { + query, values = sess.Builder.Build(fc.Where(op)) + } else { + query, values = sess.Builder.Build(fc) + } + rows, err := sess.Query(query, values...) + if err != nil { + return 0, err + } + + var count int64 + for rows.Next() { + err := rows.Scan(&count) + if err != nil { + return 0, err + } + } + + return count, nil +} + +// Query select some records +func (p ProfileDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Profile, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return []Profile{}, err + } + ms, err := p.Map(rows) + if err != nil { + return []Profile{}, err + } + + return ms, nil +} + +// Exec execute a query +func (p ProfileDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(s) + result, err := sess.Exec(query, values...) + if err != nil { + return nil, err + } + return result, nil +} + +// FriendDB Friend table type FriendDB struct { Table stmt.Table TableAlias stmt.TableAlias @@ -185,6 +346,7 @@ type FriendDB struct { UserID2ColumnAlias stmt.ColumnAlias } +// NewFriendDB Create a/an FriendDB func NewFriendDB(aliases ...string) FriendDB { alias := strings.Join(aliases, ".") if alias == "" { @@ -200,11 +362,13 @@ func NewFriendDB(aliases ...string) FriendDB { } } +// Register - func (f FriendDB) Register(mapper map[string]interface{}, dist *Friend, aliases ...string) { mapper[strings.Join(append(aliases, "UserID1"), ".")] = &dist.UserID1 mapper[strings.Join(append(aliases, "UserID2"), ".")] = &dist.UserID2 } +// Columns - func (f FriendDB) Columns() []stmt.Column { return []stmt.Column{ f.UserID1Column, @@ -212,6 +376,7 @@ func (f FriendDB) Columns() []stmt.Column { } } +// ColumnAliases - func (f FriendDB) ColumnAliases() []stmt.ColumnAlias { aliases := []stmt.ColumnAlias{ f.UserID1ColumnAlias, @@ -220,6 +385,7 @@ func (f FriendDB) ColumnAliases() []stmt.ColumnAlias { return aliases } +// Selectors - func (f FriendDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { as := f.ColumnAliases() is := make([]stmt.ValOrColOrAliasOrFuncOrSubOrFormula, len(as)) @@ -229,6 +395,7 @@ func (f FriendDB) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { return is } +// Map - func (f FriendDB) Map(rows *sql.Rows) ([]Friend, error) { cols, err := rows.Columns() if err != nil { @@ -250,3 +417,75 @@ func (f FriendDB) Map(rows *sql.Rows) ([]Friend, error) { } return dist, nil } + +// QueryOne Select single record +func (f FriendDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Friend, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return Friend{}, err + } + ms, err := f.Map(rows) + if err != nil { + return Friend{}, err + } + if len(ms) == 0 { + return Friend{}, sqlabble.NewErrRecordNotFound(f.Table.Name) + } + if len(ms) > 1 { + return Friend{}, sqlabble.NewErrFoundMultipleRecords(f.Table.Name) + } + return ms[0], nil +} + +// Count count records +func (f FriendDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperation) (int64, error) { + var query string + var values []interface{} + + fc := sqlabble.Select(sqlabble.Count(sqlabble.Wildcard)).From(f.Table) + if op != nil { + query, values = sess.Builder.Build(fc.Where(op)) + } else { + query, values = sess.Builder.Build(fc) + } + rows, err := sess.Query(query, values...) + if err != nil { + return 0, err + } + + var count int64 + for rows.Next() { + err := rows.Scan(&count) + if err != nil { + return 0, err + } + } + + return count, nil +} + +// Query select some records +func (f FriendDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Friend, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return []Friend{}, err + } + ms, err := f.Map(rows) + if err != nil { + return []Friend{}, err + } + + return ms, nil +} + +// Exec execute a query +func (f FriendDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(s) + result, err := sess.Exec(query, values...) + if err != nil { + return nil, err + } + return result, nil +} diff --git a/cmd/sqlabble/generator/converter.go b/cmd/sqlabble/generator/converter.go index 59e9e66..7a9e278 100644 --- a/cmd/sqlabble/generator/converter.go +++ b/cmd/sqlabble/generator/converter.go @@ -15,17 +15,18 @@ import ( "reflect" "strings" - "golang.org/x/tools/imports" - "github.com/minodisk/caseconv" + "golang.org/x/tools/imports" ) -const implTmpl = `package {{ .Name }} +const implTmpl = `// Code generated by sqlabble, DO NOT EDIT. +package {{ .Name }} import ( "database/sql" "strings" + "github.com/sqlabble/sqlabble" "github.com/sqlabble/sqlabble/stmt" ) @@ -35,6 +36,7 @@ import ( {{- $tableName := .DBName }} {{- $tableType := printf "%sDB" $baseType }} {{- $mapperType := printf "%sMapper" $baseType }} +// {{ $tableType }} {{ $baseType }} table type {{ $tableType }} struct{ Table stmt.Table TableAlias stmt.TableAlias @@ -50,6 +52,7 @@ type {{ $tableType }} struct{ {{- end }} } +// New{{ $tableType }} Create a/an {{ $tableType }} func New{{ $tableType }}(aliases ...string) {{ $tableType }} { alias := strings.Join(aliases, ".") if alias == "" { @@ -71,6 +74,7 @@ func New{{ $tableType }}(aliases ...string) {{ $tableType }} { } } +// Register - func ({{ $receiver }} {{ $tableType }}) Register(mapper map[string]interface{}, dist *{{ $baseType }}, aliases ...string) { {{- range .Columns }} {{- if .GoRefName }} @@ -83,6 +87,7 @@ func ({{ $receiver }} {{ $tableType }}) Register(mapper map[string]interface{}, {{- end }} } +// Columns - func ({{ $receiver }} {{ $tableType }}) Columns() []stmt.Column { return []stmt.Column{ {{- range .Columns }} @@ -95,6 +100,7 @@ func ({{ $receiver }} {{ $tableType }}) Columns() []stmt.Column { } } +// ColumnAliases - func ({{ $receiver }} {{ $tableType }}) ColumnAliases() []stmt.ColumnAlias { aliases := []stmt.ColumnAlias{ {{- range .Columns }} @@ -115,6 +121,7 @@ func ({{ $receiver }} {{ $tableType }}) ColumnAliases() []stmt.ColumnAlias { return aliases } +// Selectors - func ({{ $receiver }} {{ $tableType }}) Selectors() []stmt.ValOrColOrAliasOrFuncOrSubOrFormula { as := {{ $receiver }}.ColumnAliases() is := make([]stmt.ValOrColOrAliasOrFuncOrSubOrFormula, len(as)) @@ -124,6 +131,7 @@ func ({{ $receiver }} {{ $tableType }}) Selectors() []stmt.ValOrColOrAliasOrFunc return is } +// Map - func ({{ $receiver }} {{ $tableType }}) Map(rows *sql.Rows) ([]{{ $baseType }}, error) { cols, err := rows.Columns() if err != nil { @@ -146,6 +154,78 @@ func ({{ $receiver }} {{ $tableType }}) Map(rows *sql.Rows) ([]{{ $baseType }}, return dist, nil } +// QueryOne Select single record +func ({{ $receiver }} {{ $tableType }}) QueryOne(sess *sqlabble.Session, s stmt.Statement) ({{ $baseType }}, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return {{ $baseType }}{}, err + } + ms, err := {{ $receiver }}.Map(rows) + if err != nil { + return {{ $baseType }}{}, err + } + if len(ms) == 0 { + return {{ $baseType }}{}, sqlabble.NewErrRecordNotFound({{ $receiver }}.Table.Name) + } + if len(ms) > 1 { + return {{ $baseType }}{}, sqlabble.NewErrFoundMultipleRecords({{ $receiver }}.Table.Name) + } + return ms[0], nil +} + +// Count count records +func ({{ $receiver }} {{ $tableType }}) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperation) (int64, error) { + var query string + var values []interface{} + + fc := sqlabble.Select(sqlabble.Count(sqlabble.Wildcard)).From({{ $receiver }}.Table) + if op != nil { + query, values = sess.Builder.Build(fc.Where(op)) + } else { + query, values = sess.Builder.Build(fc) + } + rows, err := sess.Query(query, values...) + if err != nil { + return 0, err + } + + var count int64 + for rows.Next() { + err := rows.Scan(&count) + if err != nil { + return 0, err + } + } + + return count, nil +} + +// Query select some records +func ({{ $receiver }} {{ $tableType }}) Query(sess *sqlabble.Session, s stmt.Statement) ([]{{ $baseType }}, error) { + query, values := sess.Builder.Build(s) + rows, err := sess.Query(query, values...) + if err != nil { + return []{{ $baseType }}{}, err + } + ms, err := {{ $receiver }}.Map(rows) + if err != nil { + return []{{ $baseType }}{}, err + } + + return ms, nil +} + +// Exec execute a query +func ({{ $receiver }} {{ $tableType }}) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(s) + result, err := sess.Exec(query, values...) + if err != nil { + return nil, err + } + return result, nil +} + {{- end }} ` diff --git a/cmd/sqlabble/main.go b/cmd/sqlabble/main.go index 159177d..6e532e5 100644 --- a/cmd/sqlabble/main.go +++ b/cmd/sqlabble/main.go @@ -51,7 +51,7 @@ Examples: %s ./*.go %s ./**/*.go %s -suffix _gen ./**/*.go -`) +`, name, name, name) } fs.StringVar(&op.Suffix, "suffix", "_sqlabble", "suffix of the file to be generated") if err := fs.Parse(args[1:]); err != nil { diff --git a/codeship-services.yml b/codeship-services.yml index dad02aa..5cf299b 100644 --- a/codeship-services.yml +++ b/codeship-services.yml @@ -10,7 +10,7 @@ services: cached: true mysql: - image: mysql:5.6 + image: mysql:5.7 environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_DATABASE: 'sqlabble' diff --git a/docker-compose.yml b/docker-compose.yml index 6f5c53b..feca556 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,7 @@ services: - mysql mysql: - image: mysql:5.6 + image: mysql:5.7 environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_DATABASE: 'sqlabble' diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..c6ae5f3 --- /dev/null +++ b/errors.go @@ -0,0 +1,37 @@ +package sqlabble + +import "fmt" + +// ErrRecordNotFound record not found error +type ErrRecordNotFound struct { + table string +} + +func (err ErrRecordNotFound) Error() string { + return fmt.Sprintf("%s's table record not found", err.table) +} + +// NewErrRecordNotFound create an ErrRecordNotFound instance +// - table: table name +func NewErrRecordNotFound(table string) error { + return ErrRecordNotFound{ + table: table, + } +} + +// ErrFoundMultipleRecords some records found error +type ErrFoundMultipleRecords struct { + table string +} + +func (err ErrFoundMultipleRecords) Error() string { + return fmt.Sprintf("multiple records of %s's table are found", err.table) +} + +// NewErrFoundMultipleRecords create an ErrFoundMultipleRecords instance +// - table: table name +func NewErrFoundMultipleRecords(table string) error { + return ErrFoundMultipleRecords{ + table: table, + } +} diff --git a/sqlabble.go b/sqlabble.go index e1a389a..5faffc6 100644 --- a/sqlabble.go +++ b/sqlabble.go @@ -1,6 +1,9 @@ package sqlabble import ( + "database/sql" + + "github.com/sqlabble/sqlabble/builder" "github.com/sqlabble/sqlabble/stmt" ) @@ -53,3 +56,30 @@ var ( IFNULL = stmt.NewIFNULL ) + +// Session wraps sql.DB +type Session struct { + *sql.DB + Builder *builder.Builder +} + +// NewSession create a Session instance +func NewSession(builderName string, db *sql.DB) (*Session, error) { + var b *builder.Builder + switch builderName { + case "standard": + b = &builder.Standard + case "standard_indented": + b = &builder.StandardIndented + case "mysql": + b = &builder.MySQL + case "mysql_indented": + b = &builder.MySQLIndented + default: + return nil, builder.NewErrBuilderNotSupported(builderName) + } + return &Session{ + DB: db, + Builder: b, + }, nil +} diff --git a/sqlabble_test.go b/sqlabble_test.go index e78838f..8414fcb 100644 --- a/sqlabble_test.go +++ b/sqlabble_test.go @@ -211,3 +211,80 @@ func TestSelect(t *testing.T) { t.Errorf("id got %d; want %d", id, 3) } } + +func TestNewSession(t *testing.T) { + type args struct { + builderName string + } + tests := []struct { + name string + args args + want *q.Session + wantErr error + }{ + { + name: "check `standard`", + args: args{ + builderName: "standard", + }, + want: &q.Session{ + DB: nil, + Builder: &builder.Standard, + }, + wantErr: nil, + }, + { + name: "check `standard_indented`", + args: args{ + builderName: "standard_indented", + }, + want: &q.Session{ + DB: nil, + Builder: &builder.StandardIndented, + }, + wantErr: nil, + }, + { + name: "check `mysql`", + args: args{ + builderName: "mysql", + }, + want: &q.Session{ + DB: nil, + Builder: &builder.MySQL, + }, + wantErr: nil, + }, + { + name: "check `mysql_indented`", + args: args{ + builderName: "mysql_indented", + }, + want: &q.Session{ + DB: nil, + Builder: &builder.MySQLIndented, + }, + wantErr: nil, + }, + { + name: "check `hoge_fuga`", + args: args{ + builderName: "hoge_fuga", + }, + want: nil, + wantErr: builder.NewErrBuilderNotSupported("hoge_fuga"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := q.NewSession(tt.args.builderName, nil) + if !reflect.DeepEqual(err, tt.wantErr) { + t.Errorf("NewSession() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewSession() = %v, want %v", got, tt.want) + } + }) + } +} From b22bc72fdce136ceecd2486f7d670b58559d0c72 Mon Sep 17 00:00:00 2001 From: Yoshihiro Misawa Date: Fri, 1 Jun 2018 19:19:32 +0900 Subject: [PATCH 2/3] fix duplicate argument error (#49) --- cmd/sqlabble/fixtures/foo/bar/bar_want.go | 12 +++---- .../fixtures/foo/bar/baz/article_want.go | 12 +++---- .../fixtures/foo/bar/baz/comment_want.go | 12 +++---- .../fixtures/foo/bar/baz/post_want.go | 12 +++---- .../fixtures/foo/bar/baz/qux/null_want.go | 12 +++---- cmd/sqlabble/fixtures/foo/foo_want.go | 36 +++++++++---------- cmd/sqlabble/generator/converter.go | 12 +++---- 7 files changed, 54 insertions(+), 54 deletions(-) diff --git a/cmd/sqlabble/fixtures/foo/bar/bar_want.go b/cmd/sqlabble/fixtures/foo/bar/bar_want.go index c377128..bf34b22 100644 --- a/cmd/sqlabble/fixtures/foo/bar/bar_want.go +++ b/cmd/sqlabble/fixtures/foo/bar/bar_want.go @@ -104,8 +104,8 @@ func (a ArticleDB) Map(rows *sql.Rows) ([]Article, error) { } // QueryOne Select single record -func (a ArticleDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Article, error) { - query, values := sess.Builder.Build(s) +func (a ArticleDB) QueryOne(sess *sqlabble.Session, st stmt.Statement) (Article, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return Article{}, err @@ -151,8 +151,8 @@ func (a ArticleDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOper } // Query select some records -func (a ArticleDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Article, error) { - query, values := sess.Builder.Build(s) +func (a ArticleDB) Query(sess *sqlabble.Session, st stmt.Statement) ([]Article, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return []Article{}, err @@ -166,8 +166,8 @@ func (a ArticleDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Article, e } // Exec execute a query -func (a ArticleDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { - query, values := sess.Builder.Build(s) +func (a ArticleDB) Exec(sess *sqlabble.Session, st stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(st) result, err := sess.Exec(query, values...) if err != nil { return nil, err diff --git a/cmd/sqlabble/fixtures/foo/bar/baz/article_want.go b/cmd/sqlabble/fixtures/foo/bar/baz/article_want.go index 88f25e3..6d1643b 100644 --- a/cmd/sqlabble/fixtures/foo/bar/baz/article_want.go +++ b/cmd/sqlabble/fixtures/foo/bar/baz/article_want.go @@ -99,8 +99,8 @@ func (a ArticleDB) Map(rows *sql.Rows) ([]Article, error) { } // QueryOne Select single record -func (a ArticleDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Article, error) { - query, values := sess.Builder.Build(s) +func (a ArticleDB) QueryOne(sess *sqlabble.Session, st stmt.Statement) (Article, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return Article{}, err @@ -146,8 +146,8 @@ func (a ArticleDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOper } // Query select some records -func (a ArticleDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Article, error) { - query, values := sess.Builder.Build(s) +func (a ArticleDB) Query(sess *sqlabble.Session, st stmt.Statement) ([]Article, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return []Article{}, err @@ -161,8 +161,8 @@ func (a ArticleDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Article, e } // Exec execute a query -func (a ArticleDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { - query, values := sess.Builder.Build(s) +func (a ArticleDB) Exec(sess *sqlabble.Session, st stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(st) result, err := sess.Exec(query, values...) if err != nil { return nil, err diff --git a/cmd/sqlabble/fixtures/foo/bar/baz/comment_want.go b/cmd/sqlabble/fixtures/foo/bar/baz/comment_want.go index 178f31e..e46b8d6 100644 --- a/cmd/sqlabble/fixtures/foo/bar/baz/comment_want.go +++ b/cmd/sqlabble/fixtures/foo/bar/baz/comment_want.go @@ -96,8 +96,8 @@ func (c CommentDB) Map(rows *sql.Rows) ([]Comment, error) { } // QueryOne Select single record -func (c CommentDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Comment, error) { - query, values := sess.Builder.Build(s) +func (c CommentDB) QueryOne(sess *sqlabble.Session, st stmt.Statement) (Comment, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return Comment{}, err @@ -143,8 +143,8 @@ func (c CommentDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOper } // Query select some records -func (c CommentDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Comment, error) { - query, values := sess.Builder.Build(s) +func (c CommentDB) Query(sess *sqlabble.Session, st stmt.Statement) ([]Comment, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return []Comment{}, err @@ -158,8 +158,8 @@ func (c CommentDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Comment, e } // Exec execute a query -func (c CommentDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { - query, values := sess.Builder.Build(s) +func (c CommentDB) Exec(sess *sqlabble.Session, st stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(st) result, err := sess.Exec(query, values...) if err != nil { return nil, err diff --git a/cmd/sqlabble/fixtures/foo/bar/baz/post_want.go b/cmd/sqlabble/fixtures/foo/bar/baz/post_want.go index 1570093..86903bb 100644 --- a/cmd/sqlabble/fixtures/foo/bar/baz/post_want.go +++ b/cmd/sqlabble/fixtures/foo/bar/baz/post_want.go @@ -96,8 +96,8 @@ func (p PostDB) Map(rows *sql.Rows) ([]Post, error) { } // QueryOne Select single record -func (p PostDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Post, error) { - query, values := sess.Builder.Build(s) +func (p PostDB) QueryOne(sess *sqlabble.Session, st stmt.Statement) (Post, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return Post{}, err @@ -143,8 +143,8 @@ func (p PostDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperati } // Query select some records -func (p PostDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Post, error) { - query, values := sess.Builder.Build(s) +func (p PostDB) Query(sess *sqlabble.Session, st stmt.Statement) ([]Post, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return []Post{}, err @@ -158,8 +158,8 @@ func (p PostDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Post, error) } // Exec execute a query -func (p PostDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { - query, values := sess.Builder.Build(s) +func (p PostDB) Exec(sess *sqlabble.Session, st stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(st) result, err := sess.Exec(query, values...) if err != nil { return nil, err diff --git a/cmd/sqlabble/fixtures/foo/bar/baz/qux/null_want.go b/cmd/sqlabble/fixtures/foo/bar/baz/qux/null_want.go index eb50a92..ed425f4 100644 --- a/cmd/sqlabble/fixtures/foo/bar/baz/qux/null_want.go +++ b/cmd/sqlabble/fixtures/foo/bar/baz/qux/null_want.go @@ -106,8 +106,8 @@ func (a ArticleDB) Map(rows *sql.Rows) ([]Article, error) { } // QueryOne Select single record -func (a ArticleDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Article, error) { - query, values := sess.Builder.Build(s) +func (a ArticleDB) QueryOne(sess *sqlabble.Session, st stmt.Statement) (Article, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return Article{}, err @@ -153,8 +153,8 @@ func (a ArticleDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOper } // Query select some records -func (a ArticleDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Article, error) { - query, values := sess.Builder.Build(s) +func (a ArticleDB) Query(sess *sqlabble.Session, st stmt.Statement) ([]Article, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return []Article{}, err @@ -168,8 +168,8 @@ func (a ArticleDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Article, e } // Exec execute a query -func (a ArticleDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { - query, values := sess.Builder.Build(s) +func (a ArticleDB) Exec(sess *sqlabble.Session, st stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(st) result, err := sess.Exec(query, values...) if err != nil { return nil, err diff --git a/cmd/sqlabble/fixtures/foo/foo_want.go b/cmd/sqlabble/fixtures/foo/foo_want.go index 878bcb5..fa4e73f 100644 --- a/cmd/sqlabble/fixtures/foo/foo_want.go +++ b/cmd/sqlabble/fixtures/foo/foo_want.go @@ -104,8 +104,8 @@ func (u UserDB) Map(rows *sql.Rows) ([]User, error) { } // QueryOne Select single record -func (u UserDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (User, error) { - query, values := sess.Builder.Build(s) +func (u UserDB) QueryOne(sess *sqlabble.Session, st stmt.Statement) (User, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return User{}, err @@ -151,8 +151,8 @@ func (u UserDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOperati } // Query select some records -func (u UserDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]User, error) { - query, values := sess.Builder.Build(s) +func (u UserDB) Query(sess *sqlabble.Session, st stmt.Statement) ([]User, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return []User{}, err @@ -166,8 +166,8 @@ func (u UserDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]User, error) } // Exec execute a query -func (u UserDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { - query, values := sess.Builder.Build(s) +func (u UserDB) Exec(sess *sqlabble.Session, st stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(st) result, err := sess.Exec(query, values...) if err != nil { return nil, err @@ -265,8 +265,8 @@ func (p ProfileDB) Map(rows *sql.Rows) ([]Profile, error) { } // QueryOne Select single record -func (p ProfileDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Profile, error) { - query, values := sess.Builder.Build(s) +func (p ProfileDB) QueryOne(sess *sqlabble.Session, st stmt.Statement) (Profile, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return Profile{}, err @@ -312,8 +312,8 @@ func (p ProfileDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOper } // Query select some records -func (p ProfileDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Profile, error) { - query, values := sess.Builder.Build(s) +func (p ProfileDB) Query(sess *sqlabble.Session, st stmt.Statement) ([]Profile, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return []Profile{}, err @@ -327,8 +327,8 @@ func (p ProfileDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Profile, e } // Exec execute a query -func (p ProfileDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { - query, values := sess.Builder.Build(s) +func (p ProfileDB) Exec(sess *sqlabble.Session, st stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(st) result, err := sess.Exec(query, values...) if err != nil { return nil, err @@ -419,8 +419,8 @@ func (f FriendDB) Map(rows *sql.Rows) ([]Friend, error) { } // QueryOne Select single record -func (f FriendDB) QueryOne(sess *sqlabble.Session, s stmt.Statement) (Friend, error) { - query, values := sess.Builder.Build(s) +func (f FriendDB) QueryOne(sess *sqlabble.Session, st stmt.Statement) (Friend, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return Friend{}, err @@ -466,8 +466,8 @@ func (f FriendDB) Count(sess *sqlabble.Session, op stmt.ComparisonOrLogicalOpera } // Query select some records -func (f FriendDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Friend, error) { - query, values := sess.Builder.Build(s) +func (f FriendDB) Query(sess *sqlabble.Session, st stmt.Statement) ([]Friend, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return []Friend{}, err @@ -481,8 +481,8 @@ func (f FriendDB) Query(sess *sqlabble.Session, s stmt.Statement) ([]Friend, err } // Exec execute a query -func (f FriendDB) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { - query, values := sess.Builder.Build(s) +func (f FriendDB) Exec(sess *sqlabble.Session, st stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(st) result, err := sess.Exec(query, values...) if err != nil { return nil, err diff --git a/cmd/sqlabble/generator/converter.go b/cmd/sqlabble/generator/converter.go index 7a9e278..809300b 100644 --- a/cmd/sqlabble/generator/converter.go +++ b/cmd/sqlabble/generator/converter.go @@ -155,8 +155,8 @@ func ({{ $receiver }} {{ $tableType }}) Map(rows *sql.Rows) ([]{{ $baseType }}, } // QueryOne Select single record -func ({{ $receiver }} {{ $tableType }}) QueryOne(sess *sqlabble.Session, s stmt.Statement) ({{ $baseType }}, error) { - query, values := sess.Builder.Build(s) +func ({{ $receiver }} {{ $tableType }}) QueryOne(sess *sqlabble.Session, st stmt.Statement) ({{ $baseType }}, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return {{ $baseType }}{}, err @@ -202,8 +202,8 @@ func ({{ $receiver }} {{ $tableType }}) Count(sess *sqlabble.Session, op stmt.Co } // Query select some records -func ({{ $receiver }} {{ $tableType }}) Query(sess *sqlabble.Session, s stmt.Statement) ([]{{ $baseType }}, error) { - query, values := sess.Builder.Build(s) +func ({{ $receiver }} {{ $tableType }}) Query(sess *sqlabble.Session, st stmt.Statement) ([]{{ $baseType }}, error) { + query, values := sess.Builder.Build(st) rows, err := sess.Query(query, values...) if err != nil { return []{{ $baseType }}{}, err @@ -217,8 +217,8 @@ func ({{ $receiver }} {{ $tableType }}) Query(sess *sqlabble.Session, s stmt.Sta } // Exec execute a query -func ({{ $receiver }} {{ $tableType }}) Exec(sess *sqlabble.Session, s stmt.Statement) (sql.Result, error) { - query, values := sess.Builder.Build(s) +func ({{ $receiver }} {{ $tableType }}) Exec(sess *sqlabble.Session, st stmt.Statement) (sql.Result, error) { + query, values := sess.Builder.Build(st) result, err := sess.Exec(query, values...) if err != nil { return nil, err From 81ee819fbefc5c6b33e0fce7848b78462337899d Mon Sep 17 00:00:00 2001 From: Yoshihiro Misawa Date: Sat, 2 Jun 2018 02:04:11 +0900 Subject: [PATCH 3/3] add DBInterface (#50) --- sqlabble.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sqlabble.go b/sqlabble.go index 5faffc6..eba9a27 100644 --- a/sqlabble.go +++ b/sqlabble.go @@ -59,12 +59,19 @@ var ( // Session wraps sql.DB type Session struct { - *sql.DB + DBInterface Builder *builder.Builder } +// DBInterface *sql.DB or *sql.Tx +type DBInterface interface { + Query(query string, args ...interface{}) (*sql.Rows, error) + QueryRow(query string, args ...interface{}) *sql.Row + Exec(query string, args ...interface{}) (sql.Result, error) +} + // NewSession create a Session instance -func NewSession(builderName string, db *sql.DB) (*Session, error) { +func NewSession(builderName string, db DBInterface) (*Session, error) { var b *builder.Builder switch builderName { case "standard": @@ -79,7 +86,7 @@ func NewSession(builderName string, db *sql.DB) (*Session, error) { return nil, builder.NewErrBuilderNotSupported(builderName) } return &Session{ - DB: db, - Builder: b, + DBInterface: db, + Builder: b, }, nil }