go-jet / jet

Type safe SQL builder with code generation and automatic query result data mapping
Apache License 2.0
2.23k stars 110 forks source link

How to generate table names plural and use CUSTOM models in singular? #256

Closed quirell closed 11 months ago

quirell commented 11 months ago

Is your feature request related to a problem? Please describe. My tables are in plural and I use only custom models which are all in singular. Example: table name: "users" struct name: "User" I don't think it's currently possible to achieve it even with generator customization, but Describe the solution you'd like it would be posible if this alias was customizable by for example changing the template from

var {{tableTemplate.InstanceName}} = new{{tableTemplate.TypeName}}("{{schemaName}}", "{{.Name}}", "")

to

var {{tableTemplate.InstanceName}} = new{{tableTemplate.TypeName}}("{{schemaName}}", "{{.Name}}","{{.Alias}}")

and adjusting the generator accordingly.

Or is there any other way to accomplish what I want to do ?

houten11 commented 11 months ago

I don't think it's currently possible to achieve it even with generator customization, but

Yeah, I don't see a way either.

Or is there any other way to accomplish what I want to do?

I see three workarounds:

1) New sql builder package where you would create new aliased table sql builder types:

package table

import "autogenerated/table/package"

var User = Users.AS("User")
...... // other tables

Now you would, always for your SQL queries, import this package, not autogenerated one.

2) Wrap custom model with a new type before scan:

var dest struct {
     custom.User `alias:"users"`
}

err := stmt.Query(db, &dest)
  1. Alias each custom struct field:
package custom

type User struct {
   ....
   name     string `alias:"users.name"`
   password string `alias:"users.password"`
  ....
}
quirell commented 11 months ago

Thanks, that's what I thought. I'll go with the first option for now and I can create a PR that adds the functionality I need when I have some time ( I don't think that I'm the only one because it's quite common to have table names in plural and models in singular). If you of course allow it and it doesn't clash with your plans for the library.

go-jet commented 11 months ago

Yep, sounds like a good idea. We can extend template.TableSQLBuilder with a DefaultAlias field.

quirell commented 11 months ago

@go-jet Hey, I'd like to make a PR, could you give me permissions to push a branch ? Or how can I share the code with you ?

go-jet commented 11 months ago

To open a PR, you will first need to fork the project and then push your changes to the new forked repo. Once done, you can open a PR by referencing your forked repo and branch.

quirell commented 11 months ago

https://github.com/go-jet/jet/pull/259 Opened a PR. Let me know if you feel like something is missing. If everything looks good I'd be grateful if you could release a new version with this small feature.

go-jet commented 11 months ago

You can already use this feature without releasing a new official version by just referencing this new commit:

go get github.com/go-jet/jet/v2@3333358
yofriadi commented 4 months ago

for future readers, I achieve it with this template to singular my struct name

// to convert snake_case to PascalCase
import "github.com/iancoleman/strcase"

// add this option to Generate function template arg
template.Default(pg.Dialect).
    UseSchema(func(schemaMetaData metadata.Schema) template.Schema {
        return template.DefaultSchema(schemaMetaData).
            UseSQLBuilder(template.DefaultSQLBuilder().
                UseTable(func(table metadata.Table) template.TableSQLBuilder {
                    return template.DefaultTableSQLBuilder(table).
                        UseInstanceName(strcase.ToCamel(strings.TrimRight(table.Name, "s"))).
                }))
    })
geokat commented 2 months ago

For future readers who have their table names in plural and want their generated models in singular:

import "github.com/iancoleman/strcase"

...
template.Default(postgres2.Dialect).
    UseSchema(func(schemaMetaData metadata.Schema) template.Schema {
        return template.DefaultSchema(schemaMetaData).
            // https://github.com/go-jet/jet/issues/256
            UseModel(template.DefaultModel().
                UseTable(func(table metadata.Table) template.TableModel {
                    return template.DefaultTableModel(table).
                        UseTypeName(strcase.ToCamel(strings.TrimRight(table.Name, "s")))
                }),
            ).
            // This is required for scanning to work:
            // https://github.com/go-jet/jet/issues/330
            UseSQLBuilder(template.DefaultSQLBuilder().
                UseTable(func(table metadata.Table) template.TableSQLBuilder {
                    return template.DefaultTableSQLBuilder(table).
                        UseDefaultAlias(strcase.ToCamel(strings.TrimRight(table.Name, "s")))
                }),
            )
    }),
...

Note: strings.TrimRight(table.Name, "s") won't do the job well enough if any of the table names are irregular plural names (e.g. replies, diagnoses).