github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/databases/orm/db_utils.go (about)

     1  // The original package is migrated from beego and modified, you can find orignal from following link:
     2  //    "github.com/beego/beego/"
     3  //
     4  // Copyright 2023 IAC. All Rights Reserved.
     5  //
     6  // Licensed under the Apache License, Version 2.0 (the "License");
     7  // you may not use this file except in compliance with the License.
     8  // You may obtain a copy of the License at
     9  //
    10  //      http://www.apache.org/licenses/LICENSE-2.0
    11  //
    12  // Unless required by applicable law or agreed to in writing, software
    13  // distributed under the License is distributed on an "AS IS" BASIS,
    14  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15  // See the License for the specific language governing permissions and
    16  // limitations under the License.
    17  
    18  package orm
    19  
    20  import (
    21  	"fmt"
    22  	"reflect"
    23  	"time"
    24  )
    25  
    26  // get table alias.
    27  func getDbAlias(name string) *alias {
    28  	if al, ok := dataBaseCache.get(name); ok {
    29  		return al
    30  	}
    31  	panic(fmt.Errorf("unknown DataBase alias name %s", name))
    32  }
    33  
    34  // get pk column info.
    35  func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interface{}, exist bool) {
    36  	fi := mi.fields.pk
    37  
    38  	v := ind.FieldByIndex(fi.fieldIndex)
    39  	if fi.fieldType&IsPositiveIntegerField > 0 {
    40  		vu := v.Uint()
    41  		exist = vu > 0
    42  		value = vu
    43  	} else if fi.fieldType&IsIntegerField > 0 {
    44  		vu := v.Int()
    45  		exist = true
    46  		value = vu
    47  	} else if fi.fieldType&IsRelField > 0 {
    48  		_, value, exist = getExistPk(fi.relModelInfo, reflect.Indirect(v))
    49  	} else {
    50  		vu := v.String()
    51  		exist = vu != ""
    52  		value = vu
    53  	}
    54  
    55  	column = fi.column
    56  	return
    57  }
    58  
    59  // get fields description as flatted string.
    60  func getFlatParams(fi *fieldInfo, args []interface{}, tz *time.Location) (params []interface{}) {
    61  outFor:
    62  	for _, arg := range args {
    63  		if arg == nil {
    64  			params = append(params, arg)
    65  			continue
    66  		}
    67  
    68  		val := reflect.ValueOf(arg)
    69  		kind := val.Kind()
    70  		if kind == reflect.Ptr {
    71  			val = val.Elem()
    72  			kind = val.Kind()
    73  			arg = val.Interface()
    74  		}
    75  
    76  		switch kind {
    77  		case reflect.String:
    78  			v := val.String()
    79  			if fi != nil {
    80  				if fi.fieldType == TypeTimeField || fi.fieldType == TypeDateField || fi.fieldType == TypeDateTimeField {
    81  					var t time.Time
    82  					var err error
    83  					if len(v) >= 19 {
    84  						s := v[:19]
    85  						t, err = time.ParseInLocation(formatDateTime, s, DefaultTimeLoc)
    86  					} else if len(v) >= 10 {
    87  						s := v
    88  						if len(v) > 10 {
    89  							s = v[:10]
    90  						}
    91  						t, err = time.ParseInLocation(formatDate, s, tz)
    92  					} else {
    93  						s := v
    94  						if len(s) > 8 {
    95  							s = v[:8]
    96  						}
    97  						t, err = time.ParseInLocation(formatTime, s, tz)
    98  					}
    99  					if err == nil {
   100  						if fi.fieldType == TypeDateField {
   101  							v = t.In(tz).Format(formatDate)
   102  						} else if fi.fieldType == TypeDateTimeField {
   103  							v = t.In(tz).Format(formatDateTime)
   104  						} else {
   105  							v = t.In(tz).Format(formatTime)
   106  						}
   107  					}
   108  				}
   109  			}
   110  			arg = v
   111  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   112  			arg = val.Int()
   113  		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   114  			arg = val.Uint()
   115  		case reflect.Float32:
   116  			arg, _ = StrTo(ToStr(arg)).Float64()
   117  		case reflect.Float64:
   118  			arg = val.Float()
   119  		case reflect.Bool:
   120  			arg = val.Bool()
   121  		case reflect.Slice, reflect.Array:
   122  			if _, ok := arg.([]byte); ok {
   123  				continue outFor
   124  			}
   125  
   126  			var args []interface{}
   127  			for i := 0; i < val.Len(); i++ {
   128  				v := val.Index(i)
   129  
   130  				var vu interface{}
   131  				if v.CanInterface() {
   132  					vu = v.Interface()
   133  				}
   134  
   135  				if vu == nil {
   136  					continue
   137  				}
   138  
   139  				args = append(args, vu)
   140  			}
   141  
   142  			if len(args) > 0 {
   143  				p := getFlatParams(fi, args, tz)
   144  				params = append(params, p...)
   145  			}
   146  			continue outFor
   147  		case reflect.Struct:
   148  			if v, ok := arg.(time.Time); ok {
   149  				if fi != nil && fi.fieldType == TypeDateField {
   150  					arg = v.In(tz).Format(formatDate)
   151  				} else if fi != nil && fi.fieldType == TypeDateTimeField {
   152  					arg = v.In(tz).Format(formatDateTime)
   153  				} else if fi != nil && fi.fieldType == TypeTimeField {
   154  					arg = v.In(tz).Format(formatTime)
   155  				} else {
   156  					arg = v.In(tz).Format(formatDateTime)
   157  				}
   158  			} else {
   159  				typ := val.Type()
   160  				name := getFullName(typ)
   161  				var value interface{}
   162  				if mmi, ok := defaultModelCache.getByFullName(name); ok {
   163  					if _, vu, exist := getExistPk(mmi, val); exist {
   164  						value = vu
   165  					}
   166  				}
   167  				arg = value
   168  
   169  				if arg == nil {
   170  					panic(fmt.Errorf("need a valid args value, unknown table or value `%s`", name))
   171  				}
   172  			}
   173  		}
   174  
   175  		params = append(params, arg)
   176  	}
   177  	return
   178  }