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 };
36 if (len
> MAX_ESC_STRING
) {
37 lwarn("Unescaped string too large (%d bytes, %d is allowed)",
42 if (bufsize
[idx
] < len
* 2) {
47 buf_ary
[idx
] = realloc(buf_ary
[idx
], size
);
50 lwarn("Failed to allocate %d bytes for sql escape buffer", size
);
56 idx
= (idx
+ 1) & (ESC_BUFS
- 1);
57 mysql_real_escape_string(db
.link
, buf
, str
, len
);
63 * these two functions are only here to allow callers
64 * access to error reporting without having to expose
65 * the db-link to theh callers. It's also nifty as we
66 * want to remain database layer agnostic
68 const char *sql_error()
71 return mysql_error(db
.link
);
73 return "unknown error (no link)";
79 return mysql_errno(db
.link
);
84 SQL_RESULT
*sql_get_result(void)
87 return mysql_use_result(db
.link
);
92 SQL_ROW
sql_fetch_row(MYSQL_RES
*result
)
95 return mysql_fetch_row(result
);
100 void sql_free_result(SQL_RESULT
*result
)
103 mysql_free_result(result
);
106 int sql_query(const char *fmt
, ...)
113 len
= vasprintf(&query
, fmt
, ap
);
116 if (len
== -1 || !query
) {
117 lerr("sql_query: Failed to build query from format-string '%s'", fmt
);
120 if ((result
= mysql_real_query(db
.link
, query
, len
))) {
121 lerr("mysql_query(): Retrying failed query [%s]: %s",
122 query
, mysql_error(db
.link
));
126 if ((result
= mysql_real_query(db
.link
, query
, len
)))
127 lerr("mysql_query(): Dropping failed query [%s]: %s",
128 query
, mysql_error(db
.link
));
138 if (!(db
.link
= mysql_init(NULL
)))
146 if (!(mysql_real_connect(db
.link
, db
.host
, db
.user
, db
.pass
,
147 db
.name
, db
.port
, NULL
, 0)))
149 lerr("Failed to connect to '%s' at '%s':'%d' using %s:%s as credentials: %s",
150 db
.name
, db
.host
, db
.port
, db
.user
, db
.pass
, mysql_error(db
.link
));
162 mysql_close(db
.link
);
167 const char *sql_table_name(void)
170 return "report_data";
175 int sql_config(const char *key
, const char *value
)
177 if (!prefixcmp(key
, "db_database"))
178 db
.name
= strdup(value
);
179 else if (!prefixcmp(key
, "db_user"))
180 db
.user
= strdup(value
);
181 else if (!prefixcmp(key
, "db_pass"))
182 db
.pass
= strdup(value
);
183 else if (!prefixcmp(key
, "db_host"))
184 db
.host
= strdup(value
);
185 else if (!prefixcmp(key
, "db_table")) {
186 db
.table
= strdup(value
);
188 else if (!prefixcmp(key
, "db_port")) {
191 db
.port
= (unsigned int)strtoul(value
, &endp
, 0);
193 if (endp
== value
|| *endp
!= 0)
197 return -1; /* config error */