Made qs package, added single templates support

This commit is contained in:
Patrick O'brien 2016-04-19 12:02:32 +10:00
parent 270fe59117
commit dc50c0d42c
14 changed files with 190 additions and 81 deletions

View file

@ -9,9 +9,6 @@ import (
"unicode"
)
// M type is for providing where filters to Where helpers.
type M map[string]interface{}
// SelectNames returns the column names for a select statement
// Eg: col1, col2, col3
func SelectNames(results interface{}) string {

View file

@ -1,39 +1,35 @@
package boil
package qs
type QueryMod func(q *Query)
import "github.com/pobri19/sqlboiler/boil"
func (q *Query) Apply(mods ...QueryMod) {
type QueryMod func(q *boil.Query)
func (q *boil.Query) Apply(mods ...QueryMod) {
for _, mod := range mods {
mod(q)
}
}
func DB(e Executor) QueryMod {
return func(q *Query) {
q.executor = e
}
}
func Limit(limit int) QueryMod {
return func(q *Query) {
return func(q *boil.Query) {
q.limit = limit
}
}
func Join(join string) QueryMod {
return func(q *Query) {
return func(q *boil.Query) {
q.joins = append(q.joins, join)
}
}
func Select(columns ...string) QueryMod {
return func(q *Query) {
return func(q *boil.Query) {
q.selectCols = append(q.selectCols, columns...)
}
}
func Where(clause string, args ...interface{}) QueryMod {
return func(q *Query) {
return func(q *boil.Query) {
w := where{
clause: clause,
args: args,
@ -44,25 +40,25 @@ func Where(clause string, args ...interface{}) QueryMod {
}
func GroupBy(clause string) QueryMod {
return func(q *Query) {
return func(q *boil.Query) {
q.groupBy = append(q.groupBy, clause)
}
}
func OrderBy(clause string) QueryMod {
return func(q *Query) {
return func(q *boil.Query) {
q.orderBy = append(q.orderBy, clause)
}
}
func Having(clause string) QueryMod {
return func(q *Query) {
return func(q *boil.Query) {
q.having = append(q.having, clause)
}
}
func From(table string) QueryMod {
return func(q *Query) {
return func(q *boil.Query) {
q.from = table
}
}

View file

@ -1,11 +1,15 @@
package boil
package qs
import "testing"
import (
"testing"
"github.com/pobri19/sqlboiler/boil"
)
func TestApply(t *testing.T) {
t.Parallel()
q := &Query{}
q := &boil.Query{}
qfn1 := Limit(10)
qfn2 := Where("x > $1 AND y > $2", 5, 3)
@ -43,7 +47,7 @@ func TestDB(t *testing.T) {
func TestLimit(t *testing.T) {
t.Parallel()
q := &Query{}
q := &boil.Query{}
qfn := Limit(10)
qfn(q)
@ -57,7 +61,7 @@ func TestLimit(t *testing.T) {
func TestWhere(t *testing.T) {
t.Parallel()
q := &Query{}
q := &boil.Query{}
qfn := Where("x > $1 AND y > $2", 5, 3)
qfn(q)
@ -83,7 +87,7 @@ func TestWhere(t *testing.T) {
func TestGroupBy(t *testing.T) {
t.Parallel()
q := &Query{}
q := &boil.Query{}
qfn := GroupBy("col1, col2")
qfn(q)
@ -97,7 +101,7 @@ func TestGroupBy(t *testing.T) {
func TestOrderBy(t *testing.T) {
t.Parallel()
q := &Query{}
q := &boil.Query{}
qfn := OrderBy("col1 desc, col2 asc")
qfn(q)
@ -111,7 +115,7 @@ func TestOrderBy(t *testing.T) {
func TestHaving(t *testing.T) {
t.Parallel()
q := &Query{}
q := &boil.Query{}
qfn := Having("count(orders.order_id) > 10")
qfn(q)
@ -125,7 +129,7 @@ func TestHaving(t *testing.T) {
func TestFrom(t *testing.T) {
t.Parallel()
q := &Query{}
q := &boil.Query{}
qfn := From("videos a, orders b")
qfn(q)

View file

@ -1,5 +1,7 @@
package boil
import "database/sql"
type where struct {
clause string
args []interface{}
@ -7,6 +9,8 @@ type where struct {
type Query struct {
executor Executor
delete bool
update map[string]interface{}
selectCols []string
from string
joins []string
@ -17,19 +21,62 @@ type Query struct {
limit int
}
func (q *Query) buildQuery() string {
func SetDelete(q *Query, flag bool) {
q.delete = flag
}
func SetUpdate(q *Query, cols map[string]interface{}) {
q.update = cols
}
func SetExecutor(q *Query, exec Executor) {
q.executor = exec
}
func SetSelect() {
}
func SetFrom() {
}
func SetJoins() {
}
func SetWhere() {
}
func SetGroupBy() {
}
func SetOrderBy() {
}
func SetHaving() {
}
func SetLimit() {
}
func ExecQuery(q *Query) error {
return nil
}
func ExecQueryOne(q *Query) (*sql.Row, error) {
return nil, nil
}
func ExecQueryAll(q *Query) (*sql.Rows, error) {
return nil, nil
}
func buildQuery(q *Query) string {
return ""
}
// NewQuery initializes a new Query using the passed in QueryMods
func NewQuery(mods ...QueryMod) *Query {
return NewQueryX(currentDB, mods...)
}
// NewQueryX initializes a new Query using the passed in QueryMods
func NewQueryX(executor Executor, mods ...QueryMod) *Query {
q := &Query{executor: executor}
q.Apply(mods...)
return q
}

View file

@ -42,6 +42,15 @@ var sqlBoilerImports = imports{
},
}
var sqlBoilerSinglesImports = map[string]imports{
"helpers": imports{
standard: importList{},
thirdparty: importList{
`"github.com/pobri19/sqlboiler/boil"`,
},
},
}
// sqlBoilerTestImports defines the list of default test template imports.
var sqlBoilerTestImports = imports{
standard: importList{

View file

@ -76,6 +76,37 @@ func generateTestOutput(cmdData *CmdData, data *tplData) error {
return nil
}
func generateSinglesOutput(cmdData *CmdData) error {
if cmdData.SingleTemplates == nil {
return errors.New("No single templates located for generation")
}
for _, template := range cmdData.SingleTemplates {
var imps imports
resp, err := generateTemplate(template, &tplData{})
if err != nil {
return fmt.Errorf("Error generating template %s: %s", template.Name(), err)
}
fName := template.Name()
ext := filepath.Ext(fName)
fName = fName[0 : len(fName)-len(ext)]
imps.standard = sqlBoilerSinglesImports[fName].standard
imps.thirdparty = sqlBoilerSinglesImports[fName].thirdparty
fName = fName + ".go"
err = outHandler(cmdData.OutFolder, fName, cmdData.PkgName, imps, [][]byte{resp})
if err != nil {
return err
}
}
return nil
}
func generateTestMainOutput(cmdData *CmdData) error {
if cmdData.TestMainTemplate == nil {
return errors.New("No TestMain template located for generation")

View file

@ -15,6 +15,7 @@ import (
const (
templatesDirectory = "/cmds/templates"
templatesSinglesDirectory = "/cmds/templates/singles"
templatesTestDirectory = "/cmds/templates_test"
templatesTestMainDirectory = "/cmds/templates_test/main_test"
)
@ -27,6 +28,11 @@ func initTemplates(cmdData *CmdData) error {
return err
}
cmdData.SingleTemplates, err = loadTemplates(templatesSinglesDirectory)
if err != nil {
return err
}
cmdData.TestTemplates, err = loadTemplates(templatesTestDirectory)
if err != nil {
return err
@ -118,6 +124,10 @@ func (c *CmdData) run(includeTests bool) error {
}
}
if err := generateSinglesOutput(c); err != nil {
return fmt.Errorf("Unable to generate single templates output: %s", err)
}
for _, table := range c.Tables {
data := &tplData{
Table: table,

View file

@ -76,6 +76,15 @@ func TestTemplates(t *testing.T) {
t.Errorf("Templates is empty.")
}
cmdData.SingleTemplates, err = loadTemplates("templates/singles")
if err != nil {
t.Fatalf("Unable to initialize single templates: %s", err)
}
if len(cmdData.SingleTemplates) == 0 {
t.Errorf("SingleTemplates is empty.")
}
cmdData.TestTemplates, err = loadTemplates("templates_test")
if err != nil {
t.Fatalf("Unable to initialize templates: %s", err)

View file

@ -1,5 +1,4 @@
{{- $tableNameSingular := titleCaseSingular .Table.Name -}}
{{- $dbName := singular .Table.Name -}}
{{- $tableNamePlural := titleCasePlural .Table.Name -}}
{{- $varNameSingular := camelCaseSingular .Table.Name -}}
{{- $varNamePlural := camelCasePlural .Table.Name -}}
@ -9,32 +8,10 @@ type {{$varNameSingular}}Query struct {
// {{$tableNamePlural}}All retrieves all records.
func {{$tableNamePlural}}(mods ...QueryMod) {{$varNameSingular}}Query {
var {{$varNamePlural}} []*{{$tableNameSingular}}
rows, err := boil.GetDB().Query(`SELECT {{selectParamNames $dbName .Table.Columns}} FROM {{.Table.Name}}`)
if err != nil {
return nil, fmt.Errorf("{{.PkgName}}: failed to query: %v", err)
}
for rows.Next() {
{{- $tmpVarName := (print $varNamePlural "Tmp") -}}
{{$varNamePlural}}Tmp := {{$tableNameSingular}}{}
if err := rows.Scan({{scanParamNames $tmpVarName .Table.Columns}}); err != nil {
return nil, fmt.Errorf("{{.PkgName}}: failed to scan row: %v", err)
}
{{$varNamePlural}} = append({{$varNamePlural}}, &{{$varNamePlural}}Tmp)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("{{.PkgName}}: failed to read rows: %v", err)
}
return {{$varNamePlural}}, nil
return {{$tableNamePlural}}X(boil.GetDB(), mods...)
}
func {{$tableNamePlural}}X(exec boil.Executor, mods ...QueryMod) {{$tableNameSingular}}Query {
mods = append(mods, boil.From("{{.Table.Name}}"))
return NewQueryX(exec, mods...)
}

View file

@ -4,14 +4,24 @@
// Delete deletes a single {{$tableNameSingular}} record.
// Delete will match against the primary key column to find the record to delete.
func (o *{{$tableNameSingular}}) Delete(mods ...QueryMod) error {
_, err := db.Exec("DELETE FROM {{.Table.Name}} WHERE {{wherePrimaryKey .Table.PKey.Columns 1}}", {{paramsPrimaryKey "o." .Table.PKey.Columns true}})
return o.DeleteX(boil.GetDB(), mods...)
}
func (o *{{$tableNameSingular}}) DeleteX(exec boil.Executor, mods ...QueryMod) error {
mods = append(mods,
boil.From("{{.table.Name}}"),
boil.Where("{{wherePrimaryKey .Table.Pkey.Columns 1}}", {{paramsPrimaryKey "o." .Table.PKey.Columns true}}),
)
query := NewQueryX(exec, mods...)
_, err := exec.Exec("DELETE FROM {{.Table.Name}} WHERE {{wherePrimaryKey .Table.PKey.Columns 1}}", {{paramsPrimaryKey "o." .Table.PKey.Columns true}})
if err != nil {
return fmt.Errorf("{{.PkgName}}: unable to delete from {{.Table.Name}}: %s", err)
}
return nil
}
{{- end}}
func (o {{$varNameSingular}}Query) DeleteAll() error {
_, err := db.Exec("DELETE FROM {{.Table.Name}} WHERE {{wherePrimaryKey .Table.PKey.Columns 1}}", {{paramsPrimaryKey "o." .Table.PKey.Columns true}})
@ -21,3 +31,4 @@ func (o {{$varNameSingular}}Query) DeleteAll() error {
return nil
}
{{- end}}

View file

@ -1,6 +1,6 @@
{{- $tableNameSingular := titleCaseSingular .Table.Name -}}
// {{$tableNameSingular}}Insert inserts a single record.
func (o *{{$tableNameSingular}}) Insert(mods ...QueryMod) error {
func (o *{{$tableNameSingular}}) Insert(whitelist ... string) error {
if o == nil {
return 0, errors.New("{{.PkgName}}: no {{.Table.Name}} provided for insertion")
}
@ -23,7 +23,7 @@ func (o *{{$tableNameSingular}}) Insert(mods ...QueryMod) error {
return rowID, nil
}
func (o *{{$tableNameSingular}}) InsertX(exec boil.Executor, mods ...QueryMod) error {
func (o *{{$tableNameSingular}}) InsertX(exec boil.Executor, whitelist ... string) error {
if o == nil {
return 0, errors.New("{{.PkgName}}: no {{.Table.Name}} provided for insertion")
}

View file

@ -0,0 +1,15 @@
// M type is for providing where filters to Where helpers.
type M map[string]interface{}
// NewQuery initializes a new Query using the passed in QueryMods
func NewQuery(mods ...qs.QueryMod) *boil.Query {
return NewQueryX(boil.GetDB(), mods...)
}
// NewQueryX initializes a new Query using the passed in QueryMods
func NewQueryX(executor boil.Executor, mods ...qs.QueryMod) *boil.Query {
q := &Query{executor: executor}
q.Apply(mods...)
return q
}

View file

@ -38,5 +38,4 @@ func (o *{{$tableNameSingular}}) UpdateX(exec boil.Executor, whitelist ... strin
func (v {{$varNameSingular}}Query) UpdateAll(cols boil.M) error {
}
{{- end}}

View file

@ -17,13 +17,17 @@ type templater []*template.Template
// the database driver chosen by the driver flag at runtime, and a pointer to the
// output file, if one is specified with a flag.
type CmdData struct {
Tables []dbdrivers.Table
PkgName string
OutFolder string
Interface dbdrivers.Interface
DriverName string
Config *Config
Templates templater
Tables []dbdrivers.Table
PkgName string
OutFolder string
Interface dbdrivers.Interface
DriverName string
Config *Config
Templates templater
// SingleTemplates are only created once, not per table
SingleTemplates templater
TestTemplates templater
TestMainTemplate *template.Template
}