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