"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/lib-dict-backend/dict-sql.c" between
dovecot-2.3.16.tar.gz and dovecot-2.3.17.tar.gz

About: Dovecot is an IMAP and POP3 server, written with security primarily in mind.

dict-sql.c  (dovecot-2.3.16):dict-sql.c  (dovecot-2.3.17)
skipping to change at line 42 skipping to change at line 42
const void *value_binary; const void *value_binary;
size_t value_binary_size; size_t value_binary_size;
}; };
ARRAY_DEFINE_TYPE(sql_dict_param, struct sql_dict_param); ARRAY_DEFINE_TYPE(sql_dict_param, struct sql_dict_param);
struct sql_dict_iterate_context { struct sql_dict_iterate_context {
struct dict_iterate_context ctx; struct dict_iterate_context ctx;
pool_t pool; pool_t pool;
enum dict_iterate_flags flags; enum dict_iterate_flags flags;
const char **paths; const char *path;
struct sql_result *result; struct sql_result *result;
string_t *key; string_t *key;
const struct dict_sql_map *map; const struct dict_sql_map *map;
size_t key_prefix_len, pattern_prefix_len; size_t key_prefix_len, pattern_prefix_len;
unsigned int path_idx, sql_fields_start_idx, next_map_idx; unsigned int sql_fields_start_idx, next_map_idx;
bool destroyed; bool destroyed;
bool synchronous_result; bool synchronous_result;
bool iter_query_sent; bool iter_query_sent;
bool allow_null_map; /* allow next map to be NULL */ bool allow_null_map; /* allow next map to be NULL */
const char *error; const char *error;
}; };
struct sql_dict_inc_row { struct sql_dict_inc_row {
struct sql_dict_inc_row *prev; struct sql_dict_inc_row *prev;
unsigned int rows; unsigned int rows;
skipping to change at line 105 skipping to change at line 105
struct dict **dict_r, const char **error_r) struct dict **dict_r, const char **error_r)
{ {
struct sql_settings sql_set; struct sql_settings sql_set;
struct sql_dict *dict; struct sql_dict *dict;
pool_t pool; pool_t pool;
pool = pool_alloconly_create("sql dict", 2048); pool = pool_alloconly_create("sql dict", 2048);
dict = p_new(pool, struct sql_dict, 1); dict = p_new(pool, struct sql_dict, 1);
dict->pool = pool; dict->pool = pool;
dict->dict = *driver; dict->dict = *driver;
dict->username = p_strdup(pool, set->username);
dict->set = dict_sql_settings_read(uri, error_r); dict->set = dict_sql_settings_read(uri, error_r);
if (dict->set == NULL) { if (dict->set == NULL) {
pool_unref(&pool); pool_unref(&pool);
return -1; return -1;
} }
i_zero(&sql_set); i_zero(&sql_set);
sql_set.driver = driver->name; sql_set.driver = driver->name;
sql_set.connect_string = dict->set->connect; sql_set.connect_string = dict->set->connect;
sql_set.event_parent = set->event_parent; sql_set.event_parent = set->event_parent;
skipping to change at line 133 skipping to change at line 132
} }
static void sql_dict_deinit(struct dict *_dict) static void sql_dict_deinit(struct dict *_dict)
{ {
struct sql_dict *dict = (struct sql_dict *)_dict; struct sql_dict *dict = (struct sql_dict *)_dict;
sql_unref(&dict->db); sql_unref(&dict->db);
pool_unref(&dict->pool); pool_unref(&dict->pool);
} }
static void sql_dict_wait(struct dict *dict ATTR_UNUSED) static void sql_dict_wait(struct dict *_dict)
{ {
/* FIXME: lib-sql doesn't support this yet */ struct sql_dict *dict = (struct sql_dict *)_dict;
sql_wait(dict->db);
} }
/* Try to match path to map->pattern. For example pattern="shared/x/$/$/y" /* Try to match path to map->pattern. For example pattern="shared/x/$/$/y"
and path="shared/x/1/2/y", this is match and pattern_values=[1, 2]. */ and path="shared/x/1/2/y", this is match and pattern_values=[1, 2]. */
static bool static bool
dict_sql_map_match(const struct dict_sql_map *map, const char *path, dict_sql_map_match(const struct dict_sql_map *map, const char *path,
ARRAY_TYPE(const_string) *pattern_values, size_t *pat_len_r, ARRAY_TYPE(const_string) *pattern_values, size_t *pat_len_r,
size_t *path_len_r, bool partial_ok, bool recurse) size_t *path_len_r, bool partial_ok, bool recurse)
{ {
const char *path_start = path; const char *path_start = path;
skipping to change at line 348 skipping to change at line 348
const struct dict_sql_field *field, const struct dict_sql_field *field,
const char *value, const char *value_suffix, const char *value, const char *value_suffix,
ARRAY_TYPE(sql_dict_param) *params, ARRAY_TYPE(sql_dict_param) *params,
const char **error_r) const char **error_r)
{ {
return sql_dict_value_get(map, field->value_type, field->name, return sql_dict_value_get(map, field->value_type, field->name,
value, value_suffix, params, error_r); value, value_suffix, params, error_r);
} }
static int static int
sql_dict_where_build(struct sql_dict *dict, const struct dict_sql_map *map, sql_dict_where_build(const char *username, const struct dict_sql_map *map,
const ARRAY_TYPE(const_string) *values_arr, const ARRAY_TYPE(const_string) *values_arr,
bool add_username, enum sql_recurse_type recurse_type, bool add_username, enum sql_recurse_type recurse_type,
string_t *query, ARRAY_TYPE(sql_dict_param) *params, string_t *query, ARRAY_TYPE(sql_dict_param) *params,
const char **error_r) const char **error_r)
{ {
const struct dict_sql_field *pattern_fields; const struct dict_sql_field *pattern_fields;
const char *const *pattern_values; const char *const *pattern_values;
unsigned int i, count, count2, exact_count; unsigned int i, count, count2, exact_count;
pattern_fields = array_get(&map->pattern_fields, &count); pattern_fields = array_get(&map->pattern_fields, &count);
skipping to change at line 372 skipping to change at line 372
i_assert(count2 <= count); i_assert(count2 <= count);
if (count2 == 0 && !add_username) { if (count2 == 0 && !add_username) {
/* we want everything */ /* we want everything */
return 0; return 0;
} }
str_append(query, " WHERE"); str_append(query, " WHERE");
exact_count = count == count2 && recurse_type != SQL_DICT_RECURSE_NONE ? exact_count = count == count2 && recurse_type != SQL_DICT_RECURSE_NONE ?
count2-1 : count2; count2-1 : count2;
if (exact_count != array_count(values_arr)) {
*error_r = t_strdup_printf("Key continues past the matched patter
n %s", map->pattern);
return -1;
}
for (i = 0; i < exact_count; i++) { for (i = 0; i < exact_count; i++) {
if (i > 0) if (i > 0)
str_append(query, " AND"); str_append(query, " AND");
str_printfa(query, " %s = ?", pattern_fields[i].name); str_printfa(query, " %s = ?", pattern_fields[i].name);
if (sql_dict_field_get_value(map, &pattern_fields[i], if (sql_dict_field_get_value(map, &pattern_fields[i],
pattern_values[i], "", pattern_values[i], "",
params, error_r) < 0) params, error_r) < 0)
return -1; return -1;
} }
switch (recurse_type) { switch (recurse_type) {
skipping to change at line 424 skipping to change at line 429
return -1; return -1;
} }
break; break;
} }
if (add_username) { if (add_username) {
struct sql_dict_param *param = array_append_space(params); struct sql_dict_param *param = array_append_space(params);
if (count2 > 0) if (count2 > 0)
str_append(query, " AND"); str_append(query, " AND");
str_printfa(query, " %s = ?", map->username_field); str_printfa(query, " %s = ?", map->username_field);
param->value_type = DICT_SQL_TYPE_STRING; param->value_type = DICT_SQL_TYPE_STRING;
param->value_str = dict->username; param->value_str = t_strdup(username);
} }
return 0; return 0;
} }
static int static int
sql_lookup_get_query(struct sql_dict *dict, const char *key, sql_lookup_get_query(struct sql_dict *dict,
const struct dict_op_settings *set,
const char *key,
const struct dict_sql_map **map_r, const struct dict_sql_map **map_r,
struct sql_statement **stmt_r, struct sql_statement **stmt_r,
const char **error_r) const char **error_r)
{ {
const struct dict_sql_map *map; const struct dict_sql_map *map;
ARRAY_TYPE(const_string) pattern_values; ARRAY_TYPE(const_string) pattern_values;
const char *error; const char *error;
map = *map_r = sql_dict_find_map(dict, key, &pattern_values); map = *map_r = sql_dict_find_map(dict, key, &pattern_values);
if (map == NULL) { if (map == NULL) {
*error_r = t_strdup_printf( *error_r = t_strdup_printf(
"sql dict lookup: Invalid/unmapped key: %s", key); "sql dict lookup: Invalid/unmapped key: %s", key);
return -1; return -1;
} }
string_t *query = t_str_new(256); string_t *query = t_str_new(256);
ARRAY_TYPE(sql_dict_param) params; ARRAY_TYPE(sql_dict_param) params;
t_array_init(&params, 4); t_array_init(&params, 4);
str_printfa(query, "SELECT %s FROM %s", str_printfa(query, "SELECT %s FROM %s",
map->value_field, map->table); map->value_field, map->table);
if (sql_dict_where_build(dict, map, &pattern_values, if (sql_dict_where_build(set->username, map, &pattern_values,
key[0] == DICT_PATH_PRIVATE[0], key[0] == DICT_PATH_PRIVATE[0],
SQL_DICT_RECURSE_NONE, query, SQL_DICT_RECURSE_NONE, query,
&params, &error) < 0) { &params, &error) < 0) {
*error_r = t_strdup_printf( *error_r = t_strdup_printf(
"sql dict lookup: Failed to lookup key %s: %s", key, erro r); "sql dict lookup: Failed to lookup key %s: %s", key, erro r);
return -1; return -1;
} }
*stmt_r = sql_dict_statement_init(dict, str_c(query), &params); *stmt_r = sql_dict_statement_init(dict, str_c(query), &params);
return 0; return 0;
} }
skipping to change at line 522 skipping to change at line 529
struct sql_result *result, unsigned int result_idx , struct sql_result *result, unsigned int result_idx ,
unsigned int sql_field_idx) unsigned int sql_field_idx)
{ {
const struct dict_sql_field *sql_field; const struct dict_sql_field *sql_field;
sql_field = array_idx(&map->pattern_fields, sql_field_idx); sql_field = array_idx(&map->pattern_fields, sql_field_idx);
return sql_dict_result_unescape(sql_field->value_type, pool, return sql_dict_result_unescape(sql_field->value_type, pool,
result, result_idx); result, result_idx);
} }
static int sql_dict_lookup(struct dict *_dict, pool_t pool, const char *key, static int sql_dict_lookup(struct dict *_dict, const struct dict_op_settings *se
t,
pool_t pool, const char *key,
const char **value_r, const char **error_r) const char **value_r, const char **error_r)
{ {
struct sql_dict *dict = (struct sql_dict *)_dict; struct sql_dict *dict = (struct sql_dict *)_dict;
const struct dict_sql_map *map; const struct dict_sql_map *map;
struct sql_statement *stmt; struct sql_statement *stmt;
struct sql_result *result = NULL; struct sql_result *result = NULL;
int ret; int ret;
*value_r = NULL; *value_r = NULL;
if (sql_lookup_get_query(dict, key, &map, &stmt, error_r) < 0) if (sql_lookup_get_query(dict, set, key, &map, &stmt, error_r) < 0)
return -1; return -1;
result = sql_statement_query_s(&stmt); result = sql_statement_query_s(&stmt);
ret = sql_result_next_row(result); ret = sql_result_next_row(result);
if (ret < 0) { if (ret < 0) {
*error_r = t_strdup_printf("dict sql lookup failed: %s", *error_r = t_strdup_printf("dict sql lookup failed: %s",
sql_result_get_error(result)); sql_result_get_error(result));
} else if (ret > 0) { } else if (ret > 0) {
*value_r = sql_dict_result_unescape_value(map, pool, result); *value_r = sql_dict_result_unescape_value(map, pool, result);
} }
skipping to change at line 582 skipping to change at line 590
wanted. */ wanted. */
result.ret = 0; result.ret = 0;
} }
} }
ctx->callback(&result, ctx->context); ctx->callback(&result, ctx->context);
i_free(ctx); i_free(ctx);
} }
static void static void
sql_dict_lookup_async(struct dict *_dict, const char *key, sql_dict_lookup_async(struct dict *_dict,
const struct dict_op_settings *set,
const char *key,
dict_lookup_callback_t *callback, void *context) dict_lookup_callback_t *callback, void *context)
{ {
struct sql_dict *dict = (struct sql_dict *)_dict; struct sql_dict *dict = (struct sql_dict *)_dict;
const struct dict_sql_map *map; const struct dict_sql_map *map;
struct sql_dict_lookup_context *ctx; struct sql_dict_lookup_context *ctx;
struct sql_statement *stmt; struct sql_statement *stmt;
const char *error; const char *error;
if (sql_lookup_get_query(dict, key, &map, &stmt, &error) < 0) { if (sql_lookup_get_query(dict, set, key, &map, &stmt, &error) < 0) {
struct dict_lookup_result result; struct dict_lookup_result result;
i_zero(&result); i_zero(&result);
result.ret = -1; result.ret = -1;
result.error = error; result.error = error;
callback(&result, context); callback(&result, context);
} else { } else {
ctx = i_new(struct sql_dict_lookup_context, 1); ctx = i_new(struct sql_dict_lookup_context, 1);
ctx->callback = callback; ctx->callback = callback;
ctx->context = context; ctx->context = context;
skipping to change at line 620 skipping to change at line 630
{ {
struct sql_dict *dict = (struct sql_dict *)ctx->ctx.dict; struct sql_dict *dict = (struct sql_dict *)ctx->ctx.dict;
const struct dict_sql_map *maps; const struct dict_sql_map *maps;
unsigned int i, count; unsigned int i, count;
size_t pat_len, path_len; size_t pat_len, path_len;
bool recurse = (ctx->flags & DICT_ITERATE_FLAG_RECURSE) != 0; bool recurse = (ctx->flags & DICT_ITERATE_FLAG_RECURSE) != 0;
t_array_init(pattern_values, dict->set->max_pattern_fields_count); t_array_init(pattern_values, dict->set->max_pattern_fields_count);
maps = array_get(&dict->set->maps, &count); maps = array_get(&dict->set->maps, &count);
for (i = ctx->next_map_idx; i < count; i++) { for (i = ctx->next_map_idx; i < count; i++) {
if (dict_sql_map_match(&maps[i], ctx->paths[ctx->path_idx], if (dict_sql_map_match(&maps[i], ctx->path,
pattern_values, &pat_len, &path_len, pattern_values, &pat_len, &path_len,
TRUE, recurse) && TRUE, recurse) &&
(recurse || (recurse ||
array_count(pattern_values)+1 >= array_count(&maps[i].patter n_fields))) { array_count(pattern_values)+1 >= array_count(&maps[i].patter n_fields))) {
ctx->key_prefix_len = path_len; ctx->key_prefix_len = path_len;
ctx->pattern_prefix_len = pat_len; ctx->pattern_prefix_len = pat_len;
ctx->next_map_idx = i + 1; ctx->next_map_idx = i + 1;
str_truncate(ctx->key, 0); str_truncate(ctx->key, 0);
str_append(ctx->key, ctx->paths[ctx->path_idx]); str_append(ctx->key, ctx->path);
return &maps[i]; return &maps[i];
} }
} }
/* try the next path, if there is any */
ctx->path_idx++;
if (ctx->paths[ctx->path_idx] != NULL)
return sql_dict_iterate_find_next_map(ctx, pattern_values);
return NULL; return NULL;
} }
static int static int
sql_dict_iterate_build_next_query(struct sql_dict_iterate_context *ctx, sql_dict_iterate_build_next_query(struct sql_dict_iterate_context *ctx,
struct sql_statement **stmt_r, struct sql_statement **stmt_r,
const char **error_r) const char **error_r)
{ {
struct sql_dict *dict = (struct sql_dict *)ctx->ctx.dict; struct sql_dict *dict = (struct sql_dict *)ctx->ctx.dict;
const struct dict_op_settings_private *set = &ctx->ctx.set;
const struct dict_sql_map *map; const struct dict_sql_map *map;
ARRAY_TYPE(const_string) pattern_values; ARRAY_TYPE(const_string) pattern_values;
const struct dict_sql_field *pattern_fields; const struct dict_sql_field *pattern_fields;
enum sql_recurse_type recurse_type; enum sql_recurse_type recurse_type;
unsigned int i, count; unsigned int i, count;
map = sql_dict_iterate_find_next_map(ctx, &pattern_values); map = sql_dict_iterate_find_next_map(ctx, &pattern_values);
/* NULL map is allowed if we have already done some lookups */ /* NULL map is allowed if we have already done some lookups */
if (map == NULL) { if (map == NULL) {
if (!ctx->allow_null_map) { if (!ctx->allow_null_map) {
skipping to change at line 699 skipping to change at line 705
if ((ctx->flags & DICT_ITERATE_FLAG_RECURSE) != 0) if ((ctx->flags & DICT_ITERATE_FLAG_RECURSE) != 0)
recurse_type = SQL_DICT_RECURSE_FULL; recurse_type = SQL_DICT_RECURSE_FULL;
else if ((ctx->flags & DICT_ITERATE_FLAG_EXACT_KEY) != 0) else if ((ctx->flags & DICT_ITERATE_FLAG_EXACT_KEY) != 0)
recurse_type = SQL_DICT_RECURSE_NONE; recurse_type = SQL_DICT_RECURSE_NONE;
else else
recurse_type = SQL_DICT_RECURSE_ONE; recurse_type = SQL_DICT_RECURSE_ONE;
ARRAY_TYPE(sql_dict_param) params; ARRAY_TYPE(sql_dict_param) params;
t_array_init(&params, 4); t_array_init(&params, 4);
bool add_username = (ctx->paths[ctx->path_idx][0] == DICT_PATH_PRIVATE[0] bool add_username = (ctx->path[0] == DICT_PATH_PRIVATE[0]);
); if (sql_dict_where_build(set->username, map, &pattern_values, add_usernam
if (sql_dict_where_build(dict, map, &pattern_values, add_username, e,
recurse_type, query, &params, error_r) < 0) recurse_type, query, &params, error_r) < 0)
return -1; return -1;
if ((ctx->flags & DICT_ITERATE_FLAG_SORT_BY_KEY) != 0) { if ((ctx->flags & DICT_ITERATE_FLAG_SORT_BY_KEY) != 0) {
str_append(query, " ORDER BY "); str_append(query, " ORDER BY ");
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
str_printfa(query, "%s", pattern_fields[i].name); str_printfa(query, "%s", pattern_fields[i].name);
if (i < count-1) if (i < count-1)
str_append_c(query, ','); str_append_c(query, ',');
} }
skipping to change at line 743 skipping to change at line 749
} }
pool_t pool_copy = ctx->pool; pool_t pool_copy = ctx->pool;
pool_unref(&pool_copy); pool_unref(&pool_copy);
} }
static int sql_dict_iterate_next_query(struct sql_dict_iterate_context *ctx) static int sql_dict_iterate_next_query(struct sql_dict_iterate_context *ctx)
{ {
struct sql_statement *stmt; struct sql_statement *stmt;
const char *error; const char *error;
unsigned int path_idx = ctx->path_idx;
int ret; int ret;
ret = sql_dict_iterate_build_next_query(ctx, &stmt, &error); ret = sql_dict_iterate_build_next_query(ctx, &stmt, &error);
if (ret <= 0) { if (ret <= 0) {
/* this is expected error */ /* this is expected error */
if (ret == 0) if (ret == 0)
return ret; return ret;
/* failed */ /* failed */
ctx->error = p_strdup_printf(ctx->pool, ctx->error = p_strdup_printf(ctx->pool,
"sql dict iterate failed for %s: %s", "sql dict iterate failed for %s: %s",
ctx->paths[path_idx], error); ctx->path, error);
return -1; return -1;
} }
if ((ctx->flags & DICT_ITERATE_FLAG_ASYNC) == 0) { if ((ctx->flags & DICT_ITERATE_FLAG_ASYNC) == 0) {
ctx->result = sql_statement_query_s(&stmt); ctx->result = sql_statement_query_s(&stmt);
} else { } else {
i_assert(ctx->result == NULL); i_assert(ctx->result == NULL);
ctx->synchronous_result = TRUE; ctx->synchronous_result = TRUE;
pool_ref(ctx->pool); pool_ref(ctx->pool);
sql_statement_query(&stmt, sql_dict_iterate_callback, ctx); sql_statement_query(&stmt, sql_dict_iterate_callback, ctx);
ctx->synchronous_result = FALSE; ctx->synchronous_result = FALSE;
} }
return ret; return ret;
} }
static struct dict_iterate_context * static struct dict_iterate_context *
sql_dict_iterate_init(struct dict *_dict, const char *const *paths, sql_dict_iterate_init(struct dict *_dict,
enum dict_iterate_flags flags) const struct dict_op_settings *set ATTR_UNUSED,
const char *path, enum dict_iterate_flags flags)
{ {
struct sql_dict_iterate_context *ctx; struct sql_dict_iterate_context *ctx;
unsigned int i, path_count;
pool_t pool; pool_t pool;
pool = pool_alloconly_create("sql dict iterate", 512); pool = pool_alloconly_create("sql dict iterate", 512);
ctx = p_new(pool, struct sql_dict_iterate_context, 1); ctx = p_new(pool, struct sql_dict_iterate_context, 1);
ctx->ctx.dict = _dict; ctx->ctx.dict = _dict;
ctx->pool = pool; ctx->pool = pool;
ctx->flags = flags; ctx->flags = flags;
for (path_count = 0; paths[path_count] != NULL; path_count++) ; ctx->path = p_strdup(pool, path);
ctx->paths = p_new(pool, const char *, path_count + 1);
for (i = 0; i < path_count; i++)
ctx->paths[i] = p_strdup(pool, paths[i]);
ctx->key = str_new(pool, 256); ctx->key = str_new(pool, 256);
return &ctx->ctx; return &ctx->ctx;
} }
static bool sql_dict_iterate(struct dict_iterate_context *_ctx, static bool sql_dict_iterate(struct dict_iterate_context *_ctx,
const char **key_r, const char *const **values_r) const char **key_r, const char *const **values_r)
{ {
struct sql_dict_iterate_context *ctx = struct sql_dict_iterate_context *ctx =
(struct sql_dict_iterate_context *)_ctx; (struct sql_dict_iterate_context *)_ctx;
skipping to change at line 1098 skipping to change at line 1100
if (sql_dict_value_get(fields[i].map, if (sql_dict_value_get(fields[i].map,
value_type, "value", fields[i].value, value_type, "value", fields[i].value,
"", &params, error_r) < 0) "", &params, error_r) < 0)
return -1; return -1;
} }
if (build->add_username) { if (build->add_username) {
struct sql_dict_param *param = array_append_space(&params); struct sql_dict_param *param = array_append_space(&params);
str_printfa(prefix, ",%s", fields[0].map->username_field); str_printfa(prefix, ",%s", fields[0].map->username_field);
str_append(suffix, ",?"); str_append(suffix, ",?");
param->value_type = DICT_SQL_TYPE_STRING; param->value_type = DICT_SQL_TYPE_STRING;
param->value_str = dict->username; param->value_str = ctx->ctx.set.username;
} }
/* add the variable fields that were parsed from the path */ /* add the variable fields that were parsed from the path */
pattern_fields = array_get(&fields[0].map->pattern_fields, &count); pattern_fields = array_get(&fields[0].map->pattern_fields, &count);
pattern_values = array_get(build->pattern_values, &count2); pattern_values = array_get(build->pattern_values, &count2);
i_assert(count == count2); i_assert(count == count2);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
str_printfa(prefix, ",%s", pattern_fields[i].name); str_printfa(prefix, ",%s", pattern_fields[i].name);
str_append(suffix, ",?"); str_append(suffix, ",?");
if (sql_dict_field_get_value(fields[0].map, &pattern_fields[i], if (sql_dict_field_get_value(fields[0].map, &pattern_fields[i],
skipping to change at line 1163 skipping to change at line 1165
value_type, "value", fields[i].value, value_type, "value", fields[i].value,
"", &params, error_r) < 0) "", &params, error_r) < 0)
return -1; return -1;
} }
*stmt_r = sql_dict_transaction_stmt_init(ctx, str_c(prefix), &params); *stmt_r = sql_dict_transaction_stmt_init(ctx, str_c(prefix), &params);
return 0; return 0;
} }
static int static int
sql_dict_update_query(const struct dict_sql_build_query *build, sql_dict_update_query(const struct dict_sql_build_query *build,
const struct dict_op_settings_private *set,
const char **query_r, ARRAY_TYPE(sql_dict_param) *params, const char **query_r, ARRAY_TYPE(sql_dict_param) *params,
const char **error_r) const char **error_r)
{ {
struct sql_dict *dict = build->dict;
const struct dict_sql_build_query_field *fields; const struct dict_sql_build_query_field *fields;
unsigned int i, field_count; unsigned int i, field_count;
string_t *query; string_t *query;
fields = array_get(&build->fields, &field_count); fields = array_get(&build->fields, &field_count);
i_assert(field_count > 0); i_assert(field_count > 0);
query = t_str_new(64); query = t_str_new(64);
str_printfa(query, "UPDATE %s SET ", fields[0].map->table); str_printfa(query, "UPDATE %s SET ", fields[0].map->table);
for (i = 0; i < field_count; i++) { for (i = 0; i < field_count; i++) {
const char *first_value_field = const char *first_value_field =
t_strcut(fields[i].map->value_field, ','); t_strcut(fields[i].map->value_field, ',');
if (i > 0) if (i > 0)
str_append_c(query, ','); str_append_c(query, ',');
str_printfa(query, "%s=%s+?", first_value_field, str_printfa(query, "%s=%s+?", first_value_field,
first_value_field); first_value_field);
} }
if (sql_dict_where_build(dict, fields[0].map, build->pattern_values, if (sql_dict_where_build(set->username, fields[0].map, build->pattern_val ues,
build->add_username, SQL_DICT_RECURSE_NONE, build->add_username, SQL_DICT_RECURSE_NONE,
query, params, error_r) < 0) query, params, error_r) < 0)
return -1; return -1;
*query_r = str_c(query); *query_r = str_c(query);
return 0; return 0;
} }
static void sql_dict_prev_set_free(struct sql_dict_transaction_context *ctx) static void sql_dict_prev_set_free(struct sql_dict_transaction_context *ctx)
{ {
struct sql_dict_prev *prev_set; struct sql_dict_prev *prev_set;
skipping to change at line 1265 skipping to change at line 1267
} }
sql_dict_prev_set_free(ctx); sql_dict_prev_set_free(ctx);
} }
static void sql_dict_unset(struct dict_transaction_context *_ctx, static void sql_dict_unset(struct dict_transaction_context *_ctx,
const char *key) const char *key)
{ {
struct sql_dict_transaction_context *ctx = struct sql_dict_transaction_context *ctx =
(struct sql_dict_transaction_context *)_ctx; (struct sql_dict_transaction_context *)_ctx;
struct sql_dict *dict = (struct sql_dict *)_ctx->dict; struct sql_dict *dict = (struct sql_dict *)_ctx->dict;
const struct dict_op_settings_private *set = &_ctx->set;
const struct dict_sql_map *map; const struct dict_sql_map *map;
ARRAY_TYPE(const_string) pattern_values; ARRAY_TYPE(const_string) pattern_values;
string_t *query = t_str_new(256); string_t *query = t_str_new(256);
ARRAY_TYPE(sql_dict_param) params; ARRAY_TYPE(sql_dict_param) params;
const char *error; const char *error;
if (ctx->error != NULL) if (ctx->error != NULL)
return; return;
/* In theory we could unset one of the previous set/incs in this /* In theory we could unset one of the previous set/incs in this
skipping to change at line 1289 skipping to change at line 1292
sql_dict_prev_set_flush(ctx); sql_dict_prev_set_flush(ctx);
map = sql_dict_find_map(dict, key, &pattern_values); map = sql_dict_find_map(dict, key, &pattern_values);
if (map == NULL) { if (map == NULL) {
ctx->error = i_strdup_printf("dict-sql: Invalid/unmapped key: %s" , key); ctx->error = i_strdup_printf("dict-sql: Invalid/unmapped key: %s" , key);
return; return;
} }
str_printfa(query, "DELETE FROM %s", map->table); str_printfa(query, "DELETE FROM %s", map->table);
t_array_init(&params, 4); t_array_init(&params, 4);
if (sql_dict_where_build(dict, map, &pattern_values, if (sql_dict_where_build(set->username, map, &pattern_values,
key[0] == DICT_PATH_PRIVATE[0], key[0] == DICT_PATH_PRIVATE[0],
SQL_DICT_RECURSE_NONE, query, SQL_DICT_RECURSE_NONE, query,
&params, &error) < 0) { &params, &error) < 0) {
ctx->error = i_strdup_printf( ctx->error = i_strdup_printf(
"dict-sql: Failed to delete %s: %s", key, error); "dict-sql: Failed to delete %s: %s", key, error);
} else { } else {
struct sql_statement *stmt = struct sql_statement *stmt =
sql_dict_transaction_stmt_init(ctx, str_c(query), &params ); sql_dict_transaction_stmt_init(ctx, str_c(query), &params );
sql_update_stmt(ctx->sql_ctx, &stmt); sql_update_stmt(ctx->sql_ctx, &stmt);
} }
skipping to change at line 1330 skipping to change at line 1333
struct sql_dict_prev *prev_inc; struct sql_dict_prev *prev_inc;
array_foreach_modifiable(&ctx->prev_inc, prev_inc) array_foreach_modifiable(&ctx->prev_inc, prev_inc)
i_free(prev_inc->key); i_free(prev_inc->key);
array_free(&ctx->prev_inc); array_free(&ctx->prev_inc);
} }
static void sql_dict_prev_inc_flush(struct sql_dict_transaction_context *ctx) static void sql_dict_prev_inc_flush(struct sql_dict_transaction_context *ctx)
{ {
struct sql_dict *dict = (struct sql_dict *)ctx->ctx.dict; struct sql_dict *dict = (struct sql_dict *)ctx->ctx.dict;
const struct dict_op_settings_private *set = &ctx->ctx.set;
const struct sql_dict_prev *prev_incs; const struct sql_dict_prev *prev_incs;
unsigned int count; unsigned int count;
ARRAY_TYPE(const_string) pattern_values; ARRAY_TYPE(const_string) pattern_values;
struct dict_sql_build_query build; struct dict_sql_build_query build;
struct dict_sql_build_query_field *field; struct dict_sql_build_query_field *field;
ARRAY_TYPE(sql_dict_param) params; ARRAY_TYPE(sql_dict_param) params;
struct sql_dict_param *param; struct sql_dict_param *param;
const char *query, *error; const char *query, *error;
i_assert(array_is_created(&ctx->prev_inc)); i_assert(array_is_created(&ctx->prev_inc));
skipping to change at line 1380 skipping to change at line 1384
(prev_incs[i].key[0] == DICT_PATH_PRIVATE[0])); (prev_incs[i].key[0] == DICT_PATH_PRIVATE[0]));
field = array_append_space(&build.fields); field = array_append_space(&build.fields);
field->map = prev_incs[i].map; field->map = prev_incs[i].map;
field->value = NULL; /* unused */ field->value = NULL; /* unused */
param = array_append_space(&params); param = array_append_space(&params);
param->value_type = DICT_SQL_TYPE_INT; param->value_type = DICT_SQL_TYPE_INT;
param->value_int64 = prev_incs[i].value.diff; param->value_int64 = prev_incs[i].value.diff;
} }
if (sql_dict_update_query(&build, &query, &params, &error) < 0) { if (sql_dict_update_query(&build, set, &query, &params, &error) < 0) {
ctx->error = i_strdup_printf( ctx->error = i_strdup_printf(
"dict-sql: Failed to increase %u fields (first %s): %s", "dict-sql: Failed to increase %u fields (first %s): %s",
count, prev_incs[0].key, error); count, prev_incs[0].key, error);
} else { } else {
struct sql_statement *stmt = struct sql_statement *stmt =
sql_dict_transaction_stmt_init(ctx, query, &params); sql_dict_transaction_stmt_init(ctx, query, &params);
sql_update_stmt_get_rows(ctx->sql_ctx, &stmt, sql_update_stmt_get_rows(ctx->sql_ctx, &stmt,
sql_dict_next_inc_row(ctx)); sql_dict_next_inc_row(ctx));
} }
sql_dict_prev_inc_free(ctx); sql_dict_prev_inc_free(ctx);
 End of changes. 32 change blocks. 
37 lines changed or deleted 43 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)