feat: add StrictFieldMapping config

This commit is contained in:
k4n4ry 2025-12-29 23:27:27 +09:00
parent adef2f9b1a
commit f33c2ee357
4 changed files with 219 additions and 9 deletions

View file

@ -20,6 +20,8 @@ type ScanContext struct {
typesVisited typeStack // to prevent circular dependency scan
columnAlias []string
columnIndexRead []bool
unmappedFields []string
}
// NewScanContext creates new ScanContext from rows
@ -79,6 +81,33 @@ func (s *ScanContext) EnsureEveryColumnRead() {
}
}
func (s *ScanContext) recordUnmappedField(structType reflect.Type, parentField *reflect.StructField, field reflect.StructField) {
// skip private/unsettable fields (those are ignored by mapRowToStruct anyway)
if field.PkgPath != "" {
return
}
// NOTE: For unnamed/anonymous structs, Name() is empty, so String() is used for readability/uniqueness.
typeName := structType.String()
if structType.Name() != "" {
typeName = structType.Name()
}
fieldIdent := fmt.Sprintf("%s.%s", typeName, field.Name)
if parentField != nil {
fieldIdent = fmt.Sprintf("%s.%s.%s", typeName, parentField.Name, field.Name)
}
s.unmappedFields = append(s.unmappedFields, fmt.Sprintf("'%s'", fieldIdent))
}
func (s *ScanContext) EnsureEveryFieldMapped() {
if len(s.unmappedFields) == 0 {
return
}
panic("jet: fields never mapped: " + strings.Join(s.unmappedFields, ", "))
}
func createScanSlice(columnCount int) []interface{} {
scanPtrSlice := make([]interface{}, columnCount)
@ -144,6 +173,10 @@ func (s *ScanContext) getTypeInfo(structType reflect.Type, parentField *reflect.
fieldMap.Type = simpleType
}
if GlobalConfig.StrictFieldMapping && fieldMap.rowIndex == -1 && fieldMap.Type != complexType {
s.recordUnmappedField(structType, parentField, field)
}
newTypeInfo.fieldMappings = append(newTypeInfo.fieldMappings, fieldMap)
}