From e04d08364eff645150a0ebca88eef135bcb87c8d Mon Sep 17 00:00:00 2001 From: tombo Date: Sun, 31 Aug 2025 21:05:28 +0200 Subject: [PATCH 1/4] fix: delimited column identifier for dynamic fields --- .../src/hooks/__tests__/useRowWhere.test.tsx | 24 +++++++++++++++++-- packages/app/src/hooks/useRowWhere.tsx | 7 ++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/app/src/hooks/__tests__/useRowWhere.test.tsx b/packages/app/src/hooks/__tests__/useRowWhere.test.tsx index 3d63f4cc2..e21647b16 100644 --- a/packages/app/src/hooks/__tests__/useRowWhere.test.tsx +++ b/packages/app/src/hooks/__tests__/useRowWhere.test.tsx @@ -173,7 +173,7 @@ describe('processRowToWhereClause', () => { const row = { dynamic_field: '"quoted_value"' }; const result = processRowToWhereClause(row, columnMap); - expect(result).toBe("toString(dynamic_field)='quoted_value'"); + expect(result).toBe("toString(`dynamic_field`)='quoted_value'"); }); it('should handle Dynamic columns with escaped values', () => { @@ -192,7 +192,27 @@ describe('processRowToWhereClause', () => { const row = { dynamic_field: '{\\"took\\":7, not a valid json' }; const result = processRowToWhereClause(row, columnMap); expect(result).toBe( - 'toString(dynamic_field)=\'{\\"took\\":7, not a valid json\'', + 'toString(`dynamic_field`)=\'{\\"took\\":7, not a valid json\'', + ); + }); + + it('should handle Dynamic columns with delimited identifier', () => { + const columnMap = new Map([ + [ + 'dynamic_field.nested.needs\\toBeEscaped', + { + name: 'dynamic_field.nested\\ToBeEscaped', + type: 'Dynamic', + valueExpr: 'dynamic_field.nested.needs\\ToBeEscaped', + jsType: JSDataType.Dynamic, + }, + ], + ]); + + const row = { 'dynamic_field.nested.needs\\toBeEscaped': 'some string' }; + const result = processRowToWhereClause(row, columnMap); + expect(result).toBe( + `toString(\`dynamic_field\`.\`nested\`.\`needs\\ToBeEscaped\`)='some string'`, ); }); diff --git a/packages/app/src/hooks/useRowWhere.tsx b/packages/app/src/hooks/useRowWhere.tsx index 0c354f04a..da29aed29 100644 --- a/packages/app/src/hooks/useRowWhere.tsx +++ b/packages/app/src/hooks/useRowWhere.tsx @@ -68,17 +68,14 @@ export function processRowToWhereClause( if (value === 'null') { return SqlString.format(`isNull(??)`, [column]); } - if (value.length > 1000 || column.length > 1000) { - console.warn('Search value/object key too large.'); - } // TODO: update when JSON type have new version // will not work for array/object dyanmic data // escaped strings needs raw, becuase sqlString will add another layer of escaping // data other than array/object will alwayas return with dobule quote(because of CH) // remove dobule qoute to search correctly - return SqlString.format(`toString(?)='?'`, [ - SqlString.raw(valueExpr), + return SqlString.format(`toString(??)='?'`, [ + valueExpr, SqlString.raw( value[0] === '"' && value[value.length - 1] === '"' ? value.slice(1, -1) From 5d615c8b954ec0394f195b3f45f84b00ad9fc103 Mon Sep 17 00:00:00 2001 From: tombo Date: Thu, 4 Sep 2025 23:21:23 +0200 Subject: [PATCH 2/4] add changeset --- .changeset/clean-waves-smoke.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/clean-waves-smoke.md diff --git a/.changeset/clean-waves-smoke.md b/.changeset/clean-waves-smoke.md new file mode 100644 index 000000000..6b6e99e57 --- /dev/null +++ b/.changeset/clean-waves-smoke.md @@ -0,0 +1,5 @@ +--- +"@hyperdx/app": patch +--- + +fix delimited column identifier for dynamic fields From 7c3d7eb3311353b0a9c441050c3f2b57ccc4ff8c Mon Sep 17 00:00:00 2001 From: tombo Date: Mon, 29 Sep 2025 10:27:59 +0200 Subject: [PATCH 3/4] escape single quote for dynamic --- packages/app/src/hooks/__tests__/useRowWhere.test.tsx | 4 ++-- packages/app/src/hooks/useRowWhere.tsx | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/app/src/hooks/__tests__/useRowWhere.test.tsx b/packages/app/src/hooks/__tests__/useRowWhere.test.tsx index e21647b16..0878c462f 100644 --- a/packages/app/src/hooks/__tests__/useRowWhere.test.tsx +++ b/packages/app/src/hooks/__tests__/useRowWhere.test.tsx @@ -189,10 +189,10 @@ describe('processRowToWhereClause', () => { ], ]); - const row = { dynamic_field: '{\\"took\\":7, not a valid json' }; + const row = { dynamic_field: '{\\"took\\":7, this ins\'t a valid json' }; const result = processRowToWhereClause(row, columnMap); expect(result).toBe( - 'toString(`dynamic_field`)=\'{\\"took\\":7, not a valid json\'', + "toString(`dynamic_field`)='{\\\"took\\\":7, this ins't a valid json'", ); }); diff --git a/packages/app/src/hooks/useRowWhere.tsx b/packages/app/src/hooks/useRowWhere.tsx index da29aed29..e465bed90 100644 --- a/packages/app/src/hooks/useRowWhere.tsx +++ b/packages/app/src/hooks/useRowWhere.tsx @@ -73,13 +73,14 @@ export function processRowToWhereClause( // escaped strings needs raw, becuase sqlString will add another layer of escaping // data other than array/object will alwayas return with dobule quote(because of CH) - // remove dobule qoute to search correctly + // remove double quotes if present and escape single quotes return SqlString.format(`toString(??)='?'`, [ valueExpr, SqlString.raw( - value[0] === '"' && value[value.length - 1] === '"' + (value[0] === '"' && value[value.length - 1] === '"' ? value.slice(1, -1) - : value, + : value + ).replace(/'/g, "\\'"), ), ]); default: From 83dc59054afc79c86999db0553a657d98c589838 Mon Sep 17 00:00:00 2001 From: tombo Date: Tue, 7 Oct 2025 23:23:12 +0200 Subject: [PATCH 4/4] fix test --- packages/app/src/hooks/__tests__/useRowWhere.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app/src/hooks/__tests__/useRowWhere.test.tsx b/packages/app/src/hooks/__tests__/useRowWhere.test.tsx index 0878c462f..53950474b 100644 --- a/packages/app/src/hooks/__tests__/useRowWhere.test.tsx +++ b/packages/app/src/hooks/__tests__/useRowWhere.test.tsx @@ -176,7 +176,7 @@ describe('processRowToWhereClause', () => { expect(result).toBe("toString(`dynamic_field`)='quoted_value'"); }); - it('should handle Dynamic columns with escaped values', () => { + it('should handle Dynamic columns with escaped values and single quote', () => { const columnMap = new Map([ [ 'dynamic_field', @@ -192,7 +192,7 @@ describe('processRowToWhereClause', () => { const row = { dynamic_field: '{\\"took\\":7, this ins\'t a valid json' }; const result = processRowToWhereClause(row, columnMap); expect(result).toBe( - "toString(`dynamic_field`)='{\\\"took\\\":7, this ins't a valid json'", + "toString(`dynamic_field`)='{\\\"took\\\":7, this ins\\'t a valid json'", ); });