Browse Source

feat: relation across bases

pull/8367/head
Pranav C 5 months ago
parent
commit
0ee27e716c
  1. 2
      packages/nc-gui/components/smartsheet/Cell.vue
  2. 17
      packages/nc-gui/components/smartsheet/PlainCell.vue
  3. 86
      packages/nc-gui/components/smartsheet/column/LinkAdvancedOptions.vue
  4. 2
      packages/nc-gui/components/smartsheet/toolbar/FilterInput.vue
  5. 175
      packages/nocodb/src/db/BaseModelSqlv2.ts
  6. 33
      packages/nocodb/src/db/genRollupSelectv2.ts
  7. 12
      packages/nocodb/src/services/columns.service.ts
  8. 1
      packages/nocodb/tsconfig.json

2
packages/nc-gui/components/smartsheet/Cell.vue

@ -51,7 +51,7 @@ const { currentRow } = useSmartsheetRowStoreOrThrow()
const { sqlUis } = storeToRefs(useBase())
const sqlUi = ref(column.value?.source_id ? sqlUis.value[column.value?.source_id] : Object.values(sqlUis.value)[0])
const sqlUi = ref(column.value?.source_id && sqlUis.value[column.value?.source_id] ? sqlUis.value[column.value?.source_id] : Object.values(sqlUis.value)[0])
const abstractType = computed(() => column.value && sqlUi.value.getAbstractType(column.value))

17
packages/nc-gui/components/smartsheet/PlainCell.vue

@ -37,7 +37,9 @@ const { basesUser } = storeToRefs(basesStore)
const { isXcdbBase, isMssql, isMysql } = useBase()
const sqlUi = ref(column.value?.source_id ? sqlUis.value[column.value?.source_id] : Object.values(sqlUis.value)[0])
const { getPossibleAttachmentSrc } = useAttachment()
const sqlUi = ref(column.value?.source_id && sqlUis.value[column.value?.source_id] ? sqlUis.value[column.value?.source_id] : Object.values(sqlUis.value)[0])
const abstractType = computed(() => column.value && sqlUi.value.getAbstractType(column.value))
@ -246,7 +248,7 @@ const getLookupValue = (modelValue: string | null | number | Array<any>, col: Co
const getAttachmentValue = (modelValue: string | null | number | Array<any>) => {
if (Array.isArray(modelValue)) {
return modelValue.map((v) => `${v.title}`).join(', ')
return modelValue.map((v) => `${v.title} (${getPossibleAttachmentSrc(v).join(', ')})`).join(', ')
}
return modelValue as string
}
@ -341,20 +343,20 @@ const parseValue = (value: any, col: ColumnType): string => {
<template>
<span
class="plain-cell before:px-1"
class="calendar-cell text-xs before:px-1"
:class="{
'!font-bold': bold,
'font-bold': bold,
'italic': italic,
'underline': underline,
}"
data-testid="nc-plain-cell"
data-testid="nc-calendar-cell"
>
{{ parseValue(modelValue, column) }}
</span>
</template>
<style lang="scss" scoped>
.plain-cell {
.calendar-cell {
&::before {
content: '•';
padding: 0 4px;
@ -363,8 +365,5 @@ const parseValue = (value: any, col: ColumnType): string => {
content: '';
padding: 0;
}
&:first-child {
padding-left: 0;
}
}
</style>

86
packages/nc-gui/components/smartsheet/column/LinkAdvancedOptions.vue

@ -1,14 +1,15 @@
<script setup lang="ts">
import { useColumnCreateStoreOrThrow, useVModel, computed, inject, MetaInj, ref, useI18n,useBase, storeToRefs, useMetas } from '#imports'
import { useColumnCreateStoreOrThrow, useVModel, computed, inject, MetaInj, ref, useI18n,useBase,
useBases, storeToRefs, useMetas } from '#imports'
import {
isCreatedOrLastModifiedByCol,
isCreatedOrLastModifiedTimeCol,
isVirtualCol,
ModelTypes,
RelationTypes,
UITypes
} from "nocodb-sdk";
import type {ColumnType} from "nocodb-sdk";
import {useTable} from "../../../composables/useTable";
import {useTablesStore} from "../../../store/tables";
const props = defineProps<{
value: any
@ -25,7 +26,7 @@ const vModel = useVModel(props, 'value', emit)
const { validateInfos, setAdditionalValidations, onDataTypeChange } = useColumnCreateStoreOrThrow()
const baseStore = useBase()
const { tables } = storeToRefs(baseStore)
// const { tables } = storeToRefs(baseStore)
const { metas, getMeta } = useMetas()
@ -35,16 +36,30 @@ const isMm = computed(() => vModel.value.type === RelationTypes.MANY_TO_MANY)
// set default value
vModel.value.custom = {
base_id: meta.value?.base_id
}
const refTables = computed(() =>{
const { basesList, bases } = storeToRefs(useBases())
const tablesStore = useTablesStore()
const { baseTables } = storeToRefs(tablesStore)
/*const refTables = computed(() =>{
if (!tables.value || !tables.value.length) {
return []
}
return tables.value.filter((t) => t.type === ModelTypes.TABLE && t.source_id === meta.value?.source_id)
})*/
const refTables = computed(() =>{
if (!baseTables.value.get(vModel.value.custom.base_id)) {
return []
}
return [...baseTables.value.get(vModel.value.custom.base_id).filter((t) => t.type === ModelTypes.TABLE),
...(vModel.value.custom.base_id !== meta.value?.base_id ? baseTables.value.get(meta.value.base_id).filter((t) => t.type === ModelTypes.TABLE) : [])
]
})
@ -75,30 +90,37 @@ const juncTableColumns = computed(() => {
})
const filterOption = (value: string, option: { key: string }) => option.key.toLowerCase().includes(value.toLowerCase())
const onModelIdChange =async (modelId:string) =>{
// todo: optimise
await getMeta(modelId, false, false, vModel.value.custom.base_id)
await getMeta(modelId)
await onDataTypeChange()
}
const onBaseChange = async (baseId) =>{
await tablesStore.loadProjectTables(baseId)
vModel.value.custom.ref_model_id = null
}
</script>
<template>
<div v-if="validateInfos">
<div class="flex flex-row space-x-2">
<a-form-item
class="flex w-full pb-2 mt-4 nc-ltar-child-table"
label="Column"
v-bind="validateInfos['custom.column_id']"
class="flex w-full pb-2 mt-4 nc-ltar-child-table"
label="Column"
v-bind="validateInfos['custom.column_id']"
>
<a-select
v-model:value="vModel.custom.column_id"
show-search
:filter-option="filterOption"
dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onDataTypeChange"
v-model:value="vModel.custom.column_id"
show-search
:filter-option="filterOption"
dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onDataTypeChange"
>
<a-select-option v-for="column of columns" :key="column.title" :value="column.id">
<div class="flex w-full items-center gap-2">
@ -113,6 +135,32 @@ const onModelIdChange =async (modelId:string) =>{
</a-select-option>
</a-select>
</a-form-item>
<a-form-item
class="flex w-full pb-2 mt-4 nc-ltar-child-table"
label="Target base"
v-bind="validateInfos['custom.base_id']"
>
<a-select
v-model:value="vModel.custom.base_id"
show-search
:filter-option="filterOption"
dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onBaseChange(vModel.custom.base_id)"
>
<a-select-option v-for="base of basesList" :key="base.title" :value="base.id">
<div class="flex w-full items-center gap-2">
<div class="min-w-5 flex items-center justify-center">
<GeneralTableIcon :meta="base" class="text-gray-500" />
</div>
<NcTooltip class="flex-1 truncate" show-on-truncate-only>
<template #title>{{ base.title }}</template>
<span>{{ base.title }}</span>
</NcTooltip>
</div>
</a-select-option>
</a-select>
</a-form-item>
</div>
<div class="flex flex-row space-x-2">
<a-form-item
@ -127,14 +175,14 @@ const onModelIdChange =async (modelId:string) =>{
dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onModelIdChange(vModel.custom.ref_model_id)"
>
<a-select-option v-for="table of tables" :key="table.title" :value="table.id">
<a-select-option v-for="table of refTables" :key="table.title" :value="table.id">
<div class="flex w-full items-center gap-2">
<div class="min-w-5 flex items-center justify-center">
<GeneralTableIcon :meta="table" class="text-gray-500" />
</div>
<NcTooltip class="flex-1 truncate" show-on-truncate-only>
<template #title>{{ table.title }}</template>
<span>{{ table.title }}</span>
<span>{{ table.title }} <span class="text-8px">({{bases.get(table.base_id)?.title }})</span></span>
</NcTooltip>
</div>
</a-select-option>
@ -183,14 +231,14 @@ const onModelIdChange =async (modelId:string) =>{
dropdown-class-name="nc-dropdown-ltar-child-table"
@change="onModelIdChange(vModel.custom.junc_model_id)"
>
<a-select-option v-for="table of tables" :key="table.title" :value="table.id">
<a-select-option v-for="table of refTables" :key="table.title" :value="table.id">
<div class="flex w-full items-center gap-2">
<div class="min-w-5 flex items-center justify-center">
<GeneralTableIcon :meta="table" class="text-gray-500" />
</div>
<NcTooltip class="flex-1 truncate" show-on-truncate-only>
<template #title>{{ table.title }}</template>
<span>{{ table.title }}</span>
<span>{{ table.title }} <span class="text-8px">({{bases.get(table.base_id)?.title }})</span></span>
</NcTooltip>
</div>
</a-select-option>

2
packages/nc-gui/components/smartsheet/toolbar/FilterInput.vue

@ -65,7 +65,7 @@ type FilterType = keyof typeof checkTypeFunctions
const { sqlUis } = storeToRefs(useBase())
const sqlUi = ref(column.value?.source_id ? sqlUis.value[column.value?.source_id] : Object.values(sqlUis.value)[0])
const sqlUi = ref(column.value?.source_id && sqlUis.value[column.value?.source_id] ? sqlUis.value[column.value?.source_id] : Object.values(sqlUis.value)[0])
const abstractType = computed(() => column.value && sqlUi.value.getAbstractType(column.value))

175
packages/nocodb/src/db/BaseModelSqlv2.ts

@ -1713,13 +1713,14 @@ class BaseModelSqlv2 {
)) as LinkToAnotherRecordColumn
).getParentColumn(this.context);
const parentTable = await parentCol.getModel(this.context);
const childModel = await Model.getBaseModelSQL(this.context, {
const childBaseModel = await Model.getBaseModelSQL(this.context, {
model: childTable,
dbDriver: this.dbDriver,
});
await parentTable.getColumns(this.context);
const childTn = this.getTnPath(childTable);
const childTn = childBaseModel.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const qb = this.dbDriver(childTn);
@ -1736,7 +1737,7 @@ class BaseModelSqlv2 {
qb.limit(+rest?.limit || 25);
qb.offset(+rest?.offset || 0);
await childModel.selectObject({
await childBaseModel.selectObject({
qb,
fieldsSet: args.fieldSet,
});
@ -1790,7 +1791,11 @@ class BaseModelSqlv2 {
const parentTable = await parentCol.getModel(this.context);
await parentTable.getColumns(this.context);
const childTn = this.getTnPath(childTable);
const childBaseModel = await Model.getBaseModelSQL({
dbDriver: this.dbDriver,
model: childTable,
});
const childTn = childBaseModel.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const query = this.dbDriver(childTn)
@ -1945,7 +1950,12 @@ class BaseModelSqlv2 {
)) as LinkToAnotherRecordColumn;
const mmTable = await relColOptions.getMMModel(this.context);
const vtn = this.getTnPath(mmTable);
const assocBaseModel = await Model.getBaseModelSQL({
id: mmTable.id,
dbDriver: this.dbDriver,
});
const vtn = assocBaseModel.getTnPath(mmTable);
const vcn = (await relColOptions.getMMChildColumn(this.context))
.column_name;
const vrcn = (await relColOptions.getMMParentColumn(this.context))
@ -1980,8 +1990,12 @@ class BaseModelSqlv2 {
).getModel(this.context);
await parentTable.getColumns(this.context);
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const parentBaseModel = await Model.getBaseModelSQL({
id: parentTable.id,
dbDriver: this.dbDriver,
});
const childTn = childBaseModel.getTnPath(childTable);
const parentTn = parentBaseModel.getTnPath(parentTable);
const rtn = childTn;
const qb = this.dbDriver(rtn)
@ -2002,7 +2016,7 @@ class BaseModelSqlv2 {
).orWhereNull(rcn);
});
const aliasColObjMap = await childTable.getAliasColObjMap(this.context);
const aliasColObjMap = await childTable.getAliasColObjMap(this.context);
const filterObj = extractFilterFromXwhere(where, aliasColObjMap);
await this.getCustomConditionsAndApply({
@ -2096,7 +2110,13 @@ class BaseModelSqlv2 {
)) as LinkToAnotherRecordColumn;
const mmTable = await relColOptions.getMMModel(this.context);
const vtn = this.getTnPath(mmTable);
const assocBaseModel = await Model.getBaseModelSQL({
model: mmTable,
dbDriver: this.dbDriver,
});
const vtn = assocBaseModel.getTnPath(mmTable);
const vcn = (await relColOptions.getMMChildColumn(this.context))
.column_name;
const vrcn = (await relColOptions.getMMParentColumn(this.context))
@ -2112,7 +2132,12 @@ class BaseModelSqlv2 {
).getModel(this.context);
await parentTable.getColumns(this.context);
const childTn = this.getTnPath(childTable);
const childBaseModel = await Model.getBaseModelSQL({
dbDriver: this.dbDriver,
model: childTable,
});
const childTn = childBaseModel.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const rtn = childTn;
@ -2162,20 +2187,33 @@ class BaseModelSqlv2 {
)) as LinkToAnotherRecordColumn;
const mmTable = await relColOptions.getMMModel(this.context);
const vtn = this.getTnPath(mmTable);
const assocBaseModel = await Model.getBaseModelSQL({
id: mmTable.id,
dbDriver: this.dbDriver,
});
const vtn = assocBaseModel.getTnPath(mmTable);
const vcn = (await relColOptions.getMMChildColumn(this.context))
.column_name;
const vrcn = (await relColOptions.getMMParentColumn(this.context))
.column_name;
const rcn = (await relColOptions.getParentColumn(this.context)).column_name;
const cn = (await relColOptions.getChildColumn(this.context)).column_name;
const childTable = await (
await relColOptions.getParentColumn(this.context)
).getModel(this.context);
const childModel = await Model.getBaseModelSQL(this.context, {
const childTable = await (await relColOptions.getParentColumn(this.cotext)).getModel(this.cotext);
const parentTable = await (await relColOptions.getChildColumn(this.cotext)).getModel(this.cotext);
await parentTable.getColumns();
const parentBaseModel = await Model.getBaseModelSQL({
id: parentTable.id,
dbDriver: this.dbDriver,
model: childTable,
});
const childBaseModel = await Model.getBaseModelSQL({
dbDriver: this.dbDriver,
id: childTable.id,
});
const childTn = childBaseModel.getTnPath(childTable);
const parentTn = parentBaseModel.getTnPath(parentTable);
const childView = await relColOptions.getChildView(this.context);
let listArgs: any = {};
if (childView) {
@ -2188,14 +2226,6 @@ class BaseModelSqlv2 {
listArgs = dependencyFields;
}
const parentTable = await (
await relColOptions.getChildColumn(this.context)
).getModel(this.context);
await parentTable.getColumns(this.context);
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const rtn = childTn;
const qb = this.dbDriver(rtn).where((qb) =>
@ -2288,8 +2318,8 @@ class BaseModelSqlv2 {
const childView = await relColOptions.getChildView(this.context);
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const childTn = childBaseModel.getTnPath(childTable);
const parentTn = parentBaseModel.getTnPath(parentTable);
const tn = childTn;
const rtn = parentTn;
@ -2308,7 +2338,7 @@ class BaseModelSqlv2 {
await this.shuffle({ qb });
}
await childModel.selectObject({ qb });
await childBaseModel.selectObject({ qb });
const aliasColObjMap = await childTable.getAliasColObjMap(this.context);
const filterObj = extractFilterFromXwhere(where, aliasColObjMap);
@ -2330,12 +2360,11 @@ class BaseModelSqlv2 {
applyPaginate(qb, rest);
const proto = await childModel.getProto();
const proto = await childBaseModel.getProto();
const data = await this.execAndParse(
qb,
await childTable.getColumns(this.context),
);
return data.map((c) => {
c.__proto__ = proto;
return c;
@ -2367,7 +2396,12 @@ class BaseModelSqlv2 {
const childView = await relColOptions.getChildView(this.context);
const childTn = this.getTnPath(childTable);
const childBaseModel = await Model.getBaseModelSQL({
dbDriver: this.dbDriver,
model: childTable,
});
const childTn = childBaseModel.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const tn = childTn;
@ -2431,7 +2465,12 @@ class BaseModelSqlv2 {
dbDriver: this.dbDriver,
model: childTable,
});
const childBaseModel = await Model.getBaseModelSQL({
dbDriver: this.dbDriver,
model: childTable,
});
const childTn = childBaseModel.getTnPath(childTable);
const childView = await relColOptions.getChildView(this.context);
let listArgs: any = {};
if (childView) {
@ -2530,8 +2569,13 @@ class BaseModelSqlv2 {
await relColOptions.getChildColumn(this.context)
).getModel(this.context);
const parentBaseModel = await Model.getBaseModelSQL({
dbDriver: this.dbDriver,
model: parentTable,
});
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const parentTn = parentBaseModel.getTnPath(parentTable);
const rtn = parentTn;
const tn = childTn;
@ -2652,13 +2696,13 @@ class BaseModelSqlv2 {
const childTable = await (
await relColOptions.getChildColumn(this.context)
).getModel(this.context);
const parentModel = await Model.getBaseModelSQL(this.context, {
const parentBaseModel = await Model.getBaseModelSQL(this.context, {
dbDriver: this.dbDriver,
model: parentTable,
});
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const parentTn = parentBaseModel.getTnPath(parentTable);
const rtn = parentTn;
const tn = childTn;
@ -2679,7 +2723,7 @@ class BaseModelSqlv2 {
await this.shuffle({ qb });
}
await parentModel.selectObject({ qb });
await parentBaseModel.selectObject({ qb });
const aliasColObjMap = await parentTable.getAliasColObjMap(this.context);
const filterObj = extractFilterFromXwhere(where, aliasColObjMap);
@ -2706,7 +2750,7 @@ class BaseModelSqlv2 {
applyPaginate(qb, rest);
const proto = await parentModel.getProto();
const proto = await parentBaseModel.getProto();
const data = await this.execAndParse(
qb,
await parentTable.getColumns(this.context),
@ -5525,8 +5569,19 @@ class BaseModelSqlv2 {
await childTable.getColumns(this.context);
await parentTable.getColumns(this.context);
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const parentBaseModel = await Model.getBaseModelSQL({
model: parentTable,
dbDriver: this.dbDriver,
});
const childBaseModel = await Model.getBaseModelSQL({
dbDriver: this.dbDriver,
model: childTable,
});
const childTn = childBaseModel.getTnPath(childTable);
const parentTn = parentBaseModel.getTnPath(parentTable);
const relatedChildCol = getRelatedLinksColumn(
column,
@ -5582,15 +5637,20 @@ class BaseModelSqlv2 {
const vParentCol = await colOptions.getMMParentColumn(this.context);
const vTable = await colOptions.getMMModel(this.context);
const vTn = this.getTnPath(vTable);
const assocBaseModel = await Model.getBaseModelSQL({
model: vTable,
dbDriver: this.dbDriver,
});
const vTn = assocBaseModel.getTnPath(vTable);
if (this.isSnowflake || this.isDatabricks) {
const parentPK = this.dbDriver(parentTn)
const parentPK = parentBaseModel.dbDriver(parentTn)
.select(parentColumn.column_name)
.where(_wherePk(parentTable.primaryKeys, childId))
.first();
const childPK = this.dbDriver(childTn)
const childPK = childBaseModel.dbDriver(childTn)
.select(childColumn.column_name)
.where(_wherePk(childTable.primaryKeys, rowId))
.first();
@ -5621,11 +5681,13 @@ class BaseModelSqlv2 {
}
await this.updateLastModified({
baseModel: parentBaseModel,
model: parentTable,
rowIds: [childId],
cookie,
});
await this.updateLastModified({
baseModel: childBaseModel,
model: childTable,
rowIds: [rowId],
cookie,
@ -5699,6 +5761,7 @@ class BaseModelSqlv2 {
await triggerAfterRemoveChild();
await this.updateLastModified({
baseModel: parentBaseModel,
model: parentTable,
rowIds: [rowId],
cookie,
@ -5811,6 +5874,7 @@ class BaseModelSqlv2 {
await triggerAfterRemoveChild();
await this.updateLastModified({
baseModel: parentBaseModel,
model: parentTable,
rowIds: [childId],
cookie,
@ -6060,6 +6124,7 @@ class BaseModelSqlv2 {
);
await this.updateLastModified({
baseModel: parentBaseModel,
model: parentTable,
rowIds: [childId],
cookie,
@ -6176,8 +6241,18 @@ class BaseModelSqlv2 {
await childTable.getColumns(this.context);
await parentTable.getColumns(this.context);
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const parentBaseModel = await Model.getBaseModelSQL({
model: parentTable,
dbDriver: this.dbDriver,
});
const childBaseModel = await Model.getBaseModelSQL({
dbDriver: this.dbDriver,
model: childTable,
});
const childTn = childBaseModel.getTnPath(childTable);
const parentTn = parentBaseModel.getTnPath(parentTable);
const relatedChildCol = getRelatedLinksColumn(
column,
@ -6210,8 +6285,11 @@ class BaseModelSqlv2 {
const vChildCol = await colOptions.getMMChildColumn(this.context);
const vParentCol = await colOptions.getMMParentColumn(this.context);
const vTable = await colOptions.getMMModel(this.context);
const vTn = this.getTnPath(vTable);
const assocBaseModel = await Model.getBaseModelSQL({
model: vTable,
dbDriver: this.dbDriver,
});
const vTn = assocBaseModel.getTnPath(vTable);
await this.execAndParse(
this.dbDriver(vTn)
@ -6231,11 +6309,13 @@ class BaseModelSqlv2 {
);
await this.updateLastModified({
baseModel: parentBaseModel,
model: parentTable,
rowIds: [childId],
cookie,
});
await this.updateLastModified({
baseModel: childBaseModel,
model: childTable,
rowIds: [rowId],
cookie,
@ -6264,6 +6344,7 @@ class BaseModelSqlv2 {
);
await this.updateLastModified({
baseModel: parentBaseModel,
model: parentTable,
rowIds: [rowId],
cookie,
@ -6290,6 +6371,7 @@ class BaseModelSqlv2 {
);
await this.updateLastModified({
baseModel: parentBaseModel,
model: parentTable,
rowIds: [childId],
cookie,
@ -6312,6 +6394,7 @@ class BaseModelSqlv2 {
);
await this.updateLastModified({
baseModel: parentBaseModel,
model: parentTable,
rowIds: [childId],
cookie,
@ -8027,11 +8110,13 @@ class BaseModelSqlv2 {
cookie,
model = this.model,
knex = this.dbDriver,
baseModel = this,
}: {
rowIds: any | any[];
cookie?: { user?: any };
model?: Model;
knex?: XKnex;
baseModel?: BaseModelSqlv2
}) {
const columns = await model.getColumns(this.context);
@ -8055,7 +8140,7 @@ class BaseModelSqlv2 {
if (Object.keys(updateObject).length === 0) return;
const qb = knex(this.getTnPath(model.table_name)).update(updateObject);
const qb = knex(baseModel.getTnPath(model.table_name)).update(updateObject);
for (const rowId of Array.isArray(rowIds) ? rowIds : [rowIds]) {
qb.orWhere(_wherePk(model.primaryKeys, rowId));

33
packages/nocodb/src/db/genRollupSelectv2.ts

@ -7,6 +7,7 @@ import type {
} from '~/models';
import type { XKnex } from '~/db/CustomKnex';
import type { Knex } from 'knex';
import { Model } from '~/models';
export default async function ({
baseModelSqlv2,
@ -33,11 +34,20 @@ export default async function ({
const parentModel = await parentCol?.getModel(context);
const refTableAlias = `__nc_rollup`;
const parentBaseModel = await Model.getBaseModelSQL({
model: parentModel,
dbDriver: knex,
});
const childBaseModel = await Model.getBaseModelSQL({
model: childModel,
dbDriver: knex,
});
switch (relationColumnOption.type) {
case RelationTypes.HAS_MANY: {
const queryBuilder: any = knex(
knex.raw(`?? as ??`, [
baseModelSqlv2.getTnPath(childModel?.table_name),
childBaseModel.getTnPath(childModel),
refTableAlias,
]),
)
@ -46,7 +56,7 @@ export default async function ({
)
.where(
knex.ref(
`${alias || baseModelSqlv2.getTnPath(parentModel.table_name)}.${
`${alias || parentBaseModel.getTnPath(parentModel.table_name)}.${
parentCol.column_name
}`,
),
@ -62,7 +72,7 @@ export default async function ({
case RelationTypes.ONE_TO_ONE: {
const qb = knex(
knex.raw(`?? as ??`, [
baseModelSqlv2.getTnPath(childModel?.table_name),
childBaseModel.getTnPath(childModel?.table_name),
refTableAlias,
]),
)
@ -71,7 +81,7 @@ export default async function ({
)
.where(
knex.ref(
`${alias || baseModelSqlv2.getTnPath(parentModel.table_name)}.${
`${alias || parentBaseModel.getTnPath(parentModel.table_name)}.${
parentCol.column_name
}`,
),
@ -88,7 +98,10 @@ export default async function ({
const mmModel = await relationColumnOption.getMMModel(context);
const mmChildCol = await relationColumnOption.getMMChildColumn(context);
const mmParentCol = await relationColumnOption.getMMParentColumn(context);
const assocBaseModel = await Model.getBaseModelSQL({
id: mmModel.id,
dbDriver: knex,
});
if (!mmModel) {
return this.dbDriver.raw(`?`, [
NcDataErrorCodes.NC_ERR_MM_MODEL_NOT_FOUND,
@ -97,7 +110,7 @@ export default async function ({
const qb = knex(
knex.raw(`?? as ??`, [
baseModelSqlv2.getTnPath(parentModel?.table_name),
parentBaseModel.getTnPath(parentModel?.table_name),
refTableAlias,
]),
)
@ -105,9 +118,9 @@ export default async function ({
knex.ref(`${refTableAlias}.${rollupColumn.column_name}`),
)
.innerJoin(
baseModelSqlv2.getTnPath(mmModel.table_name),
assocBaseModel.getTnPath(mmModel.table_name),
knex.ref(
`${baseModelSqlv2.getTnPath(mmModel.table_name)}.${
`${assocBaseModel.getTnPath(mmModel.table_name)}.${
mmParentCol.column_name
}`,
),
@ -116,13 +129,13 @@ export default async function ({
)
.where(
knex.ref(
`${baseModelSqlv2.getTnPath(mmModel.table_name)}.${
`${assocBaseModel.getTnPath(mmModel.table_name)}.${
mmChildCol.column_name
}`,
),
'=',
knex.ref(
`${alias || baseModelSqlv2.getTnPath(childModel.table_name)}.${
`${alias || childBaseModel.getTnPath(childModel.table_name)}.${
childCol.column_name
}`,
),

12
packages/nocodb/src/services/columns.service.ts

@ -2472,9 +2472,8 @@ export class ColumnsService {
},
ignoreFkDelete = false,
) => {
if (childTable) {
if (!custom) {
let foreignKeyName;
if (childTable && !custom) {
let foreignKeyName;
// if relationColOpt is not provided, extract it from child table
// and get the foreign key name for dropping the foreign key
@ -2485,10 +2484,8 @@ export class ColumnsService {
for (const col of cols) {
if (col.uidt === UITypes.LinkToAnotherRecord) {
const colOptions =
await col.getColOptions<LinkToAnotherRecordColumn>(
context,
ncMeta,
);
await col.getColOptions<LinkToAnotherRecordColumn>(context,
ncMeta);
if (colOptions.fk_related_model_id === parentTable.id) {
return { colOptions };
}
@ -2517,7 +2514,6 @@ export class ColumnsService {
}
}
}
}
if (!relationColOpt) return;
const columnsInRelatedTable: Column[] = await relationColOpt

1
packages/nocodb/tsconfig.json

@ -41,5 +41,4 @@
]
},
"include": ["src/**/*"],
"exclude": ["src/ee", "src/ee-on-prem"]
}

Loading…
Cancel
Save