Browse Source

Merge pull request #7727 from nocodb/nc-fix/cache-del

fix: cache del and update
pull/7723/head
Raju Udava 9 months ago committed by GitHub
parent
commit
67d28205ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 18
      packages/nc-gui/components/dlg/TableDuplicate.vue
  2. 2
      packages/nc-gui/components/smartsheet/Kanban.vue
  3. 2
      packages/nc-gui/composables/useKanbanViewStore.ts
  4. 11
      packages/nocodb/src/cache/CacheMgr.ts
  5. 8
      packages/nocodb/src/cache/NocoCache.ts
  6. 10
      packages/nocodb/src/db/BaseModelSqlv2.ts
  7. 10
      packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts
  8. 34
      packages/nocodb/src/models/BaseUser.ts
  9. 41
      packages/nocodb/src/models/CalendarView.ts
  10. 17
      packages/nocodb/src/models/CalendarViewColumn.ts
  11. 102
      packages/nocodb/src/models/Column.ts
  12. 11
      packages/nocodb/src/models/Filter.ts
  13. 31
      packages/nocodb/src/models/FormView.ts
  14. 25
      packages/nocodb/src/models/FormViewColumn.ts
  15. 10
      packages/nocodb/src/models/FormulaColumn.ts
  16. 24
      packages/nocodb/src/models/GalleryView.ts
  17. 30
      packages/nocodb/src/models/GridView.ts
  18. 15
      packages/nocodb/src/models/GridViewColumn.ts
  19. 13
      packages/nocodb/src/models/Hook.ts
  20. 13
      packages/nocodb/src/models/HookFilter.ts
  21. 28
      packages/nocodb/src/models/KanbanView.ts
  22. 32
      packages/nocodb/src/models/MapView.ts
  23. 136
      packages/nocodb/src/models/Model.ts
  24. 20
      packages/nocodb/src/models/ModelRoleVisibility.ts
  25. 13
      packages/nocodb/src/models/Plugin.ts
  26. 15
      packages/nocodb/src/models/Sort.ts
  27. 46
      packages/nocodb/src/models/Source.ts
  28. 129
      packages/nocodb/src/models/View.ts
  29. 7
      packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts
  30. 11
      packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts
  31. 35
      packages/nocodb/src/utils/modelUtils.ts

18
packages/nc-gui/components/dlg/TableDuplicate.vue

@ -1,5 +1,5 @@
<script setup lang="ts">
import type { TableType } from 'nocodb-sdk'
import { type LinkToAnotherRecordType, type TableType, UITypes } from 'nocodb-sdk'
import { message } from 'ant-design-vue'
import { useVModel } from '#imports'
import type { TabType } from '#imports'
@ -31,6 +31,8 @@ const { loadTables } = baseStore
const { tables } = storeToRefs(baseStore)
const { getMeta } = useMetas()
const { t } = useI18n()
const { activeTable: _activeTable } = storeToRefs(useTablesStore())
@ -74,6 +76,20 @@ const _duplicate = async () => {
}) => {
if (data.status !== 'close') {
if (data.status === JobStatus.COMPLETED) {
const sourceTable = await getMeta(props.table.id!)
if (sourceTable) {
for (const col of sourceTable.columns || []) {
if ([UITypes.Links, UITypes.LinkToAnotherRecord].includes(col.uidt as UITypes)) {
if (col && col.colOptions) {
const relatedTableId = (col.colOptions as LinkToAnotherRecordType)?.fk_related_model_id
if (relatedTableId) {
await getMeta(relatedTableId, true)
}
}
}
}
}
await loadTables()
refreshCommandPalette()
const newTable = tables.value.find((el) => el.id === data?.data?.result?.id)

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

@ -232,7 +232,7 @@ async function onMoveStack(event: any, undo = false) {
const { fk_grp_col_id, meta: stack_meta } = kanbanMetaData.value
groupingFieldColOptions.value[oldIndex].order = newIndex
groupingFieldColOptions.value[newIndex].order = oldIndex
const stackMetaObj = JSON.parse(stack_meta as string) || {}
const stackMetaObj = parseProp(stack_meta) || {}
stackMetaObj[fk_grp_col_id as string] = groupingFieldColOptions.value
await updateKanbanMeta({
meta: stackMetaObj,

2
packages/nc-gui/composables/useKanbanViewStore.ts

@ -211,7 +211,7 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState(
const { fk_grp_col_id, meta: stack_meta } = kanbanMetaData.value
stackMetaObj.value = stack_meta ? JSON.parse(stack_meta as string) : {}
stackMetaObj.value = parseProp(stack_meta) || {}
if (stackMetaObj.value && fk_grp_col_id && stackMetaObj.value[fk_grp_col_id]) {
// keep the existing order (index of the array) but update the values done outside kanban

11
packages/nocodb/src/cache/CacheMgr.ts vendored

@ -500,6 +500,17 @@ export default abstract class CacheMgr {
});
}
async update(key: string, value: any): Promise<boolean> {
let o = await this.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o = { ...o, ...value };
// set cache
await this.set(key, o);
}
return true;
}
// wrap value with metadata
prepareValue(args: {
value: any;

8
packages/nocodb/src/cache/NocoCache.ts vendored

@ -106,6 +106,14 @@ export default class NocoCache {
);
}
public static async update(
key: string,
updateObj: Record<string, any>,
): Promise<boolean> {
if (this.cacheDisabled) return Promise.resolve(true);
return this.client.update(`${this.prefix}:${key}`, updateObj);
}
public static async destroy(): Promise<boolean> {
if (this.cacheDisabled) return Promise.resolve(true);
return this.client.destroy();

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

@ -3039,6 +3039,8 @@ class BaseModelSqlv2 {
// TODO: ag column handling for raw bulk insert
const insertDatas = raw ? datas : [];
let postInsertOps: ((rowId: any, trx?: any) => Promise<void>)[] = [];
let aiPkCol: Column;
let agPkCol: Column;
if (!raw) {
const nestedCols = (await this.model.getColumns()).filter((c) =>
@ -3194,6 +3196,9 @@ class BaseModelSqlv2 {
insertDatas.push(insertObj);
}
aiPkCol = this.model.primaryKeys.find((pk) => pk.ai);
agPkCol = this.model.primaryKeys.find((pk) => pk.meta?.ag);
}
if ('beforeBulkInsert' in this) {
@ -3219,9 +3224,6 @@ class BaseModelSqlv2 {
let responses;
const aiPkCol = this.model.primaryKeys.find((pk) => pk.ai);
const agPkCol = this.model.primaryKeys.find((pk) => pk.meta?.ag);
// insert one by one as fallback to get ids for sqlite and mysql
if (insertOneByOneAsFallback && (this.isSqlite || this.isMySQL)) {
// sqlite and mysql doesn't support returning, so insert one by one and return ids
@ -3248,9 +3250,11 @@ class BaseModelSqlv2 {
} else {
const returningArr: string[] = [];
if (!raw) {
for (const col of this.model.primaryKeys) {
returningArr.push(col.column_name);
}
}
responses =
!raw && (this.isPg || this.isMssql)

10
packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts

@ -1217,13 +1217,9 @@ export default async function formulaQueryBuilderv2(
error: e.message,
});
// update cache to reflect the error in UI
const key = `${CacheScope.COL_FORMULA}:${column.id}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o = { ...o, error: e.message };
// set cache
await NocoCache.set(key, o);
}
await NocoCache.update(`${CacheScope.COL_FORMULA}:${column.id}`, {
error: e.message,
});
}
throw new Error(`Formula error: ${e.message}`);
}

34
packages/nocodb/src/models/BaseUser.ts

@ -3,7 +3,7 @@ import type { BaseType } from 'nocodb-sdk';
import type User from '~/models/User';
import Base from '~/models/Base';
import {
// CacheDelDirection,
CacheDelDirection,
CacheGetType,
CacheScope,
MetaTable,
@ -205,17 +205,8 @@ export default class BaseUser {
roles: string,
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.BASE_USER}:${baseId}:${userId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.roles = roles;
// set cache
await NocoCache.set(key, o);
}
// set meta
return await ncMeta.metaUpdate(
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.PROJECT_USERS,
@ -227,6 +218,12 @@ export default class BaseUser {
base_id: baseId,
},
);
await NocoCache.update(`${CacheScope.BASE_USER}:${baseId}:${userId}`, {
roles,
});
return res;
}
static async update(
@ -237,18 +234,17 @@ export default class BaseUser {
) {
const updateObj = extractProps(baseUser, ['starred', 'hidden', 'order']);
const key = `${CacheScope.BASE_USER}:${baseId}:${userId}`;
// set meta
await ncMeta.metaUpdate(null, null, MetaTable.PROJECT_USERS, updateObj, {
fk_user_id: userId,
base_id: baseId,
});
// delete cache
await NocoCache.del(key);
await NocoCache.update(
`${CacheScope.BASE_USER}:${baseId}:${userId}`,
updateObj,
);
// cache and return
return await this.get(baseId, userId, ncMeta);
}
@ -265,8 +261,10 @@ export default class BaseUser {
);
// delete list cache to refresh list
await NocoCache.del(`${CacheScope.BASE_USER}:${baseId}:${userId}`);
await NocoCache.del(`${CacheScope.BASE_USER}:${baseId}:list`);
await NocoCache.deepDel(
`${CacheScope.BASE_USER}:${baseId}:${userId}`,
CacheDelDirection.CHILD_TO_PARENT,
);
return response;
}

41
packages/nocodb/src/models/CalendarView.ts

@ -2,9 +2,15 @@ import type { BoolType, MetaType } from 'nocodb-sdk';
import type { CalendarType } from 'nocodb-sdk';
import View from '~/models/View';
import { extractProps } from '~/helpers/extractProps';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
import NocoCache from '~/cache/NocoCache';
import Noco from '~/Noco';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import {
CacheDelDirection,
CacheGetType,
CacheScope,
MetaTable,
} from '~/utils/globals';
import CalendarRange from '~/models/CalendarRange';
export default class CalendarView implements CalendarType {
@ -85,24 +91,14 @@ export default class CalendarView implements CalendarType {
body: Partial<CalendarView>,
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.CALENDAR_VIEW}:${calendarId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, ['fk_cover_image_col_id', 'meta']);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
if (body.calendar_range) {
await NocoCache.del(`${CacheScope.CALENDAR_VIEW}:${calendarId}`);
// if calendar range is updated, delete cache
await NocoCache.deepDel(
`${CacheScope.CALENDAR_VIEW}:${calendarId}`,
CacheDelDirection.CHILD_TO_PARENT,
);
await ncMeta.metaDelete(
null,
null,
@ -121,15 +117,24 @@ export default class CalendarView implements CalendarType {
}),
);
}
// update meta
return await ncMeta.metaUpdate(
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.CALENDAR_VIEW,
updateObj,
prepareForDb(updateObj),
{
fk_view_id: calendarId,
},
);
// update cache
await NocoCache.update(
`${CacheScope.CALENDAR_VIEW}:${calendarId}`,
prepareForResponse(updateObj),
);
return res;
}
}

17
packages/nocodb/src/models/CalendarViewColumn.ts

@ -162,21 +162,20 @@ export default class CalendarViewColumn {
'italic',
]);
// get existing cache
const key = `${CacheScope.CALENDAR_VIEW_COLUMN}:${columnId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
Object.assign(o, updateObj);
// set cache
await NocoCache.set(key, o);
}
// update meta
return await ncMeta.metaUpdate(
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.CALENDAR_VIEW_COLUMNS,
updateObj,
columnId,
);
await NocoCache.update(
`${CacheScope.CALENDAR_VIEW_COLUMN}:${columnId}`,
updateObj,
);
return res;
}
}

102
packages/nocodb/src/models/Column.ts

@ -28,7 +28,11 @@ import {
MetaTable,
} from '~/utils/globals';
import NocoCache from '~/cache/NocoCache';
import { parseMetaProp, stringifyMetaProp } from '~/utils/modelUtils';
import {
parseMetaProp,
prepareForDb,
prepareForResponse,
} from '~/utils/modelUtils';
import { getFormulasReferredTheColumn } from '~/helpers/formulaHelpers';
const selectColors = [
@ -479,13 +483,6 @@ export default class Column<T = any> implements ColumnType {
return this.model;
}
public static async clearList({ fk_model_id }) {
await NocoCache.deepDel(
`${CacheScope.COLUMN}:${fk_model_id}:list`,
CacheDelDirection.PARENT_TO_CHILD,
);
}
public static async list(
{
fk_model_id,
@ -1084,52 +1081,20 @@ export default class Column<T = any> implements ColumnType {
});
}
// get existing cache
const key = `${CacheScope.COLUMN}:${colId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// get model column list from cache
const columnListFromCache = await NocoCache.getList(CacheScope.COLUMN, [
oldCol.fk_model_id,
]);
// update column list in cache if cache exists
if (!columnListFromCache.list?.length) {
const updatedColumnList = columnListFromCache.list.map((column: any) => {
if (column.id === colId) {
return {
...column,
...updateObj,
};
}
return column;
});
await NocoCache.setList(
CacheScope.COLUMN,
[oldCol.fk_model_id],
updatedColumnList,
);
}
// set meta
await ncMeta.metaUpdate(
null,
null,
MetaTable.COLUMNS,
{
...updateObj,
meta:
updateObj.meta && typeof updateObj.meta === 'object'
? JSON.stringify(updateObj.meta)
: updateObj.meta,
},
prepareForDb(updateObj),
colId,
);
await NocoCache.update(
`${CacheScope.COLUMN}:${colId}`,
prepareForResponse(updateObj),
);
await this.insertColOption(column, colId, ncMeta);
// on column update, delete any optimised single query cache
@ -1166,15 +1131,6 @@ export default class Column<T = any> implements ColumnType {
{ title }: { title: string },
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.COLUMN}:${colId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.title = title;
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(
null, //column.base_id || column.source_id,
@ -1186,6 +1142,8 @@ export default class Column<T = any> implements ColumnType {
colId,
);
await NocoCache.update(`${CacheScope.COLUMN}:${colId}`, { title });
const column = await Column.get({ colId }, ncMeta);
await View.clearSingleQueryCache(column.fk_model_id);
@ -1246,15 +1204,6 @@ export default class Column<T = any> implements ColumnType {
system = true,
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.COLUMN}:${colId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.system = system;
// set cache
await NocoCache.set(key, o);
}
// update system field in meta db
await ncMeta.metaUpdate(
null,
@ -1265,6 +1214,8 @@ export default class Column<T = any> implements ColumnType {
},
colId,
);
await NocoCache.update(`${CacheScope.COLUMN}:${colId}`, { system });
}
static getMaxColumnNameLength(sqlClientType: string) {
@ -1284,25 +1235,19 @@ export default class Column<T = any> implements ColumnType {
{ colId, meta }: { colId: string; meta: any },
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.COLUMN}:${colId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update meta
o.meta = meta;
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(
null,
null,
MetaTable.COLUMNS,
{
meta: stringifyMetaProp({ meta }),
},
prepareForDb({ meta }),
colId,
);
await NocoCache.update(
`${CacheScope.COLUMN}:${colId}`,
prepareForResponse({ meta }),
);
}
static async bulkInsert(
@ -1384,10 +1329,7 @@ export default class Column<T = any> implements ColumnType {
true,
);
// insert column options if any
// for (const column of columns) {
await Column.bulkInsertColOption(columns, ncMeta);
// }
return columns;
}

11
packages/nocodb/src/models/Filter.ts

@ -234,15 +234,6 @@ export default class Filter implements FilterType {
if (typeof updateObj.value === 'string')
updateObj.value = updateObj.value.slice(0, 255);
// get existing cache
const key = `${CacheScope.FILTER_EXP}:${id}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
// update alias
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// set meta
const res = await ncMeta.metaUpdate(
null,
@ -252,6 +243,8 @@ export default class Filter implements FilterType {
id,
);
await NocoCache.update(`${CacheScope.FILTER_EXP}:${id}`, updateObj);
// on update delete any optimised single query cache
{
const filter = await this.get(id, ncMeta);

31
packages/nocodb/src/models/FormView.ts

@ -7,6 +7,7 @@ import NocoCache from '~/cache/NocoCache';
import Noco from '~/Noco';
import { deserializeJSON, serializeJSON } from '~/utils/serialize';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class FormView implements FormType {
show: BoolType;
@ -88,9 +89,6 @@ export default class FormView implements FormType {
body: Partial<FormView>,
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.FORM_VIEW}:${formId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, [
'heading',
'subheading',
@ -105,20 +103,23 @@ export default class FormView implements FormType {
'meta',
]);
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
if (updateObj.meta) {
updateObj.meta = serializeJSON(updateObj.meta);
}
// update meta
return await ncMeta.metaUpdate(null, null, MetaTable.FORM_VIEW, updateObj, {
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.FORM_VIEW,
prepareForDb(updateObj),
{
fk_view_id: formId,
});
},
);
await NocoCache.update(
`${CacheScope.FORM_VIEW}:${formId}`,
prepareForResponse(updateObj),
);
return res;
}
async getColumns(ncMeta = Noco.ncMeta) {

25
packages/nocodb/src/models/FormViewColumn.ts

@ -10,6 +10,7 @@ import NocoCache from '~/cache/NocoCache';
import { extractProps } from '~/helpers/extractProps';
import { deserializeJSON, serializeJSON } from '~/utils/serialize';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class FormViewColumn implements FormColumnType {
id?: string;
@ -168,26 +169,20 @@ export default class FormViewColumn implements FormColumnType {
'enable_scanner',
]);
// get existing cache
const key = `${CacheScope.FORM_VIEW_COLUMN}:${columnId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
Object.assign(o, updateObj);
// set cache
await NocoCache.set(key, o);
}
if (updateObj.meta) {
updateObj.meta = serializeJSON(updateObj.meta);
}
// update meta
return await ncMeta.metaUpdate(
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.FORM_VIEW_COLUMNS,
updateObj,
prepareForDb(updateObj),
columnId,
);
await NocoCache.update(
`${CacheScope.FORM_VIEW_COLUMN}:${columnId}`,
prepareForResponse(updateObj),
);
return res;
}
}

10
packages/nocodb/src/models/FormulaColumn.ts

@ -74,20 +74,14 @@ export default class FormulaColumn {
'parsed_tree',
]);
// get existing cache
const key = `${CacheScope.COL_FORMULA}:${columnId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
if ('parsed_tree' in updateObj)
updateObj.parsed_tree = stringifyMetaProp(updateObj, 'parsed_tree');
// set meta
await ncMeta.metaUpdate(null, null, MetaTable.COL_FORMULA, updateObj, {
fk_column_id: columnId,
});
await NocoCache.update(`${CacheScope.COL_FORMULA}:${columnId}`, updateObj);
}
public getParsedTree() {

24
packages/nocodb/src/models/GalleryView.ts

@ -10,6 +10,7 @@ import Noco from '~/Noco';
import NocoCache from '~/cache/NocoCache';
import { extractProps } from '~/helpers/extractProps';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class GalleryView implements GalleryType {
fk_view_id?: string;
@ -98,29 +99,24 @@ export default class GalleryView implements GalleryType {
body: Partial<GalleryView>,
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.GALLERY_VIEW}:${galleryId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, ['fk_cover_image_col_id', 'meta']);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// update meta
return await ncMeta.metaUpdate(
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.GALLERY_VIEW,
updateObj,
prepareForDb(updateObj),
{
fk_view_id: galleryId,
},
);
await NocoCache.update(
`${CacheScope.GALLERY_VIEW}:${galleryId}`,
prepareForResponse(updateObj),
);
return res;
}
}

30
packages/nocodb/src/models/GridView.ts

@ -5,6 +5,7 @@ import Noco from '~/Noco';
import NocoCache from '~/cache/NocoCache';
import { extractProps } from '~/helpers/extractProps';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class GridView implements GridType {
fk_view_id: string;
@ -68,23 +69,24 @@ export default class GridView implements GridType {
body: Partial<GridView>,
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.GRID_VIEW}:${viewId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, ['row_height', 'meta']);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// update meta
return await ncMeta.metaUpdate(null, null, MetaTable.GRID_VIEW, updateObj, {
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.GRID_VIEW,
prepareForDb(updateObj),
{
fk_view_id: viewId,
});
},
);
await NocoCache.update(
`${CacheScope.GRID_VIEW}:${viewId}`,
prepareForResponse(updateObj),
);
return res;
}
}

15
packages/nocodb/src/models/GridViewColumn.ts

@ -140,15 +140,7 @@ export default class GridViewColumn implements GridColumnType {
'group_by_order',
'group_by_sort',
]);
// get existing cache
const key = `${CacheScope.GRID_VIEW_COLUMN}:${columnId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// set meta
const res = await ncMeta.metaUpdate(
null,
@ -158,6 +150,11 @@ export default class GridViewColumn implements GridColumnType {
columnId,
);
await NocoCache.update(
`${CacheScope.GRID_VIEW_COLUMN}:${columnId}`,
updateObj,
);
// on view column update, delete any optimised single query cache
{
const gridCol = await this.get(columnId, ncMeta);

13
packages/nocodb/src/models/Hook.ts

@ -209,20 +209,11 @@ export default class Hook implements HookType {
updateObj.notification = JSON.stringify(updateObj.notification);
}
// get existing cache
const key = `${CacheScope.HOOK}:${hookId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o = { ...o, ...updateObj };
// replace notification
o.notification = updateObj.notification;
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(null, null, MetaTable.HOOKS, updateObj, hookId);
await NocoCache.update(`${CacheScope.HOOK}:${hookId}`, updateObj);
return this.get(hookId, ncMeta);
}

13
packages/nocodb/src/models/HookFilter.ts

@ -152,17 +152,12 @@ export default class Filter {
'is_group',
'logical_op',
]);
// get existing cache
const key = `${CacheScope.FILTER_EXP}:${id}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
// update alias
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(null, null, MetaTable.FILTER_EXP, updateObj, id);
// update cache
await NocoCache.update(`${CacheScope.FILTER_EXP}:${id}`, updateObj);
}
static async delete(id: string, ncMeta = Noco.ncMeta) {

28
packages/nocodb/src/models/KanbanView.ts

@ -5,6 +5,7 @@ import Noco from '~/Noco';
import NocoCache from '~/cache/NocoCache';
import { extractProps } from '~/helpers/extractProps';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class KanbanView implements KanbanType {
fk_view_id: string;
@ -39,6 +40,9 @@ export default class KanbanView implements KanbanType {
view = await ncMeta.metaGet2(null, null, MetaTable.KANBAN_VIEW, {
fk_view_id: viewId,
});
view = prepareForResponse(view);
await NocoCache.set(`${CacheScope.KANBAN_VIEW}:${viewId}`, view);
}
@ -99,34 +103,28 @@ export default class KanbanView implements KanbanType {
body: Partial<KanbanView>,
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.KANBAN_VIEW}:${kanbanId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, [
'fk_cover_image_col_id',
'fk_grp_col_id',
'meta',
]);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// update meta
return await ncMeta.metaUpdate(
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.KANBAN_VIEW,
updateObj,
prepareForDb(updateObj),
{
fk_view_id: kanbanId,
},
);
await NocoCache.update(
`${CacheScope.KANBAN_VIEW}:${kanbanId}`,
prepareForResponse(updateObj),
);
return res;
}
}

32
packages/nocodb/src/models/MapView.ts

@ -6,6 +6,7 @@ import { extractProps } from '~/helpers/extractProps';
import NocoCache from '~/cache/NocoCache';
import Noco from '~/Noco';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class MapView implements MapType {
fk_view_id: string;
@ -70,22 +71,8 @@ export default class MapView implements MapType {
body: Partial<MapView>,
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.MAP_VIEW}:${mapId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, ['fk_geo_data_col_id', 'meta']);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
if (body.fk_geo_data_col_id != null) {
const mapViewColumns = await MapViewColumn.list(mapId);
const mapViewMappedByColumn = mapViewColumns.find(
@ -98,8 +85,21 @@ export default class MapView implements MapType {
}
// update meta
return await ncMeta.metaUpdate(null, null, MetaTable.MAP_VIEW, updateObj, {
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.MAP_VIEW,
prepareForDb(updateObj),
{
fk_view_id: mapId,
});
},
);
await NocoCache.update(
`${CacheScope.MAP_VIEW}:${mapId}`,
prepareForResponse(updateObj),
);
return res;
}
}

136
packages/nocodb/src/models/Model.ts

@ -26,7 +26,11 @@ import {
import NocoCache from '~/cache/NocoCache';
import Noco from '~/Noco';
import { BaseModelSqlv2 } from '~/db/BaseModelSqlv2';
import { parseMetaProp } from '~/utils/modelUtils';
import {
parseMetaProp,
prepareForDb,
prepareForResponse,
} from '~/utils/modelUtils';
export default class Model implements TableType {
copy_enabled: BoolType;
@ -641,27 +645,8 @@ export default class Model implements TableType {
if (!table_name) {
NcError.badRequest("Missing 'table_name' property in body");
}
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
let oldModel = { ...o };
// update alias
if (o) {
o.title = title;
o.table_name = table_name;
// set cache
await NocoCache.set(key, o);
} else {
oldModel = await this.get(tableId);
}
// delete alias cache
await NocoCache.del([
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.id}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.source_id}:${oldModel.id}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.title}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.source_id}:${oldModel.title}`,
]);
const oldModel = await this.get(tableId, ncMeta);
// set meta
const res = await ncMeta.metaUpdate(
@ -675,6 +660,19 @@ export default class Model implements TableType {
tableId,
);
await NocoCache.update(`${CacheScope.MODEL}:${tableId}`, {
title,
table_name,
});
// delete alias cache
await NocoCache.del([
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.id}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.source_id}:${oldModel.id}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.title}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.source_id}:${oldModel.title}`,
]);
// clear all the cached query under this model
await View.clearSingleQueryCache(tableId);
@ -693,17 +691,8 @@ export default class Model implements TableType {
}
static async markAsMmTable(tableId, isMm = true, ncMeta = Noco.ncMeta) {
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
// update alias
if (o) {
o.mm = isMm;
// set cache
await NocoCache.set(key, o);
}
// set meta
return await ncMeta.metaUpdate(
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.MODELS,
@ -712,6 +701,12 @@ export default class Model implements TableType {
},
tableId,
);
await NocoCache.update(`${CacheScope.MODEL}:${tableId}`, {
mm: isMm,
});
return res;
}
async getAliasColMapping() {
@ -737,16 +732,8 @@ export default class Model implements TableType {
order: number,
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.order = order;
// set cache
await NocoCache.set(key, o);
}
// set meta
return await ncMeta.metaUpdate(
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.MODELS,
@ -755,6 +742,12 @@ export default class Model implements TableType {
},
tableId,
);
await NocoCache.update(`${CacheScope.MODEL}:${tableId}`, {
order,
});
return res;
}
static async updatePrimaryColumn(
@ -769,14 +762,6 @@ export default class Model implements TableType {
// drop existing primary column/s
for (const col of model.columns?.filter((c) => c.pv) || []) {
// get existing cache
const key = `${CacheScope.COLUMN}:${col.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.pv = false;
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(
null,
@ -787,16 +772,12 @@ export default class Model implements TableType {
},
col.id,
);
}
// get existing cache
const key = `${CacheScope.COLUMN}:${newPvCol.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.pv = true;
// set cache
await NocoCache.set(key, o);
await NocoCache.update(`${CacheScope.COLUMN}:${col.id}`, {
pv: false,
});
}
// set meta
await ncMeta.metaUpdate(
null,
@ -808,6 +789,10 @@ export default class Model implements TableType {
newPvCol.id,
);
await NocoCache.update(`${CacheScope.COLUMN}:${newPvCol.id}`, {
pv: true,
});
const grid_views_with_column = await ncMeta.metaList2(
null,
null,
@ -829,14 +814,6 @@ export default class Model implements TableType {
}
static async setAsMm(id: any, ncMeta = Noco.ncMeta) {
// get existing cache
const key = `${CacheScope.MODEL}:${id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.mm = true;
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(
null,
@ -847,6 +824,10 @@ export default class Model implements TableType {
},
id,
);
await NocoCache.update(`${CacheScope.MODEL}:${id}`, {
mm: true,
});
}
static async getByAliasOrId(
@ -976,26 +957,25 @@ export default class Model implements TableType {
meta: string | Record<string, any>,
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
const existingCache = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (existingCache) {
try {
existingCache.meta = typeof meta === 'string' ? JSON.parse(meta) : meta;
// set cache
await NocoCache.set(key, existingCache);
} catch {}
}
// set meta
return await ncMeta.metaUpdate(
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.MODELS,
{
meta: typeof meta === 'object' ? JSON.stringify(meta) : meta,
},
prepareForDb({
meta,
}),
tableId,
);
await NocoCache.update(
`${CacheScope.MODEL}:${tableId}`,
prepareForResponse({
meta,
}),
);
return res;
}
static async getNonDefaultViewsCountAndReset(

20
packages/nocodb/src/models/ModelRoleVisibility.ts

@ -86,17 +86,8 @@ export default class ModelRoleVisibility implements ModelRoleVisibilityType {
role: string,
body: { disabled: any },
) {
// get existing cache
const key = `${CacheScope.MODEL_ROLE_VISIBILITY}:${fk_view_id}:${role}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.disabled = body.disabled;
// set cache
await NocoCache.set(key, o);
}
// set meta
return await Noco.ncMeta.metaUpdate(
const res = await Noco.ncMeta.metaUpdate(
null,
null,
MetaTable.MODEL_ROLE_VISIBILITY,
@ -108,6 +99,15 @@ export default class ModelRoleVisibility implements ModelRoleVisibilityType {
role,
},
);
await NocoCache.update(
`${CacheScope.MODEL_ROLE_VISIBILITY}:${fk_view_id}:${role}`,
{
disabled: body.disabled,
},
);
return res;
}
async delete() {

13
packages/nocodb/src/models/Plugin.ts

@ -65,16 +65,6 @@ export default class Plugin implements PluginType {
updateObj.input = JSON.stringify(updateObj.input);
}
// get existing cache
const key = `${CacheScope.PLUGIN}:${pluginId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
// update alias
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
await NocoCache.set(`${CacheScope.PLUGIN}:${o.title}`, o);
}
// set meta
await Noco.ncMeta.metaUpdate(
null,
@ -84,6 +74,9 @@ export default class Plugin implements PluginType {
pluginId,
);
await NocoCache.update(`${CacheScope.PLUGIN}:${pluginId}`, updateObj);
await NocoCache.update(`${CacheScope.PLUGIN}:${plugin.title}`, updateObj);
return this.get(pluginId);
}

15
packages/nocodb/src/models/Sort.ts

@ -148,16 +148,6 @@ export default class Sort {
}
public static async update(sortId, body, ncMeta = Noco.ncMeta) {
// get existing cache
const key = `${CacheScope.SORT}:${sortId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update fk_column_id & direction
o.fk_column_id = body.fk_column_id;
o.direction = body.direction;
// set cache
await NocoCache.set(key, o);
}
// set meta
const res = await ncMeta.metaUpdate(
null,
@ -170,6 +160,11 @@ export default class Sort {
sortId,
);
await NocoCache.update(`${CacheScope.SORT}:${sortId}`, {
fk_column_id: body.fk_column_id,
direction: body.direction,
});
// on update, delete any optimised single query cache
{
const sort = await this.get(sortId, ncMeta);

46
packages/nocodb/src/models/Source.ts

@ -17,7 +17,12 @@ import Noco from '~/Noco';
import { extractProps } from '~/helpers/extractProps';
import { NcError } from '~/helpers/catchError';
import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2';
import { parseMetaProp, stringifyMetaProp } from '~/utils/modelUtils';
import {
parseMetaProp,
prepareForDb,
prepareForResponse,
stringifyMetaProp,
} from '~/utils/modelUtils';
// todo: hide credentials
export default class Source implements SourceType {
@ -130,10 +135,6 @@ export default class Source implements SourceType {
).toString();
}
if ('meta' in updateObj) {
updateObj.meta = stringifyMetaProp(updateObj);
}
// type property is undefined even if not provided
if (!updateObj.type) {
updateObj.type = oldBase.type;
@ -143,11 +144,14 @@ export default class Source implements SourceType {
source.baseId,
null,
MetaTable.BASES,
updateObj,
prepareForDb(updateObj),
oldBase.id,
);
await NocoCache.del(`${CacheScope.BASE}:${sourceId}`);
await NocoCache.update(
`${CacheScope.BASE}:${sourceId}`,
prepareForResponse(updateObj),
);
// call before reorder to update cache
const returnBase = await this.get(oldBase.id, false, ncMeta);
@ -474,15 +478,7 @@ export default class Source implements SourceType {
if (!this.erd_uuid) {
const uuid = uuidv4();
this.erd_uuid = uuid;
// get existing cache
const key = `${CacheScope.BASE}:${this.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.erd_uuid = uuid;
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(
null,
@ -493,6 +489,10 @@ export default class Source implements SourceType {
},
this.id,
);
await NocoCache.update(`${CacheScope.BASE}:${this.id}`, {
erd_uuid: this.erd_uuid,
});
}
return this;
}
@ -500,15 +500,7 @@ export default class Source implements SourceType {
async disableShareErd(ncMeta = Noco.ncMeta) {
if (this.erd_uuid) {
this.erd_uuid = null;
// get existing cache
const key = `${CacheScope.BASE}:${this.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.erd_uuid = null;
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(
null,
@ -519,6 +511,10 @@ export default class Source implements SourceType {
},
this.id,
);
await NocoCache.update(`${CacheScope.BASE}:${this.id}`, {
erd_uuid: this.erd_uuid,
});
}
return this;
}

129
packages/nocodb/src/models/View.ts

@ -26,7 +26,12 @@ import {
MetaTable,
} from '~/utils/globals';
import Noco from '~/Noco';
import { parseMetaProp, stringifyMetaProp } from '~/utils/modelUtils';
import {
parseMetaProp,
prepareForDb,
prepareForResponse,
stringifyMetaProp,
} from '~/utils/modelUtils';
const { v4: uuidv4 } = require('uuid');
@ -858,18 +863,11 @@ export default class View implements ViewType {
}
}
// get existing cache
const key = `${cacheScope}:${colId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// set meta
const res = await ncMeta.metaUpdate(null, null, table, updateObj, colId);
await NocoCache.update(`${cacheScope}:${colId}`, updateObj);
// on view column update, delete corresponding single query cache
await View.clearSingleQueryCache(view.fk_model_id, [view]);
@ -988,15 +986,7 @@ export default class View implements ViewType {
if (!view.uuid) {
const uuid = uuidv4();
view.uuid = uuid;
// get existing cache
const key = `${CacheScope.VIEW}:${view.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.uuid = uuid;
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(
null,
@ -1007,32 +997,35 @@ export default class View implements ViewType {
},
viewId,
);
await NocoCache.update(`${CacheScope.VIEW}:${view.id}`, {
uuid: view.uuid,
});
}
if (!view.meta || !('allowCSVDownload' in view.meta)) {
const defaultMeta = {
...(view.meta ?? {}),
allowCSVDownload: true,
};
// get existing cache
const key = `${CacheScope.VIEW}:${view.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.meta = defaultMeta;
// set cache
await NocoCache.set(key, o);
}
view.meta = defaultMeta;
// set meta
await ncMeta.metaUpdate(
null,
null,
MetaTable.VIEWS,
{
meta: JSON.stringify(defaultMeta),
},
prepareForDb({
meta: defaultMeta,
}),
viewId,
);
view.meta = defaultMeta;
await NocoCache.update(
`${CacheScope.VIEW}:${view.id}`,
prepareForResponse({
meta: defaultMeta,
}),
);
}
return view;
}
@ -1042,15 +1035,6 @@ export default class View implements ViewType {
{ password }: { password: string },
ncMeta = Noco.ncMeta,
) {
// get existing cache
const key = `${CacheScope.VIEW}:${viewId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.password = password;
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(
null,
@ -1061,18 +1045,13 @@ export default class View implements ViewType {
},
viewId,
);
await NocoCache.update(`${CacheScope.VIEW}:${viewId}`, {
password,
});
}
static async sharedViewDelete(viewId, ncMeta = Noco.ncMeta) {
// get existing cache
const key = `${CacheScope.VIEW}:${viewId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.uuid = null;
// set cache
await NocoCache.set(key, o);
}
// set meta
await ncMeta.metaUpdate(
null,
@ -1083,6 +1062,10 @@ export default class View implements ViewType {
},
viewId,
);
await NocoCache.update(`${CacheScope.VIEW}:${viewId}`, {
uuid: null,
});
}
static async update(
@ -1108,37 +1091,33 @@ export default class View implements ViewType {
'uuid',
]);
// get existing cache
const key = `${CacheScope.VIEW}:${viewId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
let oldView = { ...o };
if (o) {
// update data
o = {
...o,
...updateObj,
};
if (o.is_default) {
await NocoCache.set(`${CacheScope.VIEW}:${o.fk_model_id}:default`, o);
}
// set cache
await NocoCache.set(key, o);
} else {
oldView = await this.get(viewId);
}
const oldView = await this.get(viewId, ncMeta);
// set meta
await ncMeta.metaUpdate(
null,
null,
MetaTable.VIEWS,
prepareForDb(updateObj),
viewId,
);
// reset alias cache
await NocoCache.del(
`${CacheScope.VIEW}:${oldView.fk_model_id}:${oldView.title}`,
);
// if meta data defined then stringify it
if ('meta' in updateObj) {
updateObj.meta = stringifyMetaProp(updateObj);
}
await NocoCache.update(
`${CacheScope.VIEW}:${viewId}`,
prepareForResponse(updateObj),
);
// set meta
await ncMeta.metaUpdate(null, null, MetaTable.VIEWS, updateObj, viewId);
if (oldView.is_default) {
await NocoCache.update(
`${CacheScope.VIEW}:${oldView.fk_model_id}:default`,
prepareForResponse(updateObj),
);
}
const view = await this.get(viewId);
@ -1407,7 +1386,7 @@ export default class View implements ViewType {
MetaTable.COLUMNS,
col.fk_column_id,
);
view_columns_meta.push(col_meta);
if (col_meta) view_columns_meta.push(col_meta);
}
const primary_value_column_meta = view_columns_meta.find((col) => col.pv);

7
packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts

@ -515,6 +515,8 @@ export class ExportService {
if (hasLink) {
linkStream.setEncoding('utf8');
let streamedHeaders = false;
for (const mm of mmColumns) {
if (handledMmList.includes(mm.colOptions?.fk_mm_model_id)) continue;
@ -573,8 +575,11 @@ export class ExportService {
mmOffset,
mmLimit,
mmFields,
true,
streamedHeaders ? false : true,
);
// avoid writing headers for same model multiple times
streamedHeaders = true;
} catch (e) {
this.debugLog(e);
throw e;

11
packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts

@ -1,5 +1,5 @@
import { isLinksOrLTAR, isVirtualCol, UITypes, ViewTypes } from 'nocodb-sdk';
import { Injectable } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import papaparse from 'papaparse';
import debug from 'debug';
import { elapsedTime, initTime } from '../../helpers';
@ -44,7 +44,8 @@ import { sanitizeColumnName } from '~/helpers';
@Injectable()
export class ImportService {
private readonly debugLog = debug('nc:jobs:import');
protected readonly debugLog = debug('nc:jobs:import');
protected readonly logger = new Logger(ImportService.name);
constructor(
private tablesService: TablesService,
@ -1515,7 +1516,7 @@ export class ImportService {
raw: true,
});
} catch (e) {
this.debugLog(e);
this.logger.error(e);
}
chunk = [];
parser.resume();
@ -1536,7 +1537,7 @@ export class ImportService {
raw: true,
});
} catch (e) {
this.debugLog(e);
this.logger.error(e);
}
chunk = [];
}
@ -1573,7 +1574,7 @@ export class ImportService {
});
lChunks[k] = [];
} catch (e) {
this.debugLog(e);
this.logger.error(e);
}
}
};

35
packages/nocodb/src/utils/modelUtils.ts

@ -23,3 +23,38 @@ export function stringifyMetaProp(model: any, propName = 'meta'): string {
return '{}';
}
}
export function prepareForDb(model: any, props: string | string[] = 'meta') {
if (!model) return model;
if (typeof props === 'string') {
props = [props];
}
props.forEach((prop) => {
if (prop in model) {
model[prop] = stringifyMetaProp(model, prop);
}
});
return model;
}
export function prepareForResponse(
model: any,
props: string | string[] = 'meta',
) {
if (!model) return model;
if (typeof props === 'string') {
props = [props];
}
props.forEach((prop) => {
if (prop in model) {
model[prop] = parseMetaProp(model, prop);
}
});
return model;
}

Loading…
Cancel
Save