diff --git a/src/index.ts b/src/index.ts index 3cee1fa..b495664 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,6 +34,8 @@ const charCode = { dash: 45, slash: 47, asterisk: 42, + exclamation: 33, + plus: 43, questionMark: 63, newline: 10, space: 32, @@ -129,11 +131,22 @@ const skipSqlContext = (sql: string, position: number): number => { } if (currentChar === charCode.dash && nextChar === charCode.dash) { - const lineBreak = sql.indexOf('\n', position + 2); - return lineBreak === -1 ? sql.length : lineBreak + 1; + const afterDash = sql.charCodeAt(position + 2); + + if (Number.isNaN(afterDash) || afterDash <= charCode.space) { + const lineBreak = sql.indexOf('\n', position + 2); + return lineBreak === -1 ? sql.length : lineBreak + 1; + } + + return -1; } if (currentChar === charCode.slash && nextChar === charCode.asterisk) { + const markerChar = sql.charCodeAt(position + 2); + + if (markerChar === charCode.exclamation || markerChar === charCode.plus) + return -1; + const commentEnd = sql.indexOf('*/', position + 2); return commentEnd === -1 ? sql.length : commentEnd + 2; } diff --git a/test/delimiters.test.ts b/test/delimiters.test.ts index 3488b97..c337018 100644 --- a/test/delimiters.test.ts +++ b/test/delimiters.test.ts @@ -338,6 +338,21 @@ describe('Query comments for debugging', () => { "SELECT * FROM users -- get all users\nWHERE status = 'active'" ); }); + + test('double dash without trailing whitespace is not a comment', () => { + const sql = format('SELECT 1--2, ?', ['VAL']); + assert.equal(sql, "SELECT 1--2, 'VAL'"); + }); + + test('executable comment placeholder is substituted, not skipped', () => { + const sql = format('SELECT /*!40101 ? */ , ?', ['A', 'B']); + assert.equal(sql, "SELECT /*!40101 'A' */ , 'B'"); + }); + + test('optimizer hint placeholder is substituted, not skipped', () => { + const sql = format('SELECT /*+ MAX_EXECUTION_TIME(?) */ id FROM t', [1000]); + assert.equal(sql, 'SELECT /*+ MAX_EXECUTION_TIME(1000) */ id FROM t'); + }); }); describe('Real edge cases', () => {