diff options
Diffstat (limited to 'vendor/github.com/uptrace/bun/model_map_slice.go')
-rw-r--r-- | vendor/github.com/uptrace/bun/model_map_slice.go | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/vendor/github.com/uptrace/bun/model_map_slice.go b/vendor/github.com/uptrace/bun/model_map_slice.go new file mode 100644 index 000000000..5c6f48e44 --- /dev/null +++ b/vendor/github.com/uptrace/bun/model_map_slice.go @@ -0,0 +1,162 @@ +package bun + +import ( + "context" + "database/sql" + "errors" + "sort" + + "github.com/uptrace/bun/dialect/feature" + "github.com/uptrace/bun/schema" +) + +type mapSliceModel struct { + mapModel + dest *[]map[string]interface{} + + keys []string +} + +var _ model = (*mapSliceModel)(nil) + +func newMapSliceModel(db *DB, dest *[]map[string]interface{}) *mapSliceModel { + return &mapSliceModel{ + mapModel: mapModel{ + db: db, + }, + dest: dest, + } +} + +func (m *mapSliceModel) Value() interface{} { + return m.dest +} + +func (m *mapSliceModel) SetCap(cap int) { + if cap > 100 { + cap = 100 + } + if slice := *m.dest; len(slice) < cap { + *m.dest = make([]map[string]interface{}, 0, cap) + } +} + +func (m *mapSliceModel) ScanRows(ctx context.Context, rows *sql.Rows) (int, error) { + columns, err := rows.Columns() + if err != nil { + return 0, err + } + + m.rows = rows + m.columns = columns + dest := makeDest(m, len(columns)) + + slice := *m.dest + if len(slice) > 0 { + slice = slice[:0] + } + + var n int + + for rows.Next() { + m.m = make(map[string]interface{}, len(m.columns)) + + m.scanIndex = 0 + if err := rows.Scan(dest...); err != nil { + return 0, err + } + + slice = append(slice, m.m) + n++ + } + if err := rows.Err(); err != nil { + return 0, err + } + + *m.dest = slice + return n, nil +} + +func (m *mapSliceModel) appendColumns(fmter schema.Formatter, b []byte) (_ []byte, err error) { + if err := m.initKeys(); err != nil { + return nil, err + } + + for i, k := range m.keys { + if i > 0 { + b = append(b, ", "...) + } + b = fmter.AppendIdent(b, k) + } + + return b, nil +} + +func (m *mapSliceModel) appendValues(fmter schema.Formatter, b []byte) (_ []byte, err error) { + if err := m.initKeys(); err != nil { + return nil, err + } + slice := *m.dest + + b = append(b, "VALUES "...) + if m.db.features.Has(feature.ValuesRow) { + b = append(b, "ROW("...) + } else { + b = append(b, '(') + } + + if fmter.IsNop() { + for i := range m.keys { + if i > 0 { + b = append(b, ", "...) + } + b = append(b, '?') + } + return b, nil + } + + for i, el := range slice { + if i > 0 { + b = append(b, "), "...) + if m.db.features.Has(feature.ValuesRow) { + b = append(b, "ROW("...) + } else { + b = append(b, '(') + } + } + + for j, key := range m.keys { + if j > 0 { + b = append(b, ", "...) + } + b = fmter.Dialect().Append(fmter, b, el[key]) + } + } + + b = append(b, ')') + + return b, nil +} + +func (m *mapSliceModel) initKeys() error { + if m.keys != nil { + return nil + } + + slice := *m.dest + if len(slice) == 0 { + return errors.New("bun: map slice is empty") + } + + first := slice[0] + keys := make([]string, 0, len(first)) + + for k := range first { + keys = append(keys, k) + } + + sort.Strings(keys) + m.keys = keys + + return nil +} |