dbd/common.c

changeset 17
21c4feaeafe7
child 28
44b1d78b50f5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbd/common.c	Sat Dec 06 00:32:37 2008 +0000
@@ -0,0 +1,99 @@
+#include <dbd/common.h>
+
+const char *strlower(char *in) {
+    char *s = in;
+
+    while(*s) {
+	*s= (*s <= 'Z' && *s >= 'A') ? (*s - 'A') + 'a' : *s;
+	s++;
+    }
+
+    return in;
+}
+
+/*
+ * replace '?' placeholders with $\d+ placeholders
+ * to be compatible with PSQL API
+ */
+char *replace_placeholders(lua_State *L, char native_prefix, const char *sql) {
+    size_t len = strlen(sql);
+    int num_placeholders = 0;
+    int extra_space = 0;
+    int 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 '$'
+     */ 
+    extra_space = num_placeholders * (MAX_PLACEHOLDER_SIZE-1); 
+
+    /*
+     * allocate a new string for the converted SQL statement
+     */
+    newsql = malloc(sizeof(char) * (len+extra_space+1));
+    memset(newsql, 0, sizeof(char) * (len+extra_space+1));
+    
+    /* 
+     * 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 ${num} format instead", MAX_PLACEHOLDERS);
+	    }
+
+	    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;
+}
+

mercurial