|
1 #include <dbd/common.h> |
|
2 |
|
3 const char *strlower(char *in) { |
|
4 char *s = in; |
|
5 |
|
6 while(*s) { |
|
7 *s= (*s <= 'Z' && *s >= 'A') ? (*s - 'A') + 'a' : *s; |
|
8 s++; |
|
9 } |
|
10 |
|
11 return in; |
|
12 } |
|
13 |
|
14 /* |
|
15 * replace '?' placeholders with $\d+ placeholders |
|
16 * to be compatible with PSQL API |
|
17 */ |
|
18 char *replace_placeholders(lua_State *L, char native_prefix, const char *sql) { |
|
19 size_t len = strlen(sql); |
|
20 int num_placeholders = 0; |
|
21 int extra_space = 0; |
|
22 int i; |
|
23 char *newsql; |
|
24 int newpos = 1; |
|
25 int ph_num = 1; |
|
26 int in_quote = 0; |
|
27 char format_str[4]; |
|
28 |
|
29 format_str[0] = native_prefix; |
|
30 format_str[1] = '%'; |
|
31 format_str[2] = 'u'; |
|
32 format_str[3] = '\0'; |
|
33 |
|
34 /* |
|
35 * dumb count of all '?' |
|
36 * this will match more placeholders than necessesary |
|
37 * but it's safer to allocate more placeholders at the |
|
38 * cost of a few bytes than risk a buffer overflow |
|
39 */ |
|
40 for (i = 1; i < len; i++) { |
|
41 if (sql[i] == '?') { |
|
42 num_placeholders++; |
|
43 } |
|
44 } |
|
45 |
|
46 /* |
|
47 * this is MAX_PLACEHOLDER_SIZE-1 because the '?' is |
|
48 * replaced with '$' |
|
49 */ |
|
50 extra_space = num_placeholders * (MAX_PLACEHOLDER_SIZE-1); |
|
51 |
|
52 /* |
|
53 * allocate a new string for the converted SQL statement |
|
54 */ |
|
55 newsql = malloc(sizeof(char) * (len+extra_space+1)); |
|
56 memset(newsql, 0, sizeof(char) * (len+extra_space+1)); |
|
57 |
|
58 /* |
|
59 * copy first char. In valid SQL this cannot be a placeholder |
|
60 */ |
|
61 newsql[0] = sql[0]; |
|
62 |
|
63 /* |
|
64 * only replace '?' not in a single quoted string |
|
65 */ |
|
66 for (i = 1; i < len; i++) { |
|
67 /* |
|
68 * don't change the quote flag if the ''' is preceded |
|
69 * by a '\' to account for escaping |
|
70 */ |
|
71 if (sql[i] == '\'' && sql[i-1] != '\\') { |
|
72 in_quote = !in_quote; |
|
73 } |
|
74 |
|
75 if (sql[i] == '?' && !in_quote) { |
|
76 size_t n; |
|
77 |
|
78 if (ph_num > MAX_PLACEHOLDERS) { |
|
79 luaL_error(L, "Sorry, you are using more than %d placeholders. Use ${num} format instead", MAX_PLACEHOLDERS); |
|
80 } |
|
81 |
|
82 n = snprintf(&newsql[newpos], MAX_PLACEHOLDER_SIZE, format_str, ph_num++); |
|
83 |
|
84 newpos += n; |
|
85 } else { |
|
86 newsql[newpos] = sql[i]; |
|
87 newpos++; |
|
88 } |
|
89 } |
|
90 |
|
91 /* |
|
92 * terminate string on the last position |
|
93 */ |
|
94 newsql[newpos] = '\0'; |
|
95 |
|
96 /* fprintf(stderr, "[%s]\n", newsql); */ |
|
97 return newsql; |
|
98 } |
|
99 |