76 #if !defined(SQLITE_VERSION_NUMBER) || (SQLITE_VERSION_NUMBER < 3005004)
77 #define sqlite3_prepare_v2 sqlite3_prepare
110 static void dict_sqlite_quote(
DICT *dict,
const char *raw_text,
VSTRING *result)
114 quoted_text = sqlite3_mprintf(
"%q", raw_text);
116 if (quoted_text == 0)
117 msg_fatal(
"dict_sqlite_quote: out of memory");
119 sqlite3_free(quoted_text);
124 static void dict_sqlite_close(
DICT *dict)
126 const char *myname =
"dict_sqlite_close";
127 DICT_SQLITE *dict_sqlite = (DICT_SQLITE *) dict;
130 msg_info(
"%s: %s", myname, dict_sqlite->parser->name);
132 if (sqlite3_close(dict_sqlite->db) != SQLITE_OK)
133 msg_fatal(
"%s: close %s failed", myname, dict_sqlite->parser->name);
135 myfree(dict_sqlite->dbpath);
136 myfree(dict_sqlite->query);
137 myfree(dict_sqlite->result_format);
138 if (dict_sqlite->ctx)
147 static const char *dict_sqlite_lookup(
DICT *dict,
const char *name)
149 const char *myname =
"dict_sqlite_lookup";
150 DICT_SQLITE *dict_sqlite = (DICT_SQLITE *) dict;
151 sqlite3_stmt *sql_stmt;
152 const char *query_remainder;
171 msg_info(
"%s: %s: Skipping lookup of non-UTF-8 key '%s'",
172 myname, dict_sqlite->parser->name, name);
191 msg_info(
"%s: %s: Skipping lookup of '%s'",
192 myname, dict_sqlite->parser->name, name);
201 #define INIT_VSTR(buf, len) do { \
203 buf = vstring_alloc(len); \
204 VSTRING_RESET(buf); \
205 VSTRING_TERMINATE(buf); \
208 INIT_VSTR(query, 10);
211 name, 0, query, dict_sqlite_quote))
215 msg_info(
"%s: %s: Searching with query %s",
216 myname, dict_sqlite->parser->name,
vstring_str(query));
218 if (sqlite3_prepare_v2(dict_sqlite->db,
vstring_str(query), -1,
219 &sql_stmt, &query_remainder) != SQLITE_OK)
220 msg_fatal(
"%s: %s: SQL prepare failed: %s\n",
221 myname, dict_sqlite->parser->name,
222 sqlite3_errmsg(dict_sqlite->db));
225 msg_info(
"%s: %s: Ignoring text at end of query: %s",
226 myname, dict_sqlite->parser->name, query_remainder);
231 INIT_VSTR(result, 10);
232 while ((status = sqlite3_step(sql_stmt)) != SQLITE_DONE) {
233 if (status == SQLITE_ROW) {
235 (
const char *) sqlite3_column_text(sql_stmt, 0),
237 && dict_sqlite->expansion_limit > 0
238 && ++expansion > dict_sqlite->expansion_limit) {
239 msg_warn(
"%s: %s: Expansion limit exceeded for key '%s'",
240 myname, dict_sqlite->parser->name, name);
247 msg_warn(
"%s: %s: SQL step failed for query '%s': %s\n",
248 myname, dict_sqlite->parser->name,
249 vstring_str(query), sqlite3_errmsg(dict_sqlite->db));
258 if (sqlite3_finalize(sql_stmt))
259 msg_fatal(
"%s: %s: SQL finalize failed for query '%s': %s\n",
260 myname, dict_sqlite->parser->name,
261 vstring_str(query), sqlite3_errmsg(dict_sqlite->db));
269 static void sqlite_parse_config(DICT_SQLITE *dict_sqlite,
const char *sqlitecf)
278 dict_sqlite->dbpath =
cfg_get_str(dict_sqlite->parser,
"dbpath",
"", 1, 0);
279 dict_sqlite->query =
cfg_get_str(dict_sqlite->parser,
"query", NULL, 0, 0);
280 if (dict_sqlite->query == 0) {
285 dict_sqlite->result_format =
286 cfg_get_str(dict_sqlite->parser,
"result_format",
"%s", 1, 0);
287 dict_sqlite->expansion_limit =
288 cfg_get_int(dict_sqlite->parser,
"expansion_limit", 0, 0, 0);
293 dict_sqlite->ctx = 0;
295 dict_sqlite->query, 1);
296 (void)
db_common_parse(0, &dict_sqlite->ctx, dict_sqlite->result_format, 0);
313 DICT_SQLITE *dict_sqlite;
319 if (open_flags != O_RDONLY)
321 "%s:%s map requires O_RDONLY access mode",
329 "open %s: %m", name));
332 sizeof(DICT_SQLITE));
333 dict_sqlite->dict.
lookup = dict_sqlite_lookup;
334 dict_sqlite->dict.close = dict_sqlite_close;
335 dict_sqlite->dict.flags = dict_flags;
337 dict_sqlite->parser = parser;
338 sqlite_parse_config(dict_sqlite, name);
340 if (sqlite3_open(dict_sqlite->dbpath, &dict_sqlite->db))
341 msg_fatal(
"%s:%s: Can't open database: %s\n",
344 dict_sqlite->dict.owner =
cfg_get_owner(dict_sqlite->parser);
void db_common_sql_build_query(VSTRING *query, CFG_PARSER *parser)
int valid_utf8_string(const char *, ssize_t)
int cfg_get_int(const CFG_PARSER *parser, const char *name, int defval, int min, int max)
#define DICT_FLAG_FOLD_FIX
void db_common_free_ctx(void *ctxPtr)
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
int db_common_dict_partial(void *ctxPtr)
void db_common_parse_domain(CFG_PARSER *parser, void *ctxPtr)
int db_common_expand(void *ctxArg, const char *format, const char *value, const char *key, VSTRING *result, db_quote_callback_t quote_func)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
int db_common_check_domain(void *ctxPtr, const char *addr)
char * lowercase(char *string)
const char *(* lookup)(struct DICT *, const char *)
NORETURN msg_fatal(const char *fmt,...)
#define DICT_ERR_VAL_RETURN(dict, err, val)
char * cfg_get_str(const CFG_PARSER *parser, const char *name, const char *defval, int min, int max)
#define DICT_FLAG_PATTERN
DICT * dict_sqlite_open(const char *, int, int)
CFG_PARSER * cfg_parser_free(CFG_PARSER *parser)
CFG_PARSER * cfg_parser_alloc(const char *pname)
VSTRING * vstring_free(VSTRING *vp)
int db_common_parse(DICT *dict, void **ctxPtr, const char *format, int query)
DICT * dict_alloc(const char *, const char *, ssize_t)
#define cfg_get_owner(cfg)
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
char * vstring_export(VSTRING *vp)
DICT * dict_surrogate(const char *dict_type, const char *dict_name, int open_flags, int dict_flags, const char *fmt,...)
#define DICT_FLAG_UTF8_ACTIVE
void msg_info(const char *fmt,...)