app-cloudep-trade-service/internal/model/wallet_model.go

117 lines
3.4 KiB
Go
Executable File

package model
import (
"app-cloudep-trade-service/internal/domain"
"context"
"database/sql"
"errors"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ WalletModel = (*customWalletModel)(nil)
type (
// WalletModel is an interface to be customized, add more methods here,
// and implement the added methods in customWalletModel.
WalletModel interface {
walletModel
InsertMany(ctx context.Context, wallets []*Wallet) (sql.Result, error)
Balances(ctx context.Context, req BalanceReq) ([]Wallet, error)
}
customWalletModel struct {
*defaultWalletModel
}
BalanceReq struct {
UID []string
Currency []string
Kind []domain.WalletType
}
)
// NewWalletModel returns a model for the database table.
func NewWalletModel(conn sqlx.SqlConn) WalletModel {
return &customWalletModel{
defaultWalletModel: newWalletModel(conn),
}
}
func (m *customWalletModel) InsertMany(ctx context.Context, wallets []*Wallet) (sql.Result, error) {
if len(wallets) == 0 {
return nil, fmt.Errorf("no data to insert")
}
// 構建多條記錄的佔位符,例如: (?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?), ...
valueStrings := make([]string, 0, len(wallets))
valueArgs := make([]interface{}, 0, len(wallets)*7) // 每條記錄有7個值
for _, wallet := range wallets {
valueStrings = append(valueStrings, "(?, ?, ?, ?, ?, ?, ?)")
valueArgs = append(valueArgs, wallet.Uid, wallet.Brand, wallet.Currency, wallet.Balance, wallet.WalletType, wallet.CreatedAt, wallet.UpdatedAt)
}
// 構建批量插入的 SQL 語句
query := fmt.Sprintf("insert into %s (%s) values %s", m.table, walletRowsExpectAutoSet, strings.Join(valueStrings, ","))
// 使用單一連線執行批量插入
return m.conn.ExecCtx(ctx, query, valueArgs...)
}
func (m *customWalletModel) Balances(ctx context.Context, req BalanceReq) ([]Wallet, error) {
var data []Wallet
query := fmt.Sprintf("select 'id', 'uid', 'currency', 'balance', 'type', 'update_time' from %s", m.table)
var conditions []string
var args []any
// 根據條件動態拼接 WHERE 子句
if len(req.UID) > 0 {
placeholders := strings.Repeat("?,", len(req.UID))
placeholders = placeholders[:len(placeholders)-1] // 移除最後一個逗號
conditions = append(conditions, fmt.Sprintf("uid IN (%s)", placeholders))
args = append(args, convertSliceToInterface(req.UID)...)
}
if len(req.Currency) > 0 {
placeholders := strings.Repeat("?,", len(req.Currency))
placeholders = placeholders[:len(placeholders)-1]
conditions = append(conditions, fmt.Sprintf("currency IN (%s)", placeholders))
args = append(args, convertSliceToInterface(req.Currency)...)
}
if len(req.Kind) > 0 {
placeholders := strings.Repeat("?,", len(req.Kind))
placeholders = placeholders[:len(placeholders)-1]
conditions = append(conditions, fmt.Sprintf("type IN (%s)", placeholders))
args = append(args, convertSliceToInterface(req.Kind)...)
}
// 如果有條件,則拼接 WHERE 子句
if len(conditions) > 0 {
query += " WHERE " + strings.Join(conditions, " AND ")
}
// 執行查詢
err := m.conn.QueryRowCtx(ctx, &data, query, args...)
switch {
case err == nil:
return data, nil
case errors.Is(err, sqlc.ErrNotFound):
return nil, ErrNotFound
default:
return nil, err
}
}
func convertSliceToInterface[T any](slice []T) []any {
interfaces := make([]any, 0, len(slice))
for i, v := range slice {
interfaces[i] = v
}
return interfaces
}