mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-14 18:12:05 +08:00
* Add code comments.
* Add helpful (hopefully) delimiter syntax checking. * Protect the backslash-in-string-literal parsing a bit more by only activating it inside string literals. Also move it towards the string literal handler to improve readability. * Fix regression: choose characters for secchar and thdchar that are really unused by the parser logic.
This commit is contained in:
@ -327,12 +327,22 @@ begin
|
|||||||
result := '';
|
result := '';
|
||||||
s := Trim(s);
|
s := Trim(s);
|
||||||
// Test for empty delimiter.
|
// Test for empty delimiter.
|
||||||
if s = '' then result := 'DELIMITER must be followed by a character or string';
|
if s = '' then result := 'DELIMITER must be followed by a non-comment character or string';
|
||||||
// Disallow backslash, because the MySQL CLI does so for some reason.
|
// Disallow backslash, because the MySQL CLI does so for some reason.
|
||||||
// Then again, is there any reason to be bug-per-bug compatible with some random SQL parser?
|
// Then again, is there any reason to be bug-per-bug compatible with some random SQL parser?
|
||||||
if Pos('\', s) > 0 then result := 'Backslash disallowed in DELIMITER because the MySQL CLI does not accept it';
|
if Pos('\', s) > 0 then result := 'Backslash disallowed in DELIMITER (because the MySQL CLI does not accept it)';
|
||||||
// Disallow using DELIMITER, so we don't have to deal with it in code.
|
// Disallow stuff which would be negated by the comment parsing logic.
|
||||||
if UpperCase(s) = 'DELIMITER' then result := '"DELIMITER" is disallowed as a SQL delimiter';
|
if
|
||||||
|
(Pos('/*', s) > 0) or
|
||||||
|
(Pos('--', s) > 0) or
|
||||||
|
(Pos('#', s) > 0)
|
||||||
|
then result := 'Start-of-comment tokens disallowed in DELIMITER (because it would be ignored)';
|
||||||
|
// Disallow stuff which would be negated by the SQL parser (and could slightly confuse it, if at end-of-string).
|
||||||
|
if
|
||||||
|
(Pos('''', s) > 0) or
|
||||||
|
(Pos('`', s) > 0) or
|
||||||
|
(Pos('"', s) > 0)
|
||||||
|
then result := 'String literal markers disallowed in DELIMITER (because it would be ignored)';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -468,11 +478,12 @@ begin
|
|||||||
i := i + 1;
|
i := i + 1;
|
||||||
|
|
||||||
// Helpers for multi-character tests, avoids testing for string length.
|
// Helpers for multi-character tests, avoids testing for string length.
|
||||||
secchar := '-';
|
secchar := '+';
|
||||||
thdchar := '-';
|
thdchar := '+';
|
||||||
if i < length(sql) then secchar := sql[i + 1];
|
if i < length(sql) then secchar := sql[i + 1];
|
||||||
if i + 1 < length(sql) then thdchar := sql[i + 2];
|
if i + 1 < length(sql) then thdchar := sql[i + 2];
|
||||||
|
|
||||||
|
// Turn comments into whitespace.
|
||||||
if (sql[i] = '#') and (not instring) and (not inbigcomment) then begin
|
if (sql[i] = '#') and (not instring) and (not inbigcomment) then begin
|
||||||
incomment := true;
|
incomment := true;
|
||||||
end;
|
end;
|
||||||
@ -510,6 +521,7 @@ begin
|
|||||||
if i < len then continue;
|
if i < len then continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Avoid parsing stuff inside string literals.
|
||||||
if (sql[i] in ['''', '"', '`']) and (not (backslash and instring)) and (not incomment) then begin
|
if (sql[i] in ['''', '"', '`']) and (not (backslash and instring)) and (not incomment) then begin
|
||||||
if instring and (sql[i] = encloser) then begin
|
if instring and (sql[i] = encloser) then begin
|
||||||
if secchar = encloser then
|
if secchar = encloser then
|
||||||
@ -524,6 +536,9 @@ begin
|
|||||||
if i < len then continue;
|
if i < len then continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if (instring and (sql[i] = '\')) or backslash then
|
||||||
|
backslash := not backslash;
|
||||||
|
|
||||||
// Allow a DELIMITER command in middle of SQL, like the MySQL CLI does.
|
// Allow a DELIMITER command in middle of SQL, like the MySQL CLI does.
|
||||||
if (not instring) and (not incomment) and (not inbigcomment) and (not inconditional) and (not indelimiter) and (start + 8 = i) and scanReverse(sql, i, 'delimiter', true) then begin
|
if (not instring) and (not incomment) and (not inbigcomment) and (not inconditional) and (not indelimiter) and (start + 8 = i) and scanReverse(sql, i, 'delimiter', true) then begin
|
||||||
// The allowed DELIMITER format is:
|
// The allowed DELIMITER format is:
|
||||||
@ -552,6 +567,7 @@ begin
|
|||||||
if i < len then continue;
|
if i < len then continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Handle conditional comments.
|
||||||
if (not instring) and (not incomment) and (sql[i] + secchar + thdchar = '/*!') then begin
|
if (not instring) and (not incomment) and (sql[i] + secchar + thdchar = '/*!') then begin
|
||||||
inconditional := true;
|
inconditional := true;
|
||||||
condterminated := false;
|
condterminated := false;
|
||||||
@ -584,7 +600,7 @@ begin
|
|||||||
start := i + 1;
|
start := i + 1;
|
||||||
end else begin
|
end else begin
|
||||||
tmp := '/*!' + conditional + ' ';
|
tmp := '/*!' + conditional + ' ';
|
||||||
Move(tmp[1], sql[start - length(tmp)], length(tmp));
|
move(tmp[1], sql[start - length(tmp)], length(tmp));
|
||||||
start := start - length(tmp);
|
start := start - length(tmp);
|
||||||
end;
|
end;
|
||||||
condterminated := false;
|
condterminated := false;
|
||||||
@ -595,10 +611,7 @@ begin
|
|||||||
if i < len then continue;
|
if i < len then continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (sql[i] = '\') or backslash then
|
// Add sql sentence.
|
||||||
backslash := not backslash;
|
|
||||||
|
|
||||||
// add sql sentence
|
|
||||||
if ((not instring) and (scanReverse(sql, i, delimiter, false)) or (i = len)) then begin
|
if ((not instring) and (scanReverse(sql, i, delimiter, false)) or (i = len)) then begin
|
||||||
if (i < len) then j := delimiter_length else begin
|
if (i < len) then j := delimiter_length else begin
|
||||||
// end of string, add sql sentence but only remove delimiter if it's there
|
// end of string, add sql sentence but only remove delimiter if it's there
|
||||||
|
Reference in New Issue
Block a user