static void add_valid_vertex_edges()

in src/backend/utils/adt/age_vle.c [1200:1342]


static void add_valid_vertex_edges(VLE_local_context *vlelctx,
                                   graphid vertex_id)
{
    ListGraphId *vertex_stack = NULL;
    ListGraphId *edge_stack = NULL;
    ListGraphId *edges = NULL;
    vertex_entry *ve = NULL;
    GraphIdNode *edge_in = NULL;
    GraphIdNode *edge_out = NULL;
    GraphIdNode *edge_self = NULL;

    /* get the vertex entry */
    ve = get_vertex_entry(vlelctx->ggctx, vertex_id);
    /* there better be a valid vertex */
    if (ve == NULL)
    {
        elog(ERROR, "add_valid_vertex_edges: no vertex found");
    }

    /* point to stacks */
    vertex_stack = vlelctx->dfs_vertex_stack;
    edge_stack = vlelctx->dfs_edge_stack;

    /* set to the first edge for each edge list for the specified direction */
    if (vlelctx->edge_direction == CYPHER_REL_DIR_RIGHT ||
        vlelctx->edge_direction == CYPHER_REL_DIR_NONE)
    {
        edges = get_vertex_entry_edges_out(ve);
        edge_out = (edges != NULL) ? get_list_head(edges) : NULL;
    }
    if (vlelctx->edge_direction == CYPHER_REL_DIR_LEFT ||
        vlelctx->edge_direction == CYPHER_REL_DIR_NONE)
    {
        edges = get_vertex_entry_edges_in(ve);
        edge_in = (edges != NULL) ? get_list_head(edges) : NULL;
    }
    /* set to the first selfloop edge */
    edges = get_vertex_entry_edges_self(ve);
    edge_self = (edges != NULL) ? get_list_head(edges) : NULL;

    /* add in valid vertex edges */
    while (edge_out != NULL || edge_in != NULL || edge_self != NULL)
    {
        edge_entry *ee = NULL;
        edge_state_entry *ese = NULL;
        graphid edge_id;

        /* get the edge_id from the next available edge*/
        if (edge_out != NULL)
        {
            edge_id = get_graphid(edge_out);
        }
        else if (edge_in != NULL)
        {
            edge_id = get_graphid(edge_in);
        }
        else
        {
            edge_id = get_graphid(edge_self);
        }

        /*
         * This is a fast existence check, relative to the hash search, for when
         * the path stack is small. If the edge is in the path, we skip it.
         */
        if (get_stack_size(vlelctx->dfs_path_stack) < 10 &&
            is_edge_in_path(vlelctx, edge_id))
        {
            /* set to the next available edge */
            if (edge_out != NULL)
            {
                edge_out = next_GraphIdNode(edge_out);
            }
            else if (edge_in != NULL)
            {
                edge_in = next_GraphIdNode(edge_in);
            }
            else
            {
                edge_self = next_GraphIdNode(edge_self);
            }
            continue;
        }

        /* get the edge entry */
        ee = get_edge_entry(vlelctx->ggctx, edge_id);
        /* it better exist */
        if (ee == NULL)
        {
            elog(ERROR, "add_valid_vertex_edges: no edge found");
        }
        /* get its state */
        ese = get_edge_state(vlelctx, edge_id);
        /*
         * Don't add any edges that we have already seen because they will
         * cause a loop to form.
         */
        if (!ese->used_in_path)
        {
            /* validate the edge if it hasn't been already */
            if (!ese->has_been_matched && is_an_edge_match(vlelctx, ee))
            {
                ese->has_been_matched = true;
                ese->matched = true;
            }
            else if (!ese->has_been_matched)
            {
                ese->has_been_matched = true;
                ese->matched = false;
            }
            /* if it is a match, add it */
            if (ese->has_been_matched && ese->matched)
            {
                /*
                 * We need to maintain our source vertex for each edge added
                 * if the edge_direction is CYPHER_REL_DIR_NONE. This is due
                 * to the edges having a fixed direction and the dfs
                 * algorithm working strictly through edges. With an
                 * un-directional VLE edge, you don't know the vertex that
                 * you just came from. So, we need to store it.
                 */
                 if (vlelctx->edge_direction == CYPHER_REL_DIR_NONE)
                 {
                     push_graphid_stack(vertex_stack, get_vertex_entry_id(ve));
                 }
                 push_graphid_stack(edge_stack, edge_id);
            }
        }
        /* get the next working edge */
        if (edge_out != NULL)
        {
            edge_out = next_GraphIdNode(edge_out);
        }
        else if (edge_in != NULL)
        {
            edge_in = next_GraphIdNode(edge_in);
        }
        else
        {
            edge_self = next_GraphIdNode(edge_self);
        }
    }
}