Skip to content

Commit e8a2522

Browse files
committed
Merge branch 'fix-duplicate-rows' of github.com:hackafterdark/carta into fix-duplicate-rows
2 parents 62bb4de + d20e33d commit e8a2522

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

column.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@ type column struct {
1515
i fieldIndex
1616
}
1717

18+
// allocateColumns maps result set columns into the given Mapper's fields and its sub-mappers.
19+
// It populates m.PresentColumns and m.SortedColumnIndexes, sets AncestorNames on sub-maps,
20+
// and removes claimed entries from the provided columns map.
21+
//
22+
// For a mapper marked IsBasic, the function requires exactly one remaining column in
23+
// columns and binds that single column to the mapper; otherwise it returns an error.
24+
// For non-basic mappers, it matches basic fields by name using getColumnNameCandidates
25+
// (honoring the mapper/sub-map delimiter and ancestor names) and records each matched
26+
// column (including the field index). After collecting direct-field mappings it sorts
27+
// the resulting column indexes for m.SortedColumnIndexes and then recursively allocates
28+
// columns for each sub-map.
29+
//
30+
// The function mutates the Mapper structures and the input columns map. It returns any
31+
// error returned by recursive allocation or an error when the IsBasic column constraint
32+
// is violated.
1833
func allocateColumns(m *Mapper, columns map[string]column) error {
1934
presentColumns := map[string]column{}
2035
if m.IsBasic {

load.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,18 @@ func (m *Mapper) loadRows(rows *sql.Rows, colTyps []*sql.ColumnType) (*resolver,
5757
//
5858
// for example, if a blog has many Authors
5959
//
60-
// rows are actually []*Cell, theu are passed here as interface since sql scan requires []interface{}
60+
// loadRow maps a single scanned SQL row into the resolver using the provided Mapper.
61+
//
62+
// It creates or reuses an element in rsv based on a computed unique id:
63+
// - For basic mappers (m.IsBasic) the id is "row-<rowCount>" (ensures per-row identity).
64+
// - For non-basic mappers the id is derived from the row values via getUniqueId.
65+
//
66+
// The function expects row to contain the scanned values as []*value.Cell (passed as []interface{} because sql.Scan requires that shape).
67+
// For each present column it converts the corresponding Cell into the destination field (handling pointers, nullable types, basic primitives, and known struct wrappers such as Time, NullBool, NullString, etc.).
68+
// If a column is NULL, loadRow enforces that the destination is either a pointer or a type listed in value.NullableTypes; otherwise it returns an error.
69+
// After populating the element it initializes per-submap resolvers (if any) and recursively calls loadRow for each non-nil subMap, passing the same rowCount.
70+
//
71+
// Returns an error on conversion failures, attempts to load null into non-nullable destinations, or on any recursive loadRow error.
6172
func loadRow(m *Mapper, row []interface{}, rsv *resolver, rowCount int) error {
6273
var (
6374
err error

0 commit comments

Comments
 (0)