diff --git a/src/index.ts b/src/index.ts index 018d8ef..72234df 100644 --- a/src/index.ts +++ b/src/index.ts @@ -312,8 +312,9 @@ export const escapeId = ( } const identifier = String(value); + const hasJsonOperator = identifier.indexOf('->') !== -1; - if (forbidQualified) { + if (forbidQualified || hasJsonOperator) { if (identifier.indexOf('`') === -1) return `\`${identifier}\``; return `\`${identifier.replace(regex.backtick, '``')}\``; diff --git a/test/everyday-queries.test.ts b/test/everyday-queries.test.ts index 73c65c1..761d660 100644 --- a/test/everyday-queries.test.ts +++ b/test/everyday-queries.test.ts @@ -459,6 +459,35 @@ describe('Nice to have: escapeId edge cases', () => { }); }); +describe('JSON path expressions with ?? placeholder', () => { + test('should handle JSON arrow operator with path expression', () => { + const query = format('SELECT * FROM ?? WHERE (?? = ?) LIMIT ?, ?', [ + 'certification', + "cert->>'$.name'", + 'myname', + 0, + 20, + ]); + + assert.equal( + query, + "SELECT * FROM `certification` WHERE (`cert->>'$.name'` = 'myname') LIMIT 0, 20" + ); + }); + + test('escapeId should not break JSON path expressions', () => { + const escaped = escapeId("cert->>'$.name'"); + + assert.equal(escaped, "`cert->>'$.name'`"); + }); + + test('escapeId with JSON double arrow operator', () => { + const escaped = escapeId("data->'$.user.address.city'"); + + assert.equal(escaped, "`data->'$.user.address.city'`"); + }); +}); + describe('Nice to have: Deeply nested arrays', () => { test('triple nested array for bulk insert', () => { const data = [