Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/language/src/validators/datamodel-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ export default class DataModelValidator implements AstValidator<DataModel> {
invariant(model.baseModel.ref, 'baseModel must be resolved');

// check if the base model is a delegate model
if (!isDelegateModel(model.baseModel.ref)) {
if (!isDelegateModel(model.baseModel.ref!)) {
accept('error', `Model ${model.baseModel.$refText} cannot be extended because it's not a delegate model`, {
node: model,
property: 'baseModel',
Expand Down
53 changes: 30 additions & 23 deletions packages/runtime/src/client/crud-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,14 +437,6 @@ export type SelectIncludeOmit<Schema extends SchemaDef, Model extends GetModels<
omit?: OmitInput<Schema, Model>;
};

type Distinct<Schema extends SchemaDef, Model extends GetModels<Schema>> = {
distinct?: OrArray<NonRelationFields<Schema, Model>>;
};

type Cursor<Schema extends SchemaDef, Model extends GetModels<Schema>> = {
cursor?: WhereUniqueInput<Schema, Model>;
};

export type SelectInput<
Schema extends SchemaDef,
Model extends GetModels<Schema>,
Expand Down Expand Up @@ -621,25 +613,34 @@ type OppositeRelationAndFK<

//#region Find args

type FilterArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = {
where?: WhereInput<Schema, Model>;
};

type SortAndTakeArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = {
skip?: number;
take?: number;
orderBy?: OrArray<OrderBy<Schema, Model, true, false>>;
cursor?: WhereUniqueInput<Schema, Model>;
};

export type FindArgs<
Schema extends SchemaDef,
Model extends GetModels<Schema>,
Collection extends boolean,
AllowFilter extends boolean = true,
> = (Collection extends true
? {
skip?: number;
take?: number;
orderBy?: OrArray<OrderBy<Schema, Model, true, false>>;
} & Distinct<Schema, Model> &
Cursor<Schema, Model>
: {}) &
(AllowFilter extends true
? {
where?: WhereInput<Schema, Model>;
}
: {}) &
SelectIncludeOmit<Schema, Model, Collection>;
> =
ProviderSupportsDistinct<Schema> extends true
? (Collection extends true
? SortAndTakeArgs<Schema, Model> & {
distinct?: OrArray<NonRelationFields<Schema, Model>>;
}
: {}) &
(AllowFilter extends true ? FilterArgs<Schema, Model> : {}) &
SelectIncludeOmit<Schema, Model, Collection>
: (Collection extends true ? SortAndTakeArgs<Schema, Model> : {}) &
(AllowFilter extends true ? FilterArgs<Schema, Model> : {}) &
SelectIncludeOmit<Schema, Model, Collection>;

export type FindManyArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = FindArgs<Schema, Model, true>;
export type FindFirstArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = FindArgs<Schema, Model, false>;
Expand Down Expand Up @@ -1259,6 +1260,12 @@ type HasToManyRelations<Schema extends SchemaDef, Model extends GetModels<Schema
? false
: true;

type ProviderSupportsCaseSensitivity<Schema extends SchemaDef> = Schema['provider'] extends 'postgresql' ? true : false;
type ProviderSupportsCaseSensitivity<Schema extends SchemaDef> = Schema['provider']['type'] extends 'postgresql'
? true
: false;

type ProviderSupportsDistinct<Schema extends SchemaDef> = Schema['provider']['type'] extends 'postgresql'
? true
: false;

// #endregion
92 changes: 91 additions & 1 deletion packages/runtime/src/client/crud/dialects/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
aggregate,
buildFieldRef,
buildJoinPairs,
ensureArray,
flattenCompoundUniqueFilters,
getDelegateDescendantModels,
getIdFields,
Expand Down Expand Up @@ -58,6 +59,54 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
return result;
}

buildFilterSortTake(
model: GetModels<Schema>,
args: FindArgs<Schema, GetModels<Schema>, true>,
query: SelectQueryBuilder<any, any, {}>,
) {
let result = query;

// where
if (args.where) {
result = result.where((eb) => this.buildFilter(eb, model, model, args?.where));
}

// skip && take
let negateOrderBy = false;
const skip = args.skip;
let take = args.take;
if (take !== undefined && take < 0) {
negateOrderBy = true;
take = -take;
}
result = this.buildSkipTake(result, skip, take);

// orderBy
result = this.buildOrderBy(
result,
model,
model,
args.orderBy,
skip !== undefined || take !== undefined,
negateOrderBy,
);

// distinct
if ('distinct' in args && (args as any).distinct) {
const distinct = ensureArray((args as any).distinct) as string[];
if (this.supportsDistinctOn) {
result = result.distinctOn(distinct.map((f) => sql.ref(`${model}.${f}`)));
} else {
throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
}
}

if (args.cursor) {
result = this.buildCursorFilter(model, result, args.cursor, args.orderBy, negateOrderBy);
}
return result;
}

buildFilter(
eb: ExpressionBuilder<any, any>,
model: string,
Expand Down Expand Up @@ -117,6 +166,47 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
return result;
}

private buildCursorFilter(
model: string,
query: SelectQueryBuilder<any, any, any>,
cursor: FindArgs<Schema, GetModels<Schema>, true>['cursor'],
orderBy: FindArgs<Schema, GetModels<Schema>, true>['orderBy'],
negateOrderBy: boolean,
) {
const _orderBy = orderBy ?? makeDefaultOrderBy(this.schema, model);

const orderByItems = ensureArray(_orderBy).flatMap((obj) => Object.entries<SortOrder>(obj));

const eb = expressionBuilder<any, any>();
const cursorFilter = this.buildFilter(eb, model, model, cursor);

let result = query;
const filters: ExpressionWrapper<any, any, any>[] = [];

for (let i = orderByItems.length - 1; i >= 0; i--) {
const andFilters: ExpressionWrapper<any, any, any>[] = [];

for (let j = 0; j <= i; j++) {
const [field, order] = orderByItems[j]!;
const _order = negateOrderBy ? (order === 'asc' ? 'desc' : 'asc') : order;
const op = j === i ? (_order === 'asc' ? '>=' : '<=') : '=';
andFilters.push(
eb(
eb.ref(`${model}.${field}`),
op,
eb.selectFrom(model).select(`${model}.${field}`).where(cursorFilter),
),
);
}

filters.push(eb.and(andFilters));
}

result = result.where((eb) => eb.or(filters));

return result;
}

private isLogicalCombinator(key: string): key is (typeof LOGICAL_COMBINATORS)[number] {
return LOGICAL_COMBINATORS.includes(key as any);
}
Expand Down Expand Up @@ -722,7 +812,7 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
// aggregations
if (['_count', '_avg', '_sum', '_min', '_max'].includes(field)) {
invariant(value && typeof value === 'object', `invalid orderBy value for field "${field}"`);
for (const [k, v] of Object.entries<string>(value)) {
for (const [k, v] of Object.entries<SortOrder>(value)) {
invariant(v === 'asc' || v === 'desc', `invalid orderBy value for field "${field}"`);
result = result.orderBy(
(eb) =>
Expand Down
26 changes: 1 addition & 25 deletions packages/runtime/src/client/crud/dialects/postgresql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,31 +91,7 @@ export class PostgresCrudDialect<Schema extends SchemaDef> extends BaseCrudDiale
);

if (payload && typeof payload === 'object') {
if (payload.where) {
subQuery = subQuery.where((eb) =>
this.buildFilter(eb, relationModel, relationModel, payload.where),
);
}

// skip & take
const skip = payload.skip;
let take = payload.take;
let negateOrderBy = false;
if (take !== undefined && take < 0) {
negateOrderBy = true;
take = -take;
}
subQuery = this.buildSkipTake(subQuery, skip, take);

// orderBy
subQuery = this.buildOrderBy(
subQuery,
relationModel,
relationModel,
payload.orderBy,
skip !== undefined || take !== undefined,
negateOrderBy,
);
subQuery = this.buildFilterSortTake(relationModel, payload, subQuery);
}

// add join conditions
Expand Down
27 changes: 2 additions & 25 deletions packages/runtime/src/client/crud/dialects/sqlite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,31 +85,8 @@ export class SqliteCrudDialect<Schema extends SchemaDef> extends BaseCrudDialect
);

if (payload && typeof payload === 'object') {
if (payload.where) {
subQuery = subQuery.where((eb) =>
this.buildFilter(eb, relationModel, relationModel, payload.where),
);
}

// skip & take
const skip = payload.skip;
let take = payload.take;
let negateOrderBy = false;
if (take !== undefined && take < 0) {
negateOrderBy = true;
take = -take;
}
subQuery = this.buildSkipTake(subQuery, skip, take);

// orderBy
subQuery = this.buildOrderBy(
subQuery,
relationModel,
relationModel,
payload.orderBy,
skip !== undefined || take !== undefined,
negateOrderBy,
);
// take care of where, orderBy, skip, take, cursor, and distinct
subQuery = this.buildFilterSortTake(relationModel, payload, subQuery);
}

// join conditions
Expand Down
Loading
Loading