dbgate-query-splitter
Advanced tools
Comparing version 4.10.3 to 4.10.4
@@ -24,2 +24,3 @@ export interface SplitterOptions { | ||
splitByLines: boolean; | ||
copyFromStdin: boolean; | ||
} | ||
@@ -26,0 +27,0 @@ export declare const defaultSplitterOptions: SplitterOptions; |
@@ -23,2 +23,3 @@ "use strict"; | ||
ignoreComments: false, | ||
copyFromStdin: false, | ||
}; | ||
@@ -25,0 +26,0 @@ exports.mysqlSplitterOptions = Object.assign(Object.assign({}, exports.defaultSplitterOptions), { allowCustomDelimiter: true, stringsBegins: ["'", '`'], stringsEnds: { "'": "'", '`': '`' }, stringEscapes: { "'": '\\', '`': '`' } }); |
import { SplitterOptions } from './options'; | ||
declare type SplitterSpecialMarkerType = 'copy_stdin_start' | 'copy_stdin_end' | 'copy_stdin_line'; | ||
export interface SplitStreamContext { | ||
@@ -20,2 +21,4 @@ options: SplitterOptions; | ||
wasDataInCommand: boolean; | ||
isCopyFromStdin: boolean; | ||
isCopyFromStdinCandidate: boolean; | ||
} | ||
@@ -40,2 +43,3 @@ export interface SplitLineContext extends SplitStreamContext { | ||
trimEnd?: SplitPositionDefinition; | ||
specialMarker?: SplitterSpecialMarkerType; | ||
} | ||
@@ -47,1 +51,2 @@ export declare type SplitResultItem = string | SplitResultItemRich; | ||
export declare function splitQuery(sql: string, options?: SplitterOptions): SplitResultItem[]; | ||
export {}; |
@@ -77,2 +77,19 @@ "use strict"; | ||
const ch = s[pos]; | ||
if (context.isCopyFromStdin) { | ||
if (s.slice(pos).startsWith('\\.') && !context.wasDataOnLine) { | ||
return { | ||
type: 'copy_stdin_end', | ||
length: 2, | ||
}; | ||
} | ||
let pos2 = pos; | ||
while (pos2 < context.end && s[pos2] != '\n') | ||
pos2++; | ||
if (pos2 < context.end && s[pos2] == '\n') | ||
pos2++; | ||
return { | ||
type: 'copy_stdin_line', | ||
length: pos2 - pos, | ||
}; | ||
} | ||
if (context.options.stringsBegins.includes(ch)) { | ||
@@ -193,2 +210,21 @@ pos++; | ||
} | ||
if (context.options.copyFromStdin && !context.wasDataOnLine && s.slice(pos).startsWith('COPY ')) { | ||
return { | ||
type: 'copy', | ||
length: 5, | ||
}; | ||
} | ||
if (context.isCopyFromStdinCandidate && s.slice(pos).startsWith('FROM stdin;')) { | ||
let pos2 = pos + 'FROM stdin;'.length; | ||
const pos0 = pos2 - 1; | ||
while (pos2 < context.end && s[pos2] != '\n') | ||
pos2++; | ||
if (s[pos2] == '\n') | ||
pos2++; | ||
return { | ||
type: 'copy_stdin_start', | ||
length: pos2 - pos, | ||
lengthWithoutWhitespace: pos0 - pos, | ||
}; | ||
} | ||
const dollarString = scanDollarQuotedString(context); | ||
@@ -208,2 +244,4 @@ if (dollarString) | ||
wasDataOnLine: context.wasDataOnLine, | ||
isCopyFromStdinCandidate: context.isCopyFromStdinCandidate, | ||
isCopyFromStdin: context.isCopyFromStdin, | ||
}; | ||
@@ -233,7 +271,7 @@ cloned.position += delimiter.length; | ||
} | ||
function pushQuery(context) { | ||
function pushQuery(context, specialMarker) { | ||
context.commandPart += context.source.slice(context.currentCommandStart, context.position); | ||
pushCurrentQueryPart(context); | ||
pushCurrentQueryPart(context, specialMarker); | ||
} | ||
function pushCurrentQueryPart(context) { | ||
function pushCurrentQueryPart(context, specialMarker) { | ||
const trimmed = context.commandPart.substring(context.trimCommandStartPosition - context.commandStartPosition, context.noWhitePosition - context.commandStartPosition); | ||
@@ -264,2 +302,3 @@ if (trimmed.trim()) { | ||
}, | ||
specialMarker, | ||
}); | ||
@@ -362,2 +401,36 @@ } | ||
break; | ||
case 'copy': | ||
movePosition(context, token.length, false); | ||
context.isCopyFromStdinCandidate = true; | ||
context.wasDataOnLine = true; | ||
break; | ||
case 'copy_stdin_start': | ||
movePosition(context, token.lengthWithoutWhitespace, false); | ||
movePosition(context, token.length - token.lengthWithoutWhitespace, true); | ||
context.isCopyFromStdin = true; | ||
context.isCopyFromStdinCandidate = false; | ||
context.wasDataOnLine = false; | ||
pushQuery(context, 'copy_stdin_start'); | ||
context.commandPart = ''; | ||
context.currentCommandStart = context.position; | ||
markStartCommand(context); | ||
break; | ||
case 'copy_stdin_line': | ||
movePosition(context, token.length, false); | ||
context.isCopyFromStdin = true; | ||
context.isCopyFromStdinCandidate = false; | ||
pushQuery(context, 'copy_stdin_line'); | ||
context.commandPart = ''; | ||
context.currentCommandStart = context.position; | ||
markStartCommand(context); | ||
break; | ||
case 'copy_stdin_end': | ||
movePosition(context, token.length, false); | ||
context.isCopyFromStdin = false; | ||
context.wasDataOnLine = true; | ||
pushQuery(context, 'copy_stdin_end'); | ||
context.commandPart = ''; | ||
context.currentCommandStart = context.position; | ||
markStartCommand(context); | ||
break; | ||
case 'delimiter': | ||
@@ -374,2 +447,3 @@ if (context.options.preventSingleLineSplit && containsDataAfterDelimiterOnLine(context, token)) { | ||
markStartCommand(context); | ||
context.isCopyFromStdinCandidate = false; | ||
break; | ||
@@ -437,2 +511,4 @@ } | ||
wasDataInCommand: false, | ||
isCopyFromStdin: false, | ||
isCopyFromStdinCandidate: false, | ||
pushOutput: cmd => output.push(cmd), | ||
@@ -439,0 +515,0 @@ wasDataOnLine: false, |
@@ -27,2 +27,4 @@ "use strict"; | ||
wasDataInCommand: false, | ||
isCopyFromStdin: false, | ||
isCopyFromStdinCandidate: false, | ||
options, | ||
@@ -29,0 +31,0 @@ currentDelimiter: (0, splitQuery_1.getInitialDelimiter)(options), |
@@ -191,1 +191,29 @@ "use strict"; | ||
}); | ||
test('postgres copy from stdin', () => { | ||
const input = 'COPY public."Genre" ("GenreId", "Name") FROM stdin;\n1 Rock\n2 Jazz\n3 Metal\n\\.\nCREATE TABLE xxx'; | ||
const output = (0, splitQuery_1.splitQuery)(input, Object.assign(Object.assign({}, options_1.postgreSplitterOptions), { copyFromStdin: true, returnRichInfo: true })); | ||
expect(output).toEqual(expect.arrayContaining([ | ||
expect.objectContaining({ | ||
text: 'COPY public."Genre" ("GenreId", "Name") FROM stdin', | ||
specialMarker: 'copy_stdin_start', | ||
}), | ||
expect.objectContaining({ | ||
text: '1\tRock\n', | ||
specialMarker: 'copy_stdin_line', | ||
}), | ||
expect.objectContaining({ | ||
text: '2\tJazz\n', | ||
specialMarker: 'copy_stdin_line', | ||
}), | ||
expect.objectContaining({ | ||
text: '3\tMetal\n', | ||
specialMarker: 'copy_stdin_line', | ||
}), | ||
expect.objectContaining({ | ||
specialMarker: 'copy_stdin_end', | ||
}), | ||
expect.objectContaining({ | ||
text: 'CREATE TABLE xxx', | ||
}), | ||
])); | ||
}); |
{ | ||
"version": "4.10.3", | ||
"version": "4.10.4", | ||
"name": "dbgate-query-splitter", | ||
@@ -4,0 +4,0 @@ "main": "lib/index.js", |
47872
1030