diff --git a/templates/00_struct.tpl b/templates/00_struct.tpl index 585feee..f9c3a04 100644 --- a/templates/00_struct.tpl +++ b/templates/00_struct.tpl @@ -17,6 +17,13 @@ type {{$modelName}} struct { {{end -}} } +// {{$modelName}}Filter allows you to filter on any columns by making them all pointers. +type {{$modelName}}Filter struct { + {{range $column := .Table.Columns -}} + {{titleCase $column.Name}} *{{$column.Type}} `{{generateTags $dot.Tags $column.Name}}boil:"{{$column.Name}}" json:"{{$column.Name}},omitempty" toml:"{{$column.Name}}" yaml:"{{$column.Name}},omitempty"` + {{end -}} +} + {{- if .Table.IsJoinTable -}} {{- else}} // {{$modelNameCamel}}R is where relationships are stored. diff --git a/templates/14_find.tpl b/templates/14_find.tpl index 097f184..12ffa85 100644 --- a/templates/14_find.tpl +++ b/templates/14_find.tpl @@ -53,3 +53,82 @@ func Find{{$tableNameSingular}}P(exec boil.Executor, {{$pkArgs}}, selectCols ... return retobj } + +// FindOne{{$tableNameSingular}} retrieves a single record using filters. +func FindOne{{$tableNameSingular}}(exec boil.Executor, filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + {{$varNameSingular}}Obj := &{{$tableNameSingular}}{} + + query := NewQuery(exec, qm.Select("*"), qm.From("{{.Table.Name | .SchemaTable}}")) + + r := reflect.ValueOf(filters) + for i := 0; i < r.NumField(); i++ { + f := r.Field(i) + if f.Elem().IsValid() { + queries.AppendWhere(query, r.Type().Field(i).Tag.Get("boil")+" = ?", f.Elem().Interface()) + } + } + + queries.SetLimit(query, 1) + + err := query.Bind({{$varNameSingular}}Obj) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "{{.PkgName}}: unable to select from {{.Table.Name}}") + } + + return {{$varNameSingular}}Obj, nil +} + +// FindOne{{$tableNameSingular}}G retrieves a single record using filters. +func FindOne{{$tableNameSingular}}G(filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + return FindOne{{$tableNameSingular}}(boil.GetDB(), filters) +} + +// FindOne{{$tableNameSingular}}OrInit retrieves a single record using filters, or initializes a new record if one is not found. +func FindOne{{$tableNameSingular}}OrInit(exec boil.Executor, filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + {{$varNameSingular}}Obj, err := FindOne{{$tableNameSingular}}(exec, filters) + if err != nil && errors.Cause(err) != sql.ErrNoRows { + return nil, err + } + + if {{$varNameSingular}}Obj == nil { + {{$varNameSingular}}Obj = &{{$tableNameSingular}}{} + objR := reflect.ValueOf({{$varNameSingular}}Obj).Elem() + r := reflect.ValueOf(filters) + for i := 0; i < r.NumField(); i++ { + f := r.Field(i) + if f.Elem().IsValid() { + objR.FieldByName(r.Type().Field(i).Name).Set(f.Elem()) + } + } + } + + return {{$varNameSingular}}Obj, nil +} + +// FindOne{{$tableNameSingular}}OrInit retrieves a single record using filters, or initializes a new record if one is not found. +func FindOne{{$tableNameSingular}}OrInitG(filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + return FindOne{{$tableNameSingular}}OrInit(boil.GetDB(), filters) +} + +// FindOne{{$tableNameSingular}}OrInit retrieves a single record using filters, or initializes and inserts a new record if one is not found. +func FindOne{{$tableNameSingular}}OrCreate(exec boil.Executor, filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + {{$varNameSingular}}Obj, err := FindOne{{$tableNameSingular}}OrInit(exec, filters) + if err != nil { + return nil, err + } + if {{$varNameSingular}}Obj.IsNew() { + err := {{$varNameSingular}}Obj.Insert(exec) + if err != nil { + return nil, err + } + } + return {{$varNameSingular}}Obj, nil +} + +// FindOne{{$tableNameSingular}}OrInit retrieves a single record using filters, or initializes and inserts a new record if one is not found. +func FindOne{{$tableNameSingular}}OrCreateG(filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + return FindOne{{$tableNameSingular}}OrCreate(boil.GetDB(), filters) +} diff --git a/templates/20_exists.tpl b/templates/20_exists.tpl index 22a67a0..2e20fa6 100644 --- a/templates/20_exists.tpl +++ b/templates/20_exists.tpl @@ -1,4 +1,5 @@ {{- $tableNameSingular := .Table.Name | singular | titleCase -}} +{{- $varNameSingular := .Table.Name | singular | camelCase -}} {{- $colDefs := sqlColDefinitions .Table.Columns .Table.PKey.Columns -}} {{- $pkNames := $colDefs.Names | stringMap .StringFuncs.camelCase | stringMap .StringFuncs.replaceReserved -}} {{- $pkArgs := joinSlices " " $pkNames $colDefs.Types | join ", " -}} @@ -51,3 +52,38 @@ func {{$tableNameSingular}}ExistsP(exec boil.Executor, {{$pkArgs}}) bool { return e } + +// IsNew() checks if record exists in db (aka if its primary key is set). +func (o *{{$tableNameSingular}}) IsNew() bool { + r := reflect.ValueOf(o).Elem() + for i := 0; i < r.NumField(); i++ { + column := r.Type().Field(i).Tag.Get("boil") + for _, pkColumn := range {{$varNameSingular}}PrimaryKeyColumns { + if column == pkColumn { + field := r.Field(i) + if field.Interface() != reflect.Zero(field.Type()).Interface() { + return false + } + } + } + } + return true +} + +// Save() inserts the record if it does not exist, or updates it if it does. +func (o *{{$tableNameSingular}}) Save(exec boil.Executor, whitelist ...string) error { + if o.IsNew() { + return o.Insert(exec, whitelist...) + } else { + return o.Update(exec, whitelist...) + } +} + +// SaveG() inserts the record if it does not exist, or updates it if it does. +func (o *{{$tableNameSingular}}) SaveG(whitelist ...string) error { + if o.IsNew() { + return o.InsertG(whitelist...) + } else { + return o.UpdateG(whitelist...) + } +}