advsql/types.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
}