github.com/mithrandie/csvq@v1.18.1/lib/query/view_map.go (about) 1 package query 2 3 import ( 4 "context" 5 "errors" 6 "strings" 7 8 "github.com/mithrandie/csvq/lib/file" 9 "github.com/mithrandie/csvq/lib/option" 10 "github.com/mithrandie/csvq/lib/parser" 11 "github.com/mithrandie/csvq/lib/value" 12 ) 13 14 var errTableNotLoaded = errors.New("table not loaded") 15 16 type ViewMap struct { 17 *SyncMap 18 } 19 20 func NewViewMap() ViewMap { 21 return ViewMap{ 22 NewSyncMap(), 23 } 24 } 25 26 func (m ViewMap) IsEmpty() bool { 27 return m.SyncMap == nil 28 } 29 30 func (m ViewMap) Store(identifier string, view *View) { 31 m.store(identifier, view) 32 } 33 34 func (m ViewMap) LoadDirect(identifier string) (interface{}, bool) { 35 return m.load(identifier) 36 } 37 38 func (m ViewMap) Load(identifier string) (*View, bool) { 39 if v, ok := m.load(identifier); ok { 40 return v.(*View), true 41 } 42 return nil, false 43 } 44 45 func (m ViewMap) Delete(identifier string) { 46 m.delete(identifier) 47 } 48 49 func (m ViewMap) Exists(identifier string) bool { 50 return m.exists(identifier) 51 } 52 53 func (m ViewMap) Get(identifier string) (*View, error) { 54 if view, ok := m.Load(identifier); ok { 55 return view.Copy(), nil 56 } 57 return nil, errTableNotLoaded 58 } 59 60 func (m ViewMap) GetWithInternalId(ctx context.Context, identifier string, flags *option.Flags) (*View, error) { 61 if view, ok := m.Load(identifier); ok { 62 ret := view.Copy() 63 64 ret.Header = NewHeaderWithId(ret.Header[0].View, []string{}).Merge(ret.Header) 65 66 if err := NewGoroutineTaskManager(ret.RecordLen(), -1, flags.CPU).Run(ctx, func(index int) error { 67 record := make(Record, len(ret.RecordSet[index])+1) 68 record[0] = NewCell(value.NewInteger(int64(index))) 69 for i := 0; i < len(ret.RecordSet[index]); i++ { 70 record[i+1] = ret.RecordSet[index][i] 71 } 72 ret.RecordSet[index] = record 73 return nil 74 }); err != nil { 75 return nil, err 76 } 77 78 return ret, nil 79 } 80 return nil, errTableNotLoaded 81 } 82 83 func (m ViewMap) Set(view *View) { 84 if view.FileInfo != nil { 85 m.Store(view.FileInfo.IdentifiedPath(), view) 86 } 87 } 88 89 func (m ViewMap) DisposeTemporaryTable(tablePath parser.QueryExpression) bool { 90 identifier := func() string { 91 if e, ok := tablePath.(parser.Stdin); ok { 92 return e.String() 93 } 94 return strings.ToUpper(tablePath.(parser.Identifier).Literal) 95 }() 96 97 if v, ok := m.Load(identifier); ok && v.FileInfo.IsInMemoryTable() { 98 m.Delete(identifier) 99 return true 100 } 101 return false 102 } 103 104 func (m ViewMap) Dispose(container *file.Container, identifier string) error { 105 if view, ok := m.Load(identifier); ok { 106 if view.FileInfo.Handler != nil { 107 if err := container.Close(view.FileInfo.Handler); err != nil { 108 return err 109 } 110 } 111 m.Delete(identifier) 112 } 113 return nil 114 } 115 116 func (m ViewMap) Clean(container *file.Container) error { 117 keys := m.Keys() 118 for _, k := range keys { 119 if err := m.Dispose(container, k); err != nil { 120 return err 121 } 122 } 123 return nil 124 } 125 126 func (m ViewMap) CleanWithErrors(container *file.Container) error { 127 keys := m.Keys() 128 var errs []error 129 for _, k := range keys { 130 if view, ok := m.Load(k); ok { 131 if err := container.CloseWithErrors(view.FileInfo.Handler); err != nil { 132 errs = append(errs, err.(*file.ForcedUnlockError).Errors...) 133 } 134 m.Delete(k) 135 } 136 } 137 138 return file.NewForcedUnlockError(errs) 139 }