Skip to content

Commit 8e0102b

Browse files
authored
feat(pg): makeProcField can be used to construct aggregates (#714)
1 parent c5c6a05 commit 8e0102b

3 files changed

Lines changed: 54 additions & 19 deletions

File tree

packages/graphile-build-pg/src/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ import PgColumnDeprecationPlugin from "./plugins/PgColumnDeprecationPlugin";
1717
import PgForwardRelationPlugin from "./plugins/PgForwardRelationPlugin";
1818
import PgBackwardRelationPlugin from "./plugins/PgBackwardRelationPlugin";
1919
import PgRowByUniqueConstraint from "./plugins/PgRowByUniqueConstraint";
20-
import PgComputedColumnsPlugin from "./plugins/PgComputedColumnsPlugin";
20+
import PgComputedColumnsPlugin, {
21+
getComputedColumnDetails,
22+
} from "./plugins/PgComputedColumnsPlugin";
2123
import PgQueryProceduresPlugin from "./plugins/PgQueryProceduresPlugin";
2224
import PgOrderAllColumnsPlugin from "./plugins/PgOrderAllColumnsPlugin";
2325
import PgOrderComputedColumnsPlugin from "./plugins/PgOrderComputedColumnsPlugin";
@@ -81,7 +83,7 @@ export const defaultPlugins = [
8183
PgMutationPayloadEdgePlugin,
8284
];
8385

84-
export { inflections };
86+
export { inflections, getComputedColumnDetails };
8587

8688
// TypeScript compatibility
8789
export { PgEntityKind };

packages/graphile-build-pg/src/plugins/PgComputedColumnsPlugin.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import type { Plugin, Build } from "graphile-build";
33
import type { PgClass, PgProc } from "./PgIntrospectionPlugin";
44

5-
// This interface is not official yet, don't rely on it.
65
export const getComputedColumnDetails = (
76
build: Build,
87
table: PgClass,

packages/graphile-build-pg/src/plugins/makeProcField.js

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const nullableIf = (GraphQLNonNull, condition, Type) =>
33
condition ? Type : new GraphQLNonNull(Type);
44

55
import type { Build, FieldWithHooksFunction } from "graphile-build";
6-
import type { PgProc } from "./PgIntrospectionPlugin";
6+
import type { PgProc, PgType } from "./PgIntrospectionPlugin";
77
import type { SQL } from "pg-sql2";
88
import debugSql from "./debugSql";
99
import chalk from "chalk";
@@ -28,12 +28,23 @@ export default function makeProcField(
2828
isMutation = false,
2929
isRootQuery = false,
3030
forceList = false,
31+
aggregateWrapper = null,
32+
description: overrideDescription = null,
33+
pgTypeAndModifierModifier = null,
3134
}: {
3235
fieldWithHooks: FieldWithHooksFunction,
3336
computed?: boolean,
3437
isMutation?: boolean,
3538
isRootQuery?: boolean,
3639
forceList?: boolean,
40+
aggregateWrapper?: null | ((sql: SQL) => SQL),
41+
description?: string,
42+
pgTypeAndModifierModifier?:
43+
| null
44+
| ((
45+
pgType: PgType,
46+
pgTypeModifier: null | string | number
47+
) => [PgType, null | string | number]),
3748
}
3849
) {
3950
const {
@@ -163,7 +174,24 @@ export default function makeProcField(
163174
}
164175
});
165176

166-
const rawReturnType = introspectionResultsByKind.typeById[proc.returnTypeId];
177+
/**
178+
* This is the return type the function claims to have; we
179+
* should not use it anywhere but these next few lines.
180+
*/
181+
const baseReturnType = introspectionResultsByKind.typeById[proc.returnTypeId];
182+
183+
/**
184+
* This is the return type we treat it as having, e.g. in
185+
* case it was modified by wrapping it in an aggregate or
186+
* similar.
187+
*/
188+
const rawReturnType = pgTypeAndModifierModifier
189+
? pgTypeAndModifierModifier(baseReturnType, null)[0]
190+
: baseReturnType;
191+
192+
/**
193+
* This is the type without the array wrapper.
194+
*/
167195
const returnType = rawReturnType.isPgArray
168196
? rawReturnType.arrayItemType
169197
: rawReturnType;
@@ -312,7 +340,7 @@ export default function makeProcField(
312340
};
313341
});
314342
}
315-
function makeMutationCall(
343+
function makeSqlFunctionCall(
316344
parsedResolveInfoFragment,
317345
ReturnType,
318346
{ implicitArgs = [] } = {}
@@ -438,21 +466,25 @@ export default function makeProcField(
438466
queryBuilder.select(() => {
439467
const parentTableAlias = queryBuilder.getTableAlias();
440468
const functionAlias = sql.identifier(Symbol());
441-
const sqlMutationQuery = makeMutationCall(
469+
const sqlFunctionCall = makeSqlFunctionCall(
442470
parsedResolveInfoFragment,
443471
ReturnType,
444472
{
445473
implicitArgs: [parentTableAlias],
446474
}
447475
);
448-
const query = makeQuery(
449-
parsedResolveInfoFragment,
450-
ReturnType,
451-
sqlMutationQuery,
452-
functionAlias,
453-
queryBuilder
454-
);
455-
return sql.fragment`(${query})`;
476+
if (aggregateWrapper) {
477+
return aggregateWrapper(sqlFunctionCall);
478+
} else {
479+
const query = makeQuery(
480+
parsedResolveInfoFragment,
481+
ReturnType,
482+
sqlFunctionCall,
483+
functionAlias,
484+
queryBuilder
485+
);
486+
return sql.fragment`(${query})`;
487+
}
456488
}, getSafeAliasFromAlias(parsedResolveInfoFragment.alias));
457489
},
458490
};
@@ -585,7 +617,9 @@ export default function makeProcField(
585617
};
586618

587619
return {
588-
description: proc.description
620+
description: overrideDescription
621+
? overrideDescription
622+
: proc.description
589623
? proc.description
590624
: isMutation
591625
? null
@@ -661,7 +695,7 @@ export default function makeProcField(
661695
const parsedResolveInfoFragment = parseResolveInfo(resolveInfo);
662696
parsedResolveInfoFragment.args = args; // Allow overriding via makeWrapResolversPlugin
663697
const functionAlias = sql.identifier(Symbol());
664-
const sqlMutationQuery = makeMutationCall(
698+
const sqlFunctionCall = makeSqlFunctionCall(
665699
parsedResolveInfoFragment,
666700
resolveInfo.returnType,
667701
{}
@@ -700,7 +734,7 @@ export default function makeProcField(
700734
: isPgRecord
701735
? sql.query`${intermediateIdentifier}.*`
702736
: sql.query`${intermediateIdentifier} as ${functionAlias}`
703-
} from ${sqlMutationQuery} ${intermediateIdentifier}`,
737+
} from ${sqlFunctionCall} ${intermediateIdentifier}`,
704738
functionAlias,
705739
query,
706740
isPgClass,
@@ -722,7 +756,7 @@ export default function makeProcField(
722756
const query = makeQuery(
723757
parsedResolveInfoFragment,
724758
resolveInfo.returnType,
725-
sqlMutationQuery,
759+
sqlFunctionCall,
726760
functionAlias,
727761
null,
728762
resolveContext,

0 commit comments

Comments
 (0)