diff options
| author | Christian Hopps <chopps@labn.net> | 2024-01-06 09:45:29 +0000 |
|---|---|---|
| committer | Christian Hopps <chopps@labn.net> | 2024-01-07 15:17:30 +0000 |
| commit | cf67a7e26577b0dda276324b40a602ae084e504e (patch) | |
| tree | 7019c29239c15d507736b2330ead23774d636481 /lib/northbound_oper.c | |
| parent | 00138ffb47acc58a49e93a9b291a4b9e0c92096e (diff) | |
lib: mgmtd: implement full XPath 1.0 predicate functionality
Allow user to specify full YANG compatible XPath 1.0 predicates. This
allows for trimming results of generic queries using functions and other
non-key predicates from XPath 1.0
Signed-off-by: Christian Hopps <chopps@labn.net>
Diffstat (limited to 'lib/northbound_oper.c')
| -rw-r--r-- | lib/northbound_oper.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/lib/northbound_oper.c b/lib/northbound_oper.c index bd6d870ebc..4e131154e7 100644 --- a/lib/northbound_oper.c +++ b/lib/northbound_oper.c @@ -72,6 +72,7 @@ struct nb_op_node_info { * @schema_path: the schema nodes for each node in the query string. # @query_tokstr: the query string tokenized with NUL bytes. * @query_tokens: the string pointers to each query token (node). + * @non_specific_predicate: tracks if a query_token is non-specific predicate. * @walk_root_level: The topmost specific node, +1 is where we start walking. * @walk_start_level: @walk_root_level + 1. * @query_base_level: the level the query string stops at and full walks @@ -85,6 +86,7 @@ struct nb_op_yield_state { const struct lysc_node **schema_path; char *query_tokstr; char **query_tokens; + uint8_t *non_specific_predicate; int walk_root_level; int walk_start_level; int query_base_level; @@ -158,6 +160,7 @@ static inline void nb_op_free_yield_state(struct nb_op_yield_state *ys, if (!nofree_tree && ys_root_node(ys)) lyd_free_all(ys_root_node(ys)); darr_free(ys->query_tokens); + darr_free(ys->non_specific_predicate); darr_free(ys->query_tokstr); darr_free(ys->schema_path); darr_free(ys->node_infos); @@ -1142,18 +1145,23 @@ static enum nb_error __walk(struct nb_op_yield_state *ys, bool is_resume) is_specific_node = false; if (list_start && at_clevel <= darr_lasti(ys->query_tokens) && + !ys->non_specific_predicate[at_clevel] && nb_op_schema_path_has_predicate(ys, at_clevel)) { err = lyd_new_path(&pni->inner->node, NULL, ys->query_tokens[at_clevel], NULL, 0, &node); if (!err) - /* predicate resolved to specific node */ is_specific_node = true; + else if (err == LY_EVALID) + ys->non_specific_predicate[at_clevel] = true; else { - flog_warn(EC_LIB_NB_OPERATIONAL_DATA, - "%s: unable to create node for specific query string: %s", + flog_err(EC_LIB_NB_OPERATIONAL_DATA, + "%s: unable to create node for specific query string: %s: %s", __func__, - ys->query_tokens[at_clevel]); + ys->query_tokens[at_clevel], + yang_ly_strerrcode(err)); + ret = NB_ERR; + goto done; } } @@ -1570,6 +1578,7 @@ static enum nb_error nb_op_yield(struct nb_op_yield_state *ys) static enum nb_error nb_op_ys_init_schema_path(struct nb_op_yield_state *ys, struct nb_node **last) { + struct nb_node **nb_nodes = NULL; const struct lysc_node *sn; struct nb_node *nblast; char *s, *s2; @@ -1588,6 +1597,11 @@ static enum nb_error nb_op_ys_init_schema_path(struct nb_op_yield_state *ys, */ nblast = nb_node_find(ys->xpath); if (!nblast) { + nb_nodes = nb_nodes_find(ys->xpath); + nblast = darr_len(nb_nodes) ? nb_nodes[0] : NULL; + darr_free(nb_nodes); + } + if (!nblast) { flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, ys->xpath); return NB_ERR; @@ -1614,6 +1628,7 @@ static enum nb_error nb_op_ys_init_schema_path(struct nb_op_yield_state *ys, /* create our arrays */ darr_append_n(ys->schema_path, count); darr_append_n(ys->query_tokens, count); + darr_append_nz(ys->non_specific_predicate, count); for (sn = nblast->snode; sn; sn = sn->parent) ys->schema_path[--count] = sn; @@ -1675,6 +1690,7 @@ error: darr_free(ys->query_tokstr); darr_free(ys->schema_path); darr_free(ys->query_tokens); + darr_free(ys->non_specific_predicate); return NB_ERR; } |
