简体   繁体   中英

Golang Gin Validation and SQLC

I am using SQLC to generate structures based on my schema and Gin for the web API.

After viewing this topic here: Golang how to use Validator with SqlC , I noticed the answer specifically says:

I wasn't able to change the Param structs but I guess using the table main struct use the validation.

This is exactly the behavior I am after. I noticed that if I have a query that uses a subset of a given table, eg:

-- name: CreateUserBasic :one
INSERT INTO users (
    username, email, phone
) VALUES (
    $1, $2, $3
) RETURNING *;

It yields a structure as follows:

type CreateUserBasicParams struct {
    Username string      `json:"username"`
    Email    string      `json:"email"`
    Phone    pgtype.Text `json:"phone"`
}

In my case, I even included the overrides for adding the "required" tag:

version: 2
sql:
  - engine: "postgresql"
    schema: [
      ...
    ]
    queries: [
      ...
    ]
    strict_function_checks: true
    gen:
      go:
        emit_json_tags: true
        sql_package: "pgx/v5"
        package: "hmdb"
        out: "hmdb"
        overrides:
        - db_type: users.username
          go_struct_tag: validate:"required"

But this only modifies the table struct, not any of the param structs:

type User struct {
    ID             pgtype.UUID        `json:"id"`
    Email          string             `json:"email"`
    Phone          pgtype.Text        `json:"phone"`
    Username       string             `json:"username"`
    Password       pgtype.Text        `json:"password"`
    MFAToken       pgtype.Text        `json:"mfatoken"`
    ActivationID   pgtype.UUID        `json:"activation_id"`
    ActivationCode string             `json:"activation_code"`
    CreatedAt      pgtype.Timestamptz `json:"created_at"`
    ActivatedAt    pgtype.Timestamptz `json:"activated_at"`
    Active         bool               `json:"active"`
}

Using Gin, I want to invoke the CreateUserBasic with the received data and JSON can be directly Unmashall-ed into the CreateUserBasicParams structure, but unfortunately without the decorators on the params structure, missing fields are permitted during parsing and it seems I will need to re-create a new structure with a nearly identical layout to the CreateUserBasicParams struct, only with the proper tags:

func (c *Controller) Register(ctx *gin.Context) {
    var params hmdb.CreateUserBasicParams
    if err := ctx.ShouldBindWith(&params, binding.JSON); err != nil {
        ctx.AbortWithError(http.StatusBadRequest, err)
    }
    log.Printf("Parameters:\n%+v", params)

    q := hmdb.New(c.DBPool)
    u, err := q.CreateUserBasic(ctx, params)
    if err != nil {
        ctx.AbortWithError(http.StatusBadRequest, err)
    }
    log.Printf("New User:\n%+v", u)

    ctx.JSON(http.StatusOK, gin.H{
        "message": "Good!",
    })
}

How can I best apply arbitrary validation to the SQLC-generated "Params" structures without re-creating the structure or modifying the tags?

As you are using per-column overrides, the indentation level for "overrides" should match the version line in the yaml file. For example:

version: "1"
packages:
  - name: "foo"
    path: "bar"
    . 
    .
    .
overrides:
  - column: "users.username"
    go_struct_tag: validate:"required"

Documented here - https://docs.sqlc.dev/en/stable/reference/config.html?highlight=override#per-column-type-overrides

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM