Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ export class StubPostgresDatabaseAdapter<
return results[0] ?? null;
}

private static compareByOrderBys(
orderBys: TableOrderByClause[],
private static compareByOrderBys<TFields extends Record<string, any>>(
orderBys: TableOrderByClause<TFields>[],
objectA: { [key: string]: any },
objectB: { [key: string]: any },
): 0 | 1 | -1 {
Expand Down Expand Up @@ -160,7 +160,7 @@ export class StubPostgresDatabaseAdapter<
tableName: string,
tableFieldSingleValueEqualityOperands: TableFieldSingleValueEqualityCondition[],
tableFieldMultiValueEqualityOperands: TableFieldMultiValueEqualityCondition[],
querySelectionModifiers: TableQuerySelectionModifiers,
querySelectionModifiers: TableQuerySelectionModifiers<TFields>,
): Promise<object[]> {
let filteredObjects = this.getObjectCollectionForTable(tableName);
for (const { tableField, tableValue } of tableFieldSingleValueEqualityOperands) {
Expand Down Expand Up @@ -196,16 +196,16 @@ export class StubPostgresDatabaseAdapter<
_tableName: string,
_rawWhereClause: string,
_bindings: object | any[],
_querySelectionModifiers: TableQuerySelectionModifiers,
_querySelectionModifiers: TableQuerySelectionModifiers<TFields>,
): Promise<object[]> {
throw new Error('Raw WHERE clauses not supported for StubDatabaseAdapter');
}

protected fetchManyBySQLFragmentInternalAsync(
_queryInterface: any,
_tableName: string,
_sqlFragment: SQLFragment,
_querySelectionModifiers: TableQuerySelectionModifiers,
_sqlFragment: SQLFragment<TFields>,
_querySelectionModifiers: TableQuerySelectionModifiers<TFields>,
): Promise<object[]> {
throw new Error('SQL fragments not supported for StubDatabaseAdapter');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,23 @@ export type EntityLoaderFieldNameOrderByClause<
fieldName: TSelectedFields;
};

export type EntityLoaderFieldFragmentOrderByClause = EntityLoaderBaseOrderByClause & {
export type EntityLoaderFieldFragmentOrderByClause<
TFields extends Record<string, any>,
TSelectedFields extends keyof TFields = keyof TFields,
> = EntityLoaderBaseOrderByClause & {
/**
* The SQL fragment to order by, which can reference selected fields. Example: `COALESCE(NULLIF(display_name, ''), split_part(full_name, '/', 2))`.
* May not contain ASC or DESC, as ordering direction is controlled by the `order` property.
*/
fieldFragment: SQLFragment;
fieldFragment: SQLFragment<Pick<TFields, TSelectedFields>>;
};

export type EntityLoaderOrderByClause<
TFields extends Record<string, any>,
TSelectedFields extends keyof TFields = keyof TFields,
> =
| EntityLoaderFieldNameOrderByClause<TFields, TSelectedFields>
| EntityLoaderFieldFragmentOrderByClause;
| EntityLoaderFieldFragmentOrderByClause<TFields, TSelectedFields>;

/**
* SQL modifiers that only affect the selection but not the projection.
Expand Down Expand Up @@ -88,7 +91,7 @@ export interface EntityLoaderQuerySelectionModifiers<
export type EntityLoaderFieldNameConstructorFn<
TFields extends Record<string, any>,
TSelectedFields extends keyof TFields = keyof TFields,
> = (fieldName: TSelectedFields) => SQLFragment;
> = (fieldName: TSelectedFields) => SQLFragment<TFields>;

/**
* Specification for a search field that is a manually constructed SQLFragment. Useful for complex search fields that require
Expand Down Expand Up @@ -122,7 +125,7 @@ export type EntityLoaderSearchFieldSQLFragmentFnSpecification<
* Helper function to get a SQLFragment for a given field name, which should be used to construct the final SQLFragment for the search field.
*/
getFragmentForFieldName: EntityLoaderFieldNameConstructorFn<TFields, TSelectedFields>,
) => SQLFragment;
) => SQLFragment<Pick<TFields, TSelectedFields>>;
};

/**
Expand Down Expand Up @@ -240,7 +243,7 @@ interface EntityLoaderBaseUnifiedPaginationArgs<
/**
* SQLFragment representing the WHERE clause to filter the entities being paginated.
*/
where?: SQLFragment;
where?: SQLFragment<Pick<TFields, TSelectedFields>>;

/**
* Pagination specification determining how to order and paginate results.
Expand Down Expand Up @@ -421,7 +424,7 @@ export class AuthorizationResultBasedKnexEntityLoader<
* @returns SQL query builder for building and executing SQL queries that when executed returns entity results where result error can be UnauthorizedError.
*/
loadManyBySQL(
fragment: SQLFragment,
fragment: SQLFragment<Pick<TFields, TSelectedFields>>,
modifiers: EntityLoaderQuerySelectionModifiers<TFields, TSelectedFields> = {},
): AuthorizationResultBasedSQLQueryBuilder<
TFields,
Expand Down Expand Up @@ -515,7 +518,7 @@ export class AuthorizationResultBasedSQLQueryBuilder<
TSelectedFields
>,
private readonly queryContext: EntityQueryContext,
sqlFragment: SQLFragment,
sqlFragment: SQLFragment<Pick<TFields, TSelectedFields>>,
modifiers: EntityLoaderQuerySelectionModifiers<TFields, TSelectedFields>,
) {
super(sqlFragment, modifiers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export type PostgresOrderByClause<TFields extends Record<string, any>> =
/**
* A raw SQL fragment to order by. May not contain ASC or DESC, as ordering direction is determined by the `order` property.
*/
fieldFragment: SQLFragment;
fieldFragment: SQLFragment<TFields>;

/**
* The OrderByOrdering to order by.
Expand Down Expand Up @@ -136,20 +136,20 @@ export interface PostgresQuerySelectionModifiers<TFields extends Record<string,
limit?: number;
}

export type TableOrderByClause =
export type TableOrderByClause<TFields extends Record<string, any>> =
| {
columnName: string;
order: OrderByOrdering;
nulls: NullsOrdering | undefined;
}
| {
columnFragment: SQLFragment;
columnFragment: SQLFragment<TFields>;
order: OrderByOrdering;
nulls: NullsOrdering | undefined;
};

export interface TableQuerySelectionModifiers {
orderBy: TableOrderByClause[] | undefined;
export interface TableQuerySelectionModifiers<TFields extends Record<string, any>> {
orderBy: TableOrderByClause<TFields>[] | undefined;
offset: number | undefined;
limit: number | undefined;
}
Expand Down Expand Up @@ -213,7 +213,7 @@ export abstract class BasePostgresEntityDatabaseAdapter<
tableName: string,
tableFieldSingleValueEqualityOperands: TableFieldSingleValueEqualityCondition[],
tableFieldMultiValueEqualityOperands: TableFieldMultiValueEqualityCondition[],
querySelectionModifiers: TableQuerySelectionModifiers,
querySelectionModifiers: TableQuerySelectionModifiers<TFields>,
): Promise<object[]>;

/**
Expand Down Expand Up @@ -249,7 +249,7 @@ export abstract class BasePostgresEntityDatabaseAdapter<
tableName: string,
rawWhereClause: string,
bindings: object | any[],
querySelectionModifiers: TableQuerySelectionModifiers,
querySelectionModifiers: TableQuerySelectionModifiers<TFields>,
): Promise<object[]>;

/**
Expand All @@ -262,7 +262,7 @@ export abstract class BasePostgresEntityDatabaseAdapter<
*/
async fetchManyBySQLFragmentAsync(
queryContext: EntityQueryContext,
sqlFragment: SQLFragment,
sqlFragment: SQLFragment<TFields>,
querySelectionModifiers: PostgresQuerySelectionModifiers<TFields>,
): Promise<readonly Readonly<TFields>[]> {
const results = await this.fetchManyBySQLFragmentInternalAsync(
Expand All @@ -280,18 +280,18 @@ export abstract class BasePostgresEntityDatabaseAdapter<
protected abstract fetchManyBySQLFragmentInternalAsync(
queryInterface: Knex,
tableName: string,
sqlFragment: SQLFragment,
querySelectionModifiers: TableQuerySelectionModifiers,
sqlFragment: SQLFragment<TFields>,
querySelectionModifiers: TableQuerySelectionModifiers<TFields>,
): Promise<object[]>;

private convertToTableQueryModifiers(
querySelectionModifiers: PostgresQuerySelectionModifiers<TFields>,
): TableQuerySelectionModifiers {
): TableQuerySelectionModifiers<TFields> {
const orderBy = querySelectionModifiers.orderBy;
return {
orderBy:
orderBy !== undefined
? orderBy.map((orderBySpecification): TableOrderByClause => {
? orderBy.map((orderBySpecification): TableOrderByClause<TFields> => {
if ('fieldName' in orderBySpecification) {
return {
columnName: getDatabaseFieldForEntityField(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export abstract class BaseSQLQueryBuilder<
private executed = false;

constructor(
private readonly sqlFragment: SQLFragment,
private readonly sqlFragment: SQLFragment<Pick<TFields, TSelectedFields>>,
private readonly modifiers: {
limit?: number;
offset?: number;
Expand Down Expand Up @@ -71,7 +71,7 @@ export abstract class BaseSQLQueryBuilder<
* @param order - The ordering direction (ascending or descending). Defaults to ascending.
*/
orderBySQL(
fragment: SQLFragment,
fragment: SQLFragment<Pick<TFields, TSelectedFields>>,
order: OrderByOrdering = OrderByOrdering.ASCENDING,
nulls: NullsOrdering | undefined = undefined,
): this {
Expand All @@ -92,7 +92,7 @@ export abstract class BaseSQLQueryBuilder<
/**
* Get the SQL fragment
*/
protected getSQLFragment(): SQLFragment {
protected getSQLFragment(): SQLFragment<Pick<TFields, TSelectedFields>> {
return this.sqlFragment;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export class EnforcingKnexEntityLoader<
* ```
*/
loadManyBySQL(
fragment: SQLFragment,
fragment: SQLFragment<Pick<TFields, TSelectedFields>>,
modifiers: EntityLoaderQuerySelectionModifiers<TFields, TSelectedFields> = {},
): EnforcingSQLQueryBuilder<
TFields,
Expand Down Expand Up @@ -251,7 +251,7 @@ export class EnforcingSQLQueryBuilder<
TPrivacyPolicy,
TSelectedFields
>,
sqlFragment: SQLFragment,
sqlFragment: SQLFragment<Pick<TFields, TSelectedFields>>,
modifiers: EntityLoaderQuerySelectionModifiers<TFields, TSelectedFields>,
) {
super(sqlFragment, modifiers);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { EntityConfiguration, FieldTransformer, FieldTransformerMap } from '@expo/entity';
import {
EntityConfiguration,
FieldTransformer,
FieldTransformerMap,
getDatabaseFieldForEntityField,
} from '@expo/entity';
import { Knex } from 'knex';

import {
Expand Down Expand Up @@ -119,7 +124,7 @@ export class PostgresEntityDatabaseAdapter<

private applyQueryModifiersToQuery(
query: Knex.QueryBuilder,
querySelectionModifiers: TableQuerySelectionModifiers,
querySelectionModifiers: TableQuerySelectionModifiers<TFields>,
): Knex.QueryBuilder {
const { orderBy, offset, limit } = querySelectionModifiers;

Expand All @@ -139,7 +144,9 @@ export class PostgresEntityDatabaseAdapter<
: '';
ret = ret.orderByRaw(
`(${orderBySpecification.columnFragment.sql}) ${orderBySpecification.order}${nullsSuffix}`,
orderBySpecification.columnFragment.getKnexBindings(),
orderBySpecification.columnFragment.getKnexBindings((fieldName) =>
getDatabaseFieldForEntityField(this.entityConfiguration, fieldName),
),
);
}
}
Expand All @@ -161,7 +168,7 @@ export class PostgresEntityDatabaseAdapter<
tableName: string,
tableFieldSingleValueEqualityOperands: TableFieldSingleValueEqualityCondition[],
tableFieldMultiValueEqualityOperands: TableFieldMultiValueEqualityCondition[],
querySelectionModifiers: TableQuerySelectionModifiers,
querySelectionModifiers: TableQuerySelectionModifiers<TFields>,
): Promise<object[]> {
let query = queryInterface.select().from(tableName);

Expand Down Expand Up @@ -207,7 +214,7 @@ export class PostgresEntityDatabaseAdapter<
tableName: string,
rawWhereClause: string,
bindings: object | any[],
querySelectionModifiers: TableQuerySelectionModifiers,
querySelectionModifiers: TableQuerySelectionModifiers<TFields>,
): Promise<object[]> {
let query = queryInterface.select().from(tableName).whereRaw(rawWhereClause, bindings);
query = this.applyQueryModifiersToQuery(query, querySelectionModifiers);
Expand All @@ -217,13 +224,18 @@ export class PostgresEntityDatabaseAdapter<
protected async fetchManyBySQLFragmentInternalAsync(
queryInterface: Knex,
tableName: string,
sqlFragment: SQLFragment,
querySelectionModifiers: TableQuerySelectionModifiers,
sqlFragment: SQLFragment<TFields>,
querySelectionModifiers: TableQuerySelectionModifiers<TFields>,
): Promise<object[]> {
let query = queryInterface
.select()
.from(tableName)
.whereRaw(sqlFragment.sql, sqlFragment.getKnexBindings());
.whereRaw(
sqlFragment.sql,
sqlFragment.getKnexBindings((fieldName) =>
getDatabaseFieldForEntityField(this.entityConfiguration, fieldName),
),
);
query = this.applyQueryModifiersToQuery(query, querySelectionModifiers);
return await wrapNativePostgresCallAsync(() => query);
}
Expand Down
Loading