18 #define ESC_BUFS 8 /* must be a power of 2 */
19 #define MAX_ESC_STRING 65536
21 typedef unsigned int uint
;
23 #define esc(s) sql_escape(s)
24 char *sql_escape(const char *str
)
27 static char *buf_ary
[ESC_BUFS
] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
28 static uint bufsize
[ESC_BUFS
] = { 0, 0, 0, 0, 0, 0, 0, 0 };
35 if (!db
.link
&& sql_init() < 0)
39 if (len
> MAX_ESC_STRING
) {
40 lwarn("Unescaped string too large (%d bytes, %d is allowed)",
45 if (bufsize
[idx
] < len
* 2) {
50 buf_ary
[idx
] = realloc(buf_ary
[idx
], size
);
53 lwarn("Failed to allocate %d bytes for sql escape buffer", size
);
59 idx
= (idx
+ 1) & (ESC_BUFS
- 1);
60 mysql_real_escape_string(db
.link
, buf
, str
, len
);
66 * these two functions are only here to allow callers
67 * access to error reporting without having to expose
68 * the db-link to theh callers. It's also nifty as we
69 * want to remain database layer agnostic
71 const char *sql_error()
74 return mysql_error(db
.link
);
76 return "unknown error (no link)";
82 return mysql_errno(db
.link
);
87 SQL_RESULT
*sql_get_result(void)
90 return mysql_use_result(db
.link
);
95 SQL_ROW
sql_fetch_row(MYSQL_RES
*result
)
98 return mysql_fetch_row(result
);
103 void sql_free_result(SQL_RESULT
*result
)
106 mysql_free_result(result
);
109 static int sql_reinit(void)
115 int sql_query(const char *fmt
, ...)
121 if (!db
.link
&& sql_reinit() < 0)
125 len
= vasprintf(&query
, fmt
, ap
);
128 if (len
== -1 || !query
) {
129 lerr("sql_query: Failed to build query from format-string '%s'", fmt
);
132 if ((result
= mysql_real_query(db
.link
, query
, len
))) {
133 lerr("mysql_query(): Retrying failed query [%s]: %s",
137 if (sql_init() < 0 || (result
= mysql_real_query(db
.link
, query
, len
)))
138 lerr("mysql_query(): Dropping failed query [%s]: %s",
149 if (!(db
.link
= mysql_init(NULL
)))
157 if (!(mysql_real_connect(db
.link
, db
.host
, db
.user
, db
.pass
,
158 db
.name
, db
.port
, NULL
, 0)))
160 lerr("Failed to connect to '%s' at '%s':'%d' using %s:%s as credentials: %s",
161 db
.name
, db
.host
, db
.port
, db
.user
, db
.pass
, sql_error());
173 mysql_close(db
.link
);
180 const char *sql_db_name(void)
183 return "monitor_reports";
188 const char *sql_table_name(void)
191 return "report_data";
196 int sql_config(const char *key
, const char *value
)
198 if (!prefixcmp(key
, "db_database"))
199 db
.name
= strdup(value
);
200 else if (!prefixcmp(key
, "db_user"))
201 db
.user
= strdup(value
);
202 else if (!prefixcmp(key
, "db_pass"))
203 db
.pass
= strdup(value
);
204 else if (!prefixcmp(key
, "db_host"))
205 db
.host
= strdup(value
);
206 else if (!prefixcmp(key
, "db_table")) {
207 db
.table
= strdup(value
);
209 else if (!prefixcmp(key
, "db_port")) {
212 db
.port
= (unsigned int)strtoul(value
, &endp
, 0);
214 if (endp
== value
|| *endp
!= 0)
218 return -1; /* config error */