scanAll scans all rows into a destination, which must be a slice of any type. It resets the slice length to zero before appending each element to the slice. If the destination slice type is a Struct, then StructScan will be used on each row. If the destination is some other kind of base type, the
(rows rowsi, dest interface{}, structOnly bool)
| 897 | // this is the only way to not duplicate reflect work in the new API while |
| 898 | // maintaining backwards compatibility. |
| 899 | func scanAll(rows rowsi, dest interface{}, structOnly bool) error { |
| 900 | var v, vp reflect.Value |
| 901 | |
| 902 | value := reflect.ValueOf(dest) |
| 903 | |
| 904 | // json.Unmarshal returns errors for these |
| 905 | if value.Kind() != reflect.Ptr { |
| 906 | return errors.New("must pass a pointer, not a value, to StructScan destination") |
| 907 | } |
| 908 | if value.IsNil() { |
| 909 | return errors.New("nil pointer passed to StructScan destination") |
| 910 | } |
| 911 | direct := reflect.Indirect(value) |
| 912 | |
| 913 | slice, err := baseType(value.Type(), reflect.Slice) |
| 914 | if err != nil { |
| 915 | return err |
| 916 | } |
| 917 | direct.SetLen(0) |
| 918 | |
| 919 | isPtr := slice.Elem().Kind() == reflect.Ptr |
| 920 | base := reflectx.Deref(slice.Elem()) |
| 921 | scannable := isScannable(base) |
| 922 | |
| 923 | if structOnly && scannable { |
| 924 | return structOnlyError(base) |
| 925 | } |
| 926 | |
| 927 | columns, err := rows.Columns() |
| 928 | if err != nil { |
| 929 | return err |
| 930 | } |
| 931 | |
| 932 | // if it's a base type make sure it only has 1 column; if not return an error |
| 933 | if scannable && len(columns) > 1 { |
| 934 | return fmt.Errorf("non-struct dest type %s with >1 columns (%d)", base.Kind(), len(columns)) |
| 935 | } |
| 936 | |
| 937 | if !scannable { |
| 938 | var values []interface{} |
| 939 | var m *reflectx.Mapper |
| 940 | |
| 941 | switch rows := rows.(type) { |
| 942 | case *Rows: |
| 943 | m = rows.Mapper |
| 944 | default: |
| 945 | m = mapper() |
| 946 | } |
| 947 | |
| 948 | fields := m.TraversalsByName(base, columns) |
| 949 | // if we are not unsafe and are missing fields, return an error |
| 950 | if f, err := missingFields(fields); err != nil && !isUnsafe(rows) { |
| 951 | return fmt.Errorf("missing destination name %s in %T", columns[f], dest) |
| 952 | } |
| 953 | values = make([]interface{}, len(columns)) |
| 954 | |
| 955 | for rows.Next() { |
| 956 | // create a new struct type (which returns PtrTo) and indirect it |