5

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, e.g.:

-- 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?

0

1 Answer 1

0

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.