graphile-build-pg 4.4.5 → 4.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/node8plus/QueryBuilder.d.ts +10 -2
- package/node8plus/QueryBuilder.js +80 -1
- package/node8plus/QueryBuilder.js.flow +75 -2
- package/node8plus/QueryBuilder.js.map +1 -1
- package/node8plus/index.d.ts +8 -0
- package/node8plus/index.js +7 -1
- package/node8plus/index.js.flow +6 -1
- package/node8plus/index.js.map +1 -1
- package/node8plus/plugins/PgBasicsPlugin.js +5 -3
- package/node8plus/plugins/PgBasicsPlugin.js.flow +2 -0
- package/node8plus/plugins/PgBasicsPlugin.js.map +1 -1
- package/node8plus/plugins/PgConnectionTotalCount.js +10 -4
- package/node8plus/plugins/PgConnectionTotalCount.js.flow +13 -9
- package/node8plus/plugins/PgConnectionTotalCount.js.map +1 -1
- package/node8plus/plugins/PgIntrospectionPlugin.d.ts +48 -11
- package/node8plus/plugins/PgIntrospectionPlugin.js +53 -23
- package/node8plus/plugins/PgIntrospectionPlugin.js.flow +81 -25
- package/node8plus/plugins/PgIntrospectionPlugin.js.map +1 -1
- package/node8plus/plugins/PgJWTPlugin.js +6 -1
- package/node8plus/plugins/PgJWTPlugin.js.flow +7 -1
- package/node8plus/plugins/PgJWTPlugin.js.map +1 -1
- package/node8plus/plugins/PgMutationUpdateDeletePlugin.js +2 -1
- package/node8plus/plugins/PgMutationUpdateDeletePlugin.js.flow +3 -1
- package/node8plus/plugins/PgMutationUpdateDeletePlugin.js.map +1 -1
- package/node8plus/plugins/PgRecordFunctionConnectionPlugin.js +1 -0
- package/node8plus/plugins/PgRecordFunctionConnectionPlugin.js.flow +1 -0
- package/node8plus/plugins/PgRecordFunctionConnectionPlugin.js.map +1 -1
- package/node8plus/plugins/PgScalarFunctionConnectionPlugin.js +1 -0
- package/node8plus/plugins/PgScalarFunctionConnectionPlugin.js.flow +1 -0
- package/node8plus/plugins/PgScalarFunctionConnectionPlugin.js.map +1 -1
- package/node8plus/plugins/PgTypesPlugin.js +9 -2
- package/node8plus/plugins/PgTypesPlugin.js.flow +19 -0
- package/node8plus/plugins/PgTypesPlugin.js.map +1 -1
- package/node8plus/plugins/introspectionQuery.js +1 -0
- package/node8plus/plugins/introspectionQuery.js.flow +1 -0
- package/node8plus/plugins/introspectionQuery.js.map +1 -1
- package/node8plus/queryFromResolveDataFactory.js +8 -1
- package/node8plus/queryFromResolveDataFactory.js.flow +13 -1
- package/node8plus/queryFromResolveDataFactory.js.map +1 -1
- package/package.json +7 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/queryFromResolveDataFactory.js"],"names":["identity","_","undefined","queryBuilderOptions","from","fromAlias","resolveData","inOptions","withBuilder","context","rootValue","pgQuery","pgAggregateQuery","pgCursorPrefix","reallyRawCursorPrefix","pgDontUseAsterisk","calculateHasNextPage","calculateHasPreviousPage","usesCursor","explicitlyUsesCursor","preventAsterisk","length","options","useAsterisk","rawCursorPrefix","filter","queryBuilder","QueryBuilder","i","l","generateNextPrevPageSql","sqlQueryAlias","canHaveCursorInWhere","queryHasBefore","queryHasFirst","offset","invert","sqlCommonUnbounded","sql","fragment","getTableExpression","getTableAlias","sqlCommon","buildWhereClause","isForwardOrSymmetric","literal","buildWhereBoundClause","getSelectCursor","blank","value","limit","getFinalLimitAndOffset","getPgCursorPrefix","data","cursorPrefix","map","val","withPagination","withPaginationAsFields","withCursor","selectCursor","orderBy","getOrderByExpressionsAndDirections","expr","isOrderUnique","join","setCursorComparator","cursorValue","isAfter","badCursor","whereBound","orderByExpressionsAndDirections","Error","rawPrefixes","slice","rawCursors","Array","isArray","sqlFilter","sqlCursors","sqlExpression","ascending","comparison","Number","sqlOldFilter","null","cursorValue1","getOffset","Math","max","query","build","haveFields","getSelectFieldsCount","identifier","Symbol","sqlSummaryAlias","compiledData","upper","queryHasAfter","lower","queryHasZeroLimit","getFinalLimit","first","queryHasLast","last","hasNextPage","getFinalOffset","hasPreviousPage","sqlWith","sqlFrom","fields","push","aggregateQueryBuilder","aggregateJsonBuildObject","onlyJsonField","aggregatesSql","alias","jsonbBuildObject"],"mappings":"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","sourcesContent":["// @flow\nimport QueryBuilder from \"./QueryBuilder\";\nimport type { QueryBuilderOptions } from \"./QueryBuilder\";\nimport type { RawAlias } from \"./QueryBuilder\";\nimport * as sql from \"pg-sql2\";\nimport type { SQL } from \"pg-sql2\";\nimport type { DataForType } from \"graphile-build\";\nimport isSafeInteger from \"lodash/isSafeInteger\";\nimport assert from \"assert\";\n\n// eslint-disable-next-line flowtype/no-weak-types\ntype GraphQLContext = any;\n\nconst identity = _ => _ !== null && _ !== undefined;\n\nexport default (queryBuilderOptions: QueryBuilderOptions = {}) => (\n from: SQL,\n fromAlias: ?SQL,\n resolveData: DataForType,\n inOptions: {\n withPagination?: boolean,\n withPaginationAsFields?: boolean,\n asJson?: boolean,\n asJsonAggregate?: boolean,\n addNullCase?: boolean,\n addNotDistinctFromNullCase?: boolean,\n onlyJsonField?: boolean,\n useAsterisk?: boolean,\n withCursor?: boolean,\n },\n // TODO:v5: context is not optional\n withBuilder?: ((builder: QueryBuilder) => void) | null | void,\n context?: GraphQLContext = {},\n rootValue?: any // eslint-disable-line flowtype/no-weak-types\n) => {\n const {\n pgQuery,\n pgAggregateQuery,\n pgCursorPrefix: reallyRawCursorPrefix,\n pgDontUseAsterisk,\n calculateHasNextPage,\n calculateHasPreviousPage,\n usesCursor: explicitlyUsesCursor,\n } = resolveData;\n\n const preventAsterisk = pgDontUseAsterisk\n ? pgDontUseAsterisk.length > 0\n : false;\n const options = {\n ...inOptions,\n // Allow pgDontUseAsterisk to override useAsterisk\n useAsterisk: inOptions.useAsterisk && !preventAsterisk,\n };\n\n const usesCursor: boolean =\n (explicitlyUsesCursor && explicitlyUsesCursor.length > 0) ||\n (calculateHasNextPage && calculateHasNextPage.length > 0) ||\n (calculateHasPreviousPage && calculateHasPreviousPage.length > 0) ||\n false;\n const rawCursorPrefix =\n reallyRawCursorPrefix && reallyRawCursorPrefix.filter(identity);\n\n const queryBuilder = new QueryBuilder(\n queryBuilderOptions,\n context,\n rootValue\n );\n queryBuilder.from(from, fromAlias ? fromAlias : undefined);\n\n if (withBuilder) {\n withBuilder(queryBuilder);\n }\n if (pgQuery) {\n for (let i = 0, l = pgQuery.length; i < l; i++) {\n pgQuery[i](queryBuilder, resolveData);\n }\n }\n\n function generateNextPrevPageSql(\n sqlQueryAlias,\n canHaveCursorInWhere,\n queryHasBefore,\n queryHasFirst,\n offset = 0,\n invert = false\n ) {\n /*\n * Strap in, 'coz this function gets hairy!\n *\n * The point of this function is to return SQL which will resolve to a\n * boolean true/false depending on whether or not there is a (invert ?\n * \"previous\" : \"next\") page.\n *\n * Connections have before, after, first, last and offset.\n * - Users are forbidden from setting both first and last.\n * - Users are forbidden from setting both offset and last.\n *\n * Further there are two main modes of paginating, one works by adding a\n * where clause (this is preferred, but is not always possible, and is\n * indicated by `canHaveCursorInWhere === true`) and the other works using\n * standard LIMIT/OFFSET SQL pagination (and is indicated by\n * `canHaveCursorInWhere === false`).\n *\n * The following diagram shows a full collection of records, #, starting at\n * START and ending at END. The key after, before, offset, first and last\n * variables are shown. One thing not show is that it's possible to have\n * fewer records between before and after than requested by first or last.\n * Another detail not clearly show is that if there is no `after` then\n * `START` is used, similarly if there is no `before` then `END` is used.\n *\n * #################################################### < collection\n * ^ ^<-offset->^<-first->^ ^<-last->^ ^\n * | | | | | | |\n * | | +---------+ +--------+ |\n * | | | DATA1 DATA2 | |\n * | | | | |\n * | | | | |\n * | | +-------------------------+ |\n * | | DATA3 | |\n * | after before |\n * | |\n * START END\n *\n * We want one of the three DATA blocks:\n *\n * - If `first` is set, then we want DATA1.\n * - If `last` is set then we want DATA2.\n * - If neither is set then we want DATA3.\n *\n * (Remember: you cannot set both `first` and `last` at the same time.)\n *\n * When invert === false:\n *\n * Note that both DATA2 and DATA3 end at the same point, and we only care\n * if there's data *after* the relevant DATA block, so really we only\n * care if the query specified `first` (`queryHasFirst`) which makes\n * things complex (ending at the end of DATA1), otherwise we can use\n * `before` as the bound (end of DATA2/DATA3).\n *\n * When invert === true:\n *\n * Similarly, DATA1 and DATA3 start at the same point, and we're going\n * backwards so we only care if there's data *before* the DATA block, so\n * really we just need to know if the query set `last` or not, but since\n * this is inverted we call it `queryHasFirst`.\n *\n * When `invert` is false we're calculating `hasNextPage`, when true we're\n * calculating `hasPreviousPage`.\n *\n * Because of the near-symmetry of requesting hasPreviousPage vs\n * hasNextPage we always pretend we're determining `hasNextPage`, and we\n * just invert everything.\n */\n\n const sqlCommonUnbounded = sql.fragment`\\\nselect 1\nfrom ${queryBuilder.getTableExpression()} as ${queryBuilder.getTableAlias()}`;\n /*\n * This variable is a fragment to go into an `EXISTS(...)` call (after some tweaks).\n *\n * The buildWhereClause takes three arguments:\n *\n * - includeLowerBound (we want this for hasNextPage but not hasPreviousPage)\n * - includeUpperBound (we want this for hasPreviousPage but not hasNextPage)\n * - options (specifically `{addNullCase, addNotDistinctFromNullCase}`) -\n * we just pass this through.\n *\n * So in hasNextPage mode (invert === false), this common SQL ends up\n * representing the collection from `(after || START)` onwards with no\n * upper bound. In hasPreviousPage mode (invert === true), it represents\n * everything from `(before || END)` backwards, with no lower bound.\n */\n const sqlCommon = sql.fragment`\\\n${sqlCommonUnbounded}\nwhere ${queryBuilder.buildWhereClause(!invert, invert, options)}`;\n\n /*\n * Since the offset makes the diagram asymmetric, if offset === 0\n * then the diagram is symmetric and things are simplified a little.\n */\n const isForwardOrSymmetric = !invert || offset === 0;\n\n if (!isForwardOrSymmetric) {\n assert(invert);\n assert(offset > 0);\n // We're looking for a previous page, and there's an offset, so lets just\n // assume there's a previous page where offset is smaller.\n return sql.literal(true);\n } else if (canHaveCursorInWhere) {\n assert(isForwardOrSymmetric);\n if (!queryHasBefore && !queryHasFirst) {\n assert(isForwardOrSymmetric);\n // There can be no next page since there's no upper bound\n return sql.literal(false);\n } else if (queryHasBefore && !queryHasFirst) {\n /*\n * We invert the upper buildWhereBoundClause to only represent the data\n * after `before`, then check if there's at least one record in that set.\n *\n * This only works if the `before` cursor can be represented in the\n * SQL WHERE clause, otherwise we're doing limit/offset pagination\n * which requires different logic. It also only works if there's no\n * `first` clause, otherwise there could be a next page before the\n * `before` clause.\n */\n return sql.fragment`\\\nexists(\n ${sqlCommonUnbounded}\n where ${queryBuilder.buildWhereClause(false, false, options)}\n and not (${queryBuilder.buildWhereBoundClause(invert)})\n)`;\n } else {\n assert(queryHasFirst);\n // queryHasBefore could be true or false.\n /*\n * There's a few ways that we could determine if there's a next page.\n *\n * If !queryHasBefore, we could COUNT(*) the number of rows in\n * `sqlCommon` and see if it's larger than `first`:\n * `(select count(*) > ${first} from (${sqlCommon}) __random_table_alias__)`\n *\n * If !queryHasBefore, we could build a subquery table of offsetData\n * from sqlCommon and see if it contains any rows:\n * `EXISTS(select 1 from (${sqlCommon} OFFSET ${first}) __random_table_alias__)`.\n *\n * We could see if there's at least one row in sqlCommon that's not\n * already in our chosen result set.\n *\n * We've chosen the latter approach here because it doesn't place a limit\n * on queryHasBefore.\n */\n // Drop the `first` limit, see if there are any records that aren't\n // already in the list we've fetched.\n return sql.fragment`\\\nexists(\n ${sqlCommon}\n and (${queryBuilder.getSelectCursor()})::text not in (select __cursor::text from ${sqlQueryAlias})\n ${offset === 0 ? sql.blank : sql.fragment`offset ${sql.value(offset)}`}\n)`;\n }\n } else {\n assert(!invert || offset === 0); // isForwardOrSymmetric\n assert(!canHaveCursorInWhere);\n // We're dealing with LIMIT/OFFSET pagination here, which means `natural`\n // cursors, so the `queryBuilder` factors the before/after, first/last\n // into the limit / offset.\n const { limit } = queryBuilder.getFinalLimitAndOffset();\n\n if (limit == null) {\n // If paginating backwards, then offset > 0 has already been dealt\n // with. Unbounded, so there's no next page.\n return sql.fragment`false`;\n } else if (invert) {\n assert(offset === 0);\n // Paginating backwards and there's no offset (which factors in before/after), so there's no previous page.\n return sql.fragment`false`;\n } else {\n assert(!invert);\n /*\n * We're paginating forwards; either there's a before, there's a first,\n * or both.\n *\n * We want to see if there's more than limit+offset records in sqlCommon.\n */\n return sql.fragment`\\\nexists(\n ${sqlCommon}\n offset ${sql.literal(limit + offset)}\n)`;\n }\n }\n }\n const getPgCursorPrefix = () =>\n rawCursorPrefix && rawCursorPrefix.length > 0\n ? rawCursorPrefix\n : queryBuilder.data.cursorPrefix.map(val => sql.literal(val));\n if (\n options.withPagination ||\n options.withPaginationAsFields ||\n options.withCursor\n ) {\n // Sometimes we need a __cursor even if it's not a collection; e.g. to get the edge field on a mutation\n if (usesCursor) {\n queryBuilder.selectCursor((): SQL => {\n const orderBy = queryBuilder\n .getOrderByExpressionsAndDirections()\n .map(([expr]) => expr);\n if (queryBuilder.isOrderUnique() && orderBy.length > 0) {\n return sql.fragment`json_build_array(${sql.join(\n [\n ...getPgCursorPrefix(),\n sql.fragment`json_build_array(${sql.join(orderBy, \", \")})`,\n ],\n \", \"\n )})`;\n } else {\n return sql.fragment`json_build_array(${sql.join(\n getPgCursorPrefix(),\n \", \"\n )}, (row_number() over (partition by 1)))`;\n }\n });\n }\n }\n if (options.withPagination || options.withPaginationAsFields) {\n queryBuilder.setCursorComparator((cursorValue, isAfter) => {\n function badCursor() {\n queryBuilder.whereBound(sql.fragment`false`, isAfter);\n }\n const orderByExpressionsAndDirections = queryBuilder.getOrderByExpressionsAndDirections();\n if (orderByExpressionsAndDirections.length > 0) {\n if (!queryBuilder.isOrderUnique()) {\n throw new Error(\n \"The order supplied is not unique, so before/after cursors cannot be used. Please ensure the supplied order includes all the columns from the primary key or a unique constraint.\"\n );\n }\n const rawPrefixes = cursorValue.slice(0, cursorValue.length - 1);\n const rawCursors = cursorValue[cursorValue.length - 1];\n if (rawPrefixes.length !== getPgCursorPrefix().length) {\n badCursor();\n return;\n }\n if (!Array.isArray(rawCursors)) {\n badCursor();\n return;\n }\n let sqlFilter = sql.fragment`false`;\n const sqlCursors = rawCursors.map(val => sql.value(val));\n for (let i = orderByExpressionsAndDirections.length - 1; i >= 0; i--) {\n const [sqlExpression, ascending] = orderByExpressionsAndDirections[i];\n // If ascending and isAfter then >\n // If ascending and isBefore then <\n const comparison =\n Number(ascending) ^ Number(!isAfter)\n ? sql.fragment`>`\n : sql.fragment`<`;\n\n const sqlOldFilter = sqlFilter;\n sqlFilter = sql.fragment`\\\n(\\\n (${sqlExpression} ${comparison} ${sqlCursors[i] || sql.null})\nOR\\\n (\\\n ${sqlExpression} = ${sqlCursors[i] || sql.null}\\\n AND\\\n ${sqlOldFilter}\\\n )\\\n)`;\n }\n\n // Check the cursor prefixes apply\n // TODO:v5: we should be able to do this in JS-land rather than SQL-land\n sqlFilter = sql.fragment`(((${sql.join(\n getPgCursorPrefix(),\n \", \"\n )}) = (${sql.join(\n rawPrefixes.map(val => sql.value(val)),\n \", \"\n )})) AND (${sqlFilter}))`;\n queryBuilder.whereBound(sqlFilter, isAfter);\n } else if (\n cursorValue[0] === \"natural\" &&\n isSafeInteger(cursorValue[1]) &&\n // $FlowFixMe: we know this is a number\n cursorValue[1] >= 0\n ) {\n // $FlowFixMe: we know this is a number\n const cursorValue1: number = cursorValue[1];\n if (isAfter) {\n queryBuilder.offset(() => cursorValue1);\n } else {\n queryBuilder.limit(() => {\n const offset = queryBuilder.getOffset();\n return Math.max(0, cursorValue1 - offset - 1);\n });\n }\n } else {\n throw new Error(\"Cannot use 'before'/'after' without unique 'orderBy'\");\n }\n });\n\n const query = queryBuilder.build(options);\n const haveFields = queryBuilder.getSelectFieldsCount() > 0;\n const sqlQueryAlias = sql.identifier(Symbol());\n const sqlSummaryAlias = sql.identifier(Symbol());\n //\n // Tables should ALWAYS push their PK onto the order stack, if this isn't\n // present then we're either dealing with a view or a table without a PK.\n // Either way, we don't have anything to guarantee uniqueness so we need to\n // fall back to limit/offset.\n //\n // TODO: support unique keys in PgAllRows etc\n // TODO: add a warning for cursor-based pagination when using the fallback\n // TODO: if it is a view maybe add a warning encouraging pgViewUniqueKey\n const canHaveCursorInWhere =\n queryBuilder.getOrderByExpressionsAndDirections().length > 0 &&\n queryBuilder.isOrderUnique();\n const queryHasBefore =\n queryBuilder.compiledData.whereBound.upper.length > 0;\n const queryHasAfter = queryBuilder.compiledData.whereBound.lower.length > 0;\n const queryHasZeroLimit = queryBuilder.getFinalLimit() === 0;\n const queryHasFirst = isSafeInteger(queryBuilder.compiledData.first);\n const queryHasLast = isSafeInteger(queryBuilder.compiledData.last);\n const hasNextPage = queryHasZeroLimit\n ? sql.literal(false)\n : generateNextPrevPageSql(\n sqlQueryAlias,\n canHaveCursorInWhere,\n queryHasBefore,\n queryHasFirst,\n queryBuilder.getFinalOffset() || 0\n );\n const hasPreviousPage = queryHasZeroLimit\n ? sql.literal(false)\n : generateNextPrevPageSql(\n sqlQueryAlias,\n canHaveCursorInWhere,\n queryHasAfter,\n queryHasLast,\n queryBuilder.getFinalOffset() || 0,\n true\n );\n\n const sqlWith = haveFields\n ? sql.fragment`with ${sqlQueryAlias} as (${query}), ${sqlSummaryAlias} as (select json_agg(to_json(${sqlQueryAlias})) as data from ${sqlQueryAlias})`\n : sql.fragment``;\n const sqlFrom = sql.fragment``;\n const fields: Array<[SQL, RawAlias]> = [];\n if (haveFields) {\n fields.push([\n sql.fragment`coalesce((select ${sqlSummaryAlias}.data from ${sqlSummaryAlias}), '[]'::json)`,\n \"data\",\n ]);\n if (calculateHasNextPage) {\n fields.push([hasNextPage, \"hasNextPage\"]);\n }\n if (calculateHasPreviousPage) {\n fields.push([hasPreviousPage, \"hasPreviousPage\"]);\n }\n }\n if (pgAggregateQuery && pgAggregateQuery.length) {\n const aggregateQueryBuilder = new QueryBuilder(\n queryBuilderOptions,\n context,\n rootValue\n );\n aggregateQueryBuilder.from(\n queryBuilder.getTableExpression(),\n queryBuilder.getTableAlias()\n );\n\n for (let i = 0, l = pgAggregateQuery.length; i < l; i++) {\n pgAggregateQuery[i](aggregateQueryBuilder);\n }\n const aggregateJsonBuildObject = aggregateQueryBuilder.build({\n onlyJsonField: true,\n });\n const aggregatesSql = sql.fragment`\\\n(\n select ${aggregateJsonBuildObject}\n from ${queryBuilder.getTableExpression()} as ${queryBuilder.getTableAlias()}\n where ${queryBuilder.buildWhereClause(false, false, options)}\n)`;\n fields.push([aggregatesSql, \"aggregates\"]);\n }\n if (options.withPaginationAsFields) {\n return sql.fragment`${sqlWith} select ${sql.join(\n fields.map(\n ([expr, alias]) => sql.fragment`${expr} as ${sql.identifier(alias)}`\n ),\n \", \"\n )} ${sqlFrom}`;\n } else {\n return sql.fragment`${sqlWith} select ${queryBuilder.jsonbBuildObject(\n fields\n )} ${sqlFrom}`;\n }\n } else {\n const query = queryBuilder.build(options);\n return query;\n }\n};\n"],"file":"queryFromResolveDataFactory.js"}
|
|
1
|
+
{"version":3,"sources":["../src/queryFromResolveDataFactory.js"],"names":["identity","_","undefined","queryBuilderOptions","from","fromAlias","resolveData","inOptions","withBuilder","context","rootValue","pgQuery","pgAggregateQuery","pgCursorPrefix","reallyRawCursorPrefix","pgDontUseAsterisk","calculateHasNextPage","calculateHasPreviousPage","usesCursor","explicitlyUsesCursor","preventAsterisk","length","options","useAsterisk","rawCursorPrefix","filter","queryBuilder","QueryBuilder","i","l","generateNextPrevPageSql","sqlQueryAlias","canHaveCursorInWhere","queryHasBefore","queryHasFirst","offset","invert","sqlCommonUnbounded","sql","fragment","getTableExpression","getTableAlias","sqlCommon","buildWhereClause","isForwardOrSymmetric","literal","buildWhereBoundClause","getSelectCursor","blank","value","limit","getFinalLimitAndOffset","getPgCursorPrefix","data","cursorPrefix","map","val","withPagination","withPaginationAsFields","withCursor","selectCursor","orderBy","getOrderByExpressionsAndDirections","expr","isOrderUnique","join","getFinalOffset","setCursorComparator","cursorValue","isAfter","badCursor","whereBound","orderByExpressionsAndDirections","Error","rawPrefixes","slice","rawCursors","Array","isArray","sqlFilter","sqlCursors","sqlExpression","ascending","comparison","Number","sqlOldFilter","null","cursorValue1","getOffset","Math","max","query","build","haveFields","getSelectFieldsCount","identifier","Symbol","sqlSummaryAlias","compiledData","upper","queryHasAfter","lower","queryHasZeroLimit","getFinalLimit","first","queryHasLast","last","hasNextPage","hasPreviousPage","sqlWith","sqlFrom","fields","push","aggregateQueryBuilder","aggregateJsonBuildObject","onlyJsonField","aggregatesSql","alias","jsonbBuildObject"],"mappings":"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","sourcesContent":["// @flow\nimport QueryBuilder from \"./QueryBuilder\";\nimport type { QueryBuilderOptions } from \"./QueryBuilder\";\nimport type { RawAlias } from \"./QueryBuilder\";\nimport * as sql from \"pg-sql2\";\nimport type { SQL } from \"pg-sql2\";\nimport type { DataForType } from \"graphile-build\";\nimport isSafeInteger from \"lodash/isSafeInteger\";\nimport assert from \"assert\";\n\n// eslint-disable-next-line flowtype/no-weak-types\ntype GraphQLContext = any;\n\nconst identity = _ => _ !== null && _ !== undefined;\n\nexport default (queryBuilderOptions: QueryBuilderOptions = {}) => (\n from: SQL,\n fromAlias: ?SQL,\n resolveData: DataForType,\n inOptions: {\n withPagination?: boolean,\n withPaginationAsFields?: boolean,\n asJson?: boolean,\n asJsonAggregate?: boolean,\n addNullCase?: boolean,\n addNotDistinctFromNullCase?: boolean,\n onlyJsonField?: boolean,\n useAsterisk?: boolean,\n withCursor?: boolean,\n },\n // TODO:v5: context is not optional\n withBuilder?: ((builder: QueryBuilder) => void) | null | void,\n context?: GraphQLContext = {},\n rootValue?: any // eslint-disable-line flowtype/no-weak-types\n) => {\n const {\n pgQuery,\n pgAggregateQuery,\n pgCursorPrefix: reallyRawCursorPrefix,\n pgDontUseAsterisk,\n calculateHasNextPage,\n calculateHasPreviousPage,\n usesCursor: explicitlyUsesCursor,\n } = resolveData;\n\n const preventAsterisk = pgDontUseAsterisk\n ? pgDontUseAsterisk.length > 0\n : false;\n const options = {\n ...inOptions,\n // Allow pgDontUseAsterisk to override useAsterisk\n useAsterisk: inOptions.useAsterisk && !preventAsterisk,\n };\n\n const usesCursor: boolean =\n (explicitlyUsesCursor && explicitlyUsesCursor.length > 0) ||\n (calculateHasNextPage && calculateHasNextPage.length > 0) ||\n (calculateHasPreviousPage && calculateHasPreviousPage.length > 0) ||\n false;\n const rawCursorPrefix =\n reallyRawCursorPrefix && reallyRawCursorPrefix.filter(identity);\n\n const queryBuilder = new QueryBuilder(\n queryBuilderOptions,\n context,\n rootValue\n );\n queryBuilder.from(from, fromAlias ? fromAlias : undefined);\n\n if (withBuilder) {\n withBuilder(queryBuilder);\n }\n if (pgQuery) {\n for (let i = 0, l = pgQuery.length; i < l; i++) {\n pgQuery[i](queryBuilder, resolveData);\n }\n }\n\n function generateNextPrevPageSql(\n sqlQueryAlias,\n canHaveCursorInWhere,\n queryHasBefore,\n queryHasFirst,\n offset = 0,\n invert = false\n ) {\n /*\n * Strap in, 'coz this function gets hairy!\n *\n * The point of this function is to return SQL which will resolve to a\n * boolean true/false depending on whether or not there is a (invert ?\n * \"previous\" : \"next\") page.\n *\n * Connections have before, after, first, last and offset.\n * - Users are forbidden from setting both first and last.\n * - Users are forbidden from setting both offset and last.\n *\n * Further there are two main modes of paginating, one works by adding a\n * where clause (this is preferred, but is not always possible, and is\n * indicated by `canHaveCursorInWhere === true`) and the other works using\n * standard LIMIT/OFFSET SQL pagination (and is indicated by\n * `canHaveCursorInWhere === false`).\n *\n * The following diagram shows a full collection of records, #, starting at\n * START and ending at END. The key after, before, offset, first and last\n * variables are shown. One thing not show is that it's possible to have\n * fewer records between before and after than requested by first or last.\n * Another detail not clearly show is that if there is no `after` then\n * `START` is used, similarly if there is no `before` then `END` is used.\n *\n * #################################################### < collection\n * ^ ^<-offset->^<-first->^ ^<-last->^ ^\n * | | | | | | |\n * | | +---------+ +--------+ |\n * | | | DATA1 DATA2 | |\n * | | | | |\n * | | | | |\n * | | +-------------------------+ |\n * | | DATA3 | |\n * | after before |\n * | |\n * START END\n *\n * We want one of the three DATA blocks:\n *\n * - If `first` is set, then we want DATA1.\n * - If `last` is set then we want DATA2.\n * - If neither is set then we want DATA3.\n *\n * (Remember: you cannot set both `first` and `last` at the same time.)\n *\n * When invert === false:\n *\n * Note that both DATA2 and DATA3 end at the same point, and we only care\n * if there's data *after* the relevant DATA block, so really we only\n * care if the query specified `first` (`queryHasFirst`) which makes\n * things complex (ending at the end of DATA1), otherwise we can use\n * `before` as the bound (end of DATA2/DATA3).\n *\n * When invert === true:\n *\n * Similarly, DATA1 and DATA3 start at the same point, and we're going\n * backwards so we only care if there's data *before* the DATA block, so\n * really we just need to know if the query set `last` or not, but since\n * this is inverted we call it `queryHasFirst`.\n *\n * When `invert` is false we're calculating `hasNextPage`, when true we're\n * calculating `hasPreviousPage`.\n *\n * Because of the near-symmetry of requesting hasPreviousPage vs\n * hasNextPage we always pretend we're determining `hasNextPage`, and we\n * just invert everything.\n */\n\n const sqlCommonUnbounded = sql.fragment`\\\nselect 1\nfrom ${queryBuilder.getTableExpression()} as ${queryBuilder.getTableAlias()}`;\n /*\n * This variable is a fragment to go into an `EXISTS(...)` call (after some tweaks).\n *\n * The buildWhereClause takes three arguments:\n *\n * - includeLowerBound (we want this for hasNextPage but not hasPreviousPage)\n * - includeUpperBound (we want this for hasPreviousPage but not hasNextPage)\n * - options (specifically `{addNullCase, addNotDistinctFromNullCase}`) -\n * we just pass this through.\n *\n * So in hasNextPage mode (invert === false), this common SQL ends up\n * representing the collection from `(after || START)` onwards with no\n * upper bound. In hasPreviousPage mode (invert === true), it represents\n * everything from `(before || END)` backwards, with no lower bound.\n */\n const sqlCommon = sql.fragment`\\\n${sqlCommonUnbounded}\nwhere ${queryBuilder.buildWhereClause(!invert, invert, options)}`;\n\n /*\n * Since the offset makes the diagram asymmetric, if offset === 0\n * then the diagram is symmetric and things are simplified a little.\n */\n const isForwardOrSymmetric = !invert || offset === 0;\n\n if (!isForwardOrSymmetric) {\n assert(invert);\n assert(offset > 0);\n // We're looking for a previous page, and there's an offset, so lets just\n // assume there's a previous page where offset is smaller.\n return sql.literal(true);\n } else if (canHaveCursorInWhere) {\n assert(isForwardOrSymmetric);\n if (!queryHasBefore && !queryHasFirst) {\n assert(isForwardOrSymmetric);\n // There can be no next page since there's no upper bound\n return sql.literal(false);\n } else if (queryHasBefore && !queryHasFirst) {\n /*\n * We invert the upper buildWhereBoundClause to only represent the data\n * after `before`, then check if there's at least one record in that set.\n *\n * This only works if the `before` cursor can be represented in the\n * SQL WHERE clause, otherwise we're doing limit/offset pagination\n * which requires different logic. It also only works if there's no\n * `first` clause, otherwise there could be a next page before the\n * `before` clause.\n */\n return sql.fragment`\\\nexists(\n ${sqlCommonUnbounded}\n where ${queryBuilder.buildWhereClause(false, false, options)}\n and not (${queryBuilder.buildWhereBoundClause(invert)})\n)`;\n } else {\n assert(queryHasFirst);\n // queryHasBefore could be true or false.\n /*\n * There's a few ways that we could determine if there's a next page.\n *\n * If !queryHasBefore, we could COUNT(*) the number of rows in\n * `sqlCommon` and see if it's larger than `first`:\n * `(select count(*) > ${first} from (${sqlCommon}) __random_table_alias__)`\n *\n * If !queryHasBefore, we could build a subquery table of offsetData\n * from sqlCommon and see if it contains any rows:\n * `EXISTS(select 1 from (${sqlCommon} OFFSET ${first}) __random_table_alias__)`.\n *\n * We could see if there's at least one row in sqlCommon that's not\n * already in our chosen result set.\n *\n * We've chosen the latter approach here because it doesn't place a limit\n * on queryHasBefore.\n */\n // Drop the `first` limit, see if there are any records that aren't\n // already in the list we've fetched.\n return sql.fragment`\\\nexists(\n ${sqlCommon}\n and (${queryBuilder.getSelectCursor()})::text not in (select __cursor::text from ${sqlQueryAlias})\n ${offset === 0 ? sql.blank : sql.fragment`offset ${sql.value(offset)}`}\n)`;\n }\n } else {\n assert(!invert || offset === 0); // isForwardOrSymmetric\n assert(!canHaveCursorInWhere);\n // We're dealing with LIMIT/OFFSET pagination here, which means `natural`\n // cursors, so the `queryBuilder` factors the before/after, first/last\n // into the limit / offset.\n const { limit } = queryBuilder.getFinalLimitAndOffset();\n\n if (limit == null) {\n // If paginating backwards, then offset > 0 has already been dealt\n // with. Unbounded, so there's no next page.\n return sql.fragment`false`;\n } else if (invert) {\n assert(offset === 0);\n // Paginating backwards and there's no offset (which factors in before/after), so there's no previous page.\n return sql.fragment`false`;\n } else {\n assert(!invert);\n /*\n * We're paginating forwards; either there's a before, there's a first,\n * or both.\n *\n * We want to see if there's more than limit+offset records in sqlCommon.\n */\n return sql.fragment`\\\nexists(\n ${sqlCommon}\n offset ${sql.literal(limit + offset)}\n)`;\n }\n }\n }\n const getPgCursorPrefix = () =>\n rawCursorPrefix && rawCursorPrefix.length > 0\n ? rawCursorPrefix\n : queryBuilder.data.cursorPrefix.map(val => sql.literal(val));\n if (\n options.withPagination ||\n options.withPaginationAsFields ||\n options.withCursor\n ) {\n // Sometimes we need a __cursor even if it's not a collection; e.g. to get the edge field on a mutation\n if (usesCursor) {\n queryBuilder.selectCursor((): SQL => {\n const orderBy = queryBuilder\n .getOrderByExpressionsAndDirections()\n .map(([expr]) => expr);\n if (queryBuilder.isOrderUnique() && orderBy.length > 0) {\n return sql.fragment`json_build_array(${sql.join(\n [\n ...getPgCursorPrefix(),\n sql.fragment`json_build_array(${sql.join(orderBy, \", \")})`,\n ],\n \", \"\n )})`;\n } else {\n return sql.fragment`json_build_array(${sql.join(\n getPgCursorPrefix(),\n \", \"\n )}, ${\n /*\n * NOTE[useAsterisk/row_number]: If we have useAsterisk then the\n * query with limit offset is in a subquery, so our row_number()\n * call doesn't know about it. Here we add the offset back in\n * again. See matching NOTE in QueryBuilder.js.\n */\n options.useAsterisk\n ? sql.fragment`${sql.literal(\n queryBuilder.getFinalOffset() || 0\n )} + `\n : sql.fragment``\n }(row_number() over (partition by 1)))`;\n }\n });\n }\n }\n if (options.withPagination || options.withPaginationAsFields) {\n queryBuilder.setCursorComparator((cursorValue, isAfter) => {\n function badCursor() {\n queryBuilder.whereBound(sql.fragment`false`, isAfter);\n }\n const orderByExpressionsAndDirections = queryBuilder.getOrderByExpressionsAndDirections();\n if (orderByExpressionsAndDirections.length > 0) {\n if (!queryBuilder.isOrderUnique()) {\n throw new Error(\n \"The order supplied is not unique, so before/after cursors cannot be used. Please ensure the supplied order includes all the columns from the primary key or a unique constraint.\"\n );\n }\n const rawPrefixes = cursorValue.slice(0, cursorValue.length - 1);\n const rawCursors = cursorValue[cursorValue.length - 1];\n if (rawPrefixes.length !== getPgCursorPrefix().length) {\n badCursor();\n return;\n }\n if (!Array.isArray(rawCursors)) {\n badCursor();\n return;\n }\n let sqlFilter = sql.fragment`false`;\n const sqlCursors = rawCursors.map(val => sql.value(val));\n for (let i = orderByExpressionsAndDirections.length - 1; i >= 0; i--) {\n const [sqlExpression, ascending] = orderByExpressionsAndDirections[i];\n // If ascending and isAfter then >\n // If ascending and isBefore then <\n const comparison =\n Number(ascending) ^ Number(!isAfter)\n ? sql.fragment`>`\n : sql.fragment`<`;\n\n const sqlOldFilter = sqlFilter;\n sqlFilter = sql.fragment`\\\n(\\\n (${sqlExpression} ${comparison} ${sqlCursors[i] || sql.null})\nOR\\\n (\\\n ${sqlExpression} = ${sqlCursors[i] || sql.null}\\\n AND\\\n ${sqlOldFilter}\\\n )\\\n)`;\n }\n\n // Check the cursor prefixes apply\n // TODO:v5: we should be able to do this in JS-land rather than SQL-land\n sqlFilter = sql.fragment`(((${sql.join(\n getPgCursorPrefix(),\n \", \"\n )}) = (${sql.join(\n rawPrefixes.map(val => sql.value(val)),\n \", \"\n )})) AND (${sqlFilter}))`;\n queryBuilder.whereBound(sqlFilter, isAfter);\n } else if (\n cursorValue[0] === \"natural\" &&\n isSafeInteger(cursorValue[1]) &&\n // $FlowFixMe: we know this is a number\n cursorValue[1] >= 0\n ) {\n // $FlowFixMe: we know this is a number\n const cursorValue1: number = cursorValue[1];\n if (isAfter) {\n queryBuilder.offset(() => cursorValue1);\n } else {\n queryBuilder.limit(() => {\n const offset = queryBuilder.getOffset();\n return Math.max(0, cursorValue1 - offset - 1);\n });\n }\n } else {\n throw new Error(\"Cannot use 'before'/'after' without unique 'orderBy'\");\n }\n });\n\n const query = queryBuilder.build(options);\n const haveFields = queryBuilder.getSelectFieldsCount() > 0;\n const sqlQueryAlias = sql.identifier(Symbol());\n const sqlSummaryAlias = sql.identifier(Symbol());\n //\n // Tables should ALWAYS push their PK onto the order stack, if this isn't\n // present then we're either dealing with a view or a table without a PK.\n // Either way, we don't have anything to guarantee uniqueness so we need to\n // fall back to limit/offset.\n //\n // TODO: support unique keys in PgAllRows etc\n // TODO: add a warning for cursor-based pagination when using the fallback\n // TODO: if it is a view maybe add a warning encouraging pgViewUniqueKey\n const canHaveCursorInWhere =\n queryBuilder.getOrderByExpressionsAndDirections().length > 0 &&\n queryBuilder.isOrderUnique();\n const queryHasBefore =\n queryBuilder.compiledData.whereBound.upper.length > 0;\n const queryHasAfter = queryBuilder.compiledData.whereBound.lower.length > 0;\n const queryHasZeroLimit = queryBuilder.getFinalLimit() === 0;\n const queryHasFirst = isSafeInteger(queryBuilder.compiledData.first);\n const queryHasLast = isSafeInteger(queryBuilder.compiledData.last);\n const hasNextPage = queryHasZeroLimit\n ? sql.literal(false)\n : generateNextPrevPageSql(\n sqlQueryAlias,\n canHaveCursorInWhere,\n queryHasBefore,\n queryHasFirst,\n queryBuilder.getFinalOffset() || 0\n );\n const hasPreviousPage = queryHasZeroLimit\n ? sql.literal(false)\n : generateNextPrevPageSql(\n sqlQueryAlias,\n canHaveCursorInWhere,\n queryHasAfter,\n queryHasLast,\n queryBuilder.getFinalOffset() || 0,\n true\n );\n\n const sqlWith = haveFields\n ? sql.fragment`with ${sqlQueryAlias} as (${query}), ${sqlSummaryAlias} as (select json_agg(to_json(${sqlQueryAlias})) as data from ${sqlQueryAlias})`\n : sql.fragment``;\n const sqlFrom = sql.fragment``;\n const fields: Array<[SQL, RawAlias]> = [];\n if (haveFields) {\n fields.push([\n sql.fragment`coalesce((select ${sqlSummaryAlias}.data from ${sqlSummaryAlias}), '[]'::json)`,\n \"data\",\n ]);\n if (calculateHasNextPage) {\n fields.push([hasNextPage, \"hasNextPage\"]);\n }\n if (calculateHasPreviousPage) {\n fields.push([hasPreviousPage, \"hasPreviousPage\"]);\n }\n }\n if (pgAggregateQuery && pgAggregateQuery.length) {\n const aggregateQueryBuilder = new QueryBuilder(\n queryBuilderOptions,\n context,\n rootValue\n );\n aggregateQueryBuilder.from(\n queryBuilder.getTableExpression(),\n queryBuilder.getTableAlias()\n );\n\n for (let i = 0, l = pgAggregateQuery.length; i < l; i++) {\n pgAggregateQuery[i](aggregateQueryBuilder);\n }\n const aggregateJsonBuildObject = aggregateQueryBuilder.build({\n onlyJsonField: true,\n });\n const aggregatesSql = sql.fragment`\\\n(\n select ${aggregateJsonBuildObject}\n from ${queryBuilder.getTableExpression()} as ${queryBuilder.getTableAlias()}\n where ${queryBuilder.buildWhereClause(false, false, options)}\n)`;\n fields.push([aggregatesSql, \"aggregates\"]);\n }\n if (options.withPaginationAsFields) {\n return sql.fragment`${sqlWith} select ${sql.join(\n fields.map(\n ([expr, alias]) => sql.fragment`${expr} as ${sql.identifier(alias)}`\n ),\n \", \"\n )} ${sqlFrom}`;\n } else {\n return sql.fragment`${sqlWith} select ${queryBuilder.jsonbBuildObject(\n fields\n )} ${sqlFrom}`;\n }\n } else {\n const query = queryBuilder.build(options);\n return query;\n }\n};\n"],"file":"queryFromResolveDataFactory.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphile-build-pg",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.3",
|
|
4
4
|
"description": "Build a GraphQL schema by reflection over a PostgreSQL schema. Easy to customize since it's built with plugins on graphile-build",
|
|
5
5
|
"main": "node8plus/index.js",
|
|
6
6
|
"types": "node8plus/index.d.ts",
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
},
|
|
38
38
|
"homepage": "https://github.com/graphile/graphile-build/tree/master/packages/graphile-build-pg",
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@graphile/lru": "4.
|
|
40
|
+
"@graphile/lru": "4.5.0",
|
|
41
41
|
"chalk": "^2.4.2",
|
|
42
42
|
"debug": "^4.1.1",
|
|
43
|
-
"graphile-build": "4.
|
|
43
|
+
"graphile-build": "4.5.0",
|
|
44
44
|
"graphql-iso-date": "^3.6.0",
|
|
45
45
|
"jsonwebtoken": "^8.5.1",
|
|
46
46
|
"lodash": ">=4 <5",
|
|
47
47
|
"lru-cache": ">=4 <5",
|
|
48
|
-
"pg-sql2": "4.
|
|
48
|
+
"pg-sql2": "4.5.0",
|
|
49
49
|
"postgres-interval": "^1.2.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
@@ -55,13 +55,8 @@
|
|
|
55
55
|
"@babel/cli": "^7.0.0",
|
|
56
56
|
"eslint_d": "^8.0.0",
|
|
57
57
|
"flow-copy-source": "^1.2.0",
|
|
58
|
-
"jest": "^24.8.0"
|
|
59
|
-
|
|
60
|
-
"jest": {
|
|
61
|
-
"transform": {
|
|
62
|
-
"^.+\\.jsx?$": "../../.jest-wrapper.js"
|
|
63
|
-
},
|
|
64
|
-
"testRegex": "__tests__/.*\\.test\\.js$"
|
|
58
|
+
"jest": "^24.8.0",
|
|
59
|
+
"jest-serializer-graphql-schema": "4.5.0"
|
|
65
60
|
},
|
|
66
61
|
"files": [
|
|
67
62
|
"node8plus",
|
|
@@ -71,5 +66,5 @@
|
|
|
71
66
|
"engines": {
|
|
72
67
|
"node": ">=8.6"
|
|
73
68
|
},
|
|
74
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "5fb2c6a5a258f5976f55aa06391b9be9d5f0c4fc"
|
|
75
70
|
}
|