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);
}
}
}