dovecot-1.2: pgsql: When doing negative increments, don't even t...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jan 19 04:47:55 EET 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/abb1a50a266d
changeset: 8654:abb1a50a266d
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Jan 18 21:47:47 2009 -0500
description:
pgsql: When doing negative increments, don't even try to use INSERT.

diffstat:

1 file changed, 55 insertions(+), 13 deletions(-)
src/lib-dict/dict-sql.c |   68 ++++++++++++++++++++++++++++++++++++++---------

diffs (143 lines):

diff -r 4dadcc2f6be2 -r abb1a50a266d src/lib-dict/dict-sql.c
--- 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
 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 @@ static int sql_dict_lookup(struct dict *
 
 		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 @@ static bool sql_dict_iterate_next_query(
 
 		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,23 +563,51 @@ static const char *sql_dict_set_query(co
 
 	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,
@@ -644,7 +672,7 @@ static void sql_dict_unset(struct dict_t
 		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 @@ static void sql_dict_atomic_inc_real(str
 		array_append(&build.fields, &field, 1);
 		build.extra_values = &values;
 		build.key1 = key[0];
-
-		query = sql_dict_set_query(&build);
+		build.inc = TRUE;
+
+		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 @@ static void sql_dict_atomic_inc(struct d
 		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 @@ static void sql_dict_atomic_inc(struct d
 		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);


More information about the dovecot-cvs mailing list