( t reflect.Type, fldDescs []pgconn.FieldDescription, )
| 712 | } |
| 713 | |
| 714 | func lookupNamedStructFields( |
| 715 | t reflect.Type, |
| 716 | fldDescs []pgconn.FieldDescription, |
| 717 | ) (*namedStructFields, error) { |
| 718 | key := namedStructFieldsKey{ |
| 719 | t: t, |
| 720 | colNames: joinFieldNames(fldDescs), |
| 721 | } |
| 722 | if cached, ok := namedStructFieldMap.Load(key); ok { |
| 723 | return cached.(*namedStructFields), nil |
| 724 | } |
| 725 | |
| 726 | // We could probably do two-levels of caching, where we compute the key -> fields mapping |
| 727 | // for a type only once, cache it by type, then use that to compute the column -> fields |
| 728 | // mapping for a given set of columns. |
| 729 | fieldStack := make([]int, 0, 1) |
| 730 | fields, missingField := computeNamedStructFields( |
| 731 | fldDescs, |
| 732 | t, |
| 733 | make([]structRowField, len(fldDescs)), |
| 734 | &fieldStack, |
| 735 | ) |
| 736 | for i, f := range fields { |
| 737 | if f.path == nil { |
| 738 | return nil, fmt.Errorf( |
| 739 | "struct doesn't have corresponding row field %s", |
| 740 | fldDescs[i].Name, |
| 741 | ) |
| 742 | } |
| 743 | } |
| 744 | |
| 745 | fieldsIface, _ := namedStructFieldMap.LoadOrStore( |
| 746 | key, |
| 747 | &namedStructFields{fields: fields, missingField: missingField}, |
| 748 | ) |
| 749 | return fieldsIface.(*namedStructFields), nil |
| 750 | } |
| 751 | |
| 752 | func joinFieldNames(fldDescs []pgconn.FieldDescription) string { |
| 753 | switch len(fldDescs) { |
no test coverage detected