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

Loading…
Cancel
Save