Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for custom struct tags #534

Closed
philippta opened this issue Jun 5, 2020 · 10 comments · Fixed by #1569
Closed

Add support for custom struct tags #534

philippta opened this issue Jun 5, 2020 · 10 comments · Fixed by #1569
Labels
enhancement New feature or request

Comments

@philippta
Copy link
Contributor

When working with structs, struct tags are used to add additional information to a field. This is for example very common when using validation packages. But currently there is no way to add additional struct tags to take advantage of this.

I think it would be a great idea to add a comment syntax just like the -- name:NameForQuery for table columns.

A possible option to express these custom struct tags would be to write create table statements like this:

CREATE TABLE user (
  id   BIGSERIAL PRIMARY KEY,

  -- tags:`validate:"min=10,max=0"`
  username text NOT NULL,

  -- tags:`validate:"gt=18"`
  age  integer NOT NULL,

  -- tags:`validate:"url"`
  website text NOT NULL
);

or alternatively:

CREATE TABLE user (
  id   BIGSERIAL PRIMARY KEY,
  username text NOT NULL,     -- tags:`validate:"min=10,max=0"`
  age integer NOT NULL,       -- tags:`validate:"gt=18"`
  website text NOT NULL       -- tags:`validate:"url"`
);
@kyleconroy kyleconroy added the enhancement New feature or request label Jun 9, 2020
@huangc28
Copy link

huangc28 commented Aug 14, 2020

Has anyone pickup this enhancement yet? It would be useful for generating fake data on model fields. If not I would like to give it a try with proper PSR predicated.

@fr3fou
Copy link

fr3fou commented Dec 31, 2020

Is there a way to achieve this now?
I want to ignore the password field on my user struct, like so

type User struct {
    Password string `json:"-"`
}

@ciazhar
Copy link

ciazhar commented Oct 26, 2021

up

@eliaschampi
Copy link

any solution for this issue please?

@tamoore
Copy link

tamoore commented Feb 28, 2022

@kyleconroy Would you be open to a solution that utilised the config overrides?

Something like the following:

overrides:
  - column: "chat.id"
    custom_struct_tag_key: "gorm"
    go_type: 
      type: "int"

# OR

overrides:
  - column: "chat.id"
    go_type: 
      custom_struct_tag_key: "gorm"

I think this might also need something like custom_tag_value for instances like validate where consumers want to set a custom value. Otherwise, the default would be whatever the json_tags_case_style is set to (otherwise the default format).

Further to the above, this wouldn't override json tags, it would be in addition to emitting json tags.

It seems to me that the conversation around including these in the schema is not the right place for this. Struct tags are really just a go concern, so possibly even including it in the definition of the go_type in the override might be a better place.

@preslavrachev
Copy link

@kyleconroy can we hope to see a feature like this in the foreseeable future? In my project, we started using Gorm way back in time, and it has been something we have been considering moving away from (towards sqlc). However, we rely on some 3rd party code that uses Gorm under the hood, so completely running away from it isn't feasible at the moment.

If there were a way to let sqlc generate our Gorm-compatible models, this would be fantastic. It's the one thing that's stopping us from getting all in on sqlc.

The only other alternative is still keep two copies of each model, which isn't that bad, but possibly error-prone.

@austincollinpena
Copy link

I agree that this seems like a good thing to add to the configuration file.

@josharian
Copy link
Contributor

We're facing this right now as well. I'm game to work on it, if we can get to an agreement about the design.

FWIW, I would prefer adding custom struct tags to the config file, using something like:

overrides:
  - column: chat.id
    go_struct_tag: 'validate:"required" sometagtype:"some_value"'

@austincollinpena
Copy link

I like that design

josharian added a commit to josharian/sqlc that referenced this issue Apr 25, 2022
This change adds a new type of override: go_struct_tag.
When provided for a field, it adds that struct tag to the generated code.
The provided struct tag is parsed according to the standard
package reflect rules, and its components are updated independently.
This allows struct tag overrides to be compatible with (and optionally
override) autogenerated json and db struct tags.

Fixes sqlc-dev#534
@josharian
Copy link
Contributor

Implemented in #1569 if anyone wants to kick the tires.

josharian added a commit to josharian/sqlc that referenced this issue May 25, 2022
This change adds a new type of override: go_struct_tag.
When provided for a field, it adds that struct tag to the generated code.
The provided struct tag is parsed according to the standard
package reflect rules, and its components are updated independently.
This allows struct tag overrides to be compatible with (and optionally
override) autogenerated json and db struct tags.

Fixes sqlc-dev#534
kyleconroy pushed a commit that referenced this issue Jun 10, 2022
* internal/config: use strings.Trim{Prefix,Suffix}

This is equivalent and slightly simpler.

* Makefile: fix vtproto 'go install' command

* internal/codegen/golang: simplify template tag condition

Rather than modeling when .Tag will be empty,
check directly whether .Tag is empty.

This simplifies the template and reduces the number
of places that must be touched when adding new
sources of struct tags.

* internal/codegen/golang: tweak tag formatting

Rather than inserting the colon at tag construction time,
insert it at tag formatting time.

This makes the input look a bit more natural.
This matters more, as we are about to add another,
more distant, place where we insert tags.

* all: add support for custom Go struct tags

This change adds a new type of override: go_struct_tag.
When provided for a field, it adds that struct tag to the generated code.
The provided struct tag is parsed according to the standard
package reflect rules, and its components are updated independently.
This allows struct tag overrides to be compatible with (and optionally
override) autogenerated json and db struct tags.

Fixes #534

* go.mod: bump to Go 1.18

The code uses some 1.18-only features, like strings.Cut and testing.F.

The CI requires Go 1.18.

Since Go 1.18 is now required, reflect that in the go.mod.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants