@ -1,7 +1,8 @@
import { RelationTypes , UITypes } from 'nocodb-sdk' ;
import type { NcUpgraderCtx } from '~/version-upgrader/NcUpgrader' ;
import type { MetaService } from '~/meta/meta.service' ;
import { MetaTable } from '~/utils/globals' ;
import { MetaService } from "~/meta/meta.service" ;
import { Column } from '~/models' ;
/ * *
* This upgrader look for any broken link and try to recover it
@ -25,7 +26,7 @@ export default async function ({ ncMeta }: NcUpgraderCtx) {
. leftJoin (
MetaTable . COL_RELATIONS ,
` ${ MetaTable . COLUMNS } .id ` ,
` ${ MetaTable . COL_SELECT_OP TIONS } .fk_column_id ` ,
` ${ MetaTable . COL_RELA TIONS } .fk_column_id ` ,
)
. where ( ` ${ MetaTable . COLUMNS } .uidt ` , UITypes . LinkToAnotherRecord )
. whereNull ( ` ${ MetaTable . COL_RELATIONS } .id ` ) ;
@ -78,7 +79,10 @@ export default async function ({ ncMeta }: NcUpgraderCtx) {
const linksQb = ncMeta
. knex ( MetaTable . COL_RELATIONS )
. select ( ` ${ MetaTable . COL_RELATIONS } .* ` )
. where ( ` ${ MetaTable . COL_RELATIONS } .fk_related_model_id ` , column . fk_model_id ) ;
. where (
` ${ MetaTable . COL_RELATIONS } .fk_related_model_id ` ,
column . fk_model_id ,
) ;
if ( relatedTableId ) {
linksQb
. join (
@ -87,163 +91,197 @@ export default async function ({ ncMeta }: NcUpgraderCtx) {
` ${ MetaTable . COLUMNS } .id ` ,
)
. where ( ` ${ MetaTable . COLUMNS } .fk_model_id ` , relatedTableId ) ;
}
const links = await linksQb ;
// iterate over all links which is related to current table and if found relation which doesn't have link in the related table then use it to populate colOptions
for ( const link of links ) {
let columnInCurrTable = null ;
if ( link . type === RelationTypes . HAS_MANY ) {
// check for bt column in current table
columnInCurrTable = await ncMeta
. knex ( MetaTable . COL_RELATIONS )
. join (
MetaTable . COLUMNS ,
` ${ MetaTable . COL_RELATIONS } .fk_column_id ` ,
` ${ MetaTable . COLUMNS } .id ` ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .fk_model_id ` , currentTableId )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_related_model_id ` ,
relatedTableId ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .type ` , RelationTypes . BELONGS_TO )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_child_column_id ` ,
link . fk_child_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_parent_column_id ` ,
link . fk_parent_column_id ,
) ;
} else if ( link . type === RelationTypes . ONE_TO_ONE ) {
// check for one to one column in current table and confirm type in meta
columnInCurrTable = await ncMeta
. knex ( MetaTable . COL_RELATIONS )
. join (
MetaTable . COLUMNS ,
` ${ MetaTable . COL_RELATIONS } .fk_column_id ` ,
` ${ MetaTable . COLUMNS } .id ` ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .fk_model_id ` , currentTableId )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_related_model_id ` ,
relatedTableId ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .type ` , RelationTypes . ONE_TO_ONE )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_child_column_id ` ,
link . fk_child_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_parent_column_id ` ,
link . fk_parent_column_id ,
) ;
} else if ( link . type === RelationTypes . BELONGS_TO ) {
// check for hm column in current table
columnInCurrTable = await ncMeta
. knex ( MetaTable . COL_RELATIONS )
. join (
MetaTable . COLUMNS ,
` ${ MetaTable . COL_RELATIONS } .fk_column_id ` ,
` ${ MetaTable . COLUMNS } .id ` ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .fk_model_id ` , currentTableId )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_related_model_id ` ,
relatedTableId ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .type ` , RelationTypes . HAS_MANY )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_child_column_id ` ,
link . fk_child_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_parent_column_id ` ,
link . fk_parent_column_id ,
) ;
} else if ( link . type === RelationTypes . MANY_TO_MANY ) {
// check for mtm column in current table
columnInCurrTable = await ncMeta
. knex ( MetaTable . COL_RELATIONS )
. join (
MetaTable . COLUMNS ,
` ${ MetaTable . COL_RELATIONS } .fk_column_id ` ,
` ${ MetaTable . COLUMNS } .id ` ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .fk_model_id ` , currentTableId )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_related_model_id ` ,
relatedTableId ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .type ` , RelationTypes . BELONGS_TO )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_child_column_id ` ,
link . fk_parent_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_parent_column_id ` ,
link . fk_parent_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_mm_model_id ` ,
link . fk_mm_model_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_mm_child_column_id ` ,
link . fk_mm_parent_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_mm_parent_column_id ` ,
link . fk_mm_child_column_id ,
) ;
}
const links = await linksQb ;
// iterate over all links which is related to current table and if found relation which doesn't have link in the related table then use it to populate colOptions
for ( const link of links ) {
let columnInCurrTable null ;
if ( link . type === RelationTypes . HAS_MANY ) {
// check for bt column in current table
columnInCurrTable = await ncMeta
. knex ( MetaTable . COL_RELATIONS )
. join (
MetaTable . COLUMNS ,
` ${ MetaTable . COL_RELATIONS } .fk_column_id ` ,
` ${ MetaTable . COLUMNS } .id ` ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .fk_model_id ` , currentTableId )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_related_model_id ` ,
relatedTableId ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .type ` , RelationTypes . BELONGS_TO )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_child_column_id ` ,
link . fk_child_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_parent_column_id ` ,
link . fk_parent_column_id ,
) ;
} else if ( link . type === RelationTypes . ONE_TO_ONE ) {
// check for one to one column in current table and confirm type in meta
columnInCurrTable = await ncMeta
. knex ( MetaTable . COL_RELATIONS )
. join (
MetaTable . COLUMNS ,
` ${ MetaTable . COL_RELATIONS } .fk_column_id ` ,
` ${ MetaTable . COLUMNS } .id ` ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .fk_model_id ` , currentTableId )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_related_model_id ` ,
relatedTableId ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .type ` , RelationTypes . ONE_TO_ONE )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_child_column_id ` ,
link . fk_child_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_parent_column_id ` ,
link . fk_parent_column_id ,
) ;
} else if ( link . type === RelationTypes . BELONGS_TO ) {
// check for hm column in current table
columnInCurrTable = await ncMeta
. knex ( MetaTable . COL_RELATIONS )
. join (
MetaTable . COLUMNS ,
` ${ MetaTable . COL_RELATIONS } .fk_column_id ` ,
` ${ MetaTable . COLUMNS } .id ` ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .fk_model_id ` , currentTableId )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_related_model_id ` ,
relatedTableId ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .type ` , RelationTypes . HAS_MANY )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_child_column_id ` ,
link . fk_child_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_parent_column_id ` ,
link . fk_parent_column_id ,
) ;
} else if ( link . type === RelationTypes . MANY_TO_MANY ) {
// check for mtm column in current table
columnInCurrTable = await ncMeta
. knex ( MetaTable . COL_RELATIONS )
. join (
MetaTable . COLUMNS ,
` ${ MetaTable . COL_RELATIONS } .fk_column_id ` ,
` ${ MetaTable . COLUMNS } .id ` ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .fk_model_id ` , currentTableId )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_related_model_id ` ,
relatedTableId ,
)
. where ( ` ${ MetaTable . COL_RELATIONS } .type ` , RelationTypes . BELONGS_TO )
. where (
` ${ MetaTable . COL_RELATIONS } .fk_child_column_id ` ,
link . fk_parent_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_parent_column_id ` ,
link . fk_parent_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_mm_model_id ` ,
link . fk_mm_model_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_mm_child_column_id ` ,
link . fk_mm_parent_column_id ,
)
. where (
` ${ MetaTable . COL_RELATIONS } .fk_mm_parent_column_id ` ,
link . fk_mm_child_column_id ,
) ;
if ( ! columnInCurrTable ) {
// generate meta and insert into colOptions
const commonProps = {
id : ( ncMeta as MetaService ) . genNanoid ( MetaTable . COL_RELATIONS ) ,
fk_column_id : column.id ,
fk_related_model_id : relatedTableId ,
created_at : link.created_at ,
updated_at : link.updated_at ,
virtual : link.virtual ,
} ;
// based on type insert data into colOptions
switch ( link . type ) {
case RelationTypes . HAS_MANY :
// insert data into colOptions
ncMeta . knex ( MetaTable . COL_RELATIONS ) . insert ( {
. . . commonProps ,
type : RelationTypes . BELONGS_TO ,
fk_child_column_id : link.fk_child_column_id ,
fk_parent_column_id : link.fk_parent_column_id ,
} ) ;
break ;
case RelationTypes . ONE_TO_ONE :
// todo:
const meta = {
bt : false ,
} ;
// insert data into colOptions
ncMeta . knex ( MetaTable . COL_RELATIONS ) . insert ( {
. . . commonProps ,
type : RelationTypes . ONE_TO_ONE ,
fk_child_column_id : link.fk_child_column_id ,
fk_parent_column_id : link.fk_parent_column_id ,
meta ,
} ) ;
break ;
case RelationTypes . BELONGS_TO :
// insert data into colOptions
ncMeta . knex ( MetaTable . COL_RELATIONS ) . insert ( {
. . . commonProps ,
type : RelationTypes . HAS_MANY ,
fk_child_column_id : link.fk_child_column_id ,
fk_parent_column_id : link.fk_parent_column_id ,
} ) ;
break ;
case RelationTypes . MANY_TO_MANY :
// insert data into colOptions
ncMeta . knex ( MetaTable . COL_RELATIONS ) . insert ( {
. . . commonProps ,
type : RelationTypes . ONE_TO_ONE ,
fk_child_column_id : link.fk_parent_column_id ,
fk_parent_column_id : link.fk_child_column_id ,
fk_mm_model_id : link.fk_mm_model_id ,
fk_mm_child_column_id : link.fk_mm_parent_column_id ,
fk_mm_parent_column_id : link.fk_mm_child_column_id ,
} ) ;
break ;
}
if ( ! columnInCurrTable ) {
// generate meta and insert into colOptions
// based on type insert data into colOptions
switch ( link . type ) {
case RelationTypes . HAS_MANY :
// insert data into colOptions
ncMeta . knex ( MetaTable . COL_RELATIONS ) . insert ( {
id : ( ncMeta as MetaService ) . genNanoid ( MetaTable . COL_RELATIONS ) ,
type : RelationTypes . BELONGS_TO ,
fk_column_id : column.id ,
fk_related_model_id : relatedTableId ,
break ;
case RelationTypes . ONE_TO_ONE :
// insert data into colOptions
break ;
case RelationTypes . BELONGS_TO :
// insert data into colOptions
break ;
case RelationTypes . MANY_TO_MANY :
// insert data into colOptions
break ;
}
break ;
}
break ;
} else {
logger . error (
` Couldn't find any column in current table which is related to the link ' ${ link . id } '. ` ,
) ;
// delete the link column since it's not useful anymore and not recoverable
await Column . delete (
{
workspace_id : column.workspace_id ,
base_id : column.base_id ,
} ,
column . id ,
ncMeta ,
) ;
}
}
}