package orm import ( "reflect" ) // Model - an intermediate representation of a Go struct type Model struct { Name string // the name, almost always the name of the underlying Type Type reflect.Type // the Go type this model represents Relationships map[string]*Relationship // a mapping of struct field names to Relationship pointers IDField string // the name of the field containing this model's ID Fields map[string]*Field // mapping of struct field names to Field pointers FieldsByColumnName map[string]*Field // mapping of database column names to Field pointers TableName string // the name of the table where this model's data is stored. defaults to a snake_cased version of the type/struct name if not provided explicitly via tag embeddedIsh bool // INTERNAL - whether this model is: 1) contained in another type and 2) wasn't explicitly passed to the `Models` method (i.e., it can't "exist" on its own) } func (m *Model) addField(field *Field) { field.Model = m m.Fields[field.Name] = field m.FieldsByColumnName[field.ColumnName] = field } const ( documentField = "Document" createdField = "Created" modifiedField = "Modified" ) func (m *Model) docField() *Field { return m.Fields[documentField] } func (m *Model) idField() *Field { return m.Fields[m.IDField] } func (m *Model) getPrimaryKey(val reflect.Value) (string, any) { colField := m.Fields[m.IDField] if colField == nil { return "", nil } colName := colField.ColumnName wasPtr := false if val.Kind() == reflect.Ptr { if val.IsNil() { return "", nil } val = val.Elem() wasPtr = true } if val.IsZero() && wasPtr { return "", nil } idField := val.FieldByName(m.IDField) if idField.IsValid() { return colName, idField.Interface() } return "", nil } func (m *Model) needsPrimaryKey(val reflect.Value) bool { _, pk := m.getPrimaryKey(val) return pk == nil || reflect.ValueOf(pk).IsZero() }