# Fix cursor-based pagination with lexicographic ordering for composite
fields
## Bug
The existing cursor-based pagination implementation had a bug when
handling composite fields.
When paginating through results sorted by composite fields (like
`fullName` with sub-properties `firstName` and`lastName`), the WHERE
conditions generated for cursor positioning were incorrect, leading to
records being skipped.
The previous implementation was generating wrong WHERE conditions:
For example, when paginating with a cursor like `{ firstName: 'John',
lastName: 'Doe' }`, it would generate:
```sql
WHERE firstName > 'John' AND lastName > 'Doe'
```
This is incorrect because it would miss records like `{ firstName:
'John', lastName: 'Smith' }` which should be included in forward
pagination.
## Fix
Create a new util to use proper lexicographic order when sorting a
composite field.
---------
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
57 lines
1.3 KiB
TypeScript
57 lines
1.3 KiB
TypeScript
import gql from 'graphql-tag';
|
|
import { capitalize } from 'twenty-shared/utils';
|
|
|
|
type FindManyOperationFactoryParams = {
|
|
objectMetadataSingularName: string;
|
|
objectMetadataPluralName: string;
|
|
gqlFields: string;
|
|
filter?: object;
|
|
orderBy?: object;
|
|
limit?: number;
|
|
after?: string;
|
|
before?: string;
|
|
first?: number;
|
|
last?: number;
|
|
};
|
|
|
|
export const findManyOperationFactory = ({
|
|
objectMetadataSingularName,
|
|
objectMetadataPluralName,
|
|
gqlFields,
|
|
filter = {},
|
|
orderBy = {},
|
|
limit,
|
|
after,
|
|
before,
|
|
first,
|
|
last,
|
|
}: FindManyOperationFactoryParams) => ({
|
|
query: gql`
|
|
query ${capitalize(objectMetadataPluralName)}($filter: ${capitalize(objectMetadataSingularName)}FilterInput, $orderBy: [${capitalize(objectMetadataSingularName)}OrderByInput], $limit: Int, $after: String, $before: String, $first: Int, $last: Int) {
|
|
${objectMetadataPluralName}(filter: $filter, orderBy: $orderBy, limit: $limit, after: $after, before: $before, first: $first, last: $last) {
|
|
edges {
|
|
node {
|
|
${gqlFields}
|
|
}
|
|
cursor
|
|
}
|
|
pageInfo {
|
|
hasNextPage
|
|
hasPreviousPage
|
|
startCursor
|
|
endCursor
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
variables: {
|
|
filter,
|
|
orderBy,
|
|
limit,
|
|
after,
|
|
before,
|
|
first,
|
|
last,
|
|
},
|
|
});
|