database/option.go

511 lines
12 KiB
Go

// Package database ...
//
// Description : mysql ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022-05-15 11:43
package database
import (
"encoding/json"
"git.zhangdeman.cn/zhangdeman/op_type"
"reflect"
"strings"
)
// SetOption 设置选项
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:46 2022/5/15
type SetOption func(o *Option)
// Option 扩展选项
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:05 下午 2021/8/8
type Option struct {
Model any `json:"-"` // 操作model
Table string `json:"table"` // 查询的数据表
Limit int `json:"limit"` // 限制数量
Offset int `json:"offset"` // 偏移量
In map[string]any `json:"in"` // in语句
NotIn map[string]any `json:"not_in"` // not in语句
Where map[string]any `json:"where"` // where 条件
Start map[string]any `json:"start"` // >= 条件
End map[string]any `json:"end"` // < 条件
Like map[string]string `json:"like"` // like 语句
NotLike map[string]string `json:"not_like"` // not like 语句
NotEqual map[string]any `json:"not_equal"` // != 语句
Order []string `json:"order"` // 排序规则
OR [][]SetOption `json:"or"` // or 语句, or 和其他属性 and 关系, 内部 OR 关系
}
// WithModel ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:18 2024/1/15
func WithModel(model any) SetOption {
return func(o *Option) {
o.Model = model
}
}
// WithTable 设置查询的表名
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:56 2023/3/22
func WithTable(tableName string) SetOption {
return func(o *Option) {
o.Table = tableName
}
}
// WithWhere 设置where条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:17 2022/5/15
func WithWhere[T op_type.BaseType](where map[string]T) SetOption {
return func(o *Option) {
if nil == o.Where {
o.Where = make(map[string]any)
}
for field, value := range where {
o.Where[field] = value
}
}
}
// WithLimit 设置limit条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:00 2022/5/15
func WithLimit[T op_type.Int](limit T, offset T) SetOption {
return func(o *Option) {
o.Limit = int(limit)
o.Offset = int(offset)
}
}
// WithLimitByPageAndSize 通过page和size构建条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:42 2023/10/14
func WithLimitByPageAndSize[T op_type.Int](page T, size T) SetOption {
return func(o *Option) {
if size > 0 {
o.Limit = int(size)
}
if page <= 0 {
page = 1
}
o.Offset = int((page - 1) * size)
}
}
// WithIn 设置in条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:23 2022/5/15
func WithIn[T op_type.Array](field string, value T) SetOption {
return func(o *Option) {
if nil == value {
return
}
if len(value) == 0 {
return
}
if nil == o.In {
o.In = make(map[string]any)
}
o.In[field] = value
}
}
// WithBatchIn ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:24 2022/5/15
func WithBatchIn[T op_type.Array](batchIn map[string]T) SetOption {
return func(o *Option) {
if nil == o.In {
o.In = make(map[string]any)
}
for field, value := range batchIn {
WithIn(field, value)
}
}
}
// WithNotIn 设置 notin 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:18 2022/5/15
func WithNotIn[T op_type.Array](field string, value T) SetOption {
return func(o *Option) {
if nil == o.NotIn {
o.NotIn = make(map[string]any)
}
if value == nil || len(value) == 0 {
return
}
o.NotIn[field] = value
}
}
// WithBatchNotIn 批量设置 NOT IN
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:23 2022/5/15
func WithBatchNotIn[T op_type.Array](data map[string]T) SetOption {
return func(o *Option) {
if nil == o.NotIn {
o.NotIn = make(map[string]any)
}
for field, value := range data {
if value == nil || len(value) == 0 {
continue
}
o.NotIn[field] = value
}
}
}
// WithStart >= 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:01 2022/5/15
func WithStart(field string, value any) SetOption {
return func(o *Option) {
if nil == o.Start {
o.Start = make(map[string]any)
}
o.Start[field] = value
}
}
// WithBatchStart 批量设置起始条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:03 2022/5/15
func WithBatchStart(data map[string]any) SetOption {
return func(o *Option) {
if nil == o.Start {
o.Start = make(map[string]any)
}
for field, value := range data {
o.Start[field] = value
}
}
}
// WithEnd 设置 < 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:07 2022/5/15
func WithEnd(field string, value any) SetOption {
return func(o *Option) {
if nil == o.End {
o.End = make(map[string]any)
}
o.End[field] = value
}
}
// WithBatchEnd 批量设置 < 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:10 2022/5/15
func WithBatchEnd(data map[string]any) SetOption {
return func(o *Option) {
if nil == o.End {
o.End = make(map[string]any)
}
for field, value := range data {
o.End[field] = value
}
}
}
// WithLike 设置 like 查询条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:16 2022/5/15
func WithLike(field string, value string) SetOption {
return func(o *Option) {
if nil == o.Like {
o.Like = make(map[string]string)
}
if len(value) == 0 {
return
}
o.Like[field] = value
}
}
// WithBatchLike 批量设置like条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:19 2022/5/15
func WithBatchLike(data map[string]string) SetOption {
return func(o *Option) {
if nil == o.Like {
o.Like = make(map[string]string)
}
for field, value := range data {
if len(value) == 0 {
continue
}
o.Like[field] = value
}
}
}
// WithNotLike NOT LIKE 语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:50 2022/5/15
func WithNotLike(field string, value string) SetOption {
return func(o *Option) {
if nil == o.NotLike {
o.NotLike = make(map[string]string)
}
if len(value) == 0 {
return
}
o.NotLike[field] = value
}
}
// WithBatchNotLike ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:52 2022/5/15
func WithBatchNotLike(data map[string]string) SetOption {
return func(o *Option) {
if nil == o.NotLike {
o.NotLike = make(map[string]string)
}
for field, value := range data {
if len(value) == 0 {
continue
}
o.NotLike[field] = value
}
}
}
// WithNotEqual 设置不等于语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:31 2022/5/15
func WithNotEqual[T op_type.BaseType](field string, value T) SetOption {
return func(o *Option) {
if nil == o.NotEqual {
o.NotEqual = make(map[string]any)
}
o.NotEqual[field] = value
}
}
// WithBatchNotEqual 批量设置不等于条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:33 2022/5/15
func WithBatchNotEqual[T op_type.BaseType](data map[string]T) SetOption {
return func(o *Option) {
if nil == o.NotEqual {
o.NotEqual = make(map[string]any)
}
for field, value := range data {
o.NotEqual[field] = value
}
}
}
// WithOR 设置OR语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:03 2022/7/23
func WithOR(orConditionList ...SetOption) SetOption {
return func(o *Option) {
if nil == o.OR {
o.OR = make([][]SetOption, 0)
}
o.OR = append(o.OR, orConditionList)
}
}
// WithOrder 设置排序规则
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:15 2022/10/20
func WithOrder(orderRuleList ...string) SetOption {
return func(o *Option) {
o.Order = orderRuleList
}
}
// WithOrderDesc 降序排序
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:09 2023/4/3
func WithOrderDesc(field string) SetOption {
return func(o *Option) {
if nil == o.Order {
o.Order = make([]string, 0)
}
o.Order = append(o.Order, field+" desc")
}
}
// WithOrderAsc 升序排序
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:09 2023/4/3
func WithOrderAsc(field string) SetOption {
return func(o *Option) {
if nil == o.Order {
o.Order = make([]string, 0)
}
o.Order = append(o.Order, field+" asc")
}
}
// newOption 生成新的option
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:46 2024/8/9
func newOption(setOptionList ...SetOption) *Option {
o := &Option{}
for _, item := range setOptionList {
item(o)
}
return o
}
// optionToSql 基于 option 配置生成sql
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:46 2024/8/9
func optionToSql(o *Option) (sqlBuildResult string, bindValue []any) {
bindValue = make([]any, 0)
sqlBuildResultBlockList := make([]string, 0)
// 设置where条件
for fieldName, fieldValue := range o.Where {
if nil == fieldValue {
continue
}
if reflect.TypeOf(fieldValue).Kind() == reflect.Slice {
// 传入数组, in语句
placeholder, dataList := parseInSql(fieldValue)
sqlBuildResultBlockList = append(sqlBuildResultBlockList, "`"+fieldName+"` IN ("+placeholder+")")
bindValue = append(bindValue, dataList...)
} else {
sqlBuildResultBlockList = append(sqlBuildResultBlockList, "`"+fieldName+"` = ?")
bindValue = append(bindValue, fieldValue)
}
}
// 设置不等于
for fieldName, fieldValue := range o.NotEqual {
sqlBuildResultBlockList = append(sqlBuildResultBlockList, "`"+fieldName+"` != ?")
bindValue = append(bindValue, fieldValue)
}
// in 语句
// 传入数组, in语句
for fieldName, fieldValue := range o.In {
placeholder, dataList := parseInSql(fieldValue)
sqlBuildResultBlockList = append(sqlBuildResultBlockList, "`"+fieldName+"` IN ("+placeholder+")")
bindValue = append(bindValue, dataList...)
}
// not in 语句
for fieldName, fieldValue := range o.NotIn {
placeholder, dataList := parseInSql(fieldValue)
sqlBuildResultBlockList = append(sqlBuildResultBlockList, "`"+fieldName+"` NOT IN ("+placeholder+")")
bindValue = append(bindValue, dataList...)
}
// like 语句
for fieldName, fieldValue := range o.Like {
if len(fieldValue) == 0 {
continue
}
sqlBuildResultBlockList = append(sqlBuildResultBlockList, "`"+fieldName+"` LIKE \"%?%\"")
bindValue = append(bindValue, fieldValue)
}
// NOT LIKE 语句
for fieldName, fieldValue := range o.NotLike {
if len(fieldValue) == 0 {
continue
}
sqlBuildResultBlockList = append(sqlBuildResultBlockList, "`"+fieldName+"` NOT LIKE \"%?%\"")
bindValue = append(bindValue, fieldValue)
}
// >=
for fieldName, fieldValue := range o.Start {
sqlBuildResultBlockList = append(sqlBuildResultBlockList, "`"+fieldName+"` >= ?")
bindValue = append(bindValue, fieldValue)
}
// <
for fieldName, fieldValue := range o.End {
sqlBuildResultBlockList = append(sqlBuildResultBlockList, "`"+fieldName+"` < ?")
bindValue = append(bindValue, fieldValue)
}
if len(bindValue) > 0 {
sqlBuildResult = strings.Join(sqlBuildResultBlockList, " AND ")
}
return
}
// parseInSql 解析in语句需要绑定占位符以及数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:07 2024/8/9
func parseInSql(fieldValue any) (string, []any) {
byteData, _ := json.Marshal(fieldValue)
var dataList []any
decoder := json.NewDecoder(strings.NewReader(string(byteData)))
decoder.UseNumber()
_ = decoder.Decode(&dataList)
// 生成占位符
placeholderList := make([]string, 0)
for i := 0; i < len(dataList); i++ {
placeholderList = append(placeholderList, "?")
}
return strings.Join(placeholderList, ","), dataList
}