in driver/utility.cc [2469:2592]
ulong myodbc_escape_string(STMT *stmt,
char *to, ulong to_length,
const char *from, ulong length,
bool escape_id,
bool esc_wildcard)
{
const char *to_start= to;
const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
my_bool overflow= FALSE;
myodbc::CHARSET_INFO *charset_info= stmt->dbc->cxn_charset_info;
/*
The character to be escaped by doubling it -- for identifiers it is the backquote, for string
literals it is the single quote.
*/
char double_char = (escape_id ? '`' : '\'');
/*
Whether to use backslash escapes. Note that this is not the case when escaping an identifier.
*/
bool use_backslash
= (!escape_id &&
!(stmt->dbc->mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES));
my_bool use_mb_flag= use_mb(charset_info);
for (end= from + length; from < end; ++from)
{
char escape= 0;
int tmp_length;
// Handle multi-byte sequences
if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
{
if (to + tmp_length > to_end)
{
overflow= TRUE;
break;
}
while (tmp_length--)
*to++= *from++;
--from;
continue;
}
if (double_char && *from == double_char)
escape = double_char;
/*
If the next character appears to begin a multi-byte character, we
escape that first byte of that apparent multi-byte character. (The
character just looks like a multi-byte character -- if it were actually
a multi-byte character, it would have been passed through in the test
above.)
Without this check, we can create a problem by converting an invalid
multi-byte character into a valid one. For example, 0xbf27 is not
a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \)
*/
else if (use_mb_flag && (tmp_length= my_mbcharlen(charset_info, *from)) > 1)
escape= *from;
/*
Note: If use_backslash is false then we will not set `escape` character and the logic
below will copy input to output as is.
*/
else if (use_backslash)
switch (*from)
{
case 0: // Must be escaped for 'mysql'
escape= '0';
break;
case '\n': // Must be escaped for logs
escape= 'n';
break;
case '\r':
escape= 'r';
break;
case '\\':
case '\'':
case '"': // Better safe than sorry
escape= *from;
break;
case '\032': // This gives problems on Win32
escape= 'Z';
break;
case '_': // Escaping of the pattern characters
case '%':
if (esc_wildcard)
escape = *from;
break;
}
if (escape)
{
if (to + 2 > to_end)
{
overflow= TRUE;
break;
}
*to++= (escape == double_char ? escape : '\\');
*to++= escape;
}
else
{
if (to + 1 > to_end)
{
overflow= TRUE;
break;
}
*to++= *from;
}
} // for
*to= 0;
return overflow ? (ulong)~0 : (ulong) (to - to_start);
}