Browse Source

feat: template parser - relation parsing

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/743/head
Pranav C 3 years ago
parent
commit
4ad70af467
  1. 20
      packages/nocodb/src/__tests__/template.ts
  2. 88
      packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts
  3. 35
      packages/nocodb/src/lib/sqlUi/UITypes.ts
  4. 111
      packages/nocodb/src/lib/templateParser/NcTemplateParser.ts

20
packages/nocodb/src/__tests__/template.ts

@ -12,6 +12,16 @@ export default {
cn: 'body',
uidt: 'LongText'
}
],
hasMany: [
{
tn: 'comment'
}
],
manyToMany: [
{
rtn: 'tag'
}
]
},
{
@ -20,11 +30,6 @@ export default {
{
cn: 'body',
uidt: 'LongText'
},
{
cn: 'blog_id',
uidt: 'ForeignKey',
rtn: 'blog'
}
]
},
@ -34,11 +39,6 @@ export default {
{
cn: 'title',
uidt: 'SingleLineText'
},
{
cn: 'blog_id',
uidt: 'LinkToAnotherRecord',
rtn: 'blog'
}
]
}

88
packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts

@ -4015,11 +4015,13 @@ export default class NcMetaMgr {
d => d?.meta?.dbAlias === dbAlias
);
const { tables } = new NcTemplateParser(connectionConfig?.client).parse(
const parser = new NcTemplateParser({
client: connectionConfig?.client,
template
);
});
parser.parse();
for (const table of tables) {
for (const table of parser.tables) {
console.log(table);
// create table and trigger listener
@ -4044,23 +4046,81 @@ export default class NcMetaMgr {
}
});
}
// create table
}
// iterate over tables
// iterate over tables
// map column datatypes
// create relations
// group relations
for (const relation of parser.relations) {
// if (args.args.type === 'real') {
const outrel = await this.projectMgr
.getSqlMgr({ id: projectId })
.handleRequest('relationCreate', {
...args,
args: relation
});
if (this.listener) {
await this.listener({
req: {
...args,
args: relation,
api: 'relationCreate'
},
res: outrel,
user: req.user,
ctx: {
req
}
});
}
// } else {
// const outrel = await this.xcVirtualRelationCreate(
// {...args, args: rel1Args},
// req
// );
// if (this.listener) {
// await this.listener({
// req: {
// ...args,
// args: rel1Args,
// api: 'xcVirtualRelationCreate'
// },
// res: outrel,
// user: req.user,
// ctx: {
// req
// }
// });
// }
// create tables
// }
}
// create relations
//create m2m relations
//
for (const m2mRelation of parser.m2mRelations) {
// if (args.args.type === 'real') {
const outrel = await this.xcM2MRelationCreate(
{
...args,
args: m2mRelation
},
req
);
if (this.listener) {
await this.listener({
req: {
...args,
args: m2mRelation,
api: 'xcM2MRelationCreate'
},
res: outrel,
user: req.user,
ctx: {
req
}
});
}
}
}
protected async xcExportAsCsv(args, _req, res: express.Response) {

35
packages/nocodb/src/lib/sqlUi/UITypes.ts

@ -1,6 +1,39 @@
enum UITypes {
ID = 'ID',
LinkToAnotherRecord = 'LinkToAnotherRecord',
ForeignKey = 'ForeignKey'
ForeignKey = 'ForeignKey',
Lookup = 'Lookup',
SingleLineText = 'SingleLineText',
LongText = 'LongText',
Attachment = 'Attachment',
Checkbox = 'Checkbox',
MultiSelect = 'MultiSelect',
SingleSelect = 'SingleSelect',
Collaborator = 'Collaborator',
Date = 'Date',
Year = 'Year',
Time = 'Time',
PhoneNumber = 'PhoneNumber',
Email = 'Email',
URL = 'URL',
Number = 'Number',
Decimal = 'Decimal',
Currency = 'Currency',
Percent = 'Percent',
Duration = 'Duration',
Rating = 'Rating',
Formula = 'Formula',
Rollup = 'Rollup',
Count = 'Count',
DateTime = 'DateTime',
CreateTime = 'CreateTime',
LastModifiedTime = 'LastModifiedTime',
AutoNumber = 'AutoNumber',
Geometry = 'Geometry',
JSON = 'JSON',
SpecificDBType = 'SpecificDBType',
Barcode = 'Barcode',
Button = 'Button'
}
export default UITypes;

111
packages/nocodb/src/lib/templateParser/NcTemplateParser.ts

@ -18,6 +18,7 @@ export default class NcTemplateParser {
private _tables: any[];
private _relations: any[];
private _m2mRelations: any[];
private template: any;
constructor({ client, template }) {
@ -28,12 +29,16 @@ export default class NcTemplateParser {
public parse(template?: any): any {
const tables = [];
this.template = template || this.template;
for (const tableTemplate of this.template._tables) {
for (const tableTemplate of this.template.tables) {
const table = this.extractTable(tableTemplate);
tables.push(table);
}
this._tables = tables;
for (const tableTemplate of this.template.tables) {
this.extractRelations(tableTemplate);
}
}
private extractTable(tableTemplate) {
@ -65,28 +70,97 @@ export default class NcTemplateParser {
if (!tableColumn?.cn) {
throw Error('Missing column name in template');
}
if (
tableColumn.uidt === UITypes.LinkToAnotherRecord ||
tableColumn.uidt === UITypes.ForeignKey
) {
// todo :
} else {
const column = {
...this.sqlUi.getNewColumn(''),
cn: tableColumn.cn,
_cn: tableColumn.cn,
uidt: tableColumn.uidt,
...this.sqlUi.getDataTypeForUiType(tableColumn)
};
columns.push(column);
switch (tableColumn.uidt) {
// case UITypes.ForeignKey:
// // todo :
// this.extractRelations(tableColumn, 'bt');
// break;
// case UITypes.LinkToAnotherRecord:
// // todo :
// this.extractRelations(tableColumn, 'hm');
// // this.extractRelations(tableColumn, 'mm');
// break;
default:
columns.push({
...this.sqlUi.getNewColumn(''),
cn: tableColumn.cn,
_cn: tableColumn.cn,
uidt: tableColumn.uidt,
...this.sqlUi.getDataTypeForUiType(tableColumn)
});
break;
}
}
return columns;
}
protected extractRelations(_columnTemplate) {
protected extractRelations(tableTemplate) {
if (!this._relations) this._relations = [];
if (!this._m2mRelations) this._m2mRelations = [];
for (const hasMany of tableTemplate.hasMany || []) {
const childTable = this.tables.find(table => table.tn === hasMany.tn);
const partentTable = this.tables.find(
table => table.tn === tableTemplate.tn
);
const parentPrimaryColumn = partentTable.columns.find(
column => column.uidt === UITypes.ID
);
// add a column in child table
const childColumnName = `${tableTemplate.tn}_id`;
childTable.columns.push({
cn: childColumnName,
_cn: childColumnName,
rqd: false,
pk: false,
ai: false,
cdf: null,
dt: parentPrimaryColumn.dt,
dtxp: parentPrimaryColumn.dtxp,
dtxs: parentPrimaryColumn.dtxs,
un: parentPrimaryColumn.un,
altered: 1
});
// add relation create entry
this._relations.push({
childColumn: childColumnName,
childTable: hasMany.tn,
onDelete: 'NO ACTION',
onUpdate: 'NO ACTION',
parentColumn: parentPrimaryColumn.cn,
parentTable: tableTemplate.tn,
type: 'real',
updateRelation: false
});
}
for (const manyToMany of tableTemplate.manyToMany || []) {
// @ts-ignore
const childTable = this.tables.find(table => table.tn === manyToMany.rtn);
const parentTable = this.tables.find(
table => table.tn === tableTemplate.tn
);
const parentPrimaryColumn = parentTable.columns.find(
column => column.uidt === UITypes.ID
);
const childPrimaryColumn = childTable.columns.find(
column => column.uidt === UITypes.ID
);
// add many to many relation create entry
this._m2mRelations.push({
alias: 'title8',
childColumn: childPrimaryColumn.cn,
childTable: childTable.tn,
onDelete: 'NO ACTION',
onUpdate: 'NO ACTION',
parentColumn: parentPrimaryColumn.cn,
parentTable: parentTable.tn,
type: 'real',
updateRelation: false
});
}
}
get tables(): any[] {
@ -96,4 +170,7 @@ export default class NcTemplateParser {
get relations(): any[] {
return this._relations;
}
get m2mRelations(): any[] {
return this._m2mRelations;
}
}

Loading…
Cancel
Save