1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
* Copyright (C) 2008 Sun Microsystems, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <config.h>
#include "quote.h"
#include <drizzled/lex_string.h>
namespace drizzled
{
inline
static uint32_t get_esc_bit(unsigned char *mask, unsigned char num)
{
return (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7));
}
/**
* @brief
* Returns the argument string in single quotes suitable for using in a SQL statement.
*
* @detail
* Adds a \\ before all characters that needs to be escaped in a SQL string.
* We also escape '^Z' (END-OF-FILE in windows) to avoid problems when
* running commands from a file in windows.
*
* This function is very useful when you want to generate SQL statements.
*
* @note
* val_str(NULL) returns the string 'NULL' (4 letters, without quotes).
*
* @retval str Quoted string
* @retval NULL Out of memory.
*/
String *Item_func_quote::val_str(String *str)
{
assert(fixed == 1);
/*
Bit mask that has 1 for set for the position of the following characters:
0, \, ' and ^Z
*/
static unsigned char escmask[32]=
{
0x01, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
char *from, *to, *end, *start;
String *arg= args[0]->val_str(str);
uint32_t arg_length, new_length;
if (!arg) // Null argument
{
/* Return the string 'NULL' */
str->copy(STRING_WITH_LEN("NULL"), collation.collation);
null_value= 0;
return str;
}
arg_length= arg->length();
new_length= arg_length+2; /* for beginning and ending ' signs */
for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++)
new_length+= get_esc_bit(escmask, (unsigned char) *from);
tmp_value.alloc(new_length);
/*
We replace characters from the end to the beginning
*/
to= (char*) tmp_value.ptr() + new_length - 1;
*to--= '\'';
for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--)
{
/*
We can't use the bitmask here as we want to replace \O and ^Z with 0
and Z
*/
switch (*end) {
case 0:
*to--= '0';
*to= '\\';
break;
case '\032':
*to--= 'Z';
*to= '\\';
break;
case '\'':
case '\\':
*to--= *end;
*to= '\\';
break;
default:
*to= *end;
break;
}
}
*to= '\'';
tmp_value.length(new_length);
tmp_value.set_charset(collation.collation);
null_value= 0;
return &tmp_value;
}
} /* namespace drizzled */
|