dbd/common.c

changeset 17
21c4feaeafe7
child 28
44b1d78b50f5
equal deleted inserted replaced
16:318e5dfd03b8 17:21c4feaeafe7
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

mercurial