Bind sets "dst" to the result of "src" and reports any errors.
(dst interface{}, src *sql.Rows)
| 113 | |
| 114 | // Bind sets "dst" to the result of "src" and reports any errors. |
| 115 | func (s *Schema) Bind(dst interface{}, src *sql.Rows) error { |
| 116 | typ := reflect.TypeOf(dst) |
| 117 | if typ.Kind() != reflect.Ptr { |
| 118 | return fmt.Errorf("sqlx: bind: destination not a pointer") |
| 119 | } |
| 120 | |
| 121 | typ = typ.Elem() |
| 122 | |
| 123 | originalKind := typ.Kind() |
| 124 | if typ.Kind() == reflect.Slice { |
| 125 | typ = typ.Elem() |
| 126 | } |
| 127 | |
| 128 | r, ok := s.Rows[typ] |
| 129 | if !ok { |
| 130 | return fmt.Errorf("sqlx: bind: unregistered type: %q", typ.String()) |
| 131 | } |
| 132 | |
| 133 | columnTypes, err := src.ColumnTypes() |
| 134 | if err != nil { |
| 135 | return fmt.Errorf("sqlx: bind: table: %q: %w", r.Name, err) |
| 136 | } |
| 137 | |
| 138 | if expected, got := len(r.Columns), len(columnTypes); expected != got { |
| 139 | return fmt.Errorf("sqlx: bind: table: %q: unexpected number of result columns: %d: expected: %d", r.Name, got, expected) |
| 140 | } |
| 141 | |
| 142 | val := reflex.IndirectValue(reflect.ValueOf(dst)) |
| 143 | if s.AutoCloseRows { |
| 144 | defer src.Close() |
| 145 | } |
| 146 | |
| 147 | switch originalKind { |
| 148 | case reflect.Struct: |
| 149 | if src.Next() { |
| 150 | if err = r.bindSingle(typ, val, columnTypes, src); err != nil { |
| 151 | return err |
| 152 | } |
| 153 | } else { |
| 154 | return sql.ErrNoRows |
| 155 | } |
| 156 | |
| 157 | return src.Err() |
| 158 | case reflect.Slice: |
| 159 | for src.Next() { |
| 160 | elem := reflect.New(typ).Elem() |
| 161 | if err = r.bindSingle(typ, elem, columnTypes, src); err != nil { |
| 162 | return err |
| 163 | } |
| 164 | |
| 165 | val = reflect.Append(val, elem) |
| 166 | } |
| 167 | |
| 168 | if err = src.Err(); err != nil { |
| 169 | return err |
| 170 | } |
| 171 | |
| 172 | reflect.ValueOf(dst).Elem().Set(val) |