Skip to content

Commit 8c33dd3

Browse files
author
SPRINX0\prochazka
committed
set term support for firebird
1 parent 4397d24 commit 8c33dd3

3 files changed

Lines changed: 82 additions & 0 deletions

File tree

src/options.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface SplitterOptions {
88
allowSemicolon: boolean;
99
allowCustomDelimiter: boolean;
1010
allowCustomSqlTerminator: boolean;
11+
allowCustomSetTerm: boolean;
1112
allowGoDelimiter: boolean;
1213
allowSlashDelimiter: boolean;
1314
allowDollarDollarString: boolean;
@@ -41,6 +42,7 @@ export const defaultSplitterOptions: SplitterOptions = {
4142
allowSemicolon: true,
4243
allowCustomDelimiter: false,
4344
allowCustomSqlTerminator: false,
45+
allowCustomSetTerm: false,
4446
allowGoDelimiter: false,
4547
allowSlashDelimiter: false,
4648
allowDollarDollarString: false,
@@ -136,6 +138,7 @@ export const oracleSplitterOptions: SplitterOptions = {
136138
export const firebirdSplitterOptions: SplitterOptions = {
137139
...defaultSplitterOptions,
138140

141+
allowCustomSetTerm: true,
139142
skipSeparatorBeginEnd: true,
140143
queryParameterStyle: ':', // Firebird uses colon-prefixed parameters (:param_name)
141144
};

src/splitQuery.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ const BEGIN_EXTRA_KEYWORDS_REGEX = new RegExp(`^(?:${BEGIN_EXTRA_KEYWORDS.join('
66
const END_EXTRA_KEYWORDS = ['TRANSACTION', 'IF'];
77
const END_EXTRA_KEYWORDS_REGEX = new RegExp(`^(?:${END_EXTRA_KEYWORDS.join('|')})`, 'i');
88

9+
function escapeRegExp(str: string): string {
10+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
11+
}
12+
913
type SplitterSpecialMarkerType = 'copy_stdin_start' | 'copy_stdin_end' | 'copy_stdin_line';
1014
export interface SplitStreamContext {
1115
options: SplitterOptions;
@@ -283,7 +287,22 @@ export function scanToken(context: ScannerContext): Token {
283287
}
284288
}
285289

290+
if (context.options.allowCustomSetTerm) {
291+
// Firebird: SET TERM ^ ;
292+
// The command ends with the current delimiter
293+
const firebirdPattern = new RegExp(`^SET[ \\t]+TERM[ \\t]+(\\S+)[ \\t]*${escapeRegExp(context.currentDelimiter || SEMICOLON)}`, 'i');
294+
const firebirdMatch = s.slice(pos).match(firebirdPattern);
295+
if (firebirdMatch) {
296+
return {
297+
type: 'set_sqlterminator',
298+
value: firebirdMatch[1],
299+
length: firebirdMatch[0].length,
300+
};
301+
}
302+
}
303+
286304
if (context.options.allowCustomSqlTerminator) {
305+
// Oracle: SET SQLTERMINATOR "."
287306
const m = s.slice(pos).match(/^SET[ \t]+SQLT(ERMINATOR)?[ \t]+(ON|OFF|".")/i);
288307
if (m) {
289308
if (m[2].toUpperCase() == 'OFF') {

src/splitter.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,3 +384,63 @@ END`;
384384
expect(output.length).toBe(1);
385385
expect(output[0]).toEqual(input);
386386
});
387+
388+
test('Firebird - SET TERM with trigger', () => {
389+
const input = `set term ^;
390+
alter trigger ZAK_ROZPISKY_AU
391+
as
392+
declare xpocet integer;
393+
declare xtermin_vykres timestamp;
394+
BEGIN
395+
SELECT 1 FROM TABLE1;
396+
END^
397+
set term ;^
398+
SELECT * FROM TABLE2`;
399+
const output = splitQuery(input, firebirdSplitterOptions);
400+
401+
expect(output.length).toBe(2);
402+
expect(output[0]).toMatch(/alter trigger/i);
403+
expect(output[0]).toMatch(/SELECT 1 FROM TABLE1/);
404+
expect(output[1]).toEqual('SELECT * FROM TABLE2');
405+
});
406+
407+
test('Firebird - SET TERM with procedure', () => {
408+
const input = `SET TERM ^ ;
409+
CREATE PROCEDURE test_proc
410+
AS
411+
BEGIN
412+
SELECT 1;
413+
SELECT 2;
414+
END^
415+
SET TERM ; ^
416+
SELECT 3;`;
417+
const output = splitQuery(input, firebirdSplitterOptions);
418+
419+
expect(output.length).toBe(2);
420+
expect(output[0]).toMatch(/CREATE PROCEDURE/);
421+
expect(output[0]).toMatch(/SELECT 1/);
422+
expect(output[0]).toMatch(/SELECT 2/);
423+
expect(output[1]).toEqual('SELECT 3');
424+
});
425+
426+
test('Firebird - SET TERM with multiple procedures', () => {
427+
const input = `SET TERM ^ ;
428+
CREATE PROCEDURE proc1
429+
AS
430+
BEGIN
431+
SELECT 1;
432+
END^
433+
CREATE PROCEDURE proc2
434+
AS
435+
BEGIN
436+
SELECT 2;
437+
END^
438+
SET TERM ; ^`;
439+
const output = splitQuery(input, firebirdSplitterOptions);
440+
441+
expect(output.length).toBe(2);
442+
expect(output[0]).toMatch(/proc1/);
443+
expect(output[0]).toMatch(/SELECT 1/);
444+
expect(output[1]).toMatch(/proc2/);
445+
expect(output[1]).toMatch(/SELECT 2/);
446+
});

0 commit comments

Comments
 (0)