Skip to content

Commit 7222a5b

Browse files
authored
Merge pull request #937 from constructive-io/fix/orderby-not-working-v5
fix: enable orderBy on all columns alongside filterBy in v5 plugin
2 parents a465477 + f99c1a1 commit 7222a5b

2 files changed

Lines changed: 55 additions & 15 deletions

File tree

graphile/graphile-settings/src/plugins/enable-all-filter-columns.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import type { GraphileConfig } from 'graphile-config';
22

33
/**
4-
* EnableAllFilterColumnsPlugin - Enables filtering on ALL columns, not just indexed ones.
4+
* EnableAllFilterColumnsPlugin - Enables filtering and ordering on ALL columns, not just indexed ones.
55
*
66
* WHY THIS EXISTS:
7-
* PostGraphile v5's `PgIndexBehaviorsPlugin` restricts filtering to only indexed columns
8-
* by default. This is a performance optimization - filtering on non-indexed columns can
7+
* PostGraphile v5's `PgIndexBehaviorsPlugin` restricts filtering and ordering to only indexed columns
8+
* by default. This is a performance optimization - filtering/ordering on non-indexed columns can
99
* cause slow table scans. However, for development and flexibility, we want to allow
10-
* filtering on all columns and let developers/DBAs decide which columns need indexes.
10+
* filtering and ordering on all columns and let developers/DBAs decide which columns need indexes.
1111
*
1212
* SOURCE CODE REFERENCE:
1313
* PgIndexBehaviorsPlugin marks non-indexed columns with `extensions.isIndexed = false`
14-
* and then adds `-filterBy` behavior to remove them from filters:
14+
* and then adds `-filterBy` and `-orderBy` behaviors to remove them from filters and ordering:
1515
* https://github.com/graphile/crystal/blob/924b2515c6bd30e5905ac1419a25244b40c8bb4d/graphile-build/graphile-build-pg/src/plugins/PgIndexBehaviorsPlugin.ts
1616
*
1717
* The relevant v5 code (from PgIndexBehaviorsPlugin):
@@ -25,7 +25,7 @@ import type { GraphileConfig } from 'graphile-config';
2525
* const newBehavior = [behavior];
2626
* const attr = codec.attributes[attributeName];
2727
* if (attr.extensions?.isIndexed === false) {
28-
* newBehavior.push("-filterBy", "-orderBy"); // <-- This removes filterBy!
28+
* newBehavior.push("-filterBy", "-orderBy"); // <-- This removes filterBy AND orderBy!
2929
* }
3030
* return newBehavior;
3131
* },
@@ -36,15 +36,16 @@ import type { GraphileConfig } from 'graphile-config';
3636
*
3737
* OUR FIX:
3838
* We add a behavior callback that runs AFTER PgIndexBehaviorsPlugin's "postInferred" phase
39-
* and adds `+attribute:filterBy` back to ALL columns, regardless of index status.
39+
* and adds `+attribute:filterBy` and `+attribute:orderBy` back to ALL columns, regardless of index status.
4040
*
4141
* This means:
4242
* - All columns will appear in the connection filter's filter argument
43-
* - Developers can filter by any column
44-
* - It's the developer's/DBA's responsibility to add indexes for frequently filtered columns
43+
* - All columns will appear in the connection's orderBy enum
44+
* - Developers can filter and sort by any column
45+
* - It's the developer's/DBA's responsibility to add indexes for frequently filtered/sorted columns
4546
*
4647
* PERFORMANCE WARNING:
47-
* Filtering on non-indexed columns can cause full table scans, which may be slow on large
48+
* Filtering or ordering on non-indexed columns can cause full table scans, which may be slow on large
4849
* tables. Monitor your query performance and add indexes as needed. You can check which
4950
* columns are indexed by querying pg_indexes or using EXPLAIN ANALYZE on your queries.
5051
*
@@ -56,23 +57,24 @@ import type { GraphileConfig } from 'graphile-config';
5657
export const EnableAllFilterColumnsPlugin: GraphileConfig.Plugin = {
5758
name: 'EnableAllFilterColumnsPlugin',
5859
version: '1.0.0',
59-
description: 'Enables filtering on all columns, not just indexed ones',
60+
description: 'Enables filtering and ordering on all columns, not just indexed ones',
6061

6162
schema: {
6263
entityBehavior: {
6364
pgCodecAttribute: {
6465
/**
6566
* This callback runs in the "inferred" phase AFTER PgIndexBehaviorsPlugin's
66-
* "postInferred" phase. It adds `filterBy` back to ALL columns, overriding
67-
* the `-filterBy` that PgIndexBehaviorsPlugin adds to non-indexed columns.
67+
* "postInferred" phase. It adds `filterBy` and `orderBy` back to ALL columns,
68+
* overriding the `-filterBy` and `-orderBy` that PgIndexBehaviorsPlugin adds
69+
* to non-indexed columns.
6870
*/
6971
inferred: {
7072
after: ['postInferred'],
7173
provides: ['enableAllFilters'],
7274
callback(behavior) {
73-
// Add filterBy to override any -filterBy from PgIndexBehaviorsPlugin
75+
// Add filterBy and orderBy to override PgIndexBehaviorsPlugin restrictions
7476
// The behavior system will resolve conflicts, with later additions winning
75-
return [behavior, 'filterBy'];
77+
return [behavior, 'filterBy', 'orderBy'];
7678
},
7779
},
7880
},

graphql/server-test/__tests__/__snapshots__/schema-snapshot.test.ts.snap

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,12 +1069,24 @@ enum PostOrderBy {
10691069
ID_DESC
10701070
AUTHOR_ID_ASC
10711071
AUTHOR_ID_DESC
1072+
TITLE_ASC
1073+
TITLE_DESC
10721074
SLUG_ASC
10731075
SLUG_DESC
1076+
CONTENT_ASC
1077+
CONTENT_DESC
1078+
EXCERPT_ASC
1079+
EXCERPT_DESC
1080+
IS_PUBLISHED_ASC
1081+
IS_PUBLISHED_DESC
10741082
PUBLISHED_AT_ASC
10751083
PUBLISHED_AT_DESC
1084+
VIEW_COUNT_ASC
1085+
VIEW_COUNT_DESC
10761086
CREATED_AT_ASC
10771087
CREATED_AT_DESC
1088+
UPDATED_AT_ASC
1089+
UPDATED_AT_DESC
10781090
}
10791091
10801092
"""Methods to use when ordering \`PostTag\`."""
@@ -1088,6 +1100,8 @@ enum PostTagOrderBy {
10881100
POST_ID_DESC
10891101
TAG_ID_ASC
10901102
TAG_ID_DESC
1103+
CREATED_AT_ASC
1104+
CREATED_AT_DESC
10911105
}
10921106
10931107
"""A \`Tag\` edge in the connection, with data from \`PostTag\`."""
@@ -1112,6 +1126,12 @@ enum TagOrderBy {
11121126
NAME_DESC
11131127
SLUG_ASC
11141128
SLUG_DESC
1129+
DESCRIPTION_ASC
1130+
DESCRIPTION_DESC
1131+
COLOR_ASC
1132+
COLOR_DESC
1133+
CREATED_AT_ASC
1134+
CREATED_AT_DESC
11151135
}
11161136
11171137
type User {
@@ -1290,8 +1310,16 @@ enum CommentOrderBy {
12901310
AUTHOR_ID_DESC
12911311
PARENT_ID_ASC
12921312
PARENT_ID_DESC
1313+
CONTENT_ASC
1314+
CONTENT_DESC
1315+
IS_APPROVED_ASC
1316+
IS_APPROVED_DESC
1317+
LIKES_COUNT_ASC
1318+
LIKES_COUNT_DESC
12931319
CREATED_AT_ASC
12941320
CREATED_AT_DESC
1321+
UPDATED_AT_ASC
1322+
UPDATED_AT_DESC
12951323
}
12961324
12971325
"""A \`Comment\` edge in the connection."""
@@ -1375,8 +1403,18 @@ enum UserOrderBy {
13751403
EMAIL_DESC
13761404
USERNAME_ASC
13771405
USERNAME_DESC
1406+
DISPLAY_NAME_ASC
1407+
DISPLAY_NAME_DESC
1408+
BIO_ASC
1409+
BIO_DESC
1410+
IS_ACTIVE_ASC
1411+
IS_ACTIVE_DESC
1412+
ROLE_ASC
1413+
ROLE_DESC
13781414
CREATED_AT_ASC
13791415
CREATED_AT_DESC
1416+
UPDATED_AT_ASC
1417+
UPDATED_AT_DESC
13801418
}
13811419
13821420
"""Root meta schema type"""

0 commit comments

Comments
 (0)