Browse Source

fix: avoid caching at the data-loader since it may leads to invalid data

- in our case we are using it just for making the data processing as batch
pull/6817/head
Pranav C 1 year ago
parent
commit
84487c5087
  1. 213
      packages/nocodb/src/db/BaseModelSqlv2.ts

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

@ -1711,28 +1711,35 @@ class BaseModelSqlv2 {
(await column.getColOptions()) as LinkToAnotherRecordColumn; (await column.getColOptions()) as LinkToAnotherRecordColumn;
if (colOptions?.type === 'hm') { if (colOptions?.type === 'hm') {
const listLoader = new DataLoader(async (ids: string[]) => { const listLoader = new DataLoader(
if (ids.length > 1) { async (ids: string[]) => {
const data = await this.multipleHmList( if (ids.length > 1) {
{ const data = await this.multipleHmList(
colId: column.id,
ids,
},
(listLoader as any).args,
);
return ids.map((id: string) => (data[id] ? data[id] : []));
} else {
return [
await this.hmList(
{ {
colId: column.id, colId: column.id,
id: ids[0], ids,
}, },
(listLoader as any).args, (listLoader as any).args,
), );
]; return ids.map((id: string) =>
} data[id] ? data[id] : [],
}); );
} else {
return [
await this.hmList(
{
colId: column.id,
id: ids[0],
},
(listLoader as any).args,
),
];
}
},
{
cache: false,
},
);
const self: BaseModelSqlv2 = this; const self: BaseModelSqlv2 = this;
proto[ proto[
@ -1746,29 +1753,34 @@ class BaseModelSqlv2 {
); );
}; };
} else if (colOptions.type === 'mm') { } else if (colOptions.type === 'mm') {
const listLoader = new DataLoader(async (ids: string[]) => { const listLoader = new DataLoader(
if (ids?.length > 1) { async (ids: string[]) => {
const data = await this.multipleMmList( if (ids?.length > 1) {
{ const data = await this.multipleMmList(
parentIds: ids,
colId: column.id,
},
(listLoader as any).args,
);
return data;
} else {
return [
await this.mmList(
{ {
parentId: ids[0], parentIds: ids,
colId: column.id, colId: column.id,
}, },
(listLoader as any).args, (listLoader as any).args,
), );
];
} return data;
}); } else {
return [
await this.mmList(
{
parentId: ids[0],
colId: column.id,
},
(listLoader as any).args,
),
];
}
},
{
cache: false,
},
);
const self: BaseModelSqlv2 = this; const self: BaseModelSqlv2 = this;
proto[ proto[
@ -1796,55 +1808,62 @@ class BaseModelSqlv2 {
// it takes individual keys and callback is invoked with an array of values and we can get the // it takes individual keys and callback is invoked with an array of values and we can get the
// result for all those together and return the value in the same order as in the array // result for all those together and return the value in the same order as in the array
// this way all parents data extracted together // this way all parents data extracted together
const readLoader = new DataLoader(async (_ids: string[]) => { const readLoader = new DataLoader(
// handle binary(16) foreign keys async (_ids: string[]) => {
const ids = _ids.map((id) => { // handle binary(16) foreign keys
if (pCol.ct !== 'binary(16)') return id; const ids = _ids.map((id) => {
if (pCol.ct !== 'binary(16)') return id;
// Cast the id to string.
const idAsString = id + ''; // Cast the id to string.
// Check if the id is a UUID and the column is binary(16) const idAsString = id + '';
const isUUIDBinary16 = // Check if the id is a UUID and the column is binary(16)
idAsString.length === 36 || idAsString.length === 32; const isUUIDBinary16 =
// If the id is a UUID and the column is binary(16), convert the id to a Buffer. Otherwise, return null to indicate that the id is not a UUID. idAsString.length === 36 || idAsString.length === 32;
const idAsUUID = isUUIDBinary16 // If the id is a UUID and the column is binary(16), convert the id to a Buffer. Otherwise, return null to indicate that the id is not a UUID.
? idAsString.length === 32 const idAsUUID = isUUIDBinary16
? idAsString.replace( ? idAsString.length === 32
/(.{8})(.{4})(.{4})(.{4})(.{12})/, ? idAsString.replace(
'$1-$2-$3-$4-$5', /(.{8})(.{4})(.{4})(.{4})(.{12})/,
) '$1-$2-$3-$4-$5',
: idAsString )
: null; : idAsString
: null;
return idAsUUID
? Buffer.from(idAsUUID.replace(/-/g, ''), 'hex') return idAsUUID
: id; ? Buffer.from(idAsUUID.replace(/-/g, ''), 'hex')
}); : id;
});
const data = await (
await Model.getBaseModelSQL({ const data = await (
id: pCol.fk_model_id, await Model.getBaseModelSQL({
dbDriver: this.dbDriver, id: pCol.fk_model_id,
}) dbDriver: this.dbDriver,
).list( })
{ ).list(
fieldsSet: (readLoader as any).args?.fieldsSet, {
filterArr: [ fieldsSet: (readLoader as any).args?.fieldsSet,
new Filter({ filterArr: [
id: null, new Filter({
fk_column_id: pCol.id, id: null,
fk_model_id: pCol.fk_model_id, fk_column_id: pCol.id,
value: ids as any[], fk_model_id: pCol.fk_model_id,
comparison_op: 'in', value: ids as any[],
}), comparison_op: 'in',
], }),
}, ],
true, },
); true,
);
const groupedList = groupBy(data, pCol.title); const groupedList = groupBy(data, pCol.title);
return _ids.map(async (id: string) => groupedList?.[id]?.[0]); return _ids.map(
}); async (id: string) => groupedList?.[id]?.[0],
);
},
{
cache: false,
},
);
// defining BelongsTo read resolver method // defining BelongsTo read resolver method
proto[column.title] = async function (args?: any) { proto[column.title] = async function (args?: any) {
@ -4332,7 +4351,7 @@ class BaseModelSqlv2 {
} }
async addLinks({ async addLinks({
cookie: _cookie, cookie,
childIds, childIds,
colId, colId,
rowId, rowId,
@ -4348,9 +4367,12 @@ class BaseModelSqlv2 {
if (!column || !isLinksOrLTAR(column)) if (!column || !isLinksOrLTAR(column))
NcError.notFound(`Link column ${colId} not found`); NcError.notFound(`Link column ${colId} not found`);
const row = await this.dbDriver(this.tnPath) const row = await this.readByPk(
.where(await this._wherePk(rowId)) rowId,
.first(); false,
{},
{ ignoreView: true, getHiddenColumn: true },
);
// validate rowId // validate rowId
if (!row) { if (!row) {
@ -4554,9 +4576,16 @@ class BaseModelSqlv2 {
break; break;
} }
// const response = await this.readByPk(rowId); const response = await this.readByPk(
// await this.afterInsert(response, this.dbDriver, cookie); rowId,
// await this.afterAddChild(rowId, childId, cookie); false,
{},
{ ignoreView: true, getHiddenColumn: true },
);
await this.afterUpdate(row, response, this.dbDriver, cookie);
for (const childId of childIds) {
await this.afterAddChild(rowId, childId, cookie);
}
} }
async removeLinks({ async removeLinks({

Loading…
Cancel
Save