Mercurial > dovecot > original-hg > dovecot-1.2
changeset 8654:abb1a50a266d HEAD
pgsql: When doing negative increments, don't even try to use INSERT.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 18 Jan 2009 21:47:47 -0500 |
parents | 4dadcc2f6be2 |
children | 46f95c498708 |
files | src/lib-dict/dict-sql.c |
diffstat | 1 files changed, 54 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-dict/dict-sql.c Sun Jan 18 21:02:15 2009 -0500 +++ b/src/lib-dict/dict-sql.c Sun Jan 18 21:47:47 2009 -0500 @@ -190,12 +190,12 @@ static void sql_dict_where_build(struct sql_dict *dict, const struct dict_sql_map *map, const ARRAY_TYPE(const_string) *values_arr, - const char *key, enum sql_recurse_type recurse_type, + char key1, enum sql_recurse_type recurse_type, string_t *query) { const char *const *sql_fields, *const *values; unsigned int i, count, count2, exact_count; - bool priv = *key == DICT_PATH_PRIVATE[0]; + bool priv = key1 == DICT_PATH_PRIVATE[0]; sql_fields = array_get(&map->sql_fields, &count); values = array_get(values_arr, &count2); @@ -273,7 +273,7 @@ str_printfa(query, "SELECT %s FROM %s", map->value_field, map->table); - sql_dict_where_build(dict, map, &values, key, + sql_dict_where_build(dict, map, &values, key[0], SQL_DICT_RECURSE_NONE, query); result = sql_query_s(dict->db, str_c(query)); } T_END; @@ -350,7 +350,7 @@ recurse_type = (ctx->flags & DICT_ITERATE_FLAG_RECURSE) == 0 ? SQL_DICT_RECURSE_ONE : SQL_DICT_RECURSE_FULL; - sql_dict_where_build(dict, map, &values, ctx->path, + sql_dict_where_build(dict, map, &values, ctx->path[0], recurse_type, query); if ((ctx->flags & DICT_ITERATE_FLAG_SORT_BY_KEY) != 0) { @@ -563,25 +563,53 @@ str_append(prefix, " ON DUPLICATE KEY UPDATE "); for (i = 0; i < field_count; i++) { - if (i > 0) { + if (i > 0) str_append_c(prefix, ','); - str_append_c(suffix, ','); - } str_append(prefix, fields[i].map->value_field); str_append_c(prefix, '='); if (build->inc) { str_printfa(prefix, "%s+%s", fields[i].map->value_field, fields[i].value); - str_append(suffix, fields[i].value); } else { - str_printfa(suffix, "'%s'", + str_printfa(prefix, "'%s'", sql_escape_string(dict->db, fields[i].value)); } } return str_c(prefix); } +static const char * +sql_dict_update_query(const struct dict_sql_build_query *build) +{ + struct sql_dict *dict = build->dict; + const struct dict_sql_build_query_field *fields; + unsigned int i, field_count; + string_t *query; + + i_assert(build->inc); + + fields = array_get(&build->fields, &field_count); + i_assert(field_count > 0); + + query = t_str_new(64); + str_printfa(query, "UPDATE %s SET ", fields[0].map->table); + for (i = 0; i < field_count; i++) { + if (i > 0) + str_append_c(query, ','); + str_printfa(query, "%s=%s", fields[i].map->value_field, + fields[i].map->value_field); + if (fields[i].value[0] != '-') + str_append_c(query, '+'); + else + str_append(query, fields[i].value); + } + + sql_dict_where_build(dict, fields[0].map, build->extra_values, + build->key1, SQL_DICT_RECURSE_NONE, query); + return str_c(query); +} + static void sql_dict_set(struct dict_transaction_context *_ctx, const char *key, const char *value) { @@ -644,7 +672,7 @@ string_t *query = t_str_new(256); str_printfa(query, "DELETE FROM %s", map->table); - sql_dict_where_build(dict, map, &values, key, + sql_dict_where_build(dict, map, &values, key[0], SQL_DICT_RECURSE_NONE, query); sql_update(ctx->sql_ctx, str_c(query)); } T_END; @@ -674,8 +702,15 @@ array_append(&build.fields, &field, 1); build.extra_values = &values; build.key1 = key[0]; + build.inc = TRUE; - query = sql_dict_set_query(&build); + if (diff >= 0) + query = sql_dict_set_query(&build); + else { + /* negative changes can't never be initial values, + use UPDATE directly. */ + query = sql_dict_update_query(&build); + } sql_update(ctx->sql_ctx, query); } T_END; } @@ -761,6 +796,7 @@ t_array_init(&build.fields, 1); build.extra_values = &values; build.key1 = key[0]; + build.inc = TRUE; field = array_append_space(&build.fields); field->map = ctx->prev_inc_map; @@ -769,7 +805,13 @@ field->map = map; field->value = t_strdup_printf("%lld", diff); - query = sql_dict_set_query(&build); + if (diff >= 0) + query = sql_dict_set_query(&build); + else { + /* negative changes can't never be initial values, + use UPDATE directly. */ + query = sql_dict_update_query(&build); + } sql_update(ctx->sql_ctx, query); i_free_and_null(ctx->prev_inc_key);