File: common.c

package info (click to toggle)
lua-dbi 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 448 kB
  • sloc: ansic: 3,946; sql: 291; makefile: 129
file content (137 lines) | stat: -rw-r--r-- 3,122 bytes parent folder | download | duplicates (2)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <dbd/common.h>

const char *dbd_strlower(char *in) {
	char *s = in;

	while(*s) {
		*s= (*s <= 'Z' && *s >= 'A') ? (*s - 'A') + 'a' : *s;
		s++;
	}

	return in;
}

/*
 * replace '?' placeholders with {native_prefix}\d+ placeholders
 * to be compatible with native API
 */
char *dbd_replace_placeholders(lua_State *L, char native_prefix, const char *sql) {
	size_t len = strlen(sql);
	int num_placeholders = 0;
	int extra_space = 0;
	size_t i;
	char *newsql;
	int newpos = 1;
	int ph_num = 1;
	int in_quote = 0;
	char format_str[4];

	format_str[0] = native_prefix;
	format_str[1] = '%';
	format_str[2] = 'u';
	format_str[3] = '\0';

	/*
	 * dumb count of all '?'
	 * this will match more placeholders than necessesary
	 * but it's safer to allocate more placeholders at the
	 * cost of a few bytes than risk a buffer overflow
	 */
	for (i = 1; i < len; i++) {
		if (sql[i] == '?') {
			num_placeholders++;
		}
	}

	/*
	 * this is MAX_PLACEHOLDER_SIZE-1 because the '?' is
	 * replaced with '{native_prefix}'
	 */
	extra_space = num_placeholders * (MAX_PLACEHOLDER_SIZE-1);

	/*
	 * allocate a new string for the converted SQL statement
	 */
	newsql = calloc(len+extra_space+1, sizeof(char));
	if(!newsql) {
		lua_pushliteral(L, "out of memory");
		/* lua_error does not return. */
		lua_error(L);
	}

	/*
	 * copy first char. In valid SQL this cannot be a placeholder
	 */
	newsql[0] = sql[0];

	/*
	 * only replace '?' not in a single quoted string
	 */
	for (i = 1; i < len; i++) {
		/*
		 * don't change the quote flag if the ''' is preceded
		 * by a '\' to account for escaping
		 */
		if (sql[i] == '\'' && sql[i-1] != '\\') {
			in_quote = !in_quote;
		}

		if (sql[i] == '?' && !in_quote) {
			size_t n;

			if (ph_num > MAX_PLACEHOLDERS) {
				luaL_error(L, "Sorry, you are using more than %d placeholders. Use %c{num} format instead", MAX_PLACEHOLDERS, native_prefix);
			}

			n = snprintf(&newsql[newpos], MAX_PLACEHOLDER_SIZE, format_str, ph_num++);

			newpos += n;
		} else {
			newsql[newpos] = sql[i];
			newpos++;
		}
	}

	/*
	 * terminate string on the last position
	 */
	newsql[newpos] = '\0';

	/* fprintf(stderr, "[%s]\n", newsql); */
	return newsql;
}

void dbd_register(lua_State *L, const char *name,
                  const luaL_Reg *methods, const luaL_Reg *class_methods,
                  lua_CFunction gc, lua_CFunction tostring, lua_CFunction close)
{
	/* Create a new metatable with the given name and then assign the methods
	 * to it.  Set the __index, __gc and __tostring fields appropriately.
	 */
	luaL_newmetatable(L, name);
#if LUA_VERSION_NUM < 502
	luaL_register(L, 0, methods);
#else
	luaL_setfuncs(L, methods, 0);
#endif
	lua_pushvalue(L, -1);
	lua_setfield(L, -2, "__index");

	lua_pushcfunction(L, gc);
	lua_setfield(L, -2, "__gc");

	lua_pushcfunction(L, tostring);
	lua_setfield(L, -2, "__tostring");

	lua_pushcfunction(L, close);
	lua_setfield(L, -2, "__close");

	/* Create a new table and register the class methods with it */
	lua_newtable(L);
#if LUA_VERSION_NUM < 502
	luaL_register(L, 0, class_methods);
#else
	luaL_setfuncs(L, class_methods, 0);
#endif
}