18 #define ESC_BUFS 8 /* must be a power of 2 */
19 #define MAX_ESC_STRING 65536
21 #define esc(s) sql_escape(s)
22 char *sql_escape(const char *str
)
25 static char *buf_ary
[ESC_BUFS
] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
26 static size_t bufsize
[ESC_BUFS
] = { 0, 0, 0, 0, 0, 0, 0, 0 };
34 if (len
> MAX_ESC_STRING
) {
35 lwarn("Unescaped string too large (%d bytes, %d is allowed)",
40 if (bufsize
[idx
] < len
* 2) {
41 size_t size
= len
* 2;
45 buf_ary
[idx
] = realloc(buf_ary
[idx
], size
);
48 lwarn("Failed to allocate %d bytes for sql escape buffer", size
);
54 idx
= (idx
+ 1) & (ESC_BUFS
- 1);
55 mysql_real_escape_string(db
.link
, buf
, str
, len
);
61 * these two functions are only here to allow callers
62 * access to error reporting without having to expose
63 * the db-link to theh callers. It's also nifty as we
64 * want to remain database layer agnostic
66 const char *sql_error()
69 return mysql_error(db
.link
);
71 return "unknown error (no link)";
77 return mysql_errno(db
.link
);
82 SQL_RESULT
*sql_get_result(void)
85 return mysql_use_result(db
.link
);
90 SQL_ROW
sql_fetch_row(MYSQL_RES
*result
)
93 return mysql_fetch_row(result
);
98 void sql_free_result(SQL_RESULT
*result
)
101 mysql_free_result(result
);
104 int sql_query(const char *fmt
, ...)
111 len
= vasprintf(&query
, fmt
, ap
);
114 if (len
== -1 || !query
) {
115 lerr("sql_query: Failed to build query from format-string '%s'", fmt
);
118 if ((result
= mysql_real_query(db
.link
, query
, len
))) {
119 lerr("mysql_query(): Retrying failed query [%s]: %s",
120 query
, mysql_error(db
.link
));
124 if ((result
= mysql_real_query(db
.link
, query
, len
)))
125 lerr("mysql_query(): Dropping failed query [%s]: %s",
126 query
, mysql_error(db
.link
));
136 if (!(db
.link
= mysql_init(NULL
)))
144 if (!(mysql_real_connect(db
.link
, db
.host
, db
.user
, db
.pass
,
145 db
.name
, db
.port
, NULL
, 0)))
147 lerr("Failed to connect to '%s' at '%s':'%d' using %s:%s as credentials: %s",
148 db
.name
, db
.host
, db
.port
, db
.user
, db
.pass
, mysql_error(db
.link
));
160 mysql_close(db
.link
);
165 const char *sql_table_name(void)
168 return "report_data";
173 int sql_config(const char *key
, const char *value
)
175 if (!prefixcmp(key
, "db_database"))
176 db
.name
= strdup(value
);
177 else if (!prefixcmp(key
, "db_user"))
178 db
.user
= strdup(value
);
179 else if (!prefixcmp(key
, "db_pass"))
180 db
.pass
= strdup(value
);
181 else if (!prefixcmp(key
, "db_host"))
182 db
.host
= strdup(value
);
183 else if (!prefixcmp(key
, "db_table")) {
184 db
.table
= strdup(value
);
186 else if (!prefixcmp(key
, "db_port")) {
189 db
.port
= (unsigned int)strtoul(value
, &endp
, 0);
191 if (endp
== value
|| *endp
!= 0)
195 return -1; /* config error */