95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
|
package advsql
|
||
|
|
||
|
import (
|
||
|
"log"
|
||
|
"reflect"
|
||
|
)
|
||
|
|
||
|
type structure struct {
|
||
|
TypeName string
|
||
|
Fields []field
|
||
|
}
|
||
|
|
||
|
type field struct {
|
||
|
FieldName string
|
||
|
FieldType reflect.Type
|
||
|
}
|
||
|
|
||
|
func makeFieldUsingReflect(reflectField reflect.StructField) field {
|
||
|
return field{
|
||
|
FieldName: reflectField.Name,
|
||
|
FieldType: reflectField.Type,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func compareStructures(first, second *structure) bool {
|
||
|
// compare names
|
||
|
if first.TypeName != second.TypeName {
|
||
|
log.Println("different names")
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
firstFieldAmount, secondFieldAmount := len(first.Fields), len(second.Fields)
|
||
|
|
||
|
// compare field amounts
|
||
|
if firstFieldAmount != secondFieldAmount {
|
||
|
log.Println("different field amounts")
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// compare fields
|
||
|
for i := 0; i < firstFieldAmount; i++ {
|
||
|
firstField, secondField := first.Fields[i], second.Fields[i]
|
||
|
if !compareFields(firstField, secondField) {
|
||
|
log.Println("different field:", firstField, secondField)
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func compareFields(first, second field) bool {
|
||
|
t1, t2 := first.FieldType, second.FieldType
|
||
|
|
||
|
// check if field names are equal
|
||
|
fieldNamesEqual := first.FieldName == second.FieldName
|
||
|
|
||
|
// exceptions for default comparison
|
||
|
switch true {
|
||
|
case checkBoth(first, second, isString, isByteSlice):
|
||
|
fallthrough
|
||
|
case isInt(first) && isInt(second):
|
||
|
fallthrough
|
||
|
case isUint(first) && isUint(second):
|
||
|
return fieldNamesEqual
|
||
|
|
||
|
default:
|
||
|
return t1 == t2
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TypeCheckFunc represents any function for type checking between Go and DB
|
||
|
type TypeCheckFunc func(field) bool
|
||
|
|
||
|
// checks if both check functions apply to either of the fields
|
||
|
func checkBoth(first, second field, firstCheck, secondCheck TypeCheckFunc) bool {
|
||
|
return firstCheck(first) && secondCheck(second) || firstCheck(second) && secondCheck(first)
|
||
|
}
|
||
|
|
||
|
func isString(field field) bool {
|
||
|
return field.FieldType.Kind() == reflect.String
|
||
|
}
|
||
|
|
||
|
func isInt(field field) bool {
|
||
|
return field.FieldType.Kind() == reflect.Int || field.FieldType.Kind() == reflect.Int64
|
||
|
}
|
||
|
|
||
|
func isUint(field field) bool {
|
||
|
return field.FieldType.Kind() == reflect.Uint || field.FieldType.Kind() == reflect.Uint64
|
||
|
}
|
||
|
|
||
|
func isByteSlice(field field) bool {
|
||
|
return field.FieldType.Kind() == reflect.Slice && field.FieldType.Elem().Kind() == reflect.Uint8
|
||
|
}
|