changeset 18653:fce3e3eef9f0

dict-sql: Fixed non-recursive iteration. If path has e.g. "a/$var/b/$var2" and we're iterating "a/", we shouldn't return anything under "a/*/b/".
author Timo Sirainen <tss@iki.fi>
date Tue, 12 May 2015 19:43:25 +0300
parents f0273ba240ae
children 04e169b3bfe6
files src/lib-dict/dict-sql.c
diffstat 1 files changed, 13 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-dict/dict-sql.c	Tue May 12 19:14:13 2015 +0300
+++ b/src/lib-dict/dict-sql.c	Tue May 12 19:43:25 2015 +0300
@@ -110,7 +110,7 @@
 static bool
 dict_sql_map_match(const struct dict_sql_map *map, const char *path,
 		   ARRAY_TYPE(const_string) *values, unsigned int *pat_len_r,
-		   unsigned int *path_len_r, bool partial_ok)
+		   unsigned int *path_len_r, bool partial_ok, bool recurse)
 {
 	const char *path_start = path;
 	const char *pat, *field, *p;
@@ -174,8 +174,14 @@
 	else if (!partial_ok)
 		return FALSE;
 	else {
-		/* partial matches must end with '/' */
-		return pat == map->pattern || pat[-1] == '/';
+		/* partial matches must end with '/'. */
+		if (pat != map->pattern && pat[-1] != '/')
+			return FALSE;
+		/* if we're not recursing, there should be only one $variable
+		   left. */
+		if (recurse)
+			return TRUE;
+		return pat[0] == '$' && strchr(pat, '/') == NULL;
 	}
 }
 
@@ -192,7 +198,7 @@
 		/* start matching from the previously successful match */
 		idx = (dict->prev_map_match_idx + i) % count;
 		if (dict_sql_map_match(&maps[idx], path, values,
-				       &len, &len, FALSE)) {
+				       &len, &len, FALSE, FALSE)) {
 			dict->prev_map_match_idx = idx;
 			return &maps[idx];
 		}
@@ -314,13 +320,14 @@
 	struct sql_dict *dict = (struct sql_dict *)ctx->ctx.dict;
 	const struct dict_sql_map *maps;
 	unsigned int i, count, pat_len, path_len;
+	bool recurse = (ctx->flags & DICT_ITERATE_FLAG_RECURSE) != 0;
 
 	t_array_init(values, dict->set->max_field_count);
 	maps = array_get(&dict->set->maps, &count);
 	for (i = ctx->next_map_idx; i < count; i++) {
 		if (dict_sql_map_match(&maps[i], ctx->paths[ctx->path_idx],
-				       values, &pat_len, &path_len, TRUE) &&
-		    ((ctx->flags & DICT_ITERATE_FLAG_RECURSE) != 0 ||
+				       values, &pat_len, &path_len, TRUE, recurse) &&
+		    (recurse ||
 		     array_count(values)+1 >= array_count(&maps[i].sql_fields))) {
 			ctx->key_prefix_len = path_len;
 			ctx->pattern_prefix_len = pat_len;