Giter VIP home page Giter VIP logo

goen's Introduction

Build Status wercker status Coverage Status godoc Go Report Card License: MIT

goen

goen is a typesafe GOlang ENtity interface for relational databases.

It provides a way of programmatically to interact with relational databases. It aims to implement in a go way and not to provide fully ORM features.

goen has following concepts:

  • No any fields or methods introducing into user's struct
  • Work with plain go's database/sql
  • Based on RTTI
  • Support bulk operation
  • Go generate is used only for utilities, it's not a core logic

Installation

go get -u github.com/kamichidu/goen/...

goen provides a binary tool used by go generate, please be sure that $GOPATH/bin is on your $PATH .

Usage

Write your first entity is.

package entity

type User struct {
    UserID int `goen:"" primary_key:""`
    Name, Email, PasswordHash string
}

Then put the following on any file of that package:

//go:generate goen -o goen.go

Now, all you have to do is run go generate ./... and a goen.go file will be generated.

Define entities

An entity is just a go struct have a struct tag goen:"" . All fields of this struct will be columns in the database table. An entity also needs to have one primary key. The primary key is defined using the primary_key:"" struct tag on the primary key fields.

Let's review the rules and conventions for entity fields:

  • All the fields with basic types or types that implement sql.Scanner and driver.Valuer will be considered a column in the table of their matching type.
  • By default, the name of a table/view will be the name of the struct converted to lower snake case (e.g.User => user, UserFriend => user_friend)
  • By default, the name of a column will be the name of the struct field converted to lower snake case (e.g. UserName => user_name, UserID => user_id). You can override it with the struct tag column:"custom_name".

Struct tags

Tag Description
goen:"" Indicates this struct as an entity. goen finds structs that have this struct tag.
table:"table_name" Specifies a table name.
view:"view_name" Specifies a view name for readonly entity.
primary_key:"" Indicates this field is a part of primary key
primary_key:"column_name" Indicates this field is a part of primary key and specifies a column name
primary_key:"column_name,omitempty" Indicates this field is a part of primary key, specifies a column name and this field is omitting if empty
primary_key:",omitempty" Indicates this field is a part of primary key, and this field is omitting if empty
column:"column_name" Specifies a column name
column:"column_name,omitempty" Specifies a column name and this field is omitting if empty
column:",omitempty" Specifies this field is omitting if empty
foreign_key:"column_name" Indicates this field is referencing another entity, and specifies keys
foreign_key:"column_name1,column_name2:reference_column_name" Indicates this field is referencing another entity, and specifies key pairs
ignore:"" Specifies this columns is to be ignored

goen's People

Contributors

c000 avatar kamichidu avatar lambdalisue avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

c000 ippei-miyake

goen's Issues

Better error message

panic if map type field found on go generate:

`panic: goen: unknown expr type *ast.MapType```

its unclear message.

panic-ing on generate if some dependencies have non-gomod module.

Masterminds/squirrel has go.mod, but lann/builder isn't.
goen fails to parse deps like below.

/usr/src/goen/example # cat entity.go
package example

import (
        "time"

        "github.com/Masterminds/squirrel"
        uuid "github.com/satori/go.uuid"
)

var _ squirrel.Sqlizer = squirrel.Eq{}

//go:generate goen -o goen.go
type Blog struct {
        BlogID uuid.UUID `goen:"" table:"blogs" primary_key:""`

        Name string

        Author string

        Posts []*Post `foreign_key:"blog_id"`
}

type Post struct {
        Timestamp

        BlogID uuid.UUID `goen:"" table:"posts"`

        PostID int `primary_key:",omitempty"`

        Title string

        Content string

        // "order" is a sql keyword
        Order int

        Blog *Blog `foreign_key:"blog_id"`
}

type Timestamp struct {
        CreatedAt time.Time
        UpdatedAt time.Time
        DeletedAt *time.Time
}
/usr/src/goen/example # go generate .
2019/11/13 06:40:58 generator.go:143: analyzing package "example"
2019/11/13 06:40:58 generator.go:214: analyzing file "postgres_test.go"
2019/11/13 06:40:58 generator.go:214: analyzing file "sqlite3_test.go"
2019/11/13 06:40:58 generator.go:214: analyzing file "entity.go"
2019/11/13 06:40:58 generator.go:240: analyzing struct type "Blog"
2019/11/13 06:40:58 generator.go:281: analyzing struct field Blog.BlogID as column
panic: goen: unable to assume package name "github.com/Masterminds/squirrel": type-checking package "github.com/Masterminds/squirrel" failed (/go/pkg/mod/github.com/!masterminds/[email protected]/case.go:7:2: could not import github.com/lann/builder (type-checking package "github.com/lann/builder" failed (/go/pkg/mod/github.com/lann/[email protected]/builder.go:5:2: could not import github.com/lann/ps (cannot find package "github.com/lann/ps" in any of:
        /usr/local/go/src/github.com/lann/ps (from $GOROOT)
        /go/src/github.com/lann/ps (from $GOPATH)))))

goroutine 1 [running]:
github.com/kamichidu/goen/internal/asts.AssumePkgName(0xc0003d95c1, 0x1f, 0xa4b12a, 0x1)
        /usr/src/goen/internal/asts/asts.go:107 +0x153
github.com/kamichidu/goen/internal/asts.FindPkgPath(0xc000178300, 0xc0003c7f1c, 0x4, 0x9b6cb, 0x9b6cc)
        /usr/src/goen/internal/asts/asts.go:92 +0x164
github.com/kamichidu/goen/internal.(*aType).Kind.func1(0xb31b60, 0xc0003e3d40, 0x203000, 0x203000)
        /usr/src/goen/internal/structs_a.go:199 +0x2b7
github.com/kamichidu/goen/internal/asts.VisitorFunc.Visit(0xc000372100, 0xb31b60, 0xc0003e3d40, 0x8, 0x40d109)
        /usr/src/goen/internal/asts/asts.go:14 +0x3a
go/ast.Walk(0xb2dc80, 0xc000372100, 0xb31b60, 0xc0003e3d40)
        /usr/local/go/src/go/ast/walk.go:52 +0x66
github.com/kamichidu/goen/internal.(*aType).Kind(0xc0003720e0, 0xc00026b5b0)
        /usr/src/goen/internal/structs_a.go:220 +0xca
github.com/kamichidu/goen/generator.(*Generator).safePkgImport(0xc00026bef8, 0xb3de00, 0xc0003720e0, 0x7, 0x2, 0x3, 0x4)
        /usr/src/goen/generator/generator.go:250 +0x74
github.com/kamichidu/goen/generator.(*Generator).walkStruct(0xc000c4def8, 0xb376c0, 0xc000381be0, 0x1, 0x1)
        /usr/src/goen/generator/generator.go:287 +0x410
github.com/kamichidu/goen/generator.(*Generator).walkFile(0xc000c4def8, 0xc0004bb410, 0xc000178300, 0x1, 0x1)
        /usr/src/goen/generator/generator.go:241 +0x258
github.com/kamichidu/goen/generator.(*Generator).walkPkg(0xc000c4def8, 0xc0004bb410, 0xc00026bac8, 0x1)
        /usr/src/goen/generator/generator.go:216 +0x1e0
github.com/kamichidu/goen/generator.(*Generator).ParseDir(0xc000c4def8, 0x1, 0x1)
        /usr/src/goen/generator/generator.go:151 +0x1db
main.run(0xb2d6a0, 0xc000098000, 0xb2d6e0, 0xc000098008, 0xb2d6e0, 0xc000098010, 0xc000084150, 0x3, 0x3, 0x0)
        /usr/src/goen/cmd/goen/main.go:172 +0x73f
main.main()
        /usr/src/goen/cmd/goen/main.go:208 +0x8a
entity.go:13: running "goen": exit status 2

Many-to-one relation does not work

Many-to-one relation with multiple column does not work.

Work

type Table struct {
	ignore some fields...
	ColOne   int
	ColTwo   int
	RefTable *RefTable `foreign_key:"col_one"`
}

NOT Work

type Table struct {
	ignore some fields...
	ColOne   int
	ColTwo   int
	RefTable *RefTable `foreign_key:"col_one,col_two"`
}

Is the value discarded when RowKey is nil?

goen/compiler.go

Lines 169 to 174 in 8fe7ba9

for curr.Next() != nil && c.isCompat(patch, curr.Next().GetValue()) {
curr = curr.Next()
if np := curr.GetValue(); np.RowKey != nil {
cond = append(cond, opts.RowKeyToSqlizer(np.RowKey))
}
}

If RowKey is nil, it seems that the value of curr is discarded.
Is this expected?

quote column names

when column name is database keyword, it will get query error.
should always quote column names.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.