postgres short circuit empty find results
This commit is contained in:
@@ -13,7 +13,6 @@ export const create: Create = async function create({
|
||||
adapter: this,
|
||||
data,
|
||||
fields: collection.fields,
|
||||
locale: req.locale,
|
||||
operation: 'create',
|
||||
tableName: toSnakeCase(collectionSlug),
|
||||
});
|
||||
|
||||
@@ -49,7 +49,7 @@ export const find: Find = async function find(
|
||||
const selectFields: Record<string, GenericColumn> = {
|
||||
id: table.id,
|
||||
};
|
||||
if (orderBy) {
|
||||
if (orderBy.column) {
|
||||
selectFields.sort = orderBy.column;
|
||||
}
|
||||
|
||||
@@ -79,13 +79,30 @@ export const find: Find = async function find(
|
||||
const result = await selectQuery
|
||||
.offset((page - 1) * limit)
|
||||
.limit(limit === 0 ? undefined : limit);
|
||||
|
||||
if (result.length === 0) {
|
||||
return {
|
||||
docs: [],
|
||||
totalDocs: 0,
|
||||
limit,
|
||||
totalPages: 0,
|
||||
page: 1,
|
||||
pagingCounter: 0,
|
||||
hasPrevPage: false,
|
||||
hasNextPage: false,
|
||||
prevPage: null,
|
||||
nextPage: null,
|
||||
};
|
||||
}
|
||||
// set the id in an object for sorting later
|
||||
result.forEach(({ id }, i) => {
|
||||
orderedIDMap[id as (number | string)] = i;
|
||||
});
|
||||
findManyArgs.where = inArray(this.tables[tableName].id, Object.keys(orderedIDMap));
|
||||
} else {
|
||||
findManyArgs.where = where;
|
||||
if (where) {
|
||||
findManyArgs.where = where;
|
||||
}
|
||||
// orderBy will only be set if a complex sort is needed on a relation
|
||||
if (sort) {
|
||||
if (sort[0] === '-') {
|
||||
|
||||
@@ -143,10 +143,11 @@ export const getTableColumnFromPath = ({
|
||||
|
||||
case 'relationship':
|
||||
case 'upload': {
|
||||
newTableName = `${toSnakeCase(tableName)}_relationships`;
|
||||
let relationshipFields;
|
||||
if (typeof field.relationTo === 'string') {
|
||||
relationshipFields = adapter.payload.collections[field.relationTo];
|
||||
newTableName = `${toSnakeCase(field.relationTo)}`;
|
||||
joins[newTableName] = eq(adapter.tables[newTableName].id, adapter.tables[`${toSnakeCase(tableName)}_relationships`][`${toSnakeCase(field.relationTo)}ID`]);
|
||||
relationshipFields = adapter.payload.collections[field.relationTo].config.fields;
|
||||
if (locale && field.localized && adapter.payload.config.localization) {
|
||||
joins[newTableName] = and(
|
||||
eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID),
|
||||
@@ -162,7 +163,7 @@ export const getTableColumnFromPath = ({
|
||||
adapter,
|
||||
collectionPath: pathSegments.slice(1)
|
||||
.join('.'),
|
||||
fields: relationshipFields as Field[],
|
||||
fields: relationshipFields,
|
||||
joins,
|
||||
locale,
|
||||
pathSegments: pathSegments.slice(1),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { and, eq, gt, gte, inArray, isNotNull, lt, lte, ne, notInArray, or } from 'drizzle-orm';
|
||||
import { and, eq, gt, gte, ilike, inArray, isNotNull, lt, lte, ne, notInArray, or } from 'drizzle-orm';
|
||||
|
||||
export const operatorMap = {
|
||||
greater_than_equal: gte,
|
||||
@@ -6,6 +6,7 @@ export const operatorMap = {
|
||||
less_than: lt,
|
||||
greater_than: gt,
|
||||
in: inArray,
|
||||
like: ilike,
|
||||
// TODO:
|
||||
// all: all,
|
||||
not_in: notInArray,
|
||||
|
||||
@@ -19,6 +19,7 @@ type Args = {
|
||||
tableName: string,
|
||||
fields: Field[]
|
||||
}
|
||||
|
||||
export async function parseParams({
|
||||
joins,
|
||||
where,
|
||||
@@ -30,49 +31,57 @@ export async function parseParams({
|
||||
let result: SQL;
|
||||
const constraints: SQL[] = [];
|
||||
|
||||
if (typeof where === 'object') {
|
||||
if (typeof where === 'object' && Object.keys(where).length > 0) {
|
||||
// We need to determine if the whereKey is an AND, OR, or a schema path
|
||||
for (const relationOrPath of Object.keys(where)) {
|
||||
const condition = where[relationOrPath];
|
||||
let conditionOperator: 'and' | 'or';
|
||||
if (relationOrPath.toLowerCase() === 'and') {
|
||||
conditionOperator = 'and';
|
||||
} else if (relationOrPath.toLowerCase() === 'or') {
|
||||
conditionOperator = 'or';
|
||||
}
|
||||
if (Array.isArray(condition)) {
|
||||
const builtConditions = await buildAndOrConditions({
|
||||
joins,
|
||||
fields,
|
||||
adapter,
|
||||
locale,
|
||||
tableName,
|
||||
where: condition,
|
||||
});
|
||||
if (builtConditions.length > 0) result = operatorMap[conditionOperator](result, ...builtConditions);
|
||||
} else {
|
||||
// It's a path - and there can be multiple comparisons on a single path.
|
||||
// For example - title like 'test' and title not equal to 'tester'
|
||||
// So we need to loop on keys again here to handle each operator independently
|
||||
const pathOperators = where[relationOrPath];
|
||||
if (typeof pathOperators === 'object') {
|
||||
for (const operator of Object.keys(pathOperators)) {
|
||||
if (validOperators.includes(operator as Operator)) {
|
||||
const tableColumn = getTableColumnFromPath({
|
||||
adapter,
|
||||
collectionPath: relationOrPath,
|
||||
fields,
|
||||
joins,
|
||||
locale,
|
||||
pathSegments: relationOrPath.split('.'),
|
||||
tableName,
|
||||
});
|
||||
const queryValue = sanitizeQueryValue({
|
||||
field: tableColumn.field,
|
||||
operator,
|
||||
val: where[relationOrPath][operator],
|
||||
});
|
||||
constraints.push(operatorMap[operator](tableColumn.table[tableColumn.columnName], queryValue));
|
||||
if (relationOrPath) {
|
||||
const condition = where[relationOrPath];
|
||||
let conditionOperator: 'and' | 'or';
|
||||
if (relationOrPath.toLowerCase() === 'and') {
|
||||
conditionOperator = 'and';
|
||||
} else if (relationOrPath.toLowerCase() === 'or') {
|
||||
conditionOperator = 'or';
|
||||
}
|
||||
if (Array.isArray(condition)) {
|
||||
const builtConditions = await buildAndOrConditions({
|
||||
joins,
|
||||
fields,
|
||||
adapter,
|
||||
locale,
|
||||
tableName,
|
||||
where: condition,
|
||||
});
|
||||
if (builtConditions.length > 0) {
|
||||
if (result) {
|
||||
result = operatorMap[conditionOperator](result, ...builtConditions);
|
||||
} else {
|
||||
result = operatorMap[conditionOperator](...builtConditions);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// It's a path - and there can be multiple comparisons on a single path.
|
||||
// For example - title like 'test' and title not equal to 'tester'
|
||||
// So we need to loop on keys again here to handle each operator independently
|
||||
const pathOperators = where[relationOrPath];
|
||||
if (typeof pathOperators === 'object') {
|
||||
for (const operator of Object.keys(pathOperators)) {
|
||||
if (validOperators.includes(operator as Operator)) {
|
||||
const tableColumn = getTableColumnFromPath({
|
||||
adapter,
|
||||
collectionPath: relationOrPath,
|
||||
fields,
|
||||
joins,
|
||||
locale,
|
||||
pathSegments: relationOrPath.split('.'),
|
||||
tableName,
|
||||
});
|
||||
const queryValue = sanitizeQueryValue({
|
||||
field: tableColumn.field,
|
||||
operator,
|
||||
val: where[relationOrPath][operator],
|
||||
});
|
||||
constraints.push(operatorMap[operator](tableColumn.table[tableColumn.columnName], queryValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +89,11 @@ export async function parseParams({
|
||||
}
|
||||
}
|
||||
if (constraints.length > 0) {
|
||||
result = and(result, ...constraints);
|
||||
if (result) {
|
||||
result = and(result, ...constraints);
|
||||
} else {
|
||||
result = and(...constraints);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user