“ non-Value type UserRowStatus returned from Value”的错误处理

前言

在执行数据库插入语句的时候,返回错误语句“ non-Value type UserRowStatus returned from Value”。在网络上查询大量资料后发现,目前对于此错误的记录比较少,特此分析该错误情况和分析过程

背景

mysql version:mysql Ver 14.14 Distrib 5.7.41, for Linux (x86_64) using EditLine wrapper
go version:go1.19.3 darwin/arm64
sqlc version:v1.16.0
sql driver version:github.com/go-sql-driver/mysql v1.7.1

本项目使用sqlc工具包,根据SQL语句,自动生成惯用的数据库操作代码
sqlc工具包链接:https://sqlc.dev

环境说明

数据库创建语句

CREATE TABLE `user`
(
    `id`            int PRIMARY KEY AUTO_INCREMENT,
    `created_ts`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_ts`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `row_status`    ENUM ('NORMAL', 'ARCHIVED') NOT NULL DEFAULT "NORMAL",
    `role`          ENUM ('HOST', 'ADMIN', 'USER') NOT NULL DEFAULT "USER",
    `username`      varchar(255) UNIQUE NOT NULL,
    `email`         varchar(255)        NOT NULL DEFAULT "",
    `nickname`      varchar(255)        NOT NULL DEFAULT "",
    `password_hash` varchar(255)        NOT NULL DEFAULT "",
    `open_id`       varchar(255) UNIQUE NOT NULL,
    `avatar_url`    varchar(255)        NOT NULL DEFAULT ""
);

数据库操作语句(sqlc根据操作语句,自动生成数据库操作代码)

-- name: PatchUser :exec
UPDATE user
SET updated_ts    = COALESCE(sqlc.narg(updated_ts), updated_ts),
    row_status    = COALESCE(sqlc.narg(row_status), row_status),
    username      = COALESCE(sqlc.narg(username), username),
    email         = COALESCE(sqlc.narg(email), email),
    nickname      = COALESCE(sqlc.narg(nickname), nickname),
    avatar_url    = COALESCE(sqlc.narg(avatar_url), avatar_url),
    password_hash = COALESCE(sqlc.narg(password_hash), password_hash),
    open_id       = COALESCE(sqlc.narg(open_id), open_id)
WHERE id = ?;

数据库操作代码(该代码由sqlc自动生成)

PatchUser:更新用户信息的数据库操作函数
PatchUserParams:更新用户信息的参数
NullUserRowStatus:更新用户信息中UserRowStatus枚举数据类型

type NullUserRowStatus struct {
	UserRowStatus UserRowStatus
	Valid         bool // Valid is true if UserRowStatus is not NULL
}

type PatchUserParams struct {
	UpdatedTs    sql.NullTime
	RowStatus    NullUserRowStatus
	Username     sql.NullString
	Email        sql.NullString
	Nickname     sql.NullString
	AvatarUrl    sql.NullString
	PasswordHash sql.NullString
	OpenID       sql.NullString
	ID           int32
}

func (q *Queries) PatchUser(ctx context.Context, arg PatchUserParams) error {
	_, err := q.db.ExecContext(ctx, patchUser,
		arg.UpdatedTs,
		arg.RowStatus,
		arg.Username,
		arg.Email,
		arg.Nickname,
		arg.AvatarUrl,
		arg.PasswordHash,
		arg.OpenID,
		arg.ID,
	)
	return err
}

问题分析

  1. 错误语句“ non-Value type UserRowStatus returned from Value”是在sql driver中打印出来的错误语句,所以我们需要去sql driver中寻找错误的出处

  2. 找到错误语句的出处,并分析上下环境。发现问题出现在IsValue函数的返回值上
    在这里插入图片描述

  3. 深入解析IsValue函数
    sql driver只支持六种数据类型:[]byte, bool, float64, int64, string, time.Time
    显然UserRowStatus不在其中,所有返回错误
    在这里插入图片描述

问题总结

由于在数据库创建语句中定义了枚举类型,然后sqlc生成数据库操作函数代码的时候,定义了新的结构体UserRowStatus来实现枚举。然而数据库操作中又不支持UserRowStatus的数据类型操作,所以返回错误语句“ non-Value type UserRowStatus returned from Value”

**接下来,**为了继续使用sqlc工具包(主要是因为快捷好用,不用自己去苦逼得写数据库操作函数),只能将数据库建表语句中的枚举类型去掉,改成从数据库操作函数层对数据内容进行约束

在网上也找到一个类似的案例:https://www.coder.work/article/210950

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值