Skip to content

Commit

Permalink
oracle support
Browse files Browse the repository at this point in the history
  • Loading branch information
janproch committed Jun 1, 2024
1 parent fb647f5 commit 6a35d93
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 2 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Supports following SQL dialects:
- PostgreSQL
- SQLite
- Microsoft SQL Server
- Oracle

## Usage

Expand Down Expand Up @@ -96,3 +97,5 @@ yarn test
- Dollar strings (PostgreSQL)
- GO separators (MS SQL)
- Custom delimiter, setby DELIMITER keyword (MySQL)
- Slash separator (Oracle)
- SET SQLTERMINATOR (Oracle)
15 changes: 15 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ export interface SplitterOptions {

allowSemicolon: boolean;
allowCustomDelimiter: boolean;
allowCustomSqlTerminator: boolean;
allowGoDelimiter: boolean;
allowSlashDelimiter: boolean;
allowDollarDollarString: boolean;
noSplit: boolean;
doubleDashComments: boolean;
Expand All @@ -29,7 +31,9 @@ export const defaultSplitterOptions: SplitterOptions = {

allowSemicolon: true,
allowCustomDelimiter: false,
allowCustomSqlTerminator: false,
allowGoDelimiter: false,
allowSlashDelimiter: false,
allowDollarDollarString: false,
noSplit: false,

Expand Down Expand Up @@ -100,3 +104,14 @@ export const redisSplitterOptions: SplitterOptions = {

splitByLines: true,
};

export const oracleSplitterOptions: SplitterOptions = {
...defaultSplitterOptions,

allowCustomSqlTerminator: true,
allowSlashDelimiter: true,

stringsBegins: ["'", '"'],
stringsEnds: { "'": "'", '"': '"' },
stringEscapes: { "'": "'", '"': '"' },
};
51 changes: 49 additions & 2 deletions src/splitQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ interface Token {
| 'whitespace'
| 'eoln'
| 'data'
| 'slash_delimiter'
| 'set_delimiter'
| 'set_sqlterminator'
| 'comment'
| 'go_delimiter'
| 'create_routine';
Expand Down Expand Up @@ -231,12 +233,49 @@ function scanToken(context: ScannerContext): Token {
}
}

if (context.options.allowCustomSqlTerminator) {
const m = s.slice(pos).match(/^SET[ \t]+SQLT(ERMINATOR)?[ \t]+(ON|OFF|".")/i);
if (m) {
if (m[2].toUpperCase() == 'OFF') {
return {
type: 'set_sqlterminator',
value: null,
length: m[0].length,
};
}
if (m[2].toUpperCase() == 'ON') {
return {
type: 'set_sqlterminator',
value: SEMICOLON,
length: m[0].length,
};
}
if (m[2].startsWith('"')) {
return {
type: 'set_sqlterminator',
value: m[2].slice(1, -1),
length: m[0].length,
};
}
}
}

if ((context.options.allowGoDelimiter || context.options.adaptiveGoSplit) && !context.wasDataOnLine) {
const m = s.slice(pos).match(/^GO[\t\r ]*(\n|$)/i);
if (m) {
return {
type: 'go_delimiter',
length: m[0].length - 1,
length: m[0].endsWith('\n') ? m[0].length - 1 : m[0].length,
};
}
}

if (context.options.allowSlashDelimiter && !context.wasDataOnLine) {
const m = s.slice(pos).match(/^\/[\t\r ]*(\n|$)/i);
if (m) {
return {
type: 'slash_delimiter',
length: m[0].endsWith('\n') ? m[0].length - 1 : m[0].length,
};
}
}
Expand All @@ -246,7 +285,7 @@ function scanToken(context: ScannerContext): Token {
if (m) {
return {
type: 'create_routine',
length: m[0].length - 1,
length: m[0].length,
};
}
}
Expand Down Expand Up @@ -403,6 +442,7 @@ export function splitQueryLine(context: SplitLineContext) {
movePosition(context, token.length, true);
break;
case 'set_delimiter':
case 'set_sqlterminator':
pushQuery(context);
context.commandPart = '';
context.currentDelimiter = token.value;
Expand All @@ -420,6 +460,13 @@ export function splitQueryLine(context: SplitLineContext) {
context.currentDelimiter = SEMICOLON;
}
break;
case 'slash_delimiter':
pushQuery(context);
context.commandPart = '';
movePosition(context, token.length, false);
context.currentCommandStart = context.position;
markStartCommand(context);
break;
case 'create_routine':
movePosition(context, token.length, false);
if (context.options.adaptiveGoSplit) {
Expand Down
25 changes: 25 additions & 0 deletions src/splitter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
mongoSplitterOptions,
noSplitSplitterOptions,
redisSplitterOptions,
oracleSplitterOptions,
} from './options';
import { splitQuery } from './splitQuery';

Expand Down Expand Up @@ -224,3 +225,27 @@ test('count lines with flush', () => {
])
);
});

test('shash delimiter', () => {
const input = 'SELECT 1\n/\nSELECT 2\n';
const output = splitQuery(input, oracleSplitterOptions);
expect(output).toEqual(['SELECT 1', 'SELECT 2']);
});

test('go delimiter on the end', () => {
const input = 'SELECT 1\nGO';
const output = splitQuery(input, mssqlSplitterOptions);
expect(output).toEqual(['SELECT 1']);
});

test('oracle procedure', () => {
const input = 'SET SQLT OFF\nCREATE PROC1\nSELECT 1;\nEND\n/';
const output = splitQuery(input, oracleSplitterOptions);
expect(output).toEqual(['CREATE PROC1\nSELECT 1;\nEND']);
});

test('oracle custom terminator', () => {
const input = 'SET SQLTERMINATOR "%"\nSELECT 1%\nSELECT 2';
const output = splitQuery(input, oracleSplitterOptions);
expect(output).toEqual(['SELECT 1', 'SELECT 2']);
});

0 comments on commit 6a35d93

Please sign in to comment.