QueryRelationships queries the database for relationships based on the provided filter.
(_ context.Context, tenantID string, filter *base.TupleFilter, _ string, pagination database.CursorPagination)
| 35 | |
| 36 | // QueryRelationships queries the database for relationships based on the provided filter. |
| 37 | func (r *DataReader) QueryRelationships(_ context.Context, tenantID string, filter *base.TupleFilter, _ string, pagination database.CursorPagination) (it *database.TupleIterator, err error) { |
| 38 | txn := r.database.DB.Txn(false) |
| 39 | defer txn.Abort() |
| 40 | |
| 41 | var lowerBound string |
| 42 | |
| 43 | if pagination.Cursor() != "" { |
| 44 | var t database.ContinuousToken |
| 45 | t, err = utils.EncodedContinuousToken{Value: pagination.Cursor()}.Decode() |
| 46 | if err != nil { |
| 47 | return nil, err |
| 48 | } |
| 49 | lowerBound = t.(utils.ContinuousToken).Value |
| 50 | } |
| 51 | |
| 52 | // Get the index and arguments based on the filter. |
| 53 | index, args := utils.GetRelationTuplesIndexNameAndArgsByFilters(tenantID, filter) |
| 54 | |
| 55 | // Get the result iterator based on the index and arguments. |
| 56 | var result memdb.ResultIterator |
| 57 | result, err = txn.LowerBound(constants.RelationTuplesTable, index, args...) |
| 58 | if err != nil { |
| 59 | return nil, errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String()) |
| 60 | } |
| 61 | |
| 62 | // Filter the result iterator and add the tuples to the collection. |
| 63 | tup := make([]storage.RelationTuple, 0, 10) |
| 64 | fit := memdb.NewFilterIterator(result, utils.FilterRelationTuplesQuery(tenantID, filter)) |
| 65 | for obj := fit.Next(); obj != nil; obj = fit.Next() { |
| 66 | t, ok := obj.(storage.RelationTuple) |
| 67 | if !ok { |
| 68 | return nil, errors.New(base.ErrorCode_ERROR_CODE_TYPE_CONVERSATION.String()) |
| 69 | } |
| 70 | tup = append(tup, t) |
| 71 | } |
| 72 | |
| 73 | // Sort tuples based on the provided order field |
| 74 | sort.Slice(tup, func(i, j int) bool { |
| 75 | switch pagination.Sort() { |
| 76 | case "entity_id": |
| 77 | return tup[i].EntityID < tup[j].EntityID |
| 78 | case "subject_id": |
| 79 | return tup[i].SubjectID < tup[j].SubjectID |
| 80 | default: |
| 81 | return false // No sorting if order field is invalid |
| 82 | } |
| 83 | }) |
| 84 | |
| 85 | var tuples []*base.Tuple |
| 86 | count := uint32(0) |
| 87 | limit := pagination.Limit() |
| 88 | |
| 89 | for _, t := range tup { |
| 90 | // Skip tuples below the lower bound |
| 91 | switch pagination.Sort() { |
| 92 | case "entity_id": |
| 93 | if t.EntityID < lowerBound { |
| 94 | continue |
nothing calls this directly
no test coverage detected