From 8c9b85693cab73a4addeaad02059a156deb2b082 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Wed, 1 Mar 2023 19:02:06 +0530 Subject: [PATCH] refactor: bulk data apis Signed-off-by: Pranav C --- .../controllers/dataController/bulkData.ts | 91 ++++++++++++++++ .../src/lib/services/dataService/bulkData.ts | 102 ++++++++++++++++++ .../src/lib/services/dataService/helpers.ts | 31 ++++++ .../src/lib/services/dataService/index.ts | 28 +---- packages/nocodb/src/lib/services/index.ts | 1 + 5 files changed, 226 insertions(+), 27 deletions(-) create mode 100644 packages/nocodb/src/lib/controllers/dataController/bulkData.ts create mode 100644 packages/nocodb/src/lib/services/dataService/bulkData.ts create mode 100644 packages/nocodb/src/lib/services/dataService/helpers.ts diff --git a/packages/nocodb/src/lib/controllers/dataController/bulkData.ts b/packages/nocodb/src/lib/controllers/dataController/bulkData.ts new file mode 100644 index 0000000000..5f169d21e2 --- /dev/null +++ b/packages/nocodb/src/lib/controllers/dataController/bulkData.ts @@ -0,0 +1,91 @@ +import { Request, Response, Router } from 'express'; +import ncMetaAclMw from '../../meta/helpers/ncMetaAclMw'; +import apiMetrics from '../../meta/helpers/apiMetrics'; +import { bulkDataService } from '../../services'; + +async function bulkDataInsert(req: Request, res: Response) { + res.json( + await bulkDataService.bulkDataInsert({ + body: req.body, + cookie: req, + projectName: req.params.projectName, + tableName: req.params.tableName, + }) + ); +} + +async function bulkDataUpdate(req: Request, res: Response) { + res.json( + await bulkDataService.bulkDataUpdate({ + body: req.body, + cookie: req, + projectName: req.params.projectName, + tableName: req.params.tableName, + }) + ); +} + +// todo: Integrate with filterArrJson bulkDataUpdateAll +async function bulkDataUpdateAll(req: Request, res: Response) { + res.json( + await bulkDataService.bulkDataUpdateAll({ + body: req.body, + cookie: req, + projectName: req.params.projectName, + tableName: req.params.tableName, + query: req.query, + }) + ); +} + +async function bulkDataDelete(req: Request, res: Response) { + res.json( + await bulkDataService.bulkDataDelete({ + body: req.body, + cookie: req, + projectName: req.params.projectName, + tableName: req.params.tableName, + }) + ); +} + +// todo: Integrate with filterArrJson bulkDataDeleteAll +async function bulkDataDeleteAll(req: Request, res: Response) { + res.json( + await bulkDataService.bulkDataDeleteAll({ + // cookie: req, + projectName: req.params.projectName, + tableName: req.params.tableName, + query: req.query, + }) + ); +} +const router = Router({ mergeParams: true }); + +router.post( + '/api/v1/db/data/bulk/:orgs/:projectName/:tableName', + apiMetrics, + ncMetaAclMw(bulkDataInsert, 'bulkDataInsert') +); +router.patch( + '/api/v1/db/data/bulk/:orgs/:projectName/:tableName', + apiMetrics, + ncMetaAclMw(bulkDataUpdate, 'bulkDataUpdate') +); +router.patch( + '/api/v1/db/data/bulk/:orgs/:projectName/:tableName/all', + apiMetrics, + ncMetaAclMw(bulkDataUpdateAll, 'bulkDataUpdateAll') +); +router.delete( + '/api/v1/db/data/bulk/:orgs/:projectName/:tableName', + apiMetrics, + ncMetaAclMw(bulkDataDelete, 'bulkDataDelete') +); +router.delete( + '/api/v1/db/data/bulk/:orgs/:projectName/:tableName/all', + apiMetrics, + ncMetaAclMw(bulkDataDeleteAll, 'bulkDataDeleteAll') +); + +export default router; diff --git a/packages/nocodb/src/lib/services/dataService/bulkData.ts b/packages/nocodb/src/lib/services/dataService/bulkData.ts new file mode 100644 index 0000000000..2ac6b5a20b --- /dev/null +++ b/packages/nocodb/src/lib/services/dataService/bulkData.ts @@ -0,0 +1,102 @@ +import { BaseModelSqlv2 } from '../../db/sql-data-mapper/lib/sql/BaseModelSqlv2'; +import { Base, Model } from '../../models'; +import NcConnectionMgrv2 from '../../utils/common/NcConnectionMgrv2'; +import { getViewAndModelByAliasOrId, PathParams } from './helpers'; + +type BulkOperation = + | 'bulkInsert' + | 'bulkUpdate' + | 'bulkUpdateAll' + | 'bulkDelete' + | 'bulkDeleteAll'; + +export async function getModelViewBase(param: PathParams) { + const { model, view } = await getViewAndModelByAliasOrId(param); + + const base = await Base.get(model.base_id); + return { model, view, base }; +} + +export async function executeBulkOperation( + param: PathParams & { + operation: T; + options: Parameters; + } +) { + const { model, view, base } = await getModelViewBase(param); + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + viewId: view?.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + return await baseModel[param.operation].apply(null, param.options); +} + +// todo: Integrate with filterArrJson bulkDataUpdateAll +export async function bulkDataInsert( + param: PathParams & { + body: any; + cookie: any; + } +) { + return await executeBulkOperation({ + ...param, + operation: 'bulkInsert', + options: [param.body, { cookie: param.cookie }], + }); +} + +// todo: Integrate with filterArrJson bulkDataUpdateAll +export async function bulkDataUpdate( + param: PathParams & { + body: any; + cookie: any; + } +) { + return await executeBulkOperation({ + ...param, + operation: 'bulkUpdate', + options: [param.body, { cookie: param.cookie }], + }); +} + +// todo: Integrate with filterArrJson bulkDataUpdateAll +export async function bulkDataUpdateAll( + param: PathParams & { + body: any; + cookie: any; + query: any; + } +) { + return await executeBulkOperation({ + ...param, + operation: 'bulkUpdateAll', + options: [param.query, param.body, { cookie: param.cookie }], + }); +} + +export async function bulkDataDelete( + param: PathParams & { + body: any; + cookie: any; + } +) { + return await executeBulkOperation({ + ...param, + operation: 'bulkDelete', + options: [param.body, { cookie: param.cookie }], + }); +} + +// todo: Integrate with filterArrJson bulkDataDeleteAll +export async function bulkDataDeleteAll( + param: PathParams & { + query: any; + } +) { + return await executeBulkOperation({ + ...param, + operation: 'bulkDeleteAll', + options: [param.query], + }); +} diff --git a/packages/nocodb/src/lib/services/dataService/helpers.ts b/packages/nocodb/src/lib/services/dataService/helpers.ts new file mode 100644 index 0000000000..bed4f78f3a --- /dev/null +++ b/packages/nocodb/src/lib/services/dataService/helpers.ts @@ -0,0 +1,31 @@ +import { NcError } from '../../meta/helpers/catchError' +import { Model, View } from '../../models' +import Project from '../../models/Project' + + +export interface PathParams { + projectName: string; + tableName: string; + viewName?: string; +} + +export async function getViewAndModelByAliasOrId(param: { + projectName: string; + tableName: string; + viewName?: string; +}) { + const project = await Project.getWithInfoByTitleOrId(param.projectName); + + const model = await Model.getByAliasOrId({ + project_id: project.id, + aliasOrId: param.tableName, + }); + const view = + param.viewName && + (await View.getByTitleOrId({ + titleOrId: param.viewName, + fk_model_id: model.id, + })); + if (!model) NcError.notFound('Table not found'); + return { model, view }; +} diff --git a/packages/nocodb/src/lib/services/dataService/index.ts b/packages/nocodb/src/lib/services/dataService/index.ts index 42d7a05556..0dd7ba3d02 100644 --- a/packages/nocodb/src/lib/services/dataService/index.ts +++ b/packages/nocodb/src/lib/services/dataService/index.ts @@ -3,14 +3,8 @@ import getAst from '../../db/sql-data-mapper/lib/sql/helpers/getAst'; import { NcError } from '../../meta/helpers/catchError'; import { PagedResponseImpl } from '../../meta/helpers/PagedResponse'; import { Base, Model, View } from '../../models'; -import Project from '../../models/Project'; import NcConnectionMgrv2 from '../../utils/common/NcConnectionMgrv2'; - -interface PathParams { - projectName: string; - tableName: string; - viewName: string; -} +import { getViewAndModelByAliasOrId, PathParams } from './helpers' export async function dataList(param: PathParams & { query: any }) { const { model, view } = await getViewAndModelByAliasOrId(param); @@ -328,26 +322,6 @@ export async function getGroupedDataList(param: { return data; } -export async function getViewAndModelByAliasOrId(param: { - projectName: string; - tableName: string; - viewName?: string; -}) { - const project = await Project.getWithInfoByTitleOrId(param.projectName); - - const model = await Model.getByAliasOrId({ - project_id: project.id, - aliasOrId: param.tableName, - }); - const view = - param.viewName && - (await View.getByTitleOrId({ - titleOrId: param.viewName, - fk_model_id: model.id, - })); - if (!model) NcError.notFound('Table not found'); - return { model, view }; -} export async function dataListByViewId(param: { viewId: string; query: any }) { const view = await View.get(param.viewId); diff --git a/packages/nocodb/src/lib/services/index.ts b/packages/nocodb/src/lib/services/index.ts index 6bcf4667aa..4a5e9dacae 100644 --- a/packages/nocodb/src/lib/services/index.ts +++ b/packages/nocodb/src/lib/services/index.ts @@ -27,3 +27,4 @@ export * as projectUserService from './projectUserService'; export * as attachmentService from './attachmentService'; export * as hookFilterService from './hookFilterService'; export * as dataService from './dataService'; +export * as bulkDataService from './dataService/bulkData';