Skip to content
This repository has been archived by the owner on Aug 18, 2020. It is now read-only.

Commit

Permalink
Merge pull request #82 from dadleyy/bitwise
Browse files Browse the repository at this point in the history
bitwise updater apis
  • Loading branch information
dadleyy authored Mar 17, 2018
2 parents 01e292d + 1b3b625 commit 3e00ca0
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 70 deletions.
51 changes: 30 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,27 +71,32 @@ and value are separated by an equal sign (`=`). For example, a user record may l
package models

type User struct {
table string `marlow:"tableName=users"`
ID uint `marlow:"column=id"`
Name string `marlow:"column=name"`
Email string `marlow:"column=email"`
table string `marlow:"tableName=users"`
ID uint `marlow:"column=id"`
Name string `marlow:"column=name"`
Email string `marlow:"column=email"`
SettingsMask uint8 `marlow:"column=settings&bitmask"`
}
```

In this example, marlow would create the following `UserStore` interface in the `models` package:

```go
type UserStore interface {
UpdateUserName(string, *UserBlueprint) (int64, error, string)
UpdateUserID(uint, *UserBlueprint) (int64, error)
FindUsers(*UserBlueprint) ([]*User, error)
CountUsers(*UserBlueprint) (int, error)
SelectIDs(*UserBlueprint) ([]uint, error)
SelectEmails(*UserBlueprint) ([]string, error)
SelectUserEmails(*UserBlueprint) ([]string, error)
CreateUsers(...User) (int64, error)
UpdateUserEmail(string, *UserBlueprint) (int64, error, string)
UpdateUserID(uint, *UserBlueprint) (int64, error, string)
UpdateUserEmail(string, *UserBlueprint) (int64, error)
DropUserSettingsMask(uint8, *UserBlueprint) (int64, error)
UpdateUserName(string, *UserBlueprint) (int64, error)
SelectUserNames(*UserBlueprint) ([]string, error)
AddUserSettingsMask(uint8, *UserBlueprint) (int64, error)
CountUsers(*UserBlueprint) (int, error)
SelectUserIDs(*UserBlueprint) ([]uint, error)
UpdateUserSettingsMask(uint8, *UserBlueprint) (int64, error)
DeleteUsers(*UserBlueprint) (int64, error)
SelectNames(*UserBlueprint) ([]string, error)
SelectUserSettingsMasks(*UserBlueprint) ([]uint8, error)
}
```

Expand All @@ -100,16 +105,19 @@ querying against the database. In this example, the `UserBlueprint` generated fo

```go
type UserBlueprint struct {
IDRange []uint
ID []uint
NameLike []string
Name []string
EmailLike []string
Email []string
Limit int
Offset int
OrderBy string
OrderDirection string
IDRange []uint
ID []uint
NameLike []string
Name []string
EmailLike []string
Email []string
SettingsMaskRange []uint8
SettingsMask []uint8
Inclusive bool
Limit int
Offset int
OrderBy string
OrderDirection string
}
```

Expand Down Expand Up @@ -137,6 +145,7 @@ For every other field found on the source `struct`, marlow will use the followin
| :--- | :--- |
| `column` | This is the column that any raw sql generated will target when scanning/selecting/querying this field. |
| `autoIncrement` | If `true`, this flag will prevent marlow from generating sql during creation that would attempt to insert the value of the field for the column. |
| `bitmask` | If present, the compiler will generate `AddRecordFieldMask` and `DropRecordFieldMask` methods which will perform native bitwise operations as `UPDATE` queries to the datbase. |

#### Generated Coverage & Documentation

Expand Down
2 changes: 1 addition & 1 deletion examples/library/models/author.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type Author struct {
Name string `marlow:"column=name"`
UniversityID sql.NullInt64 `marlow:"column=university_id"`
ReaderRating float64 `marlow:"column=rating"`
AuthorFlags uint8 `marlow:"column=flags"`
AuthorFlags uint8 `marlow:"column=flags&bitmask"`
Birthday time.Time `marlow:"column=birthday"`
}

Expand Down
48 changes: 48 additions & 0 deletions examples/library/models/author_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,54 @@ func Test_Author(t *testing.T) {

})

g.Describe("bitwise operations on bitmask", func() {
var blueprint *AuthorBlueprint

g.BeforeEach(func() {
birthday, e := time.Parse(time.RFC3339, "1821-11-11T15:04:05Z")
g.Assert(e).Equal(nil)
created, e := store.CreateAuthors(Author{
Name: "Bit Author",
Birthday: birthday,
})
g.Assert(e).Equal(nil)
blueprint = &AuthorBlueprint{
ID: []int{int(created)},
}
})

g.AfterEach(func() {
_, e := store.DeleteAuthors(blueprint)
g.Assert(e).Equal(nil)
})

g.It("allows the user to add to the bitmask", func() {
_, e := store.UpdateAuthorAuthorFlags(1, blueprint)
g.Assert(e).Equal(nil)
flags, e := store.SelectAuthorAuthorFlags(blueprint)
g.Assert(e).Equal(nil)
g.Assert(len(flags)).Equal(1)
g.Assert(fmt.Sprintf("%b", flags[0])).Equal("1")
_, e = store.AddAuthorAuthorFlags(2, blueprint)
g.Assert(e).Equal(nil)
flags, e = store.SelectAuthorAuthorFlags(blueprint)
g.Assert(e).Equal(nil)
g.Assert(len(flags)).Equal(1)
g.Assert(fmt.Sprintf("%b", flags[0])).Equal("11")
})

g.It("allows the user to remove from the bitmask", func() {
_, e := store.UpdateAuthorAuthorFlags(7, blueprint)
g.Assert(e).Equal(nil)
_, e = store.DropAuthorAuthorFlags(2, blueprint)
g.Assert(e).Equal(nil)
flags, e := store.SelectAuthorAuthorFlags(blueprint)
g.Assert(e).Equal(nil)
g.Assert(len(flags)).Equal(1)
g.Assert(fmt.Sprintf("%b", flags[0])).Equal("101")
})
})

g.Describe("DeleteAuthors", func() {

g.It("returns an error and a negative number with an empty blueprint", func() {
Expand Down
22 changes: 0 additions & 22 deletions marlow/blueprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,6 @@ import "go/types"
import "github.com/dadleyy/marlow/marlow/writing"
import "github.com/dadleyy/marlow/marlow/constants"

func getTypeInfo(fieldType string) types.BasicInfo {
var typeInfo types.BasicInfo

for _, t := range constants.NumericCustomTypes {
if t == fieldType {
return types.IsNumeric
}
}

for _, t := range types.Typ {
n := t.Name()

if fieldType != n {
continue
}

typeInfo = t.Info()
}

return typeInfo
}

func writeBlueprint(destination io.Writer, record marlowRecord) error {
out := writing.NewGoWriter(destination)

Expand Down
3 changes: 3 additions & 0 deletions marlow/constants/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ const (
// ColumnConfigOption is the key of the value used on individual fields that represents which column marlow queries.
ColumnConfigOption = "column"

// ColumnBitmaskOption is used to indicate a field is a bitmask & can be used to generate bitwise ops.
ColumnBitmaskOption = "bitmask"

// QueryableConfigOption boolean value, true/false based on fields ability to be updated.
QueryableConfigOption = "queryable"

Expand Down
27 changes: 27 additions & 0 deletions marlow/type_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package marlow

import "go/types"
import "github.com/dadleyy/marlow/marlow/constants"

// getTypeInfo returns a types.BasicInfo mask value based on the string provided.
func getTypeInfo(fieldType string) types.BasicInfo {
var typeInfo types.BasicInfo

for _, t := range constants.NumericCustomTypes {
if t == fieldType {
return types.IsNumeric
}
}

for _, t := range types.Typ {
n := t.Name()

if fieldType != n {
continue
}

typeInfo = t.Info()
}

return typeInfo
}
31 changes: 31 additions & 0 deletions marlow/type_info_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package marlow

import "testing"
import "go/types"
import "github.com/franela/goblin"

func Test_getTypeInfo(t *testing.T) {
g := goblin.Goblin(t)

g.Describe("getTypeInfo", func() {
g.It("returns a numeric type for time.Time", func() {
v := getTypeInfo("time.Time")
g.Assert(v & types.IsNumeric).Equal(v)
})

g.It("returns a boolean type for bools", func() {
v := getTypeInfo("bool")
g.Assert(v & types.IsBoolean).Equal(v)
})

g.It("returns a string type for strings", func() {
v := getTypeInfo("string")
g.Assert(v & types.IsString).Equal(v)
})

g.It("returns a numeric type for ints", func() {
v := getTypeInfo("int")
g.Assert(v & types.IsNumeric).Equal(v)
})
})
}
Loading

0 comments on commit 3e00ca0

Please sign in to comment.