Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
queryBuilder.offset(() => cursorValue1);
} else {
queryBuilder.limit(() => {
const offset = queryBuilder.getOffset();
return Math.max(0, cursorValue1 - offset - 1);
});
}
} else {
throw new Error("Cannot use 'before'/'after' without unique 'orderBy'");
}
});
const query = queryBuilder.build(options);
const haveFields = queryBuilder.getSelectFieldsCount() > 0;
const sqlQueryAlias = sql.identifier(Symbol());
const sqlSummaryAlias = sql.identifier(Symbol());
//
// Tables should ALWAYS push their PK onto the order stack, if this isn't
// present then we're either dealing with a view or a table without a PK.
// Either way, we don't have anything to guarantee uniqueness so we need to
// fall back to limit/offset.
//
// TODO: support unique keys in PgAllRows etc
// TODO: add a warning for cursor-based pagination when using the fallback
// TODO: if it is a view maybe add a warning encouraging pgViewUniqueKey
const canHaveCursorInWhere =
queryBuilder.getOrderByExpressionsAndDirections().length > 0 &&
queryBuilder.isOrderUnique();
const queryHasBefore =
queryBuilder.compiledData.whereBound.upper.length > 0;
const queryHasAfter = queryBuilder.compiledData.whereBound.lower.length > 0;
const queryHasZeroLimit = queryBuilder.getFinalLimit() === 0;
if (isAfter) {
queryBuilder.offset(() => cursorValue1);
} else {
queryBuilder.limit(() => {
const offset = queryBuilder.getOffset();
return Math.max(0, cursorValue1 - offset - 1);
});
}
} else {
throw new Error("Cannot use 'before'/'after' without unique 'orderBy'");
}
});
const query = queryBuilder.build(options);
const haveFields = queryBuilder.getSelectFieldsCount() > 0;
const sqlQueryAlias = sql.identifier(Symbol());
const sqlSummaryAlias = sql.identifier(Symbol());
//
// Tables should ALWAYS push their PK onto the order stack, if this isn't
// present then we're either dealing with a view or a table without a PK.
// Either way, we don't have anything to guarantee uniqueness so we need to
// fall back to limit/offset.
//
// TODO: support unique keys in PgAllRows etc
// TODO: add a warning for cursor-based pagination when using the fallback
// TODO: if it is a view maybe add a warning encouraging pgViewUniqueKey
const canHaveCursorInWhere =
queryBuilder.getOrderByExpressionsAndDirections().length > 0 &&
queryBuilder.isOrderUnique();
const queryHasBefore =
queryBuilder.compiledData.whereBound.upper.length > 0;
const queryHasAfter = queryBuilder.compiledData.whereBound.lower.length > 0;
(outputArgName, idx) =>
sql.query`(${sqlValuesAlias}.output_value_list)[${sql.literal(
idx + 1
)}]::${sql.identifier(
outputArgTypes[idx].namespaceName,
outputArgTypes[idx].name
)} as ${sql.identifier(
// According to https://www.postgresql.org/docs/10/static/sql-createfunction.html,
// "If you omit the name for an output argument, the system will choose a default column name."
// In PG 9.x and 10, the column names appear to be assigned with a `column` prefix.
outputArgName !== "" ? outputArgName : `column${idx + 1}`
)}`
),
)}]`
: sql.query`(${sqlResultSourceAlias}.${sqlResultSourceAlias})::${sqlTypeIdentifier}`;
const result = await performQuery(
pgClient,
sql.query`with ${sqlResultSourceAlias} as (${sqlMutationQuery}) select (${selectionField})::text from ${sqlResultSourceAlias}`
);
const { rows } = result;
const firstNonNullRow = rows.find(row => row !== null);
// TODO: we should be able to have `pg` not interpret the results as
// objects and instead just return them as arrays - then we can just do
// `row[0]`. PR welcome!
const firstKey = firstNonNullRow && Object.keys(firstNonNullRow)[0];
const rawValues = rows.map(row => row && row[firstKey]);
const values = rawValues.filter(rawValue => rawValue !== null);
const sqlValuesAlias = sql.identifier(Symbol());
const convertFieldBack = isPgClassLike
? sql.query`\
select (str::${sqlTypeIdentifier}).*
from unnest((${sql.value(values)})::text[]) str`
: outputArgNames != null && outputArgTypes != null // It's a record
? sql.query`\
select ${sql.join(
outputArgNames.map(
(outputArgName, idx) =>
sql.query`(${sqlValuesAlias}.output_value_list)[${sql.literal(
idx + 1
)}]::${sql.identifier(
outputArgTypes[idx].namespaceName,
outputArgTypes[idx].name
)} as ${sql.identifier(
// According to https://www.postgresql.org/docs/10/static/sql-createfunction.html,
order by (row_number() over (partition by 1)) desc`; /* We don't need to factor useAsterisk into this row_number() usage */
}
if (useAsterisk) {
/*
* NOTE[useAsterisk/row_number]: since LIMIT/OFFSET is inside this
* subquery, row_number() outside of this subquery WON'T include the
* offset. We must add it back wherever row_number() is used.
*/
fragment = sql.fragment`select ${fields} from (${fragment}) ${this.getTableAlias()}`;
}
if (asJsonAggregate) {
const aggAlias = Symbol();
fragment = sql.fragment`select json_agg(${sql.identifier(
aggAlias,
"object"
)}) from (${fragment}) as ${sql.identifier(aggAlias)}`;
fragment = sql.fragment`select coalesce((${fragment}), '[]'::json)`;
}
return fragment;
}
? sql.fragment` NULLS LAST`
: sql.blank
}`
),
","
)}`
: sql.blank
}
${(isSafeInteger(limit) && sql.fragment`limit ${sql.literal(limit)}`) ||
sql.blank}
${(offset && sql.fragment`offset ${sql.literal(offset)}`) || sql.blank}`;
if (flip) {
const flipAlias = Symbol();
fragment = sql.fragment`\
with ${sql.identifier(flipAlias)} as (
${fragment}
)
select *
from ${sql.identifier(flipAlias)}
order by (row_number() over (partition by 1)) desc`; /* We don't need to factor useAsterisk into this row_number() usage */
}
if (useAsterisk) {
/*
* NOTE[useAsterisk/row_number]: since LIMIT/OFFSET is inside this
* subquery, row_number() outside of this subquery WON'T include the
* offset. We must add it back wherever row_number() is used.
*/
fragment = sql.fragment`select ${fields} from (${fragment}) ${this.getTableAlias()}`;
}
if (asJsonAggregate) {
const aggAlias = Symbol();
(outputArgName, idx) =>
sql.query`${sqlResultSourceAlias}.${sql.identifier(
// According to https://www.postgresql.org/docs/10/static/sql-createfunction.html,
// "If you omit the name for an output argument, the system will choose a default column name."
// In PG 9.x and 10, the column names appear to be assigned with a `column` prefix.
outputArgName !== "" ? outputArgName : `column${idx + 1}`
)}::text`
),
)
select *
from ${sql.identifier(flipAlias)}
order by (row_number() over (partition by 1)) desc`; /* We don't need to factor useAsterisk into this row_number() usage */
}
if (useAsterisk) {
/*
* NOTE[useAsterisk/row_number]: since LIMIT/OFFSET is inside this
* subquery, row_number() outside of this subquery WON'T include the
* offset. We must add it back wherever row_number() is used.
*/
fragment = sql.fragment`select ${fields} from (${fragment}) ${this.getTableAlias()}`;
}
if (asJsonAggregate) {
const aggAlias = Symbol();
fragment = sql.fragment`select json_agg(${sql.identifier(
aggAlias,
"object"
)}) from (${fragment}) as ${sql.identifier(aggAlias)}`;
fragment = sql.fragment`select coalesce((${fragment}), '[]'::json)`;
}
return fragment;
}
primaryKeys.map(key =>
escapeLarge(
sql.fragment`${this.getTableAlias()}.${sql.identifier(key.name)}`,
key.type
)
),
([sqlFragment, alias]) =>
sql.fragment`to_json(${sqlFragment}) as ${sql.identifier(alias)}`
),