Giter VIP home page Giter VIP logo

protoc-gen-gorm's Introduction

protoc-gen-gorm

Purpose

A protobuf (https://developers.google.com/protocol-buffers/) compiler plugin designed to simplify the API calls needed to perform simple object persistence tasks. This is currently accomplished by creating a secondary .pb.gorm.go file which contains sister objects to those generated in the standard .pb.go file satisfying these criteria:

  • Go field decorators/tags can be defined by option in the .proto file for GORM/SQL
  • There are options for dropping fields from the PB object, or adding additional fields (not generally recommended, as it reduces clarity of .proto file)
  • Converters between PB version and ORM version of the objects are included
  • Hook interfaces allow for custom application logic

Prerequisites

1. Protobuf Compiler

The protobuf compiler (protoc) is required.

Official instructions

Abbreviated version

2. Golang Protobuf Code Generator

Get the golang protobuf code generator:

Before Go 1.17

go get -u github.com/golang/protobuf/protoc-gen-go

Starting from Go 1.17

go install github.com/golang/protobuf/protoc-gen-go@latest

3. Vendored Dependencies

Retrieve and install the vendored dependencies for this project with go mod:

go mod tidy

Installation

To use this tool, install it from code with make install, go install github.com/infobloxopen/protoc-gen-gorm@latest directly, or go get github.com/infobloxopen/protoc-gen-gorm.

Usage

Once installed, the --gorm_out=. or --gorm_out=${GOPATH}src option can be specified in a protoc command to generate the .pb.gorm.go files.

Any message types with the option (gorm.opts).ormable = true will have the following autogenerated:

  • A struct with ORM compatible types and the "ORM" suffix
  • GORM tags built from the field options [(gorm.field).tag = {..., tag: value, ...}].
  • A {PbType}.ToORM and {TypeORM}.ToPB function
  • Additional, unexposed fields added from the option (gorm.opts) = {include: []}, either of a built-in type e.g. {type: "int32", name: "secret_key"}, or an imported type, e.g. {type: "StringArray", name: "array", package:"github.com/lib/pq"}.
  • Barebones C/U/R/D/L handlers that accept the protobuf versions (as from an API call), a context (used with the multiaccount option and for collection operators https://github.com/infobloxopen/atlas-app-toolkit#collection-operators), and a gorm.DB then perform the basic operation on the DB with the object
  • Interface hooks for before and after each conversion that can be implemented to add custom handling.

Any services with the option (gorm.server).autogen = true will have basic grpc server generated:

  • For service methods with names starting with Create|Read|Update|Delete generated implementation will call basic CRUD handlers.
  • For other methods return &MethodResponse{}, nil stub is generated.

For CRUD methods to be generated correctly you need to follow specific conventions:

  • Request messages for Create and Update methods should have an Ormable Type in a field named payload, for Read and Delete methods an id field is required. Nothing is required in the List request.
  • Response messages for Create, Read, and Update require an Ormable Type in a field named result and for List a repeated Ormable Type named results.
  • Delete methods require the (gorm.method).object_type option to indicate which Ormable Type it should delete, and has no response type requirements.

To customize the generated server, embed it into a new type and override any desired functions.

If conventions are not met stubs are generated for CRUD methods. As seen in the feature_demo/demo_service example.

To leverage DB specific features, specify the DB engine during generation using the --gorm_out="engine={postgres,...}:{path}". Currently only Postgres has special type support, any other choice will behave as default.

The generated code can also integrate with the grpc server gorm transaction middleware provided in the atlas-app-toolkit using the service level option option (gorm.server).txn_middleware = true.

Examples

Example .proto files and generated .pb.gorm.go files are included in the 'example' directory. The user file contains model examples from GORM documentation, the feature_demo/demo_types demonstrates the type handling and multi_account functions, and the feature_demo/demo_service shows the service autogeneration.

Running make example will recompile all these test proto files, if you want to test the effects of changing the options and fields.

Supported Types

Within the proto files, the following types are supported:

  • standard primitive types uint32, uint64, int32, int64, float, double, bool, string map to the same type at ORM level
  • google wrapper types google.protobuf.StringValue, .BoolValue, .UInt32Value, .FloatValue, etc. map to pointers of the internal type at the ORM level, e.g. *string, *bool, *uint32, *float
  • [google timestamp type]((https://github.com/golang/protobuf/blob/master/ptypes/timestamp/timestamp.proto) google.protobuf.Timestamp maps to time.Time type at the ORM level
  • custom wrapper types gorm.types.UUID and gorm.types.UUIDValue, which wrap strings and convert to a uuid.UUID and *uuid.UUID at the ORM level, from https://github.com/satori/go.uuid. A null or missing gorm.types.UUID will become a ZeroUUID (00000000-0000-0000-0000-000000000000) at the ORM level.
  • custom wrapper type gorm.types.JSONValue, which wraps a string in protobuf containing arbitrary JSON and converts to custom types.Jsonb type if Postgres is the selected DB engine, otherwise it is currently dropped.
  • custom wrapper type gorm.types.InetValue, which wraps a string and will convert to the types.Inet type at ORM level, which uses the golang net.IPNet type to hold an ip address and mask, IPv4 and IPv6 compatible, with the scan and value functions necessary to write to DBs. Like JSONValue, currently dropped if DB engine is not Postgres
  • types can be imported from other .proto files within the same package (protoc invocation) or between packages. All associations can be generated properly within the same package, but cross package only the belongs-to and many-to-many will work.
  • some repeated types can be automatically handled for Postgres by github.com/lib/pq, and as long as the engine is set to postgres then to/from mappings will be created (see the example called example/postgres_arrays/postgres_arrays.proto):
    • []bool: pq.BoolArray
    • []float64: pq.Float64Array
    • []int64: pq.Int64Array
    • []string: pq.StringArray

Associations

The plugin supports the following GORM associations:

  • Belongs-To
  • Has-One
  • Has-Many
  • Many-To-Many

Note: polymorphic associations are currently not supported.

Association is defined by adding a field of some ormable message type(either single or repeated).

message Contact {
    option (gorm.opts).ormable = true;
    uint64 id = 1;
    string name = 2;
    repeated Email emails = 3;
    Address home_address = 4;
}

Has-One is a default association for a single message type.

message Contact {
    option (gorm.opts).ormable = true;
    uint64 id = 1;
    string first_name = 2;
    string middle_name = 3;
    string last_name = 4;
    Address address = 5;
}

message Address {
    option (gorm.opts).ormable = true;
    string address = 1;
    string city = 2;
    string state = 3;
    string zip = 4;
    string country = 5;
}

Set (gorm.field).belongs_to option on the field in order to define Belongs-To.

message Contact {
    option (gorm.opts).ormable = true;
    uint64 id = 1;
    string first_name = 2;
    string middle_name = 3;
    string last_name = 4;
    Profile profile = 5 [(gorm.field).belongs_to = {}];
}

message Profile {
    option (gorm.opts).ormable = true;
    uint64 id = 1;
    string name = 2;
    string notes = 3;
}

Has-Many is a default association for a repeated message type.

message Contact {
    option (gorm.opts).ormable = true;
    uint64 id = 1;
    string first_name = 2;
    string middle_name = 3;
    string last_name = 4;
    repeated Email emails = 5;
}

message Email {
    option (gorm.opts).ormable = true;
    string address = 1;
    bool is_primary = 2;
}

Set (gorm.field).many_to_many option on the field in order to define Many-To-Many.

message Contact {
    option (gorm.opts).ormable = true;
    uint64 id = 1;
    string first_name = 2;
    string middle_name = 3;
    string last_name = 4;
    repeated Group groups = 5 [(gorm.field).many_to_many = {}];
}

message Group {
    option (gorm.opts).ormable = true;
    uint64 id = 1;
    string name = 2;
    string notes = 3;
}

For each association type, except Many-To-Many, foreign keys pointing to primary keys(association keys) are automatically created if they don't exist in proto messages, their names correspond to GORM default foreign key names. GORM association tags are also automatically inserted.

Customization

  • For each association type you are able to override default foreign key and association key by setting foreignKey and references options.
  • For each association type you are able to override default behavior of creating/updating the record. It's references can be created/updated depending on disable_association_autoupdate, disable_association_autocreate options, which effectively produces statements to prevent Association auto behavior (much like in tags were used in gormV1). Check out official association docs for more information.
  • For each association type you are able to set preload option, which generates required code (with the same meaning gormV1 preload tag was working). Check out GORM docs.
  • By default when updating child associations are wiped and replaced. This functionality can be switched to work the same way gorm handles this see [GORM]https://gorm.io/docs/associations.html this is done by adding one of the gorm association handler options, the options are append ([GORM]https://gorm.io/docs/associations.html#Append-Associations), clear ([GORM]https://gorm.io/docs/associations.html#Clear-Associations) and replace ([GORM]https://gorm.io/docs/associations.html#Replace-Associations).
  • For Has-Many you are able to set position_field so additional field is created if it doesn't exist in proto message to maintain association ordering. Corresponding CRUDL handlers do all the necessary work to maintain the ordering.
  • For automatically created foreign key and position field you're able to assign GORM tags by setting foreignkey_tag and position_field_tag options.
  • For Many-To-Many you're able to override default join table name and column names by setting jointable, joinForeignKey and joinReferences options.

Check out user to see a real example of associations usage.

Limitations

Currently only proto3 is supported.

This project is currently in development, and is expected to undergo "breaking" (and fixing) changes

Contributing

Pull requests are welcome!

Any new feature should include tests for that feature.

Before pushing changes, run the tests with:

make gentool-test

This will run the tests in a docker container with specific known versions of dependencies.

Before the tests run, they generate code. Commit any new and modified generated code as part of your pull request.

protoc-gen-gorm's People

Contributors

amaskalenka avatar anpiakhota-infoblox avatar askurydzin avatar calebjh avatar chinmayb avatar chrusty avatar davidraleigh avatar dependabot[bot] avatar dkukharau avatar dmacthedestroyer avatar drewwells avatar emilev-ms avatar evgeniy-l avatar gaxxx avatar gshirazi avatar jaytaylor avatar johnbelamaric avatar kd7lxl avatar khous avatar mathiasgrund avatar mewis avatar mfridman avatar michaelskuratovichns avatar ogvnrvo avatar richardfelkl avatar sbhagate-infoblox avatar sliverhorn avatar tttoad avatar yreshetko avatar ystankevich avatar

Stargazers

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

Watchers

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

protoc-gen-gorm's Issues

fail `go get github.com/infobloxopen/protoc-gen-gorm` with golang 1.13

go get github.com/infobloxopen/protoc-gen-gorm

 github.com/infobloxopen/protoc-gen-gorm/plugin
go/src/github.com/infobloxopen/protoc-gen-gorm/plugin/imports.go:114:16: cannot use dep (type string) as type generator.GoPackageName in argument to p.Generator.PrintImport
go/src/github.com/infobloxopen/protoc-gen-gorm/plugin/imports.go:114:16: cannot use dep (type string) as type generator.GoImportPath in argument to p.Generator.PrintImport
go/src/github.com/infobloxopen/protoc-gen-gorm/plugin/imports.go:123:16: cannot use a (type string) as type generator.GoPackageName in argument to p.Generator.PrintImport
go/src/github.com/infobloxopen/protoc-gen-gorm/plugin/imports.go:123:36: cannot use githubImports[a].packagePath (type string) as type generator.GoImportPath in argument to p.Generator.PrintImport
go/src/github.com/infobloxopen/protoc-gen-gorm/plugin/plugin.go:111:26: cannot use file.FileDescriptorProto (type *descriptor.FileDescriptorProto) as type string in argument to p.Generator.SetFile
go/src/github.com/infobloxopen/protoc-gen-gorm/plugin/plugin.go:149:13: p.FileOf undefined (type *OrmPlugin has no field or method FileOf)
go/src/github.com/infobloxopen/protoc-gen-gorm/plugin/plugin.go:187:13: p.FileOf undefined (type *OrmPlugin has no field or method FileOf)

go get github.com/infobloxopen/protoc-gen-gorm is throwing compilation errors

go get github.com/infobloxopen/protoc-gen-gorm

github.com/infobloxopen/protoc-gen-gorm/plugin

../../../github.com/infobloxopen/protoc-gen-gorm/plugin/imports.go:106:16: cannot use dep (type string) as type generator.GoPackageName in argument to p.Generator.PrintImport
../../../github.com/infobloxopen/protoc-gen-gorm/plugin/imports.go:106:16: cannot use dep (type string) as type generator.GoImportPath in argument to p.Generator.PrintImport
../../../github.com/infobloxopen/protoc-gen-gorm/plugin/imports.go:115:16: cannot use a (type string) as type generator.GoPackageName in argument to p.Generator.PrintImport
../../../github.com/infobloxopen/protoc-gen-gorm/plugin/imports.go:115:36: cannot use githubImports[a].packagePath (type string) as type generator.GoImportPath in argument to p.Generator.PrintImport
../../../github.com/infobloxopen/protoc-gen-gorm/plugin/plugin.go:101:13: p.Generator.SetFile undefined (type *generator.Generator has no field or method SetFile)
../../../github.com/infobloxopen/protoc-gen-gorm/plugin/plugin.go:133:13: p.FileOf undefined (type *OrmPlugin has no field or method FileOf)

Sharing "gormable" protobuf between several project in different programming languages.

Greetings!

Let's say, I have following *.proto:

syntax = "proto3";

package proto;
option go_package = "github.com/amricko0b/prototest";

import "github.com/infobloxopen/protoc-gen-gorm/options/gorm.proto";

message Account {
    uint64 id = 1;
    string number = 2;
    double available = 10;
    double reserve = 11;
    string version = 12;
    string state = 13;
    option (gorm.opts) = {
        ormable: true
    };
}

For case of generating Golang code everything works fine. But what if I try to generate code for some other languages? When I do this for TypeScript (using protoc-gen-ts), I obviously get "Import was not found" error for file gorm.proto.

What should I do to keep my protobuf language-independent and still save gorm support?

Invalid type casting from uint32 to string

string of int32 result is a invalid. Need to use strconv.Itoa instead of string in plugin/plugin.go

var Size_ *int32 
var sz int32 = 500 
Size_ = &sz 
fmt.Println(string(*Size_))
   > Ǵ
fmt.Println(fmt.Sprintf("%d", *Size_))
   > 500

https://play.golang.org/p/ob2LInRaI83

The following two references are incorrect:

gormRes += fmt.Sprintf("size:%s;", string(tag.GetSize_()))

gormRes += fmt.Sprintf("size:%s;", string(tag.GetSize_()))
gormRes += fmt.Sprintf("precision:%s;", string(tag.GetPrecision()))

Time type managing

Hi Infoblox Team.

Could you advise if the plugin supports Time type for postgress (not timestamp or date).
When I use regular google.protobuf.Timestamp the time is casted to time.Time as 0000-00-00Thh:mm:ss and this is a problem.

Thanks in advance for your answer.

Prefix requirement for default handlers leads to poor organization

Documentation states that RPC methods starting with Create/Update etc will be used to call default implementations. Having multiple methods that start with a common prefix does not allow for the methods to be grouped appropriately in things like "godoc".

Add support for having methods that have a common Suffix instead.

Generated code does not compile with ApplyCollectionOperators error.

This looks really promising, thanks for releasing it :) Noticing the following compile error for a simple ormable message:

events.pb.gorm.go:190:42: not enough arguments in call to "vendor/github.com/infobloxopen/atlas-app-toolkit/gorm".ApplyCollectionOperators
have (*"vendor/github.com/jinzhu/gorm".DB, *query.Filtering, *query.Sorting, *query.Pagination, *query.FieldSelection)
want (*"vendor/github.com/jinzhu/gorm".DB, interface {}, *query.Filtering, *query.Sorting, *query.Pagination, *query.FieldSelection)

Message looks like this:

message AccountCreatedEvent {
	option (gorm.opts).ormable = true;
	string user_id = 1;
}

Relevant generated code looks like this:

	ormResponse := []AccountCreatedEventORM{}
	f, s, p, fs, err := getCollectionOperators(req)
	if err != nil {
		return nil, err
	}
	db, err = gorm2.ApplyCollectionOperators(db, f, s, p, fs) // Missing obj parameter here.

Readonly fields?

There are readonly fields many time.

message Shop {
    option (gorm.opts) = {
        ormable: true,
        multi_account: true,
        include: [
            {type: "*time.Time", name: "deleted_at"} // this field is non-visible. it's ok.
        ]
    };

    string name = 4;

    // We want the fields below to be visible, but can't writable.
    string id = 1 [(gorm.field).tag = {primary_key: true}]; 
    google.protobuf.Timestamp created_at = 2;
    google.protobuf.Timestamp updated_at = 3;
}

I have tried this library. https://github.com/infobloxopen/protoc-gen-atlas-validate
Then I cant assign the created_at field in request.payload.
But~ the created_at was still be updated to empty.
Because If I don't assign the created_at field, it will be transfer into request as empty value.

Golang "context" import in separate files.

Hello everyone!

I've go my messages model and services in seprated *.proto files.
Hence, after compilation I have two *.pb.gorm.go files - with structures and with autogenerated CRUD services. Both of them - in the same package.

Trouble: Golang's package "context" is imported in *.pb.gorm.go file with structures but none of him found in file with services.

It produces a compilation error, because context is undefined.
Am I able to fix this somehow ? Or so, should I keep everything in one *.proto file ?

Custom `Parent GORM struct`?

eg:
There is a field named id for all tables.
The we want to use the xid.

package pb

import (
	"github.com/jinzhu/gorm"
	"github.com/rs/xid"
)

func (ormObj *ShopORM) BeforeCreate(scope *gorm.Scope) error {
	return scope.SetColumn("Id", xid.New().String())
}

func (ormObj *UserORM) BeforeCreate(scope *gorm.Scope) error {
	return scope.SetColumn("Id", xid.New().String())
}

If I can custom the parent gorm struct name in proto, then no need to write the callbacks for every table.
I think It's also acceptable for only support a empty parent gorm struct. :)

"to" mappings for StringArrays

I'm working on a project where I want to store string-arrays in Postgres. The proto-generation mostly works, but don't result in any mappings for the arrays.

The generated gorm.pb files end up containing // Repeated type []string is not an ORMable message type. Instead I want them to have something like this:

       for _, v := range m.SomeStringArray{
               to.SomeStringArray = append(to.SomeStringArray, v)
       }

I've forked and make a working example, but this is kinda hard-coded (and its highly possible that I'm missing the point).

Let me know if this sounds like something you'd be interested in, and we can discuss the cleanest way to implement it. Obviously there are other types of array handled by github.com/lib/pq too.

"strings" package is not imported in the generated .pb.gorm.go file

While trying to compile the following proto, the generated .pb.gorm.go file does not import "strings" package even though the package is used in .pb.gorm.go

syntax = "proto3";

package service;

import "github.com/infobloxopen/protoc-gen-gorm/options/gorm.proto";
import "github.com/infobloxopen/protoc-gen-gorm/types/types.proto";

service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  option (gorm.opts).ormable = true;
  string name = 1;
  gorm.types.JSONValue tags = 2;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

This results in a failure while building the application

# github.com/learning/test.service/pkg/pb
pkg/pb/service.pb.gorm.go:155:22: undefined: strings

Protoc is not generating any gorm files

Hello,
I have a problem, that I can't see any generated code in my project directory after running (in Makefile):

protos:
	@protoc \
		-I /usr/local/include \
		-I ${GOPATH}/src \
		--go_out=${GOPATH}/src \
		--gorm_out=${GOPATH}/src \
		--proto_path=. \
		database.proto

What is the problem source?

XXX.pb.gorm.go,package name error

My Command :
protoc -I. -I$GOPATH/src --proto_path=. --gorm_out=engine=grpc.orm:proto --go_out=plugins=grpc:proto --proto_path=. *.proto

But I got XXX.pb.gorm.go , but it package is

package __grpc

My Sample Proto FIle

`
syntax = "proto3";
package grpc.orm;
import "google/protobuf/timestamp.proto";
import "github.com/infobloxopen/protoc-gen-gorm/options/gorm.proto";

option go_package = ".;grpc";
message Example {
option (gorm.opts) = {ormable: true};
int64 id = 1;
int64 type = 2;
string logic_class = 3;
string name = 4;

}
`

some fields are not created

Hi, I have the following proto file

message Game {
  uint64 id = 1;
  string name = 2;
  string slug = 3;
  string description = 4;
  string image = 5;
  string video = 6;
  bool disabled = 7;
  google.protobuf.Timestamp created_at = 8;
  google.protobuf.Timestamp updated_at = 9;
  google.protobuf.Timestamp deleted_at = 10;

  option (gorm.opts) = {
    ormable: true,
  };
}

message BGame {
  uint64 id = 1;
  uint64 branch = 2;
  Game parent = 3 [(gorm.field).belongs_to = {}];
  Process process = 4;
  google.protobuf.Timestamp created_at = 5;
  google.protobuf.Timestamp updated_at = 6;
  google.protobuf.Timestamp deleted_at = 7;

  option (gorm.opts) = {
    ormable: true,
  };
}

message Process {
  string path = 1;
  repeated string args = 2;
  repeated string watchers = 3;
  string pre_exec = 4;
  string post_exec = 5;

  option (gorm.opts) = {
    ormable: true,
  };
}

created_at, updated_at and deleted_at fields are not created.
associations are not created.

Am I doing something wrong here?
Thanks

Overwriting Update should restrict itself

Instead of strict update removing all children and re-adding them, it should only remove children not present in the update request (a filtered delete). No advanced logic should be needed to handle the case where the PUT child objects don't have IDs populated yet.

1:many convention breaks with snake_case parent key name

the following proto message:

message Contact {
    option (gorm.opts) = {ormable: true};
    uint64 id = 1;
    repeated Address addresses = 6;
}

message Address {
  option (gorm.opts).ormable = true;
  uint64 id = 1;
  uint64 contact_id = 2;
}

fails with the following error:

protoc-gen-gogo: error:Child type Address seems to have no foreign key field linking it to parent type Contact : expected field ContactID in Address associated with field ID in Contact
--gorm_out: protoc-gen-gorm: Plugin failed with status code 1.
make: *** [protobuf] Error 1

changing the uint64 contact_id = 2; to be contactid (no underscore) gets it to compile properly, but this doesn't comply to the naming best practices for proto files

`fieldSelection` depends on `gateway.ForwardResponseMessage`, but no gen.

We must wrote it manually.

I think we can assign a param for gen tool to determine whether gen the override.gw.pb.go.

package pb

import (
	"github.com/infobloxopen/atlas-app-toolkit/gateway"
)

func init() {
	forward_Shops_Create_0 = gateway.ForwardResponseMessage

	forward_Shops_Read_0 = gateway.ForwardResponseMessage

	forward_Shops_Update_0 = gateway.ForwardResponseMessage

	forward_Shops_Delete_0 = gateway.ForwardResponseMessage

	forward_Shops_List_0 = gateway.ForwardResponseMessage
}

#181 migrates github.com/golang/protobuf from v0.0.0-20180706225418-1325a051a275 -> v1.3.1 but doesn't using gogo/protobuf require us to also use github.com/golang/protobuf with v1.0.0?

Hi,

I was under the impression that the version of gogo/protobuf must match for build and runtime dependencies

In this PR #181 the version was updated and I'm wondering if that potentially breaks projects that try to use gorm and the protogen-go-gorm compiler? For instance the release notes of gogo/protbuf https://github.com/gogo/protobuf/releases/tag/v1.0.0

This is the first tag of golang/protobuf and gogo/protobuf is syncing with this process.
This release also includes:
minor fixes
compatibility with go 1.10 beta
compatibility with protoc 3.5.1

Is this project still under active development?

Hello,
Is this project still under planned development?

If yes, I'd like to help fix some of these issues with the recent Go Modules and API changes.

I'd like to help because I'd like to use this approach for a project I'm working on.

Many thanks,
Charles

association_autoupdate does not work with DefaultStrictUpdate

The generated default server uses DefaultStrictUpdate. This deletes all children of the item you are trying to patch.
e.g

filterProjects := ProjectORM{}
if ormObj.Id == 0 {
    return nil, errors1.EmptyIdError
}
filterProjects.ClientId = new(uint32)
*filterProjects.ClientId = ormObj.Id
if err = db.Where(filterProjects).Delete(ProjectORM{}).Error; err != nil {
    return nil, err
}

I do not understand the thinking behind this.

This means that https://github.com/infobloxopen/protoc-gen-gorm/blob/master/README.md#customization trying to control the behaviour of associations wont work as you have no control over whether children are deleted.

When using

[(gorm.field).has_many = {
        association_autoupdate: false
}]

children should not be effected or in my opinion better yet, children should never be effected as this is a un-foreseen side effect and this logic should be left to the implementer to control

Also please note this only "deletes children" when using deleted_at for soft delete.

Need support of `_non_nested_fields`/`_all`/`_nested_fields` for `_fields`

eg:
We often need list users without return nested fields.
For performance considerations, I have tagged preload:false for nested fields.
Then I want list the users just with return nested filed shop.
So I set the value shop,name,descritpion....... for _fileds.
This is awkward with so many fields in user.

I think we need _non_nested_fields/_all/_nested_fields.
Then I can set the value shop,_non_nested_fields. :)

go mod / dep ensure fails

Could not introduce github.com/infobloxopen/[email protected], as its subpackage github.com/infobloxopen/protoc-gen-gorm/errors is missing. (Package is required by (root).)

version 0.15.1 or master

Implement filter by parent for list

I would like to implement something that allows us to work using this design pattern
https://cloud.google.com/apis/design/resources

The main part I am after is been able to specify the parent and then the auto generated endpoint will only return results based on what parent is passed.

I have not completely thought about this yet so this is more a question of
A - is it worth me looking into to
B - is there a particular way you would like me o go about this.

I was just thinking for the List request message you can specify the parent column.
something like

  message ChildRequest {
    string parent_field = 1;
    uint32 parent = 2;
  }


  rpc GetChildResource(ChildRequest) returns (ListResponse) {
      option (google.api.http) = {
          get: "/api/clients/{parent}/projects"
      };
  }

what do you think?

Need support of GORM `preload` option

E.g.

type User struct {
  gorm.Model
  Name       string
  CompanyID  uint
  Company    Company `gorm:"preload:false"` // not preloaded
  Role       Role                           // preloaded
}

DefaultRead handler should not preload a model if preload is set to false.

Generated DELETE Function Doesn't Work With FKs

Updating contacts example app with a one:many example. Seeing

  "error": {
    "status": 500,
    "code": "UNKNOWN",
    "message": "pq: update or delete on table \"contacts\" violates foreign key constraint \"emails_contact_id_fkey\" on table \"emails\""
  }
}

indicates that nested objects aren't deleted in the same way that updates and creates are automatically handled.

1:many child object naming is inconsistent

Refer to this example PR comment in #18 for an example demonstrating the issue.

Certain names for child objects don't get handled properly as a result of the ORM models attempting to produce go-lintable names instead of the default pb.go naming convention. In this case, the proto message was named AclItem, which generated a pb.go struct named AclItem and a gorm.pb.go struct named ACLItemORM.

A simple workaround is to use the name ACLItem in the .proto file, but this behavior should be addressed nonetheless.

Imports handling

Imports could be handled a bit more elegantly with the use of PluginImports mixin.
e.g.

func (p *ormPlugin) Generate(file *generator.FileDescriptor) {
        ...
	p.PluginImports = generator.NewPluginImports(p.Generator)
        p.gormPkgName = generator.NewImport("github.com/jinzhu/gorm")
        p.lftPkgName = generator.NewImport("github.com/Infoblox-CTO/ngp.api.toolkit/op/gorm")
        ...
}

Unique package aliases will be generated for both imports.
Implementation of

func (p *ormPlugin) GenerateImports(file *generator.FileDescriptor)

is not required, it's supplied by the mixin.
Check out how protoc-gen-gogo plugins use it.

File *.pb.gorm.go aren't generated.

I have file model.proto

syntax = "proto3";
package model;
import "github.com/infobloxopen/protoc-gen-gorm/options/gorm.proto";
import "google/protobuf/timestamp.proto";

option go_package = "service/model;model";

message Example {
    option (gorm.opts) = {
        ormable: true
    };
    int32 id = 1;
    string example = 2;
}

and after running command

sudo protoc -I ~/go/src/  ~/go/src/service/model/model.proto --go_out=plugins=grpc:/$GOPATH/src

I get only model.pd.go file but should get also model.gorm.pd.go file but I don't get it.

Error on import message, is not ormable.

When import another proto file import "color/color_service.proto" and try to use message with "option (gorm.opts) = {ormable: true}", i got an error: "error:color.Color is not ormable.".

color_service.proto

message Color {
    option (gorm.opts) = {ormable: true};
    string name = 1;
}

part_service.proto

import "options/gorm.proto";
import "color/color_service.proto";
message Part {
    option (gorm.opts) = {ormable: true};
    string name = 1;
    int32 status = 2;
    color.Color color = 3;
}

errors from protoc --proto_path=. --go_out=. --gorm_out=. proto/product/product.proto

Run
protoc --proto_path=. --go_out=. --gorm_out=. proto/product/product.proto

Then got errors

github.com/infobloxopen/protoc-gen-gorm/options/gorm.proto: File not found.
github.com/infobloxopen/atlas-app-toolkit/query/collection_operators.proto: File not found.
proto/product/product.proto: Import "github.com/infobloxopen/protoc-gen-gorm/options/gorm.proto" was not found or had errors.
proto/product/product.proto: Import "github.com/infobloxopen/atlas-app-toolkit/query/collection_operators.proto" was not found or had errors.
proto/product/product.proto:38:5: "infoblox.api.FieldSelection" is not defined.
proto/product/product.proto:83:5: "infoblox.api.Filtering" is not defined.
proto/product/product.proto:84:5: "infoblox.api.Sorting" is not defined.
proto/product/product.proto:85:5: "infoblox.api.FieldSelection" is not defined.
proto/product/product.proto:86:5: "infoblox.api.Pagination" is not defined.

In fact
github.com/infobloxopen/protoc-gen-gorm/options/gorm.proto: File not found. and
github.com/infobloxopen/atlas-app-toolkit/query/collection_operators.proto:
are exist

Incorrect Order of columns

It looks like the order of columns becomes alphabetical, regardless of how the column names are ordered in the proto file. This is a major issue when migrating to the new schema. Is there a way to preserve the order of columns as specified in the proto file?

func (p *OrmPlugin) getSortedFieldNames(fields map[string]*Field) []string {

Not found or had errors

I can't import anything from protoc-gen-gorm to proto files:
"import github.com/infobloxopen/protoc-gen-gorm/options/gorm.proto was not found or had errors."
I'm using GO111MODULE = auto, is that the cause? I am quite confused with the path of gomodules and GOPATH ...

GO111MODULE="auto"
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/sergiofm/.cache/go-build"
GOENV="/home/sergiofm/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/sergiofm/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build121241381=/tmp/go-build -gno-record-gcc-switches"

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.