1 /*
2  ** Zabbix
3  ** Copyright (C) 2001-2021 Zabbix SIA
4  **
5  ** This program is free software; you can redistribute it and/or modify
6  ** it under the terms of the GNU General Public License as published by
7  ** the Free Software Foundation; either version 2 of the License, or
8  ** (at your option) any later version.
9  **
10  ** This program is distributed in the hope that it will be useful,
11  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  ** GNU General Public License for more details.
14  **
15  ** You should have received a copy of the GNU General Public License
16  ** along with this program; if not, write to the Free Software
17  ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  **/
19 
20 #include "zbxserver.h"
21 #include "log.h"
22 #include "valuecache.h"
23 #include "evalfunc.h"
24 #include "zbxeval.h"
25 #include "expression.h"
26 
27 #define ZBX_ITEM_QUERY_UNSET		0x0000
28 
29 #define ZBX_ITEM_QUERY_HOST_SELF	0x0001
30 #define ZBX_ITEM_QUERY_HOST_ONE		0x0002
31 #define ZBX_ITEM_QUERY_HOST_ANY		0x0004
32 
33 #define ZBX_ITEM_QUERY_KEY_ONE		0x0010
34 #define ZBX_ITEM_QUERY_KEY_SOME		0x0020
35 #define ZBX_ITEM_QUERY_KEY_ANY		0x0040
36 #define ZBX_ITEM_QUERY_FILTER		0x0100
37 
38 #define ZBX_ITEM_QUERY_ERROR		0x8000
39 
40 #define ZBX_ITEM_QUERY_MANY		(ZBX_ITEM_QUERY_HOST_ANY |\
41 					ZBX_ITEM_QUERY_KEY_SOME | ZBX_ITEM_QUERY_KEY_ANY |\
42 					ZBX_ITEM_QUERY_FILTER)
43 
44 #define ZBX_ITEM_QUERY_ITEM_ANY		(ZBX_ITEM_QUERY_HOST_ANY | ZBX_ITEM_QUERY_KEY_ANY)
45 
46 /* one item query data - index in hostkeys items */
47 typedef struct
48 {
49 	int	dcitem_hk_index;
50 }
51 zbx_expression_query_one_t;
52 
53 /* many item query data - matching itemids */
54 typedef struct
55 {
56 	zbx_vector_uint64_t	itemids;
57 }
58 zbx_expression_query_many_t;
59 
60 /* expression item query */
61 typedef struct
62 {
63 	/* query flags, see see ZBX_ITEM_QUERY_* defines */
64 	zbx_uint32_t		flags;
65 
66 	/* the item query /host/key?[filter] */
67 	zbx_item_query_t	ref;
68 
69 	/* the query error */
70 	char			*error;
71 
72 	/* the expression item query data, zbx_expression_query_one_t or zbx_expression_query_many_t */
73 	void			*data;
74 }
75 zbx_expression_query_t;
76 
77 /* group - hostids cache */
78 typedef struct
79 {
80 	char			*name;
81 	zbx_vector_uint64_t	hostids;
82 }
83 zbx_expression_group_t;
84 
85 /* item - tags cache */
86 typedef struct
87 {
88 	zbx_uint64_t		itemid;
89 	zbx_vector_ptr_t	tags;
90 }
91 zbx_expression_item_t;
92 
expression_query_free_one(zbx_expression_query_one_t * query)93 static void	expression_query_free_one(zbx_expression_query_one_t *query)
94 {
95 	zbx_free(query);
96 }
97 
expression_query_free_many(zbx_expression_query_many_t * query)98 static void	expression_query_free_many(zbx_expression_query_many_t *query)
99 {
100 	zbx_vector_uint64_destroy(&query->itemids);
101 	zbx_free(query);
102 }
103 
expression_query_free(zbx_expression_query_t * query)104 static void	expression_query_free(zbx_expression_query_t *query)
105 {
106 	zbx_eval_clear_query(&query->ref);
107 
108 	if (ZBX_ITEM_QUERY_ERROR == query->flags)
109 		zbx_free(query->error);
110 	else if (0 != (query->flags & ZBX_ITEM_QUERY_MANY))
111 		expression_query_free_many((zbx_expression_query_many_t*) query->data);
112 	else
113 		expression_query_free_one((zbx_expression_query_one_t*) query->data);
114 
115 	zbx_free(query);
116 }
117 
118 /******************************************************************************
119  *                                                                            *
120  * Function: test_key_param_wildcard_cb                                       *
121  *                                                                            *
122  * Purpose: check if key parameter is a wildcard '*'                          *
123  *                                                                            *
124  ******************************************************************************/
test_key_param_wildcard_cb(const char * data,int key_type,int level,int num,int quoted,void * cb_data,char ** param)125 static int	test_key_param_wildcard_cb(const char *data, int key_type, int level, int num, int quoted,
126 		void *cb_data, char **param)
127 {
128 	ZBX_UNUSED(key_type);
129 	ZBX_UNUSED(num);
130 	ZBX_UNUSED(quoted);
131 	ZBX_UNUSED(param);
132 
133 	if (0 == level)
134 		return SUCCEED;
135 
136 	if ('*' == data[0] && '\0' == data[1])
137 	{
138 		*(int *)cb_data = 1;
139 		return FAIL;
140 	}
141 
142 	return SUCCEED;
143 }
144 
145 /******************************************************************************
146  *                                                                            *
147  * Function: expression_create_query                                          *
148  *                                                                            *
149  * Purpose: create expression item query from item query /host/key?[filter]   *
150  *                                                                            *
151  * Parameters: itemquery - [IN] the item query                                *
152  *                                                                            *
153  * Return value: The created expression item query.                           *
154  *                                                                            *
155  ******************************************************************************/
expression_create_query(const char * itemquery)156 static zbx_expression_query_t*	expression_create_query(const char *itemquery)
157 {
158 	zbx_expression_query_t	*query;
159 
160 	query = (zbx_expression_query_t *)zbx_malloc(NULL, sizeof(zbx_expression_query_t));
161 	memset(query, 0, sizeof(zbx_expression_query_t));
162 
163 	query->flags = ZBX_ITEM_QUERY_UNSET;
164 
165 	if (0 != zbx_eval_parse_query(itemquery, strlen(itemquery), &query->ref))
166 	{
167 		if (NULL == query->ref.host)
168 			query->flags |= ZBX_ITEM_QUERY_HOST_SELF;
169 		else if ('*' == *query->ref.host)
170 			query->flags |= ZBX_ITEM_QUERY_HOST_ANY;
171 		else
172 			query->flags |= ZBX_ITEM_QUERY_HOST_ONE;
173 
174 		if (NULL != query->ref.filter)
175 			query->flags |= ZBX_ITEM_QUERY_FILTER;
176 
177 		if ('*' == *query->ref.key)
178 		{
179 			query->flags |= ZBX_ITEM_QUERY_KEY_ANY;
180 		}
181 		else if (NULL != strchr(query->ref.key, '*'))
182 		{
183 			int	wildcard = 0;
184 
185 			replace_key_params_dyn(&query->ref.key, ZBX_KEY_TYPE_ITEM, test_key_param_wildcard_cb,
186 					&wildcard, NULL, 0);
187 
188 			if (0 != wildcard)
189 				query->flags |= ZBX_ITEM_QUERY_KEY_SOME;
190 			else
191 				query->flags |= ZBX_ITEM_QUERY_KEY_ONE;
192 		}
193 		else
194 			query->flags |= ZBX_ITEM_QUERY_KEY_ONE;
195 	}
196 
197 	return query;
198 }
199 
200 /******************************************************************************
201  *                                                                            *
202  * Function: expression_group_free                                            *
203  *                                                                            *
204  ******************************************************************************/
expression_group_free(zbx_expression_group_t * group)205 static void	expression_group_free(zbx_expression_group_t *group)
206 {
207 	zbx_free(group->name);
208 	zbx_vector_uint64_destroy(&group->hostids);
209 	zbx_free(group);
210 }
211 
212 /******************************************************************************
213  *                                                                            *
214  * Function: expression_get_group                                             *
215  *                                                                            *
216  * Purpose: get group from cache by name                                      *
217  *                                                                            *
218  * Parameters: eval - [IN] the evaluation data                                *
219  *             name - [IN] the group name                                     *
220  *                                                                            *
221  * Return value: The cached group.                                            *
222  *                                                                            *
223  * Comments: Cache group if necessary.                                        *
224  *                                                                            *
225  ******************************************************************************/
expression_get_group(zbx_expression_eval_t * eval,const char * name)226 static zbx_expression_group_t	*expression_get_group(zbx_expression_eval_t *eval, const char *name)
227 {
228 	int			i;
229 	zbx_expression_group_t	*group;
230 
231 	for (i = 0; i < eval->groups.values_num; i++)
232 	{
233 		group = (zbx_expression_group_t *)eval->groups.values[i];
234 
235 		if (0 == strcmp(group->name, name))
236 			return group;
237 	}
238 
239 	group = (zbx_expression_group_t *)zbx_malloc(NULL, sizeof(zbx_expression_group_t));
240 	group->name = zbx_strdup(NULL, name);
241 	zbx_vector_uint64_create(&group->hostids);
242 	zbx_dc_get_hostids_by_group_name(name, &group->hostids);
243 	zbx_vector_ptr_append(&eval->groups, group);
244 
245 	return group;
246 }
247 
248 /******************************************************************************
249  *                                                                            *
250  * Function: expression_get_item                                              *
251  *                                                                            *
252  * Purpose: get item from cache by itemid                                     *
253  *                                                                            *
254  * Parameters: eval    - [IN] the evaluation data                             *
255  *             itemid  - [IN] the item identifier                             *
256  *                                                                            *
257  * Return value: The cached item.                                             *
258  *                                                                            *
259  * Comments: Cache item if necessary.                                         *
260  *                                                                            *
261  ******************************************************************************/
expression_get_item(zbx_expression_eval_t * eval,zbx_uint64_t itemid)262 static zbx_expression_item_t	*expression_get_item(zbx_expression_eval_t *eval, zbx_uint64_t itemid)
263 {
264 	int		i;
265 	zbx_expression_item_t	*item;
266 
267 	for (i = 0; i < eval->itemtags.values_num; i++)
268 	{
269 		item = (zbx_expression_item_t *)eval->itemtags.values[i];
270 
271 		if (item->itemid == itemid)
272 			return item;
273 	}
274 
275 	item = (zbx_expression_item_t *)zbx_malloc(NULL, sizeof(zbx_expression_group_t));
276 	item->itemid = itemid;
277 	zbx_vector_ptr_create(&item->tags);
278 	zbx_dc_get_item_tags(itemid, &item->tags);
279 	zbx_vector_ptr_append(&eval->itemtags, item);
280 
281 	return item;
282 }
283 
284 /******************************************************************************
285  *                                                                            *
286  * Function: expression_item_free                                             *
287  *                                                                            *
288  ******************************************************************************/
expression_item_free(zbx_expression_item_t * item)289 static void	expression_item_free(zbx_expression_item_t *item)
290 {
291 	zbx_vector_ptr_clear_ext(&item->tags, (zbx_clean_func_t) zbx_free_item_tag);
292 	zbx_vector_ptr_destroy(&item->tags);
293 	zbx_free(item);
294 }
295 
296 /******************************************************************************
297  *                                                                            *
298  * Function: expression_init_query_one                                        *
299  *                                                                            *
300  * Purpose: initialize one item query                                         *
301  *                                                                            *
302  * Parameters: eval  - [IN] the evaluation data                               *
303  *             query - [IN] the query to initialize                           *
304  *                                                                            *
305  ******************************************************************************/
expression_init_query_one(zbx_expression_eval_t * eval,zbx_expression_query_t * query)306 static void	expression_init_query_one(zbx_expression_eval_t *eval, zbx_expression_query_t *query)
307 {
308 	zbx_expression_query_one_t	*data;
309 
310 	data = (zbx_expression_query_one_t *)zbx_malloc(NULL, sizeof(zbx_expression_query_one_t));
311 	data->dcitem_hk_index = eval->one_num++;
312 	query->data = data;
313 }
314 
315 /******************************************************************************
316  *                                                                            *
317  * Function: replace_key_param_wildcard_cb                                    *
318  *                                                                            *
319  * Purpose: replace wildcards '*'in key parameters with % and escape existing *
320  *          %, \ characters for SQL like operation                            *
321  *                                                                            *
322  ******************************************************************************/
replace_key_param_wildcard_cb(const char * data,int key_type,int level,int num,int quoted,void * cb_data,char ** param)323 static int	replace_key_param_wildcard_cb(const char *data, int key_type, int level, int num, int quoted, void *cb_data,
324 		char **param)
325 {
326 	char	*tmp;
327 
328 	ZBX_UNUSED(key_type);
329 	ZBX_UNUSED(num);
330 	ZBX_UNUSED(cb_data);
331 
332 	if (0 == level)
333 		return SUCCEED;
334 
335 	if ('*' == data[0] && '\0' == data[1])
336 	{
337 		*param = zbx_strdup(NULL, "%");
338 		return SUCCEED;
339 	}
340 
341 	if (NULL == strchr(data, '%') && NULL == strchr(data, '\\'))
342 		return SUCCEED;
343 
344 	tmp = zbx_strdup(NULL, data);
345 	unquote_key_param(tmp);
346 	*param = zbx_dyn_escape_string(tmp, "\\%%");
347 	zbx_free(tmp);
348 
349 	/* escaping cannot result in unquotable parameter */
350 	if (FAIL == quote_key_param(param, quoted))
351 	{
352 		THIS_SHOULD_NEVER_HAPPEN;
353 		zbx_free(*param);
354 	}
355 
356 	return SUCCEED;
357 }
358 
359 /******************************************************************************
360  *                                                                            *
361  * Function: expression_match_item_key                                        *
362  *                                                                            *
363  * Purpose: check if item key matches the pattern                             *
364  *                                                                            *
365  * Parameters: item_key - [IN] the item key to match                          *
366  *             pattern  - [IN] the pattern                                    *
367  *                                                                            *
368  ******************************************************************************/
expression_match_item_key(const char * item_key,const AGENT_REQUEST * pattern)369 static int	expression_match_item_key(const char *item_key, const AGENT_REQUEST *pattern)
370 {
371 	AGENT_REQUEST	key;
372 	int		i, ret = FAIL;
373 
374 	init_request(&key);
375 
376 	if (SUCCEED != parse_item_key(item_key, &key))
377 		goto out;
378 
379 	if (pattern->nparam != key.nparam)
380 		goto out;
381 
382 	if (0 != strcmp(pattern->key, key.key))
383 		goto out;
384 
385 	for (i = 0; i < key.nparam; i++)
386 	{
387 		if (0 == strcmp(pattern->params[i], "*"))
388 			continue;
389 
390 		if (0 != strcmp(pattern->params[i], key.params[i]))
391 			goto out;
392 	}
393 
394 	ret = SUCCEED;
395 out:
396 	free_request(&key);
397 
398 	return ret;
399 }
400 
401 typedef struct
402 {
403 	zbx_uint64_t	itemid;
404 	zbx_uint64_t	hostid;
405 	zbx_expression_eval_t	*eval;
406 }
407 zbx_expression_eval_many_t;
408 
409 /******************************************************************************
410  *                                                                            *
411  * Function: expression_get_item_candidates                                   *
412  *                                                                            *
413  * Purpose: get itemids + hostids of items that might match query based on    *
414  *          host, key and filter groups                                       *
415  *                                                                            *
416  * Parameters: eval            - [IN] the evaluation data                     *
417  *             query           - [IN] the expression item query               *
418  *             groups          - [IN] the groups in filter template           *
419  *             filter_template - [IN] the group filter template with {index}  *
420  *                                    placeholders referring to a group in    *
421  *                                    groups vector                           *
422  *             itemhosts       - [out] itemid+hostid pairs matching query     *
423  *                                                                            *
424  ******************************************************************************/
expression_get_item_candidates(zbx_expression_eval_t * eval,const zbx_expression_query_t * query,const zbx_vector_str_t * groups,const char * filter_template,zbx_vector_uint64_pair_t * itemhosts)425 static void	expression_get_item_candidates(zbx_expression_eval_t *eval, const zbx_expression_query_t *query,
426 		const zbx_vector_str_t *groups, const char *filter_template, zbx_vector_uint64_pair_t *itemhosts)
427 {
428 	DB_RESULT	result;
429 	DB_ROW		row;
430 	char		*sql = NULL, *esc, *clause = "where";
431 	size_t		sql_alloc = 0, sql_offset = 0;
432 	AGENT_REQUEST	pattern;
433 
434 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select i.itemid,i.hostid");
435 
436 	if (0 != (query->flags & ZBX_ITEM_QUERY_KEY_SOME))
437 	{
438 		init_request(&pattern);
439 		if (SUCCEED != parse_item_key(query->ref.key, &pattern))
440 		{
441 			THIS_SHOULD_NEVER_HAPPEN;
442 			zbx_free(sql);
443 			return;
444 		}
445 
446 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ",i.key_");
447 	}
448 
449 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " from items i");
450 
451 	if (0 != (query->flags & ZBX_ITEM_QUERY_HOST_ONE))
452 	{
453 		esc = DBdyn_escape_string(query->ref.host);
454 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, ",hosts h"
455 				" where h.hostid=i.hostid"
456 				" and h.host='%s'", esc);
457 		zbx_free(esc);
458 		clause = "and";
459 	}
460 	else if (0 != (query->flags & ZBX_ITEM_QUERY_HOST_SELF))
461 	{
462 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where i.hostid=" ZBX_FS_UI64,
463 				eval->hostid);
464 		clause = "and";
465 	}
466 
467 	if (0 != (query->flags & ZBX_ITEM_QUERY_KEY_SOME))
468 	{
469 		char	*key;
470 
471 		key = zbx_strdup(NULL, query->ref.key);
472 		replace_key_params_dyn(&key, ZBX_KEY_TYPE_ITEM, replace_key_param_wildcard_cb, NULL, NULL, 0);
473 
474 		esc = DBdyn_escape_string(key);
475 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " %s i.key_ like '%s'", clause, esc);
476 		zbx_free(esc);
477 		zbx_free(key);
478 		clause = "and";
479 	}
480 	else if (0 != (query->flags & ZBX_ITEM_QUERY_KEY_ONE))
481 	{
482 		esc = DBdyn_escape_string(query->ref.key);
483 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " %s i.key_='%s'", clause, esc);
484 		zbx_free(esc);
485 		clause = "and";
486 	}
487 
488 	if (0 != (query->flags & ZBX_ITEM_QUERY_FILTER) && NULL != filter_template && '\0' != *filter_template)
489 	{
490 		zbx_uint64_t		index;
491 		int			pos = 0, last_pos = 0;
492 		zbx_token_t		token;
493 		zbx_expression_group_t	*group;
494 
495 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " %s ", clause);
496 
497 		for (; SUCCEED == zbx_token_find(filter_template, pos, &token, ZBX_TOKEN_SEARCH_FUNCTIONID); pos++)
498 		{
499 			if (ZBX_TOKEN_OBJECTID != token.type)
500 				continue;
501 
502 			if (SUCCEED != is_uint64_n(filter_template + token.loc.l + 1, token.loc.r - token.loc.l - 1,
503 					&index) && (int)index < groups->values_num)
504 			{
505 				continue;
506 			}
507 
508 			group = expression_get_group(eval, groups->values[index]);
509 
510 			zbx_strncpy_alloc(&sql, &sql_alloc, &sql_offset, filter_template + last_pos,
511 					token.loc.l - last_pos);
512 
513 			if (' ' == sql[sql_offset - 1])
514 				sql_offset--;
515 
516 			if (0 < group->hostids.values_num)
517 			{
518 				DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.hostid", group->hostids.values,
519 						group->hostids.values_num);
520 			}
521 			else
522 				zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " 1=0");
523 
524 			last_pos = token.loc.r + 1;
525 			pos = token.loc.r;
526 		}
527 
528 		if ('\0' != filter_template[last_pos])
529 			zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, filter_template + last_pos);
530 	}
531 
532 	result = DBselect("%s", sql);
533 
534 	while (NULL != (row = DBfetch(result)))
535 	{
536 		zbx_uint64_pair_t	pair;
537 
538 		if (0 == (query->flags & ZBX_ITEM_QUERY_KEY_SOME) ||
539 				(NULL != pattern.key && SUCCEED == expression_match_item_key(row[2], &pattern)))
540 		{
541 			ZBX_STR2UINT64(pair.first, row[0]);
542 			ZBX_STR2UINT64(pair.second, row[1]);
543 			zbx_vector_uint64_pair_append(itemhosts, pair);
544 		}
545 	}
546 	DBfree_result(result);
547 
548 	if (0 != (query->flags & ZBX_ITEM_QUERY_KEY_SOME))
549 		free_request(&pattern);
550 
551 	zbx_free(sql);
552 }
553 
554 /******************************************************************************
555  *                                                                            *
556  * Function: expression_item_check_tag                                        *
557  *                                                                            *
558  * Purpose: check if the item matches the tag                                 *
559  *                                                                            *
560  * Parameters: item - [IN] the item with tags                                 *
561  *             tag  - [IN] the tag to match in format <tag name>[:<tag value>]*
562  *                                                                            *
563  * Return value: SUCCEED - the item matches the specified tag                 *
564  *               FAIL    - otherwise                                          *
565  *                                                                            *
566  ******************************************************************************/
expression_item_check_tag(zbx_expression_item_t * item,const char * tag)567 static int	expression_item_check_tag(zbx_expression_item_t *item, const char *tag)
568 {
569 	int		i;
570 	size_t		taglen;
571 	const char	*value;
572 
573 	if (NULL != (value = strchr(tag, ':')))
574 	{
575 		taglen = (value - tag);
576 		value++;
577 	}
578 	else
579 		taglen = strlen(tag);
580 
581 	for (i = 0; i < item->tags.values_num; i++)
582 	{
583 		zbx_item_tag_t	*itemtag = (zbx_item_tag_t *)item->tags.values[i];
584 
585 		if (taglen != strlen(itemtag->tag.tag) || 0 != memcmp(tag, itemtag->tag.tag, taglen))
586 			continue;
587 
588 		if (NULL == value)
589 			return SUCCEED;
590 
591 		if (0 == strcmp(itemtag->tag.value, value))
592 			return SUCCEED;
593 	}
594 
595 	return FAIL;
596 }
597 
598 /******************************************************************************
599  *                                                                            *
600  * Function: expression_eval_filter                                           *
601  *                                                                            *
602  * Purpose: evaluate filter function                                          *
603  *                                                                            *
604  * Parameters: name     - [IN] the function name (not zero terminated)        *
605  *             len      - [IN] the function name length                       *
606  *             args_num - [IN] the number of function arguments               *
607  *             args     - [IN] an array of the function arguments.            *
608  *             data     - [IN] the caller data used for function evaluation   *
609  *             ts       - [IN] the function execution time                    *
610  *             value    - [OUT] the function return value                     *
611  *             error    - [OUT] the error message if function failed          *
612  *                                                                            *
613  * Return value: SUCCEED - the function was evaluated successfully            *
614  *               FAIL    - otherwise                                          *
615  *                                                                            *
616  * Comments: The group/tag comparisons in filter are converted to function    *
617  *           calls that are evaluated by this callback.                       *
618  *                                                                            *
619  ******************************************************************************/
expression_eval_filter(const char * name,size_t len,int args_num,const zbx_variant_t * args,void * data,const zbx_timespec_t * ts,zbx_variant_t * value,char ** error)620 static int	expression_eval_filter(const char *name, size_t len, int args_num, const zbx_variant_t *args,
621 		void *data, const zbx_timespec_t *ts, zbx_variant_t *value, char **error)
622 {
623 	zbx_expression_eval_many_t	*many = (zbx_expression_eval_many_t *)data;
624 
625 	ZBX_UNUSED(ts);
626 	ZBX_UNUSED(len);
627 
628 	if (1 != args_num)
629 	{
630 		*error = zbx_strdup(NULL, "invalid number of arguments");
631 		return FAIL;
632 	}
633 
634 	if (ZBX_VARIANT_STR != args[0].type)
635 	{
636 		*error = zbx_strdup(NULL, "invalid argument flags");
637 		return FAIL;
638 	}
639 
640 	if (0 == strncmp(name, "group", ZBX_CONST_STRLEN("group")))
641 	{
642 		zbx_expression_group_t *group;
643 
644 		group = expression_get_group(many->eval, args[0].data.str);
645 
646 		if (FAIL != zbx_vector_uint64_bsearch(&group->hostids, many->hostid, ZBX_DEFAULT_UINT64_COMPARE_FUNC))
647 			zbx_variant_set_dbl(value, 1);
648 		else
649 			zbx_variant_set_dbl(value, 0);
650 
651 		return SUCCEED;
652 	}
653 	else if (0 == strncmp(name, "tag", ZBX_CONST_STRLEN("tag")))
654 	{
655 		zbx_expression_item_t	*item;
656 
657 		item = expression_get_item(many->eval, many->itemid);
658 
659 		if (SUCCEED == expression_item_check_tag(item, args[0].data.str))
660 			zbx_variant_set_dbl(value, 1);
661 		else
662 			zbx_variant_set_dbl(value, 0);
663 
664 		return SUCCEED;
665 	}
666 	else
667 	{
668 		*error = zbx_strdup(NULL, "unknown function");
669 		return FAIL;
670 	}
671 }
672 
673 /******************************************************************************
674  *                                                                            *
675  * Function: expression_init_query_many                                       *
676  *                                                                            *
677  * Purpose: initialize many item query                                        *
678  *                                                                            *
679  * Parameters: eval    - [IN] the evaluation data                             *
680  *             query   - [IN] the query to initialize                         *
681  *                                                                            *
682  ******************************************************************************/
expression_init_query_many(zbx_expression_eval_t * eval,zbx_expression_query_t * query)683 static void	expression_init_query_many(zbx_expression_eval_t *eval, zbx_expression_query_t *query)
684 {
685 	zbx_expression_query_many_t	*data;
686 	char				*error = NULL, *errmsg = NULL, *filter_template = NULL;
687 	int				i, ret = FAIL;
688 	zbx_eval_context_t		ctx;
689 	zbx_vector_uint64_pair_t	itemhosts;
690 	zbx_vector_str_t		groups;
691 	zbx_vector_uint64_t		itemids;
692 
693 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() /%s/%s?[%s]", __func__, ZBX_NULL2EMPTY_STR(query->ref.host),
694 			ZBX_NULL2EMPTY_STR(query->ref.key), ZBX_NULL2EMPTY_STR(query->ref.filter));
695 
696 	zbx_eval_init(&ctx);
697 
698 	zbx_vector_uint64_create(&itemids);
699 	zbx_vector_uint64_pair_create(&itemhosts);
700 	zbx_vector_str_create(&groups);
701 
702 	if (ZBX_ITEM_QUERY_ITEM_ANY == (query->flags & ZBX_ITEM_QUERY_ITEM_ANY))
703 	{
704 		error = zbx_strdup(NULL, "item query must have at least a host or an item key defined");
705 		goto out;
706 	}
707 
708 	if (0 != (query->flags & ZBX_ITEM_QUERY_FILTER))
709 	{
710 		if (SUCCEED != zbx_eval_parse_expression(&ctx, query->ref.filter, ZBX_EVAL_PARSE_QUERY_EXPRESSION,
711 				&errmsg))
712 		{
713 			error = zbx_dsprintf(NULL, "failed to parse item query filter: %s", errmsg);
714 			zbx_free(errmsg);
715 			goto out;
716 		}
717 
718 		zbx_eval_prepare_filter(&ctx);
719 
720 		if (FAIL == zbx_eval_get_group_filter(&ctx, &groups, &filter_template, &errmsg))
721 		{
722 			error = zbx_dsprintf(NULL, "failed to extract groups from item filter: %s", errmsg);
723 			zbx_free(errmsg);
724 			goto out;
725 		}
726 	}
727 
728 	expression_get_item_candidates(eval, query, &groups, filter_template, &itemhosts);
729 
730 	if (0 != (query->flags & ZBX_ITEM_QUERY_FILTER))
731 	{
732 		zbx_expression_eval_many_t	eval_data;
733 		zbx_variant_t		filter_value;
734 
735 		eval_data.eval = eval;
736 
737 		for (i = 0; i < itemhosts.values_num; i++)
738 		{
739 			eval_data.itemid = itemhosts.values[i].first;
740 			eval_data.hostid = itemhosts.values[i].second;
741 
742 			if (SUCCEED != zbx_eval_execute_ext(&ctx, NULL, expression_eval_filter, NULL, (void *)&eval_data,
743 					&filter_value, &errmsg))
744 			{
745 				zabbix_log(LOG_LEVEL_DEBUG, "failed to evaluate item query filter: %s", errmsg);
746 				zbx_free(errmsg);
747 				continue;
748 			}
749 
750 			if (SUCCEED != zbx_variant_convert(&filter_value, ZBX_VARIANT_DBL))
751 			{
752 				zabbix_log(LOG_LEVEL_DEBUG, "unexpected item query filter evaluation result:"
753 						" value:\"%s\" of type \"%s\"", zbx_variant_value_desc(&filter_value),
754 						zbx_variant_type_desc(&filter_value));
755 
756 				zbx_variant_clear(&filter_value);
757 				continue;
758 			}
759 
760 			if (SUCCEED != zbx_double_compare(filter_value.data.dbl, 0))
761 				zbx_vector_uint64_append(&itemids, eval_data.itemid);
762 		}
763 	}
764 	else
765 	{
766 		for (i = 0; i < itemhosts.values_num; i++)
767 			zbx_vector_uint64_append(&itemids, itemhosts.values[i].first);
768 	}
769 
770 	if (0 == itemids.values_num)
771 	{
772 		error = zbx_strdup(NULL, "no items matching query");
773 		goto out;
774 	}
775 
776 	if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG))
777 	{
778 		for (i = 0; i < itemids.values_num; i++)
779 			zabbix_log(LOG_LEVEL_DEBUG, "%s() itemid:" ZBX_FS_UI64, __func__, itemids.values[i]);
780 	}
781 
782 	data = (zbx_expression_query_many_t *)zbx_malloc(NULL, sizeof(zbx_expression_query_many_t));
783 	data->itemids = itemids;
784 	query->data = data;
785 	eval->many_num++;
786 
787 	ret = SUCCEED;
788 out:
789 	if (0 != (query->flags & ZBX_ITEM_QUERY_FILTER) && SUCCEED == zbx_eval_status(&ctx))
790 		zbx_eval_clear(&ctx);
791 
792 	if (SUCCEED != ret)
793 	{
794 		query->error = error;
795 		query->flags = ZBX_ITEM_QUERY_ERROR;
796 		zbx_vector_uint64_destroy(&itemids);
797 	}
798 
799 	zbx_free(filter_template);
800 
801 	zbx_vector_uint64_pair_destroy(&itemhosts);
802 
803 	zbx_vector_str_clear_ext(&groups, zbx_str_free);
804 	zbx_vector_str_destroy(&groups);
805 
806 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() items:%d", __func__, (SUCCEED == ret ? data->itemids.values_num : -1));
807 }
808 
809 /******************************************************************************
810  *                                                                            *
811  * Function: expression_cache_dcitems_hk                                      *
812  *                                                                            *
813  * Purpose: cache items used in one item queries                              *
814  *                                                                            *
815  * Parameters: eval - [IN] the evaluation data                                *
816  *                                                                            *
817  ******************************************************************************/
expression_cache_dcitems_hk(zbx_expression_eval_t * eval)818 static void	expression_cache_dcitems_hk(zbx_expression_eval_t *eval)
819 {
820 	int	i;
821 
822 	eval->hostkeys = (zbx_host_key_t *)zbx_malloc(NULL, sizeof(zbx_host_key_t) * eval->one_num);
823 	eval->dcitems_hk = (DC_ITEM *)zbx_malloc(NULL, sizeof(DC_ITEM) * eval->one_num);
824 	eval->errcodes_hk = (int *)zbx_malloc(NULL, sizeof(int) * eval->one_num);
825 
826 	for (i = 0; i < eval->queries.values_num; i++)
827 	{
828 		zbx_expression_query_t	*query = (zbx_expression_query_t *)eval->queries.values[i];
829 		zbx_expression_query_one_t	*data;
830 
831 		if (0 != (query->flags & ZBX_ITEM_QUERY_MANY) || ZBX_ITEM_QUERY_ERROR == query->flags)
832 			continue;
833 
834 		data = (zbx_expression_query_one_t *)query->data;
835 
836 		eval->hostkeys[data->dcitem_hk_index].host = query->ref.host;
837 		eval->hostkeys[data->dcitem_hk_index].key = query->ref.key;
838 	}
839 
840 	DCconfig_get_items_by_keys(eval->dcitems_hk, eval->hostkeys, eval->errcodes_hk, eval->one_num);
841 }
842 
843 /******************************************************************************
844  *                                                                            *
845  * Purpose: dcitem reference vector lookup functions                          *
846  *                                                                            *
847  ******************************************************************************/
compare_dcitems_by_itemid(const void * d1,const void * d2)848 static	int	compare_dcitems_by_itemid(const void *d1, const void *d2)
849 {
850 	DC_ITEM	*dci1 = *(DC_ITEM **)d1;
851 	DC_ITEM	*dci2 = *(DC_ITEM **)d2;
852 
853 	ZBX_RETURN_IF_NOT_EQUAL(dci1->itemid, dci2->itemid);
854 
855 	return 0;
856 }
857 
expression_find_dcitem_by_itemid(const void * d1,const void * d2)858 static int	expression_find_dcitem_by_itemid(const void *d1, const void *d2)
859 {
860 	zbx_uint64_t	itemid = **(zbx_uint64_t **)d1;
861 	DC_ITEM		*dci = *(DC_ITEM **)d2;
862 
863 	ZBX_RETURN_IF_NOT_EQUAL(itemid, dci->itemid);
864 
865 	return 0;
866 }
867 
868 /******************************************************************************
869  *                                                                            *
870  * Function: expression_cache_dcitems                                         *
871  *                                                                            *
872  * Purpose: cache items used in many item queries                             *
873  *                                                                            *
874  * Parameters: eval - [IN] the evaluation data                                *
875  *                                                                            *
876  ******************************************************************************/
expression_cache_dcitems(zbx_expression_eval_t * eval)877 static void	expression_cache_dcitems(zbx_expression_eval_t *eval)
878 {
879 	int			i, j;
880 	zbx_vector_uint64_t	itemids;
881 
882 	zbx_vector_uint64_create(&itemids);
883 
884 	if (0 != eval->one_num)
885 	{
886 		for (i = 0; i < eval->one_num; i++)
887 		{
888 			if (SUCCEED != eval->errcodes_hk[i])
889 				continue;
890 
891 			zbx_vector_ptr_append(&eval->dcitem_refs, &eval->dcitems_hk[i]);
892 		}
893 
894 		zbx_vector_ptr_sort(&eval->dcitem_refs, compare_dcitems_by_itemid);
895 	}
896 
897 	for (i = 0; i < eval->queries.values_num; i++)
898 	{
899 		zbx_expression_query_t	*query = (zbx_expression_query_t *)eval->queries.values[i];
900 		zbx_expression_query_many_t	*data;
901 
902 		if (0 == (query->flags & ZBX_ITEM_QUERY_MANY))
903 			continue;
904 
905 		data = (zbx_expression_query_many_t *)query->data;
906 
907 		for (j = 0; j < data->itemids.values_num; j++)
908 			zbx_vector_uint64_append(&itemids, data->itemids.values[j]);
909 	}
910 
911 	zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
912 	zbx_vector_uint64_uniq(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
913 
914 	for (i = 0; i < itemids.values_num;)
915 	{
916 		if (FAIL != zbx_vector_ptr_bsearch(&eval->dcitem_refs, &itemids.values[i], expression_find_dcitem_by_itemid))
917 		{
918 			zbx_vector_uint64_remove(&itemids, i);
919 			continue;
920 		}
921 		i++;
922 	}
923 
924 	if (0 != (eval->dcitems_num = itemids.values_num))
925 	{
926 		zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
927 
928 		eval->dcitems = (DC_ITEM *)zbx_malloc(NULL, sizeof(DC_ITEM) * itemids.values_num);
929 		eval->errcodes = (int *)zbx_malloc(NULL, sizeof(int) * itemids.values_num);
930 
931 		DCconfig_get_items_by_itemids(eval->dcitems, itemids.values, eval->errcodes, itemids.values_num);
932 
933 		for (i = 0; i < itemids.values_num; i++)
934 		{
935 			if (SUCCEED != eval->errcodes[i])
936 				continue;
937 
938 			zbx_vector_ptr_append(&eval->dcitem_refs, &eval->dcitems[i]);
939 		}
940 
941 		zbx_vector_ptr_sort(&eval->dcitem_refs, compare_dcitems_by_itemid);
942 	}
943 
944 	zbx_vector_uint64_destroy(&itemids);
945 }
946 
947 /******************************************************************************
948  *                                                                            *
949  * Function: expression_eval_one                                              *
950  *                                                                            *
951  * Purpose: evaluate historical function for one item query                   *
952  *                                                                            *
953  * Parameters: eval     - [IN] the evaluation data                            *
954  *             query    - [IN] the item query                                 *
955  *             name     - [IN] the function name (not zero terminated)        *
956  *             len      - [IN] the function name length                       *
957  *             args_num - [IN] the number of function arguments               *
958  *             args     - [IN] an array of the function arguments.            *
959  *             data     - [IN] the caller data used for function evaluation   *
960  *             ts       - [IN] the function execution time                    *
961  *             value    - [OUT] the function return value                     *
962  *             error    - [OUT] the error message if function failed          *
963  *                                                                            *
964  * Return value: SUCCEED - the function was executed successfully             *
965  *               FAIL    - otherwise                                          *
966  *                                                                            *
967  ******************************************************************************/
expression_eval_one(zbx_expression_eval_t * eval,zbx_expression_query_t * query,const char * name,size_t len,int args_num,const zbx_variant_t * args,const zbx_timespec_t * ts,zbx_variant_t * value,char ** error)968 static int	expression_eval_one(zbx_expression_eval_t *eval, zbx_expression_query_t *query, const char *name,
969 		size_t len, int args_num, const zbx_variant_t *args, const zbx_timespec_t *ts, zbx_variant_t *value, char **error)
970 {
971 	char			func_name[MAX_STRING_LEN], *params = NULL;
972 	size_t			params_alloc = 0, params_offset = 0;
973 	DC_ITEM			*item;
974 	int			i, ret = FAIL;
975 	zbx_expression_query_one_t	*data;
976 
977 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() %.*s(/%s/%s?[%s],...)", __func__, (int )len, name,
978 			ZBX_NULL2EMPTY_STR(query->ref.host), ZBX_NULL2EMPTY_STR(query->ref.key),
979 			ZBX_NULL2EMPTY_STR(query->ref.filter));
980 
981 	data = (zbx_expression_query_one_t *)query->data;
982 
983 	if (SUCCEED != eval->errcodes_hk[data->dcitem_hk_index])
984 	{
985 		*error = zbx_dsprintf(NULL, "item \"/%s/%s\" does not exist",
986 				eval->hostkeys[data->dcitem_hk_index].host, eval->hostkeys[data->dcitem_hk_index].key);
987 		goto out;
988 	}
989 
990 	item = &eval->dcitems_hk[data->dcitem_hk_index];
991 
992 	/* do not evaluate if the item is disabled or belongs to a disabled host */
993 
994 	if (ITEM_STATUS_ACTIVE != item->status)
995 	{
996 		*error = zbx_dsprintf(NULL, "item \"/%s/%s\" is disabled", eval->hostkeys[data->dcitem_hk_index].host,
997 				eval->hostkeys[data->dcitem_hk_index].key);
998 		goto out;
999 	}
1000 
1001 	if (HOST_STATUS_MONITORED != item->host.status)
1002 	{
1003 		*error = zbx_dsprintf(NULL, "host \"%s\" is not monitored", eval->hostkeys[data->dcitem_hk_index].host);
1004 		goto out;
1005 	}
1006 
1007 	memcpy(func_name, name, len);
1008 	func_name[len] = '\0';
1009 
1010 	/* If the item is NOTSUPPORTED then evaluation is allowed for:   */
1011 	/*   - functions white-listed in evaluatable_for_notsupported(). */
1012 	/*     Their values can be evaluated to regular numbers even for */
1013 	/*     NOTSUPPORTED items. */
1014 	/*   - other functions. Result of evaluation is ZBX_UNKNOWN.     */
1015 
1016 	if (ITEM_STATE_NOTSUPPORTED == item->state && FAIL == zbx_evaluatable_for_notsupported(func_name))
1017 	{
1018 		/* compose and store 'unknown' message for future use */
1019 		*error = zbx_dsprintf(NULL, "item \"/%s/%s\" is not supported",
1020 				eval->hostkeys[data->dcitem_hk_index].host, eval->hostkeys[data->dcitem_hk_index].key);
1021 		goto out;
1022 	}
1023 
1024 	if (0 == args_num)
1025 	{
1026 		ret = evaluate_function2(value, item, func_name, "", ts, error);
1027 		goto out;
1028 	}
1029 
1030 	for (i = 0; i < args_num; i++)
1031 	{
1032 		if (0 != i)
1033 			zbx_chrcpy_alloc(&params, &params_alloc, &params_offset, ',');
1034 
1035 		switch (args[i].type)
1036 		{
1037 			case ZBX_VARIANT_DBL:
1038 				zbx_snprintf_alloc(&params, &params_alloc, &params_offset, ZBX_FS_DBL64,
1039 						args[i].data.dbl);
1040 				break;
1041 			case ZBX_VARIANT_STR:
1042 				zbx_strquote_alloc(&params, &params_alloc, &params_offset, args[i].data.str);
1043 				break;
1044 			case ZBX_VARIANT_UI64:
1045 				zbx_snprintf_alloc(&params, &params_alloc, &params_offset, ZBX_FS_UI64,
1046 						args[i].data.ui64);
1047 				break;
1048 			case ZBX_VARIANT_NONE:
1049 				break;
1050 			default:
1051 				*error = zbx_dsprintf(NULL, " unsupported argument #%d type \"%s\"", i + 1,
1052 						zbx_variant_type_desc(&args[i]));
1053 				goto out;
1054 		}
1055 	}
1056 
1057 	ret = evaluate_function2(value, item, func_name, ZBX_NULL2EMPTY_STR(params), ts, error);
1058 out:
1059 	zbx_free(params);
1060 
1061 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s value:%s flags:%s", __func__, zbx_result_string(ret),
1062 			zbx_variant_value_desc(value), zbx_variant_type_desc(value));
1063 
1064 	return ret;
1065 }
1066 
1067 #define ZBX_VALUE_FUNC_UNKNOWN	0
1068 #define ZBX_VALUE_FUNC_MIN	1
1069 #define ZBX_VALUE_FUNC_AVG	2
1070 #define ZBX_VALUE_FUNC_MAX	3
1071 #define ZBX_VALUE_FUNC_SUM	4
1072 #define ZBX_VALUE_FUNC_COUNT	5
1073 #define ZBX_VALUE_FUNC_LAST	6
1074 
1075 
1076 #define MATCH_STRING(x, name, len)	ZBX_CONST_STRLEN(x) == len && 0 == memcmp(name, x, len)
1077 
get_function_by_name(const char * name,size_t len)1078 static int	get_function_by_name(const char *name, size_t len)
1079 {
1080 
1081 	if (MATCH_STRING("avg_foreach", name, len))
1082 		return ZBX_VALUE_FUNC_AVG;
1083 
1084 	if (MATCH_STRING("count_foreach", name, len))
1085 		return ZBX_VALUE_FUNC_COUNT;
1086 
1087 	if (MATCH_STRING("last_foreach", name, len))
1088 		return ZBX_VALUE_FUNC_LAST;
1089 
1090 	if (MATCH_STRING("max_foreach", name, len))
1091 		return ZBX_VALUE_FUNC_MAX;
1092 
1093 	if (MATCH_STRING("min_foreach", name, len))
1094 		return ZBX_VALUE_FUNC_MIN;
1095 
1096 	if (MATCH_STRING("sum_foreach", name, len))
1097 		return ZBX_VALUE_FUNC_SUM;
1098 
1099 	return ZBX_VALUE_FUNC_UNKNOWN;
1100 }
1101 
1102 /******************************************************************************
1103  *                                                                            *
1104  * Function: evaluate_history_func_min                                        *
1105  *                                                                            *
1106  * Purpose: calculate minimum value from the history value vector             *
1107  *                                                                            *
1108  * Parameters: values      - [IN] a vector containing history values          *
1109  *             value_type  - [IN] the type of values. Only float/uint64       *
1110  *                           values are supported.                            *
1111  *             result      - [OUT] the resulting value                        *
1112  *                                                                            *
1113  ******************************************************************************/
evaluate_history_func_min(zbx_vector_history_record_t * values,int value_type,double * result)1114 static void	evaluate_history_func_min(zbx_vector_history_record_t *values, int value_type, double *result)
1115 {
1116 	int	i;
1117 
1118 	if (ITEM_VALUE_TYPE_UINT64 == value_type)
1119 	{
1120 		*result = (double)values->values[0].value.ui64;
1121 
1122 		for (i = 1; i < values->values_num; i++)
1123 			if ((double)values->values[i].value.ui64 < *result)
1124 				*result = (double)values->values[i].value.ui64;
1125 	}
1126 	else
1127 	{
1128 		*result = values->values[0].value.dbl;
1129 
1130 		for (i = 1; i < values->values_num; i++)
1131 			if (values->values[i].value.dbl < *result)
1132 				*result = values->values[i].value.dbl;
1133 	}
1134 }
1135 
1136 /******************************************************************************
1137  *                                                                            *
1138  * Function: evaluate_history_func_max                                        *
1139  *                                                                            *
1140  * Purpose: calculate maximum value from the history value vector             *
1141  *                                                                            *
1142  * Parameters: values      - [IN] a vector containing history values          *
1143  *             value_type  - [IN] the type of values. Only float/uint64       *
1144  *                           values are supported.                            *
1145  *             result      - [OUT] the resulting value                        *
1146  *                                                                            *
1147  ******************************************************************************/
evaluate_history_func_max(zbx_vector_history_record_t * values,int value_type,double * result)1148 static void	evaluate_history_func_max(zbx_vector_history_record_t *values, int value_type, double *result)
1149 {
1150 	int	i;
1151 
1152 	if (ITEM_VALUE_TYPE_UINT64 == value_type)
1153 	{
1154 		*result = (double)values->values[0].value.ui64;
1155 
1156 		for (i = 1; i < values->values_num; i++)
1157 			if ((double)values->values[i].value.ui64 > *result)
1158 				*result = (double)values->values[i].value.ui64;
1159 	}
1160 	else
1161 	{
1162 		*result = values->values[0].value.dbl;
1163 
1164 		for (i = 1; i < values->values_num; i++)
1165 			if (values->values[i].value.dbl > *result)
1166 				*result = values->values[i].value.dbl;
1167 	}
1168 }
1169 
1170 /******************************************************************************
1171  *                                                                            *
1172  * Function: evaluate_history_func_sum                                        *
1173  *                                                                            *
1174  * Purpose: calculate sum of values from the history value vector             *
1175  *                                                                            *
1176  * Parameters: values      - [IN] a vector containing history values          *
1177  *             value_type  - [IN] the type of values. Only float/uint64       *
1178  *                           values are supported.                            *
1179  *             result      - [OUT] the resulting value                        *
1180  *                                                                            *
1181  ******************************************************************************/
evaluate_history_func_sum(zbx_vector_history_record_t * values,int value_type,double * result)1182 static void	evaluate_history_func_sum(zbx_vector_history_record_t *values, int value_type, double *result)
1183 {
1184 	int	i;
1185 
1186 	*result = 0;
1187 
1188 	if (ITEM_VALUE_TYPE_UINT64 == value_type)
1189 	{
1190 		for (i = 0; i < values->values_num; i++)
1191 			*result += (double)values->values[i].value.ui64;
1192 	}
1193 	else
1194 	{
1195 		for (i = 0; i < values->values_num; i++)
1196 			*result += values->values[i].value.dbl;
1197 	}
1198 }
1199 
1200 /******************************************************************************
1201  *                                                                            *
1202  * Function: evaluate_history_func_avg                                        *
1203  *                                                                            *
1204  * Purpose: calculate average value of values from the history value vector   *
1205  *                                                                            *
1206  * Parameters: values      - [IN] a vector containing history values          *
1207  *             value_type  - [IN] the type of values. Only float/uint64       *
1208  *                           values are supported.                            *
1209  *             result      - [OUT] the resulting value                        *
1210  *                                                                            *
1211  ******************************************************************************/
evaluate_history_func_avg(zbx_vector_history_record_t * values,int value_type,double * result)1212 static void	evaluate_history_func_avg(zbx_vector_history_record_t *values, int value_type, double *result)
1213 {
1214 	evaluate_history_func_sum(values, value_type, result);
1215 	*result /= values->values_num;
1216 }
1217 
1218 /******************************************************************************
1219  *                                                                            *
1220  * Function: evaluate_history_func_count                                      *
1221  *                                                                            *
1222  * Purpose: calculate number of values in value vector                        *
1223  *                                                                            *
1224  * Parameters: values      - [IN] a vector containing history values          *
1225  *             value_type  - [IN] the type of values. Only float/uint64       *
1226  *                           values are supported.                            *
1227  *             result      - [OUT] the resulting value                        *
1228  *                                                                            *
1229  ******************************************************************************/
evaluate_history_func_count(zbx_vector_history_record_t * values,double * result)1230 static void	evaluate_history_func_count(zbx_vector_history_record_t *values, double *result)
1231 {
1232 	*result = (double)values->values_num;
1233 }
1234 
1235 /******************************************************************************
1236  *                                                                            *
1237  * Function: evaluate_history_func_last                                       *
1238  *                                                                            *
1239  * Purpose: calculate the last (newest) value in value vector                 *
1240  *                                                                            *
1241  * Parameters: values      - [IN] a vector containing history values          *
1242  *             result      - [OUT] the resulting value                        *
1243  *                                                                            *
1244  ******************************************************************************/
evaluate_history_func_last(zbx_vector_history_record_t * values,int value_type,double * result)1245 static void	evaluate_history_func_last(zbx_vector_history_record_t *values, int value_type, double *result)
1246 {
1247 	if (ITEM_VALUE_TYPE_UINT64 == value_type)
1248 		*result = (double)values->values[0].value.ui64;
1249 	else
1250 		*result = values->values[0].value.dbl;
1251 }
1252 
1253 /******************************************************************************
1254  *                                                                            *
1255  * Function: evaluate_history_func                                            *
1256  *                                                                            *
1257  * Purpose: calculate function with values from value vector                  *
1258  *                                                                            *
1259  * Parameters: values      - [IN] a vector containing history values          *
1260  *             value_type  - [IN] the type of values. Only float/uint64       *
1261  *                           values are supported.                            *
1262  *             func        - [IN] the function to calculate. Only             *
1263  *                           ZBX_VALUE_FUNC_MIN, ZBX_VALUE_FUNC_AVG,          *
1264  *                           ZBX_VALUE_FUNC_MAX, ZBX_VALUE_FUNC_SUM,          *
1265  *                           ZBX_VALUE_FUNC_COUNT, ZBX_VALUE_FUNC_LAST        *
1266  *                           functions are supported.                         *
1267  *             result      - [OUT] the resulting value                        *
1268  *                                                                            *
1269  ******************************************************************************/
evaluate_history_func(zbx_vector_history_record_t * values,int value_type,int func,double * result)1270 static void	evaluate_history_func(zbx_vector_history_record_t *values, int value_type, int func,
1271 		double *result)
1272 {
1273 	switch (func)
1274 	{
1275 		case ZBX_VALUE_FUNC_MIN:
1276 			evaluate_history_func_min(values, value_type, result);
1277 			break;
1278 		case ZBX_VALUE_FUNC_AVG:
1279 			evaluate_history_func_avg(values, value_type, result);
1280 			break;
1281 		case ZBX_VALUE_FUNC_MAX:
1282 			evaluate_history_func_max(values, value_type, result);
1283 			break;
1284 		case ZBX_VALUE_FUNC_SUM:
1285 			evaluate_history_func_sum(values, value_type, result);
1286 			break;
1287 		case ZBX_VALUE_FUNC_COUNT:
1288 			evaluate_history_func_count(values, result);
1289 			break;
1290 		case ZBX_VALUE_FUNC_LAST:
1291 			evaluate_history_func_last(values, value_type, result);
1292 			break;
1293 	}
1294 }
1295 
1296 /******************************************************************************
1297  *                                                                            *
1298  * Function: get_dcitem                                                       *
1299  *                                                                            *
1300  * Purpose: get item from cache by itemid                                     *
1301  *                                                                            *
1302  * Parameters: eval    - [IN] the evaluation data                             *
1303  *             itemid  - [IN] the item identifier                             *
1304  *                                                                            *
1305  * Return value: The cached item.                                             *
1306  *                                                                            *
1307  ******************************************************************************/
get_dcitem(zbx_vector_ptr_t * dcitem_refs,zbx_uint64_t itemid)1308 static DC_ITEM	*get_dcitem(zbx_vector_ptr_t *dcitem_refs, zbx_uint64_t itemid)
1309 {
1310 	int	index;
1311 
1312 	if (FAIL == (index = zbx_vector_ptr_bsearch(dcitem_refs, &itemid, expression_find_dcitem_by_itemid)))
1313 		return NULL;
1314 
1315 	return dcitem_refs->values[index];
1316 }
1317 
1318 /******************************************************************************
1319  *                                                                            *
1320  * Function: expression_eval_many                                             *
1321  *                                                                            *
1322  * Purpose: evaluate historical function for multiple items (aggregate checks)*
1323  *                                                                            *
1324  * Parameters: eval     - [IN] the evaluation data                            *
1325  *             query    - [IN] the calculated item query                      *
1326  *             name     - [IN] the function name (not zero terminated)        *
1327  *             len      - [IN] the function name length                       *
1328  *             args_num - [IN] the number of function arguments               *
1329  *             args     - [IN] an array of the function arguments.            *
1330  *             data     - [IN] the caller data used for function evaluation   *
1331  *             ts       - [IN] the function execution time                    *
1332  *             value    - [OUT] the function return value                     *
1333  *             error    - [OUT] the error message if function failed          *
1334  *                                                                            *
1335  * Return value: SUCCEED - the function was executed successfully             *
1336  *               FAIL    - otherwise                                          *
1337  *                                                                            *
1338  ******************************************************************************/
expression_eval_many(zbx_expression_eval_t * eval,zbx_expression_query_t * query,const char * name,size_t len,int args_num,const zbx_variant_t * args,const zbx_timespec_t * ts,zbx_variant_t * value,char ** error)1339 static int	expression_eval_many(zbx_expression_eval_t *eval, zbx_expression_query_t *query, const char *name,
1340 		size_t len, int args_num, const zbx_variant_t *args, const zbx_timespec_t *ts, zbx_variant_t *value,
1341 		char **error)
1342 {
1343 	zbx_expression_query_many_t		*data;
1344 	int				ret = FAIL, item_func, count, seconds, i;
1345 	zbx_vector_history_record_t	values;
1346 	zbx_vector_dbl_t		*results;
1347 	double				result;
1348 	zbx_variant_t			arg;
1349 
1350 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() %.*s(/%s/%s?[%s],...)", __func__, (int)len, name,
1351 			ZBX_NULL2EMPTY_STR(query->ref.host), ZBX_NULL2EMPTY_STR(query->ref.key),
1352 			ZBX_NULL2EMPTY_STR(query->ref.filter));
1353 
1354 	ZBX_UNUSED(args_num);
1355 
1356 	data = (zbx_expression_query_many_t *)query->data;
1357 
1358 	if (ZBX_VALUE_FUNC_UNKNOWN == (item_func = get_function_by_name(name, len)))
1359 	{
1360 		*error = zbx_strdup(NULL, "unsupported function");
1361 		goto out;
1362 	}
1363 
1364 	if (ZBX_VALUE_FUNC_LAST == item_func)
1365 	{
1366 		count = 1;
1367 		seconds = 0;
1368 	}
1369 	else
1370 	{
1371 		if (1 != args_num)
1372 		{
1373 			*error = zbx_strdup(NULL, "invalid number of function parameters");
1374 			goto out;
1375 		}
1376 
1377 		if (ZBX_VARIANT_STR == args[0].type)
1378 		{
1379 			if (FAIL == is_time_suffix(args[0].data.str, &seconds, ZBX_LENGTH_UNLIMITED))
1380 			{
1381 				*error = zbx_strdup(NULL, "invalid second parameter");
1382 				goto out;
1383 			}
1384 		}
1385 		else
1386 		{
1387 			zbx_variant_copy(&arg, &args[0]);
1388 
1389 			if (SUCCEED != zbx_variant_convert(&arg, ZBX_VARIANT_DBL))
1390 			{
1391 				zbx_variant_clear(&arg);
1392 				*error = zbx_strdup(NULL, "invalid second parameter");
1393 				goto out;
1394 			}
1395 
1396 			seconds = arg.data.dbl;
1397 			zbx_variant_clear(&arg);
1398 		}
1399 		count = 0;
1400 	}
1401 
1402 	results = (zbx_vector_dbl_t *)zbx_malloc(NULL, sizeof(zbx_vector_dbl_t));
1403 	zbx_vector_dbl_create(results);
1404 
1405 	for (i = 0; i < data->itemids.values_num; i++)
1406 	{
1407 		DC_ITEM	*dcitem;
1408 
1409 		if (NULL == (dcitem = get_dcitem(&eval->dcitem_refs, data->itemids.values[i])))
1410 			continue;
1411 
1412 		if (ITEM_STATUS_ACTIVE != dcitem->status)
1413 			continue;
1414 
1415 		if (HOST_STATUS_MONITORED != dcitem->host.status)
1416 			continue;
1417 
1418 		if (ITEM_VALUE_TYPE_FLOAT != dcitem->value_type && ITEM_VALUE_TYPE_UINT64 != dcitem->value_type)
1419 			continue;
1420 
1421 		zbx_history_record_vector_create(&values);
1422 
1423 		if (SUCCEED == zbx_vc_get_values(dcitem->itemid, dcitem->value_type, &values, seconds, count, ts) &&
1424 				0 < values.values_num)
1425 		{
1426 			evaluate_history_func(&values, dcitem->value_type, item_func, &result);
1427 			zbx_vector_dbl_append(results, result);
1428 		}
1429 
1430 		zbx_history_record_vector_destroy(&values, dcitem->value_type);
1431 	}
1432 
1433 	if (0 == results->values_num)
1434 	{
1435 		zbx_vector_dbl_destroy(results);
1436 		zbx_free(results);
1437 
1438 		*error = zbx_strdup(NULL, "no data for query");
1439 		goto out;
1440 	}
1441 
1442 	zbx_variant_set_dbl_vector(value, results);
1443 
1444 	ret = SUCCEED;
1445 out:
1446 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s value:%s flags:%s", __func__, zbx_result_string(ret),
1447 			zbx_variant_value_desc(value), zbx_variant_type_desc(value));
1448 
1449 	return ret;
1450 }
1451 
1452 /******************************************************************************
1453  *                                                                            *
1454  * Function: expression_eval_history                                          *
1455  *                                                                            *
1456  * Purpose: evaluate historical function                                      *
1457  *                                                                            *
1458  * Parameters: name     - [IN] the function name (not zero terminated)        *
1459  *             len      - [IN] the function name length                       *
1460  *             args_num - [IN] the number of function arguments               *
1461  *             args     - [IN] an array of the function arguments.            *
1462  *             data     - [IN] the caller data used for function evaluation   *
1463  *             ts       - [IN] the function execution time                    *
1464  *             value    - [OUT] the function return value                     *
1465  *             error    - [OUT] the error message if function failed          *
1466  *                                                                            *
1467  * Return value: SUCCEED - the function was executed successfully             *
1468  *               FAIL    - otherwise                                          *
1469  *                                                                            *
1470  ******************************************************************************/
expression_eval_history(const char * name,size_t len,int args_num,const zbx_variant_t * args,void * data,const zbx_timespec_t * ts,zbx_variant_t * value,char ** error)1471 static int	expression_eval_history(const char *name, size_t len, int args_num, const zbx_variant_t *args,
1472 		void *data, const zbx_timespec_t *ts, zbx_variant_t *value, char **error)
1473 {
1474 	int			ret = FAIL;
1475 	zbx_expression_eval_t		*eval;
1476 	zbx_expression_query_t	*query;
1477 	char			*errmsg = NULL;
1478 
1479 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() function:%.*s", __func__, (int )len, name);
1480 
1481 	zbx_variant_set_none(value);
1482 
1483 	if (0 == args_num)
1484 	{
1485 		*error = zbx_strdup(NULL, "Cannot evaluate function: invalid number of arguments");
1486 		goto out;
1487 	}
1488 
1489 	if (len >= MAX_STRING_LEN)
1490 	{
1491 		*error = zbx_strdup(NULL, "Cannot evaluate function: name too long");
1492 		goto out;
1493 	}
1494 
1495 	eval = (zbx_expression_eval_t *)data;
1496 
1497 	/* the historical function item query argument is replaced with corresponding itemrefs index */
1498 	query = (zbx_expression_query_t *)eval->queries.values[(int) args[0].data.ui64];
1499 
1500 	if (ZBX_ITEM_QUERY_ERROR == query->flags)
1501 	{
1502 		*error = zbx_dsprintf(NULL, "Cannot evaluate function: %s", query->error);
1503 		goto out;
1504 	}
1505 
1506 	if (0 == (query->flags & ZBX_ITEM_QUERY_MANY))
1507 	{
1508 		ret = expression_eval_one(eval, query, name, len, args_num - 1, args + 1, ts, value, &errmsg);
1509 	}
1510 	else if (ZBX_EXPRESSION_AGGREGATE == eval->mode)
1511 	{
1512 		ret = expression_eval_many(eval, query, name, len, args_num - 1, args + 1, ts, value, &errmsg);
1513 	}
1514 	else
1515 	{
1516 		errmsg = zbx_strdup(NULL, "aggregate queries are not supported");
1517 		ret = FAIL;
1518 	}
1519 
1520 	if (SUCCEED != ret)
1521 	{
1522 		*error = zbx_dsprintf(NULL, "Cannot evaluate function: %s", errmsg);
1523 		zbx_free(errmsg);
1524 	}
1525 out:
1526 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s error:%s", __func__, zbx_result_string(ret),
1527 			ZBX_NULL2EMPTY_STR(*error));
1528 
1529 	return ret;
1530 }
1531 
1532 /******************************************************************************
1533  *                                                                            *
1534  * Function: expression_eval_common                                           *
1535  *                                                                            *
1536  * Purpose: evaluate common function                                          *
1537  *                                                                            *
1538  * Parameters: name     - [IN] the function name (not zero terminated)        *
1539  *             len      - [IN] the function name length                       *
1540  *             args_num - [IN] the number of function arguments               *
1541  *             args     - [IN] an array of the function arguments.            *
1542  *             data     - [IN] the caller data used for function evaluation   *
1543  *             ts       - [IN] the function execution time                    *
1544  *             value    - [OUT] the function return value                     *
1545  *             error    - [OUT] the error message if function failed          *
1546  *                                                                            *
1547  * Return value: SUCCEED - the function was executed successfully             *
1548  *               FAIL    - otherwise                                          *
1549  *                                                                            *
1550  * Comments: There are no custom common functions in expressions items, but   *
1551  *           it's used to check for /host/key query quoting errors instead.   *
1552  *                                                                            *
1553  ******************************************************************************/
expression_eval_common(const char * name,size_t len,int args_num,const zbx_variant_t * args,void * data,const zbx_timespec_t * ts,zbx_variant_t * value,char ** error)1554 static int	expression_eval_common(const char *name, size_t len, int args_num, const zbx_variant_t *args,
1555 		void *data, const zbx_timespec_t *ts, zbx_variant_t *value, char **error)
1556 {
1557 	ZBX_UNUSED(data);
1558 	ZBX_UNUSED(ts);
1559 	ZBX_UNUSED(value);
1560 
1561 	if (SUCCEED != zbx_is_trigger_function(name, len))
1562 	{
1563 		*error = zbx_strdup(NULL, "Cannot evaluate formula: unsupported function");
1564 		return FAIL;
1565 	}
1566 
1567 	if (0 == args_num)
1568 	{
1569 		*error = zbx_strdup(NULL, "Cannot evaluate function: invalid number of arguments");
1570 		return FAIL;
1571 	}
1572 
1573 	if (ZBX_VARIANT_STR == args[0].type)
1574 	{
1575 		zbx_item_query_t query;
1576 
1577 		if (0 != zbx_eval_parse_query(args[0].data.str, strlen(args[0].data.str), &query))
1578 		{
1579 			zbx_eval_clear_query(&query);
1580 			*error = zbx_strdup(NULL, "Cannot evaluate function: quoted item query argument");
1581 			return FAIL;
1582 		}
1583 	}
1584 
1585 	*error = zbx_strdup(NULL, "Cannot evaluate function: invalid first argument");
1586 	return FAIL;
1587 }
1588 
1589 /******************************************************************************
1590  *                                                                            *
1591  * Function: expression_eval_init                                             *
1592  *                                                                            *
1593  * Purpose: initialize expression evaluation data                             *
1594  *                                                                            *
1595  * Parameters: eval     - [IN] the evaluation data                            *
1596  *             mode     - [IN] ZBX_EXPRESSION_NORMAL - support only single    *
1597  *                             item queries                                   *
1598  *                             ZBX_EXPRESSION_AGGREGATE - support aggregate   *
1599  *                             item queries                                   *
1600  *             ctx      - [IN] the parsed expression                          *
1601  *                                                                            *
1602  ******************************************************************************/
zbx_expression_eval_init(zbx_expression_eval_t * eval,int mode,zbx_eval_context_t * ctx)1603 void	zbx_expression_eval_init(zbx_expression_eval_t *eval, int mode, zbx_eval_context_t *ctx)
1604 {
1605 	int			i;
1606 	zbx_expression_query_t	*query;
1607 	zbx_vector_str_t	filters;
1608 
1609 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1610 
1611 	zbx_vector_str_create(&filters);
1612 	zbx_eval_extract_item_refs(ctx, &filters);
1613 
1614 	zbx_vector_ptr_create(&eval->queries);
1615 	zbx_vector_ptr_create(&eval->groups);
1616 	zbx_vector_ptr_create(&eval->itemtags);
1617 	zbx_vector_ptr_create(&eval->dcitem_refs);
1618 
1619 	eval->ctx = ctx;
1620 	eval->mode = mode;
1621 	eval->one_num = 0;
1622 	eval->many_num = 0;
1623 	eval->dcitems_num = 0;
1624 	eval->hostid = 0;
1625 
1626 	for (i = 0; i < filters.values_num; i++)
1627 	{
1628 		query = expression_create_query(filters.values[i]);
1629 		zbx_vector_ptr_append(&eval->queries, query);
1630 
1631 		if (ZBX_ITEM_QUERY_UNSET == query->flags)
1632 		{
1633 			query->error = zbx_strdup(NULL, "invalid item query filter");
1634 			query->flags = ZBX_ITEM_QUERY_ERROR;
1635 		}
1636 	}
1637 
1638 	zbx_vector_str_clear_ext(&filters, zbx_str_free);
1639 	zbx_vector_str_destroy(&filters);
1640 
1641 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1642 }
1643 
1644 /******************************************************************************
1645  *                                                                            *
1646  * Function: expression_eval_clear                                            *
1647  *                                                                            *
1648  * Purpose: free resources allocated by expression evaluation data            *
1649  *                                                                            *
1650  * Parameters: eval     - [IN] the evaluation data                            *
1651  *                                                                            *
1652  ******************************************************************************/
zbx_expression_eval_clear(zbx_expression_eval_t * eval)1653 void	zbx_expression_eval_clear(zbx_expression_eval_t *eval)
1654 {
1655 	if (0 != eval->one_num)
1656 	{
1657 		DCconfig_clean_items(eval->dcitems_hk, eval->errcodes_hk, eval->one_num);
1658 		zbx_free(eval->dcitems_hk);
1659 		zbx_free(eval->errcodes_hk);
1660 		zbx_free(eval->hostkeys);
1661 	}
1662 
1663 	if (0 != eval->dcitems_num)
1664 	{
1665 		DCconfig_clean_items(eval->dcitems, eval->errcodes, eval->dcitems_num);
1666 		zbx_free(eval->dcitems);
1667 		zbx_free(eval->errcodes);
1668 	}
1669 
1670 	zbx_vector_ptr_destroy(&eval->dcitem_refs);
1671 
1672 	zbx_vector_ptr_clear_ext(&eval->itemtags, (zbx_clean_func_t) expression_item_free);
1673 	zbx_vector_ptr_destroy(&eval->itemtags);
1674 
1675 	zbx_vector_ptr_clear_ext(&eval->groups, (zbx_clean_func_t) expression_group_free);
1676 	zbx_vector_ptr_destroy(&eval->groups);
1677 
1678 	zbx_vector_ptr_clear_ext(&eval->queries, (zbx_clean_func_t) expression_query_free);
1679 	zbx_vector_ptr_destroy(&eval->queries);
1680 }
1681 
1682 /******************************************************************************
1683  *                                                                            *
1684  * Function: zbx_expression_eval_resolve_item_hosts                           *
1685  *                                                                            *
1686  * Purpose: resolve calculated item formula empty and macro host references   *
1687  *          (// , {HOST.HOST}) to host names                                  *
1688  *                                                                            *
1689  * Parameters: eval - [IN] the evaluation data                                *
1690  *             item - [IN] the calculated item                                *
1691  *                                                                            *
1692  ******************************************************************************/
zbx_expression_eval_resolve_item_hosts(zbx_expression_eval_t * eval,const DC_ITEM * item)1693 void	zbx_expression_eval_resolve_item_hosts(zbx_expression_eval_t *eval, const DC_ITEM *item)
1694 {
1695 	int	i;
1696 
1697 	eval->hostid = item->host.hostid;
1698 
1699 	for (i = 0; i < eval->queries.values_num; i++)
1700 	{
1701 		zbx_expression_query_t	*query = (zbx_expression_query_t *)eval->queries.values[i];
1702 
1703 		if (0 != (ZBX_ITEM_QUERY_HOST_SELF & query->flags) || 0 == strcmp(query->ref.host, "{HOST.HOST}"))
1704 			query->ref.host = zbx_strdup(query->ref.host, item->host.host);
1705 	}
1706 }
1707 
1708 typedef struct
1709 {
1710 	int	num;
1711 	char	*host;
1712 }
1713 zbx_host_index_t;
1714 
1715 
host_index_compare(const void * d1,const void * d2)1716 static int	host_index_compare(const void *d1, const void *d2)
1717 {
1718 	const int	*i1 = *(const int **)d1;
1719 	const int	*i2 = *(const int **)d2;
1720 
1721 	return *i1 - *i2;
1722 }
1723 
host_index_free(zbx_host_index_t * index)1724 static void	host_index_free(zbx_host_index_t *index)
1725 {
1726 	zbx_free(index->host);
1727 	zbx_free(index);
1728 }
1729 
1730 /******************************************************************************
1731  *                                                                            *
1732  * Function: zbx_expression_eval_resolve_trigger_hosts                        *
1733  *                                                                            *
1734  * Purpose: resolve expression macro empty and macro host references          *
1735  *          (// , {HOST.HOST}, {HOST.HOST<N>}) to  host names                 *
1736  *                                                                            *
1737  * Parameters: eval    - [IN] the evaluation data                             *
1738  *             trigger - [IN] the calculated item                             *
1739  *                                                                            *
1740  ******************************************************************************/
zbx_expression_eval_resolve_trigger_hosts(zbx_expression_eval_t * eval,const DB_TRIGGER * trigger)1741 void	zbx_expression_eval_resolve_trigger_hosts(zbx_expression_eval_t *eval, const DB_TRIGGER *trigger)
1742 {
1743 	int			i, func_num, index;
1744 	zbx_vector_ptr_t	hosts;
1745 	zbx_host_index_t	*hi;
1746 
1747 	zbx_vector_ptr_create(&hosts);
1748 
1749 	for (i = 0; i < eval->queries.values_num; i++)
1750 	{
1751 		zbx_expression_query_t	*query = (zbx_expression_query_t *)eval->queries.values[i];
1752 
1753 		if (0 != (ZBX_ITEM_QUERY_HOST_ONE & query->flags))
1754 			func_num = zbx_host_macro_index(query->ref.host);
1755 		else if (0 != (ZBX_ITEM_QUERY_HOST_SELF & query->flags))
1756 			func_num = 1;
1757 		else
1758 			func_num = -1;
1759 
1760 		if (-1 == func_num)
1761 			continue;
1762 
1763 		if (FAIL == (index = zbx_vector_ptr_search(&hosts, &func_num, host_index_compare)))
1764 		{
1765 			hi = (zbx_host_index_t *)zbx_malloc(NULL, sizeof(zbx_host_index_t));
1766 			hi->num = func_num;
1767 			hi->host = NULL;
1768 			DBget_trigger_value(trigger, &hi->host, func_num, ZBX_REQUEST_HOST_HOST);
1769 			zbx_vector_ptr_append(&hosts, hi);
1770 		}
1771 		else
1772 			hi = (zbx_host_index_t *)hosts.values[index];
1773 
1774 		if (NULL != hi->host)
1775 		{
1776 			query->ref.host = zbx_strdup(query->ref.host, hi->host);
1777 		}
1778 		else
1779 		{
1780 			query->error = zbx_dsprintf(NULL, "invalid host \"%s\"", ZBX_NULL2EMPTY_STR(query->ref.host));
1781 			query->flags = ZBX_ITEM_QUERY_ERROR;
1782 		}
1783 	}
1784 
1785 	zbx_vector_ptr_clear_ext(&hosts, (zbx_clean_func_t)host_index_free);
1786 	zbx_vector_ptr_destroy(&hosts);
1787 }
1788 
1789 /******************************************************************************
1790  *                                                                            *
1791  * Function: zbx_expression_eval_execute                                      *
1792  *                                                                            *
1793  * Purpose: execute expression containing history functions                   *
1794  *                                                                            *
1795  * Parameters: eval  - [IN] the evaluation data                               *
1796  *             ts    - [IN] the calculated item                               *
1797  *             value - [OUT] the expression evaluation result                 *
1798  *             error - [OUT] the error message                                *
1799  *                                                                            *
1800  * Return value: SUCCEED - the expression was evaluated successfully.         *
1801  *               FAIL    - otherwise.                                         *
1802  *                                                                            *
1803  ******************************************************************************/
zbx_expression_eval_execute(zbx_expression_eval_t * eval,const zbx_timespec_t * ts,zbx_variant_t * value,char ** error)1804 int	zbx_expression_eval_execute(zbx_expression_eval_t *eval, const zbx_timespec_t *ts, zbx_variant_t *value,
1805 		char **error)
1806 {
1807 	int	i, ret;
1808 
1809 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1810 
1811 	if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG))
1812 	{
1813 		char	*expression = NULL;
1814 
1815 		zbx_eval_compose_expression(eval->ctx, &expression);
1816 		zabbix_log(LOG_LEVEL_DEBUG, "%s() expression:'%s'", __func__, expression);
1817 		zbx_free(expression);
1818 	}
1819 
1820 	for (i = 0; i < eval->queries.values_num; i++)
1821 	{
1822 		zbx_expression_query_t	*query = (zbx_expression_query_t *)eval->queries.values[i];
1823 
1824 		if (ZBX_ITEM_QUERY_ERROR != query->flags)
1825 		{
1826 			if (0 != (query->flags & ZBX_ITEM_QUERY_MANY))
1827 				expression_init_query_many(eval, query);
1828 			else
1829 				expression_init_query_one(eval, query);
1830 		}
1831 	}
1832 
1833 	/* cache items for functions using one item queries */
1834 	if (0 != eval->one_num)
1835 		expression_cache_dcitems_hk(eval);
1836 
1837 	/* cache items for functions using many item queries */
1838 	if (0 != eval->many_num)
1839 		expression_cache_dcitems(eval);
1840 
1841 	zbx_variant_set_none(value);
1842 
1843 	ret = zbx_eval_execute_ext(eval->ctx, ts, expression_eval_common, expression_eval_history, (void *)eval, value,
1844 			error);
1845 
1846 	zbx_vc_flush_stats();
1847 
1848 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s value:%s error:%s", __func__, zbx_result_string(ret),
1849 			zbx_variant_value_desc(value), ZBX_NULL2EMPTY_STR(*error));
1850 
1851 	return ret;
1852 }
1853