diff --git a/.changeset/range-bound-escapes.md b/.changeset/range-bound-escapes.md new file mode 100644 index 0000000000..39b9e79cec --- /dev/null +++ b/.changeset/range-bound-escapes.md @@ -0,0 +1,12 @@ +--- +'@hyperdx/common-utils': patch +'@hyperdx/api': patch +'@hyperdx/app': patch +--- + +fix: decode escaped characters in Lucene range bounds + +A range bound with an escaped colon, such as +`Timestamp:[2024-01-01T10\:00\:00 TO *]`, sent the internal placeholder to +ClickHouse (`'2024-01-01T10HDX_COLON00HDX_COLON00'`) and the query failed. Range +bounds are now decoded the same way as other search terms. diff --git a/packages/common-utils/src/__tests__/queryParser.test.ts b/packages/common-utils/src/__tests__/queryParser.test.ts index c3f897b3db..b6bb091786 100644 --- a/packages/common-utils/src/__tests__/queryParser.test.ts +++ b/packages/common-utils/src/__tests__/queryParser.test.ts @@ -842,6 +842,14 @@ describe('CustomSchemaSQLSerializerV2 - range bounds', () => { lucene: 'Timestamp:{2024-01-01 TO 2024-06-01}', sql: "((Timestamp > '2024-01-01' AND Timestamp < '2024-06-01'))", }, + { + lucene: 'Timestamp:[2024-01-01T10\\:00\\:00 TO *]', + sql: "((Timestamp >= '2024-01-01T10:00:00'))", + }, + { + lucene: 'Host:[localhost:3000 TO localhost:3999]', + sql: "((Host BETWEEN 'localhost:3000' AND 'localhost:3999'))", + }, { lucene: 'LogAttributes.duration_ms:{100 TO 500}', sql: "((`LogAttributes`['duration_ms'] > 100 AND `LogAttributes`['duration_ms'] < 500 AND indexHint(mapContains(`LogAttributes`, 'duration_ms'))))", diff --git a/packages/common-utils/src/queryParser.ts b/packages/common-utils/src/queryParser.ts index 61326a599a..37cc098afa 100644 --- a/packages/common-utils/src/queryParser.ts +++ b/packages/common-utils/src/queryParser.ts @@ -2083,8 +2083,8 @@ async function nodeTerm( const rangedTerm = node; return serializer.range( field, - rangedTerm.term_min, - rangedTerm.term_max, + decodeSpecialTokens(rangedTerm.term_min), + decodeSpecialTokens(rangedTerm.term_max), isNegatedField, context, rangedTerm.inclusive,