github.com/ravendb/ravendb-go-client@v0.0.0-20240229102137-4474ee7aa0fa/load_operation.go (about) 1 package ravendb 2 3 import ( 4 "fmt" 5 "reflect" 6 "strings" 7 ) 8 9 // LoadOperation represents a load operation 10 type LoadOperation struct { 11 session *InMemoryDocumentSessionOperations 12 13 ids []string 14 includes []string 15 idsToCheckOnServer []string 16 } 17 18 func NewLoadOperation(session *InMemoryDocumentSessionOperations) *LoadOperation { 19 return &LoadOperation{ 20 session: session, 21 } 22 } 23 24 func (o *LoadOperation) createRequest() (*GetDocumentsCommand, error) { 25 if len(o.idsToCheckOnServer) == 0 { 26 return nil, nil 27 } 28 29 if o.session.checkIfIdAlreadyIncluded(o.ids, o.includes) { 30 return nil, nil 31 } 32 33 if err := o.session.incrementRequestCount(); err != nil { 34 return nil, err 35 } 36 37 return NewGetDocumentsCommand(o.idsToCheckOnServer, o.includes, false) 38 } 39 40 func (o *LoadOperation) byID(id string) *LoadOperation { 41 if id == "" { 42 return o 43 } 44 45 if o.ids == nil { 46 o.ids = []string{id} 47 } 48 49 if o.session.IsLoadedOrDeleted(id) { 50 return o 51 } 52 53 o.idsToCheckOnServer = append(o.idsToCheckOnServer, id) 54 return o 55 } 56 57 func (o *LoadOperation) withIncludes(includes []string) *LoadOperation { 58 o.includes = includes 59 return o 60 } 61 62 func (o *LoadOperation) byIds(ids []string) *LoadOperation { 63 o.ids = stringArrayCopy(ids) 64 65 seen := map[string]struct{}{} 66 for _, id := range ids { 67 if id == "" { 68 continue 69 } 70 idl := strings.ToLower(id) 71 if _, ok := seen[idl]; ok { 72 continue 73 } 74 seen[idl] = struct{}{} 75 o.byID(id) 76 } 77 return o 78 } 79 80 func (o *LoadOperation) getDocument(result interface{}) error { 81 return o.getDocumentWithID(result, o.ids[0]) 82 } 83 84 func (o *LoadOperation) getDocumentWithID(result interface{}, id string) error { 85 if id == "" { 86 // TODO: should return default value? 87 //return ErrNotFound 88 return nil 89 } 90 91 if o.session.IsDeleted(id) { 92 // TODO: return ErrDeleted? 93 //return ErrNotFound 94 return nil 95 } 96 97 doc := o.session.documentsByID.getValue(id) 98 if doc == nil { 99 doc = o.session.includedDocumentsByID[id] 100 } 101 if doc == nil { 102 //return ErrNotFound 103 return nil 104 } 105 106 return o.session.TrackEntityInDocumentInfo(result, doc) 107 } 108 109 var stringType = reflect.TypeOf("") 110 111 // TODO: also handle a pointer to a map? 112 func (o *LoadOperation) getDocuments(results interface{}) error { 113 // results must be map[string]*struct 114 //fmt.Printf("LoadOperation.getDocuments: results type: %T\n", results) 115 m := reflect.ValueOf(results) 116 if m.Type().Kind() != reflect.Map { 117 return fmt.Errorf("results should be a map[string]*struct, is %s. tp: %s", m.Type().String(), m.Type().String()) 118 } 119 mapKeyType := m.Type().Key() 120 if mapKeyType != stringType { 121 return fmt.Errorf("results should be a map[string]*struct, is %s. tp: %s", m.Type().String(), m.Type().String()) 122 } 123 mapElemPtrType := m.Type().Elem() 124 if mapElemPtrType.Kind() != reflect.Ptr { 125 return fmt.Errorf("results should be a map[string]*struct, is %s. tp: %s", m.Type().String(), m.Type().String()) 126 } 127 mapElemType := mapElemPtrType.Elem() 128 if mapElemType.Kind() != reflect.Struct { 129 return fmt.Errorf("results should be a map[string]*struct, is %s. tp: %s", m.Type().String(), m.Type().String()) 130 } 131 132 uniqueIds := stringArrayCopy(o.ids) 133 stringArrayRemove(&uniqueIds, "") 134 uniqueIds = stringArrayRemoveDuplicatesNoCase(uniqueIds) 135 for _, id := range uniqueIds { 136 v := reflect.New(mapElemPtrType).Interface() 137 err := o.getDocumentWithID(v, id) 138 if err != nil { 139 return err 140 } 141 key := reflect.ValueOf(id) 142 v2 := reflect.ValueOf(v).Elem() // convert *<type> to <type> 143 m.SetMapIndex(key, v2) 144 } 145 146 return nil 147 } 148 149 func (o *LoadOperation) setResult(result *GetDocumentsResult) { 150 if result == nil { 151 return 152 } 153 154 o.session.registerIncludes(result.Includes) 155 156 results := result.Results 157 for _, document := range results { 158 // TODO: Java also does document.isNull() 159 if document == nil { 160 continue 161 } 162 newDocumentInfo := getNewDocumentInfo(document) 163 o.session.documentsByID.add(newDocumentInfo) 164 } 165 166 o.session.registerMissingIncludes(result.Results, result.Includes, o.includes) 167 }