database/gdb: When using pbentity in issue scan, if cache is used, timestamppb.Time conversion will report an error
Go version
go version go1.22.3 darwin/amd64
GoFrame version
v2.7.1
Can this bug be reproduced with the latest release?
Option Yes
What did you do?
pbentity.Blog
message Blog {
uint32 Id = 1 ; // Blog ID
string Title = 2 ; // Title
string Content = 3 ; // Content
string Nickname = 4 ; // Nickname
google.protobuf.Timestamp CreateAt = 5 ; // Created Time
google.protobuf.Timestamp UpdateAt = 6 ; // Updated Time
google.protobuf.Timestamp DeleteAt = 7 ; // Deleted Time
}
program:
var blog *pbentity.Blog
err := dao.Blog.Ctx(ctx).Cache(gdb.CacheOption{
Duration: time.Hour,
Name: "GetById",
Force: false,
}).Where(do.Blog{
Id: id,
}).Scan(&blog)
return blog, err
What did you see happen?
It is ok when not using cache, but an error will be reported when using cache:
reflect.Value.Convert: value of type *gvar.Var cannot be converted to type timestamppb.Timestamp
What did you expect to see?
The result of using cache should be the same as the result of not using cache.
Please provide the database table structures for [dao.Blog], [pbentity.Blog], and related information to facilitate the replication of bugs
@wln32 dao.Blog
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"github.com/yiqiang3344/gf-micro/example/blog/internal/dao/internal"
)
// internalBlogDao is internal type for wrapping internal DAO implements.
type internalBlogDao = *internal.BlogDao
// blogDao is the data access object for table blog.
// You can define custom methods on it to extend its functionality as you wish.
type blogDao struct {
internalBlogDao
}
var (
// Blog is globally public accessible object for table blog operations.
Blog = blogDao{
internal.NewBlogDao(),
}
)
// Fill with you ideas below.
dao.internal.blog
// ==========================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// BlogDao is the data access object for table blog.
type BlogDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns BlogColumns // columns contains all the column names of Table for convenient usage.
}
// BlogColumns defines and stores column names for table blog.
type BlogColumns struct {
Id string // Blog ID
Title string // Title
Content string // Content
Nickname string // Nickname
CreateAt string // Created Time
UpdateAt string // Updated Time
DeleteAt string // Deleted Time
}
// blogColumns holds the columns for table blog.
var blogColumns = BlogColumns{
Id: "id",
Title: "title",
Content: "content",
Nickname: "nickname",
CreateAt: "create_at",
UpdateAt: "update_at",
DeleteAt: "delete_at",
}
// NewBlogDao creates and returns a new DAO object for table data access.
func NewBlogDao() *BlogDao {
return &BlogDao{
group: "default",
table: "blog",
columns: blogColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *BlogDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *BlogDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *BlogDao) Columns() BlogColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *BlogDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *BlogDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *BlogDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}
pbentity.blog.proto
// ==========================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
syntax = "proto3";
package pbentity;
option go_package = "github.com/yiqiang3344/gf-micro/example/blog/api/pbentity";
import "google/protobuf/timestamp.proto";
message Blog {
uint32 Id = 1 ; // Blog ID
string Title = 2 ; // Title
string Content = 3 ; // Content
string Nickname = 4 ; // Nickname
google.protobuf.Timestamp CreateAt = 5 ; // Created Time
google.protobuf.Timestamp UpdateAt = 6 ; // Updated Time
google.protobuf.Timestamp DeleteAt = 7 ; // Deleted Time
}
@yiqiang3344 @wln32 Duplicated with issue https://github.com/gogf/gf/issues/3571 , I think it might be better provide a timestamp type for grpc under contrib/grpc/timestappb that implements UnmarshalValue(interface{}) error, and replace the imported google.golang.org/protobuf/types/known/timestamppb to github.com/gogf/contrib/grpc/timestamppb in CLI when generating pbentity.
Another way is to provide grpc proto and types as gtime.Time.
Hello @yiqiang3344. We like your proposal/feedback and would appreciate a contribution via a Pull Request by you or another community member. We thank you in advance for your contribution and are looking forward to reviewing it! 你好 @yiqiang3344。我们喜欢您的提案/反馈,并希望您或其他社区成员通过拉取请求做出贡献。我们提前感谢您的贡献,并期待对其进行审查。
Also related https://github.com/gogf/gf/issues/2409