Skip to content

Commit

Permalink
refactor: table view modify by native sql (#194)
Browse files Browse the repository at this point in the history
* refactor: table modify by native sql

* refactor: view modify by native sql
  • Loading branch information
tea-artist committed Oct 12, 2023
1 parent a16716b commit eee85d5
Show file tree
Hide file tree
Showing 13 changed files with 379 additions and 338 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ export class TableController {
@Param('tableId') tableId: string,
@Query(new ZodValidationPipe(getTableQuerySchema)) query: IGetTableQuery
): Promise<ITableVo> {
return await this.tableService.getTable(baseId, tableId, query);
return await this.tableOpenApiService.getTable(baseId, tableId, query);
}

@Get()
async getTables(@Param('baseId') baseId: string): Promise<ITableListVo> {
return await this.tableService.getTables(baseId);
return await this.tableOpenApiService.getTables(baseId);
}

@Post()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,36 @@ import type {
ICreateTablePreparedRo,
ICreateTableRo,
IFieldVo,
IGetTableQuery,
ITableFullVo,
ITableOp,
ITableVo,
IViewRo,
IViewVo,
} from '@teable-group/core';
import {
FieldKeyType,
getUniqName,
generateTableId,
IdPrefix,
TableOpBuilder,
} from '@teable-group/core';
import { FieldKeyType } from '@teable-group/core';
import { PrismaService } from '@teable-group/db-main-prisma';
import { ShareDbService } from '../../../share-db/share-db.service';
import { createFieldInstanceByVo } from '../../field/model/factory';
import { FieldCreatingService } from '../../field/open-api/field-creating.service';
import { RecordOpenApiService } from '../../record/open-api/record-open-api.service';
import { RecordService } from '../../record/record.service';
import { createViewInstanceByRo } from '../../view/model/factory';
import { ViewOpenApiService } from '../../view/open-api/view-open-api.service';
import { TableService } from '../table.service';

@Injectable()
export class TableOpenApiService {
private logger = new Logger(TableOpenApiService.name);
constructor(
private readonly shareDbService: ShareDbService,
private readonly prismaService: PrismaService,
private readonly recordOpenApiService: RecordOpenApiService,
private readonly viewOpenApiService: ViewOpenApiService,
private readonly recordService: RecordService,
private readonly tableService: TableService,
private readonly fieldCreatingService: FieldCreatingService
) {}

private async createView(tableId: string, viewRos: IViewRo[]) {
const viewCreationPromises = viewRos.map(async (fieldRo) => {
const viewInstance = createViewInstanceByRo(fieldRo);
return this.viewOpenApiService.createView(tableId, viewInstance);
const viewCreationPromises = viewRos.map(async (viewRo) => {
return this.viewOpenApiService.createView(tableId, viewRo);
});
return await Promise.all(viewCreationPromises);
}
Expand Down Expand Up @@ -91,70 +83,47 @@ export class TableOpenApiService {
}

async createTableMeta(baseId: string, tableRo: ICreateTableRo) {
const tableRaws = await this.prismaService.txClient().tableMeta.findMany({
where: { deletedTime: null },
select: { name: true, order: true },
});
const tableId = generateTableId();
const names = tableRaws.map((table) => table.name);
const uniqName = getUniqName(tableRo.name ?? 'New table', names);

const order =
tableRaws.reduce((acc, cur) => {
return acc > cur.order ? acc : cur.order;
}, 0) + 1;

const snapshot = this.createTable2Op({
id: tableId,
name: uniqName,
description: tableRo.description,
icon: tableRo.icon,
order,
lastModifiedTime: new Date().toISOString(),
});

const collection = `${IdPrefix.Table}_${baseId}`;
const connection = this.shareDbService.getConnection();
const doc = connection.get(collection, tableId);
const tableVo = await new Promise<ITableVo>((resolve, reject) => {
doc.create(snapshot, (error) => {
if (error) return reject(error);
resolve(doc.data);
});
});

const { dbTableName } = await this.prismaService.txClient().tableMeta.findUniqueOrThrow({
where: { id: tableId },
select: { dbTableName: true },
});
return await this.tableService.createTable(baseId, tableRo);
}

return {
...tableVo,
dbTableName,
};
async getTable(baseId: string, tableId: string, query: IGetTableQuery): Promise<ITableVo> {
const { viewId, fieldKeyType, includeContent } = query;
if (includeContent) {
return await this.tableService.getFullTable(baseId, tableId, viewId, fieldKeyType);
}
return await this.tableService.getTableMeta(baseId, tableId);
}

private createTable2Op(tableVo: ITableOp) {
return TableOpBuilder.creator.build(tableVo);
async getTables(baseId: string): Promise<ITableVo[]> {
const tablesMeta = await this.prismaService.txClient().tableMeta.findMany({
orderBy: { order: 'asc' },
where: { baseId, deletedTime: null },
});
const tableIds = tablesMeta.map((tableMeta) => tableMeta.id);
const tableTime = await this.tableService.getTableLastModifiedTime(tableIds);
const tableDefaultViewIds = await this.tableService.getTableDefaultViewId(tableIds);
return tablesMeta.map((tableMeta, i) => {
const time = tableTime[i];
const defaultViewId = tableDefaultViewIds[i];
if (!defaultViewId) {
throw new Error('defaultViewId is not found');
}
return {
...tableMeta,
description: tableMeta.description ?? undefined,
icon: tableMeta.icon ?? undefined,
lastModifiedTime: time || tableMeta.lastModifiedTime.toISOString(),
defaultViewId,
};
});
}

async deleteTable(baseId: string, tableId: string) {
const collection = `${IdPrefix.Table}_${baseId}`;
return await this.prismaService.$tx(
async (prisma) => {
const doc = this.shareDbService.getConnection().get(collection, tableId);
// delete field for table
await new Promise((resolve, reject) => {
doc.fetch((error) => {
if (error) return reject(error);
doc.del({}, (error) => {
if (error) return reject(error);
this.logger.log(`delete document ${collection}.${tableId} succeed!`);
resolve(doc.data);
});
});
});
await this.tableService.deleteTable(baseId, tableId);

// delete field for table
await prisma.field.deleteMany({
where: { tableId },
});
Expand All @@ -164,22 +133,15 @@ export class TableOpenApiService {
where: { tableId },
});

// clear tableMeta
const deleteTable = await prisma.tableMeta.delete({
where: { id: tableId },
});
const dbTableName = deleteTable.dbTableName;
this.logger.log('Dropping: ', dbTableName);

// clear ops
// clear ops for view/field/record
await prisma.ops.deleteMany({
where: { collection: tableId },
});

// clean ops for table
await prisma.ops.deleteMany({
where: { docId: tableId },
});
// drop db table
await prisma.$executeRawUnsafe(`DROP TABLE "${dbTableName}"`);
},
{
maxWait: 100000,
Expand Down
3 changes: 2 additions & 1 deletion apps/nestjs-backend/src/features/table/table.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Module } from '@nestjs/common';
import { AttachmentsTableService } from '../attachments/attachments-table.service';
import { CalculationModule } from '../calculation/calculation.module';
import { FieldModule } from '../field/field.module';
import { RecordModule } from '../record/record.module';
import { ViewModule } from '../view/view.module';
import { TableService } from './table.service';

@Module({
imports: [FieldModule, RecordModule, ViewModule],
imports: [CalculationModule, FieldModule, RecordModule, ViewModule],
providers: [TableService, AttachmentsTableService],
exports: [FieldModule, RecordModule, ViewModule, TableService],
})
Expand Down
Loading

0 comments on commit eee85d5

Please sign in to comment.