1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-11-24 08:12:24 +02:00

Server: Fixed Item and Log page when using Postgres

This commit is contained in:
Laurent Cozic 2021-05-25 20:29:59 +02:00
parent 12a66342db
commit ee0f23718b
5 changed files with 48 additions and 21 deletions

View File

@ -97,7 +97,10 @@ export default abstract class BaseModel<T> {
}
if (mainTable) {
output = output.map(f => `${mainTable}.${f}`);
output = output.map(f => {
if (f.includes(`${mainTable}.`)) return f;
return `${mainTable}.${f}`;
});
}
return output;

View File

@ -68,7 +68,7 @@ export default class ChangeModel extends BaseModel<Change> {
return results;
}
private changesForUserQuery(userId: Uuid): Knex.QueryBuilder {
private changesForUserQuery(userId: Uuid, count: boolean): Knex.QueryBuilder {
// When need to get:
//
// - All the CREATE and DELETE changes associated with the user
@ -78,15 +78,8 @@ export default class ChangeModel extends BaseModel<Change> {
// UPDATE changes do not have the user_id set because they are specific
// to the item, not to a particular user.
return this
const query = this
.db('changes')
.select([
'id',
'item_id',
'item_name',
'type',
'updated_time',
])
.where(function() {
void this.whereRaw('((type = ? OR type = ?) AND user_id = ?)', [ChangeType.Create, ChangeType.Delete, userId])
// Need to use a RAW query here because Knex has a "not a
@ -96,6 +89,20 @@ export default class ChangeModel extends BaseModel<Change> {
// https://github.com/knex/knex/issues/1851
.orWhereRaw('type = ? AND item_id IN (SELECT item_id FROM user_items WHERE user_id = ?)', [ChangeType.Update, userId]);
});
if (count) {
void query.countDistinct('id', { as: 'total' });
} else {
void query.select([
'id',
'item_id',
'item_name',
'type',
'updated_time',
]);
}
return query;
}
public async allByUser(userId: Uuid, pagination: Pagination = null): Promise<PaginatedChanges> {
@ -106,9 +113,9 @@ export default class ChangeModel extends BaseModel<Change> {
...pagination,
};
const query = this.changesForUserQuery(userId);
const countQuery = query.clone();
const itemCount = (await countQuery.countDistinct('id', { as: 'total' }))[0].total;
const query = this.changesForUserQuery(userId, false);
const countQuery = this.changesForUserQuery(userId, true);
const itemCount = (await countQuery.first()).total;
void query
.orderBy(pagination.order[0].by, pagination.order[0].dir)
@ -140,7 +147,7 @@ export default class ChangeModel extends BaseModel<Change> {
if (!changeAtCursor) throw new ErrorResyncRequired();
}
const query = this.changesForUserQuery(userId);
const query = this.changesForUserQuery(userId, false);
// If a cursor was provided, apply it to the query.
if (changeAtCursor) {

View File

@ -130,4 +130,16 @@ describe('ItemModel', function() {
}
});
test('should count items', async function() {
const { user: user1 } = await createUserAndSession(1, true);
await createItemTree(user1.id, '', {
'000000000000000000000000000000F1': {
'00000000000000000000000000000001': null,
},
});
expect(await models().item().childrenCount(user1.id)).toBe(2);
});
});

View File

@ -349,13 +349,18 @@ export default class ItemModel extends BaseModel<Item> {
}
private childrenQuery(userId: Uuid, pathQuery: string = '', options: LoadOptions = {}): Knex.QueryBuilder {
private childrenQuery(userId: Uuid, pathQuery: string = '', count: boolean = false, options: LoadOptions = {}): Knex.QueryBuilder {
const query = this
.db('user_items')
.leftJoin('items', 'user_items.item_id', 'items.id')
.select(this.selectFields(options, ['id', 'name', 'updated_time'], 'items'))
.where('user_items.user_id', '=', userId);
if (count) {
void query.countDistinct('items.id', { as: 'total' });
} else {
void query.select(this.selectFields(options, ['id', 'name', 'updated_time'], 'items'));
}
if (pathQuery) {
// We support /* as a prefix only. Anywhere else would have
// performance issue or requires a revert index.
@ -376,14 +381,14 @@ export default class ItemModel extends BaseModel<Item> {
public async children(userId: Uuid, pathQuery: string = '', pagination: Pagination = null, options: LoadOptions = {}): Promise<PaginatedItems> {
pagination = pagination || defaultPagination();
const query = this.childrenQuery(userId, pathQuery, options);
const query = this.childrenQuery(userId, pathQuery, false, options);
return paginateDbQuery(query, pagination, 'items');
}
public async childrenCount(userId: Uuid, pathQuery: string = ''): Promise<number> {
const query = this.childrenQuery(userId, pathQuery);
const r = await query.countDistinct('items.id', { as: 'total' });
return r[0].total;
const query = this.childrenQuery(userId, pathQuery, true);
const r = await query.first();
return r ? r.total : 0;
}
private async joplinItemPath(jopId: string): Promise<Item[]> {

View File

@ -68,7 +68,7 @@ export async function beforeAllDb(unitName: string) {
// initConfig({
// DB_CLIENT: 'pg',
// POSTGRES_DATABASE: createdDbPath_,
// POSTGRES_DATABASE: unitName,
// POSTGRES_USER: 'joplin',
// POSTGRES_PASSWORD: 'joplin',
// }, {