Skip to content

Commit

Permalink
add忘れ
Browse files Browse the repository at this point in the history
  • Loading branch information
mazrean committed Aug 1, 2020
1 parent 3b6ed8f commit 07242ae
Show file tree
Hide file tree
Showing 14 changed files with 363 additions and 24 deletions.
3 changes: 2 additions & 1 deletion boiler/base/boil_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (b *BoilBase) MakeFile(file io.WriteCloser, tmpNameBase string, vars interf
}
tmpFile := builder.String()

defines := []string{"where", "select", "insert", "update", "delete"}
defines := []string{"where", "select", "insert", "update", "delete", "join", "joined_where", "joined_select"}
defineFiles := make([]string, 0, len(defines))
for _, v := range defines {
fp, err = FS.Open("/_" + v + ".tpl")
Expand All @@ -88,6 +88,7 @@ func (b *BoilBase) MakeFile(file io.WriteCloser, tmpNameBase string, vars interf
"isLast": func(i int, l int) bool {
return i == l-1
},
"toUpper": strings.ToUpper,
}

tmp, err := template.New(tmpNameBase).Funcs(funcMap).Parse(tmpFile)
Expand Down
126 changes: 124 additions & 2 deletions boiler/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package boiler
import (
"bytes"
"fmt"
"strings"

"github.com/titech-cpp/sqlboiler/boiler/base"
"github.com/titech-cpp/sqlboiler/model"
Expand All @@ -22,6 +23,7 @@ func NewCode(basePath string, yaml *model.Yaml) (*Code, error) {
tables := make([]*model.CodeTable, 0, len(yaml.Tables))
for key, val := range yaml.Tables {
columns := make([]*model.CodeColumn, 0, len(val))
joinMap := map[string][]*model.CodeJoinColumn{}
for _, v := range val {
name, err := model.NewNameDetail(v.Name)
if err != nil {
Expand All @@ -44,6 +46,21 @@ func NewCode(basePath string, yaml *model.Yaml) (*Code, error) {
foreign.Column = yamlForeign

foreigns = append(foreigns, foreign)

joinTable, err := model.NewNameDetail(k)
if err != nil {
return nil, fmt.Errorf("Name Detail Constructor(%s) Error: %w", k, err)
}

joinColumn, err := model.NewNameDetail(yamlForeign)
if err != nil {
return nil, fmt.Errorf("Name Detail Constructor(%s) Error: %w", k, err)
}

joinMap[joinTable.Snake] = append(joinMap[joinTable.Snake], &model.CodeJoinColumn{
This: name,
Target: joinColumn,
})
}

column := &model.CodeColumn{
Expand Down Expand Up @@ -72,9 +89,22 @@ func NewCode(basePath string, yaml *model.Yaml) (*Code, error) {
if err != nil {
return nil, fmt.Errorf("Name Detail Constructor(%s) Error: %w", key, err)
}

joins := []*model.CodeJoin{}
for table, column := range joinMap {
tableName, err := model.NewNameDetail(table)
if err != nil {
return nil, fmt.Errorf("Name Detail Constructor(%s) Error: %w", table, err)
}
joins = append(joins, &model.CodeJoin{
Table: tableName,
Column: column,
})
}
table := &model.CodeTable{
Name: name,
Columns: columns,
Joins: joins,
}
tables = append(tables, table)
}
Expand All @@ -89,6 +119,7 @@ func NewCode(basePath string, yaml *model.Yaml) (*Code, error) {
code.BoilerBase = boilBase
code.CopyerBase = copyBase
code.Code = codeContainer
code.makeJoinedTables()

return code, nil
}
Expand All @@ -105,7 +136,7 @@ func (c *Code) BoilCode() error {
return fmt.Errorf("Make Base Directory Error(Copy): %w", err)
}

fileNames := []string{"tables.go", "nullable_tables.go", "pointer_tables.go", "types.go", "db.go", "migrate.go"}
fileNames := []string{"types.go", "db.go", "migrate.go"}
for _, fileName := range fileNames {
fw, err := c.BoilerBase.MakeFileWriter(fileName)
if err != nil {
Expand All @@ -117,7 +148,7 @@ func (c *Code) BoilCode() error {
}
}

fileNames = []string{"migrate", "where"}
fileNames = []string{"migrate", "where", "join"}
for _, fileName := range fileNames {
fw, err := c.CopyerBase.MakeFileWriter(fileName)
if err != nil {
Expand All @@ -129,6 +160,24 @@ func (c *Code) BoilCode() error {
}
}

for _, table := range c.JoinedTables {
strTables := make([]string, 0, len(table.Tables))
for _, v := range table.Tables {
strTables = append(strTables, v.Name.Snake)
}

fileName := fmt.Sprintf("join_%s_query.go", strings.Join(strTables, "_"))
fw, err := c.BoilerBase.MakeFileWriter(fileName)
if err != nil {
return fmt.Errorf("Make File Writer Error(%s): %w", fileName, err)
}
fileName = "joined_queries.go"
err = c.BoilerBase.MakeFile(fw, fileName, table)
if err != nil {
return fmt.Errorf("Make File Error(%s): %w", fileName, err)
}
}

for _, table := range c.Tables {
fileName := fmt.Sprintf("%s_query.go", table.Name.Snake)
fw, err := c.BoilerBase.MakeFileWriter(fileName)
Expand All @@ -145,6 +194,79 @@ func (c *Code) BoilCode() error {
return nil
}

func (c *Code) makeJoinedTables() error {
joinedTables := []*model.CodeJoinedTable{}

tableMap := map[string]*model.CodeTable{}
for _, table := range c.Tables {
tableMap[table.Name.Snake] = table
}

for _, table := range c.Tables {
for _, join := range table.Joins {
joinedTable, ok := tableMap[join.Table.Snake]
if !ok {
return fmt.Errorf("invalid join table: %s", join.Table)
}

joinedJoins := []*model.CodeJoin{}
for _, v := range append(table.Joins, joinedTable.Joins...) {
if v != join {
joinedJoins = append(joinedJoins, v)
}
}

joinedTables = append(joinedTables, &model.CodeJoinedTable{
Tables: []*model.CodeTable{
table,
joinedTable,
},
Joins: joinedJoins,
})
}
}

c.JoinedTables = append(c.JoinedTables, joinedTables...)

return nil
}

func (c *Code) makeDoubleJoinedTables(tables []*model.CodeJoinedTable, tableMap map[string]*model.CodeTable) error {
joinedTables := []*model.CodeJoinedTable{}

for _, table := range tables {
for _, join := range table.Joins {
joinedJoins := []*model.CodeJoin{}
for _, v := range table.Joins {
if v != join {
joinedJoins = append(joinedJoins, v)
}
}

joinedTable, ok := tableMap[join.Table.Snake]
if !ok {
return fmt.Errorf("invalid join table: %s", join.Table)
}

joinedTables = append(joinedTables, &model.CodeJoinedTable{
Tables: append(table.Tables, joinedTable),
Joins: joinedJoins,
})
}
}

c.JoinedTables = append(c.JoinedTables, joinedTables...)

if len(joinedTables) != 0 {
err := c.makeDoubleJoinedTables(joinedTables, tableMap)
if err != nil {
return err
}
}

return nil
}

func typeParser(sqlType string) (*model.CodeSQLTypes, error) {
sqlBool := &model.CodeSQLTypes{
NotNull: "bool",
Expand Down
24 changes: 22 additions & 2 deletions model/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import (

// Code コード生成用の構造体
type Code struct {
DB DB
Tables []*CodeTable
DB DB
Tables []*CodeTable
JoinedTables []*CodeJoinedTable
}

// Check 同一か確認
Expand All @@ -27,10 +28,29 @@ func (c *Code) Check(cd *Code) error {
return nil
}

// CodeJoin JOINの情報
type CodeJoin struct {
Table *NameDetail
Column []*CodeJoinColumn
}

// CodeJoinColumn JOINのカラムの情報
type CodeJoinColumn struct {
This *NameDetail
Target *NameDetail
}

// CodeJoinedTable JOIN後のテーブル
type CodeJoinedTable struct {
Tables []*CodeTable
Joins []*CodeJoin
}

// CodeTable テーブルの構造体
type CodeTable struct {
Name *NameDetail
Columns []*CodeColumn
Joins []*CodeJoin
}

// Check 同一か確認
Expand Down
2 changes: 1 addition & 1 deletion statik/statik.go

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions template/_join.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{define "join"}}{{$v := .Name}}{{range .Joins}}{{$upperTable := .Table.UpperCamel}}{{$snakeTable := .Table.Snake}}
func (q *{{printf $v.UpperCamel}}Query) Join{{.Table.UpperCamel}}(this {{printf $v.LowerCamel}}, target {{.Table.LowerCamel}}, joinType query.JoinType, direction... query.JoinDirection) *Join{{printf $v.UpperCamel}}{{printf $upperTable}}Query {
var first string
var second string
switch this { {{range .Column}}
case {{printf $v.UpperCamel}}{{.This.UpperCamel}}:
first = "{{printf $v.Snake}}.{{.This.Snake}}"
if target != {{printf $upperTable}}{{.Target.UpperCamel}} {
return nil
}
second = "{{$snakeTable}}.{{.Target.UpperCamel}}"{{end}}
default:
return nil
}
return &Join{{printf $v.UpperCamel}}{{printf $upperTable}}Query{
db: q.db,
joins: []*query.Join{
query.NewJoin(joinType, first, second, direction...),
},
}
}
{{end}}{{end}}
5 changes: 5 additions & 0 deletions template/_joined_join.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{define "joinedJoin"}}{{$v := .Tables}}{{range .Joins}}
func (q *Join{{range $v}}{{.Name.UpperCamel}}{{end}}Query) Join{{.}}() *Join{{range $v}}{{.Name.UpperCamel}}{{end}}{{.}}Query {
return &Join{{range $v}}{{.Name.UpperCamel}}{{end}}{{.}}Query{}
}
{{end}}{{end}}
84 changes: 84 additions & 0 deletions template/_joined_select.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{{define "joinedSelect"}}{{$l := len .Tables}}
func (q *Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}Query) Find() (*Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}Table,error) {
whereMap := q.createWhereMap()
whereQuery, whereArgs := q.whereStruct.Where(whereMap)
args := []interface{}{}
if len(whereArgs) != 0 {
args = append(args, whereArgs...)
}

queryTable := "{{range $i,$v := .Tables}}{{if ne $i 0}} " + (*(q.joins[{{printf "%d" $i}}-1]))[0] + " {{end}}{{$v.Name.Snake}}{{if ne $i 0}} " + (*(q.joins[{{printf "%d" $i}}-1]))[1] + " {{end}}{{end}}"

query := fmt.Sprintf("SELECT * FROM %s %s LIMIT 1", queryTable, whereQuery)

fmt.Println(query)
rows, err := q.db.Query(query, args...)
if err != nil {
return nil, fmt.Errorf("Execute Query Error: %w", err)
}
defer rows.Close()

nullableTable := new(nullableJoin{{range .Tables}}{{.Name.UpperCamel}}{{end}}Table)
dests := []interface{}{}{{range .Tables}}{{$upperTable := .Name.UpperCamel}}{{range .Columns}}
dests = append(dests, &(nullableTable.{{printf $upperTable}}.{{.Name.UpperCamel}})){{end}}{{end}}
if rows.Next() {
err = rows.Scan(dests...)
if err != nil {
return nil, fmt.Errorf("Scaning Rows Error: %w", err)
}
} else {
return nil, RECORD_NOT_FOUND
}

table := new(Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}Table){{range .Tables}}{{$upperTable := .Name.UpperCamel}}{{range .Columns}}{{if .Null}}
if nullableTable.{{printf $upperTable}}.{{.Name.UpperCamel}}.Valid {
table.{{printf $upperTable}}.{{.Name.UpperCamel}} = nullableTable.{{printf $upperTable}}.{{.Name.UpperCamel}}.{{.Type.Code.Upper}}
}{{else}}
table.{{printf $upperTable}}.{{.Name.UpperCamel}} = nullableTable.{{printf $upperTable}}.{{.Name.UpperCamel}}{{end}}{{end}}{{end}}

return table, nil
}

func (q *Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}Query) Select() ([]*Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}Table,error) {
whereMap := q.createWhereMap()
whereQuery, whereArgs := q.whereStruct.Where(whereMap)
args := []interface{}{}
if len(whereArgs) != 0 {
args = append(args, whereArgs...)
}

queryTable := "{{range $i,$v := .Tables}}{{if ne $i 0}} " + (*(q.joins[{{printf "%d" $i}}-1]))[0] + " {{end}}{{$v.Name.Snake}}{{if ne $i 0}} " + (*(q.joins[{{printf "%d" $i}}-1]))[1] + " {{end}}{{end}}"

query := fmt.Sprintf("SELECT * FROM %s %s", queryTable, whereQuery)

fmt.Println(query)
rows, err := q.db.Query(query, args...)
if err != nil {
return nil, fmt.Errorf("Execute Query Error: %w", err)
}
defer rows.Close()

tables := []*Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}Table{}
for rows.Next() {
nullableTable := new(nullableJoin{{range .Tables}}{{.Name.UpperCamel}}{{end}}Table)
dests := []interface{}{}{{range .Tables}}{{$upperTable := .Name.UpperCamel}}{{range .Columns}}
dests = append(dests, &(nullableTable.{{printf $upperTable}}.{{.Name.UpperCamel}})){{end}}{{end}}
err = rows.Scan(dests...)
if err != nil {
return nil, fmt.Errorf("Scaning Rows Error: %w", err)
}

table := new(Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}Table){{range .Tables}}{{$upperTable := .Name.UpperCamel}}{{range .Columns}}{{if .Null}}
if nullableTable.{{printf $upperTable}}.{{.Name.UpperCamel}}.Valid {
table.{{printf $upperTable}}.{{.Name.UpperCamel}} = nullableTable.{{printf $upperTable}}.{{.Name.UpperCamel}}.{{.Type.Code.Upper}}
}{{else}}
table.{{printf $upperTable}}.{{.Name.UpperCamel}} = nullableTable.{{printf $upperTable}}.{{.Name.UpperCamel}}{{end}}{{end}}{{end}}

tables = append(tables, table)
}

return tables, nil
}
{{end}}
17 changes: 17 additions & 0 deletions template/_joined_where.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{define "joinedWhere"}}
func (q *Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}Query) createWhereMap() map[string]interface{} {
whereMap := map[string]interface{}{}{{range .Tables}}{{$upperTable := .Name.UpperCamel}}{{range .Columns}}
if q.table.{{printf $upperTable}}.{{.Name.UpperCamel}} != nil {
whereMap["{{.Name.Snake}}"] = *(q.table.{{printf $upperTable}}.{{.Name.UpperCamel}})
}{{end}}{{end}}
return whereMap
}

func (q *Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}Query) Where(table *Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}) *Join{{range .Tables}}{{.Name.UpperCamel}}{{end}}Query { {{range .Tables}}{{$upperTable := .Name.UpperCamel}}{{range .Columns}}
if table.{{printf $upperTable}}.{{.Name.UpperCamel}} != nil {
q.table.{{printf $upperTable}}.{{.Name.UpperCamel}} = table.{{printf $upperTable}}.{{.Name.UpperCamel}}
}{{end}}{{end}}

return q
}
{{end}}
Loading

0 comments on commit 07242ae

Please sign in to comment.