Browse Source

feat: implement upgrader to migrate existing xcdb relations

Signed-off-by: Pranav C <pranavxc@gmail.com>
test/reset-fail
Pranav C 1 year ago
parent
commit
f8ed2a3974
  1. 84
      packages/nocodb/src/version-upgrader/ncXcdbLTARUpgrader.ts

84
packages/nocodb/src/version-upgrader/ncXcdbLTARUpgrader.ts

@ -1,41 +1,92 @@
import { RelationTypes, UITypes } from 'nocodb-sdk'; import { RelationTypes, UITypes } from 'nocodb-sdk';
import ProjectMgrv2 from '../db/sql-mgr/v2/ProjectMgrv2'; import { MetaTable } from '../meta/meta.service';
import type SqlMgrv2 from '../db/sql-mgr/v2/SqlMgrv2'; import NcConnectionMgrv2 from '../utils/common/NcConnectionMgrv2';
import type { MetaService } from '../meta/meta.service'; import type { MetaService } from '../meta/meta.service';
import type { LinkToAnotherRecordColumn, Model } from '../models'; import type { LinkToAnotherRecordColumn, Model } from '../models';
import type { NcUpgraderCtx } from './NcUpgrader'; import type { NcUpgraderCtx } from './NcUpgrader';
// An upgrader for upgrading LTAR relations in XCDB bases
// it will delete all the foreign keys and create a new index
// and treat all the LTAR as virtual
async function upgradeModelRelations({ async function upgradeModelRelations({
model, model,
sqlMgr, relations,
ncMeta, ncMeta,
sqlClient,
}: { }: {
ncMeta: MetaService; ncMeta: MetaService;
model: Model; model: Model;
sqlMgr: SqlMgrv2; sqlClient: ReturnType<
(typeof NcConnectionMgrv2)['getSqlClient']
> extends Promise<infer U>
? U
: ReturnType<(typeof NcConnectionMgrv2)['getSqlClient']>;
relations: {
tn: string;
rtn: string;
cn: string;
rcn: string;
}[];
}) { }) {
// Iterate over each column and upgrade LTAR // Iterate over each column and upgrade LTAR
for (const column of await model.getColumns()) { for (const column of await model.getColumns(ncMeta)) {
if (column.uidt !== UITypes.LinkToAnotherRecord) { if (column.uidt !== UITypes.LinkToAnotherRecord) {
continue; continue;
} }
const colOptions = await column.getColOptions<LinkToAnotherRecordColumn>(); const colOptions = await column.getColOptions<LinkToAnotherRecordColumn>(
ncMeta,
);
switch (colOptions.type) { switch (colOptions.type) {
// case RelationTypes.MANY_TO_MANY:
//
// break;
case RelationTypes.HAS_MANY: case RelationTypes.HAS_MANY:
{ {
// skip if virtual
if (colOptions.virtual) {
break;
}
const parentCol = await colOptions.getParentColumn(ncMeta);
const childCol = await colOptions.getChildColumn(ncMeta);
const parentModel = await parentCol.getModel(ncMeta);
const childModel = await childCol.getModel(ncMeta);
// delete the foreign key constraint if exists // delete the foreign key constraint if exists
const relation = relations.find((r) => {
return (
parentCol.column_name === r.rcn &&
childCol.column_name === r.cn &&
parentModel.table_name === r.rtn &&
childModel.table_name === r.tn
);
});
// delete the relation
if (relation) {
await sqlClient.relationDelete(relation);
}
// create a new index for the column // create a new index for the column
const indexArgs = {
columns: [relation.cn],
tn: relation.tn,
non_unique: true,
};
await sqlClient.indexCreate(indexArgs);
} }
break; break;
// case RelationTypes.BELONGS_TO:
// break;
} }
// update the relation as virtual
await ncMeta.metaUpdate(
null,
null,
MetaTable.COL_RELATIONS,
{ virtual: true },
colOptions.id,
);
} }
} }
@ -47,14 +98,19 @@ async function upgradeBaseRelations({
ncMeta: MetaService; ncMeta: MetaService;
base: any; base: any;
}) { }) {
const sqlMgr = ProjectMgrv2.getSqlMgr({ id: base.project_id }, ncMeta); // const sqlMgr = ProjectMgrv2.getSqlMgr({ id: base.project_id }, ncMeta);
const sqlClient = await NcConnectionMgrv2.getSqlClient(base, ncMeta.knex);
// get all relations
const relations = (await sqlClient.relationListAll())?.data?.list;
// get models for the base // get models for the base
const models = await ncMeta.metaList2(null, base.id, 'models'); const models = await ncMeta.metaList2(null, base.id, 'models');
// get all columns and filter out relations and upgrade // get all columns and filter out relations and upgrade
for (const model of models) { for (const model of models) {
await upgradeModelRelations({ ncMeta, model, sqlMgr }); await upgradeModelRelations({ ncMeta, model, sqlClient, relations });
} }
} }

Loading…
Cancel
Save