ReadRelationships reads relationships from the database taking into account the pagination.
(_ context.Context, tenantID string, filter *base.TupleFilter, _ string, pagination database.Pagination)
| 114 | |
| 115 | // ReadRelationships reads relationships from the database taking into account the pagination. |
| 116 | func (r *DataReader) ReadRelationships(_ context.Context, tenantID string, filter *base.TupleFilter, _ string, pagination database.Pagination) (collection *database.TupleCollection, ct database.EncodedContinuousToken, err error) { |
| 117 | txn := r.database.DB.Txn(false) |
| 118 | defer txn.Abort() |
| 119 | |
| 120 | var lowerBound uint64 |
| 121 | if pagination.Token() != "" { |
| 122 | var t database.ContinuousToken |
| 123 | t, err = utils.EncodedContinuousToken{Value: pagination.Token()}.Decode() |
| 124 | if err != nil { |
| 125 | return nil, database.NewNoopContinuousToken().Encode(), err |
| 126 | } |
| 127 | lowerBound, err = strconv.ParseUint(t.(utils.ContinuousToken).Value, 10, 64) |
| 128 | if err != nil { |
| 129 | return nil, database.NewNoopContinuousToken().Encode(), errors.New(base.ErrorCode_ERROR_CODE_INVALID_CONTINUOUS_TOKEN.String()) |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | index, args := utils.GetRelationTuplesIndexNameAndArgsByFilters(tenantID, filter) |
| 134 | |
| 135 | // Get the result iterator using lower bound. |
| 136 | var result memdb.ResultIterator |
| 137 | result, err = txn.LowerBound(constants.RelationTuplesTable, index, args...) // Query with lower bound |
| 138 | if err != nil { |
| 139 | return nil, database.NewNoopContinuousToken().Encode(), errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String()) |
| 140 | } |
| 141 | |
| 142 | // Filter the result iterator and add the tuples to the array. |
| 143 | tup := make([]storage.RelationTuple, 0, 10) |
| 144 | fit := memdb.NewFilterIterator(result, utils.FilterRelationTuplesQuery(tenantID, filter)) |
| 145 | for obj := fit.Next(); obj != nil; obj = fit.Next() { |
| 146 | t, ok := obj.(storage.RelationTuple) |
| 147 | if !ok { |
| 148 | return nil, database.NewNoopContinuousToken().Encode(), errors.New(base.ErrorCode_ERROR_CODE_TYPE_CONVERSATION.String()) |
| 149 | } |
| 150 | tup = append(tup, t) |
| 151 | } |
| 152 | |
| 153 | // Sort the tuples and append them to the collection. |
| 154 | sort.Slice(tup, func(i, j int) bool { |
| 155 | return tup[i].ID < tup[j].ID |
| 156 | }) |
| 157 | |
| 158 | tuples := make([]*base.Tuple, 0, pagination.PageSize()+1) |
| 159 | for _, t := range tup { |
| 160 | if t.ID >= lowerBound { |
| 161 | tuples = append(tuples, t.ToTuple()) |
| 162 | if pagination.PageSize() != 0 && len(tuples) > int(pagination.PageSize()) { |
| 163 | return database.NewTupleCollection(tuples[:pagination.PageSize()]...), utils.NewContinuousToken(strconv.FormatUint(t.ID, 10)).Encode(), nil |
| 164 | } |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | return database.NewTupleCollection(tuples...), database.NewNoopContinuousToken().Encode(), nil |
| 169 | } |
| 170 | |
| 171 | // QuerySingleAttribute queries the database for a single attribute based on the provided filter. |
| 172 | func (r *DataReader) QuerySingleAttribute(_ context.Context, tenantID string, filter *base.AttributeFilter, _ string) (attribute *base.Attribute, err error) { |
nothing calls this directly
no test coverage detected