Skip to content

Commit

Permalink
fix(utils/Format): prevent dynamic field overwrite when building dyna…
Browse files Browse the repository at this point in the history
…mic row

see #399
  • Loading branch information
rakuzen25 committed Dec 26, 2024
1 parent 1750962 commit 6bac264
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
11 changes: 11 additions & 0 deletions milvus/utils/Format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,10 @@ export const buildDynamicRow = (

// iterate through each key in the input data object
for (let key in originRow) {
if (key === dynamicFieldName) {
// ignore the dynamic field key for now
continue;
}
row[dynamicFieldName] = row[dynamicFieldName] || ({} as JSON); // initialize the dynamic field object

if (fieldMap.has(key)) {
Expand All @@ -467,6 +471,13 @@ export const buildDynamicRow = (
}
}

// do this last to prevent any non-deterministic behavior with loop order
if (originRow[dynamicFieldName]) {
// extend the dynamic field object with the input dynamic field object
row[dynamicFieldName] = row[dynamicFieldName] || ({} as JSON);
Object.assign(row[dynamicFieldName] as JSON, originRow[dynamicFieldName]);
}

return row; // return the generated dynamic row object
};

Expand Down
65 changes: 65 additions & 0 deletions test/utils/Format.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,71 @@ describe('utils/format', () => {
});
});

it('should return an object with dynamicField key when data contains keys not in fieldsDataMap and an empty dynamicField object', () => {
const dynamicField = 'dynamic';
const data = { key1: 'value1', key2: 'value2', [dynamicField]: {} };
const fieldsDataMap = new Map([
[
'key1',
{
name: 'key1',
type: 'VarChar',
data: [{ key1: 'value1' }],
} as _Field,
],
[
// this mirrors the dynamic field map in grpc.Data._insert method
dynamicField,
{
name: dynamicField,
type: 'JSON',
data: [],
} as _Field,
],
]);
const result = buildDynamicRow(data, fieldsDataMap, dynamicField, []);
expect(result).toEqual({
key1: 'value1',
[dynamicField]: { key2: 'value2' },
});
});

it('should return an object with dynamicField key when data contains keys not in fieldsDataMap and a non-empty dynamicField object', () => {
const dynamicField = 'dynamic';
const data = {
key1: 'value1',
key2: 'value2',
[dynamicField]: {
key2: 'value22',
key3: 'value3',
},
};
const fieldsDataMap = new Map([
[
'key1',
{
name: 'key1',
type: 'VarChar',
data: [{ key1: 'value1' }],
} as _Field,
],
[
// this mirrors the dynamic field map in grpc.Data._insert method
dynamicField,
{
name: dynamicField,
type: 'JSON',
data: [],
} as _Field,
],
]);
const result = buildDynamicRow(data, fieldsDataMap, dynamicField, []);
expect(result).toEqual({
key1: 'value1',
[dynamicField]: { key2: 'value22', key3: 'value3' },
});
});

it('should return an empty string if no credentials are provided', () => {
const authString = getAuthString({});
expect(authString).toEqual('');
Expand Down

0 comments on commit 6bac264

Please sign in to comment.