def _get_fk_relations_linking_tables(table_names, fk_relations):
  """Returns (List of table names, List of (col name, col name))."""

  if not table_names:
    raise UnsupportedSqlError('The SQL query has not referenced any tables!')

  # Build map of (child table, parent table) to (child column, parent column).
  fk_relations_map = {}
  for relation in fk_relations:
    # TODO(petershaw): Consider adding warning if overwriting key.
    # This can lead to ambiguous conversions back to fully-specified SQL.
    fk_relations_map[(relation.child_table,
                      relation.parent_table)] = (relation.child_column,
                                                 relation.parent_column)
    # Also add the reverse.
    fk_relations_map[(relation.parent_table,
                      relation.child_table)] = (relation.parent_column,
                                                relation.child_column)
  # Greedily connect all tables using available foreign key relations.
  # Artbirary choose the first table_name to start.
  visited_tables = [table_names[0]]
  unvisited_tables = table_names[1:]
  fk_relations = []
  while unvisited_tables:
    fk_relation = _get_fk_relations_helper(unvisited_tables, visited_tables,
                                           fk_relations_map)
    if fk_relation:
      fk_relations.append(fk_relation)
    else:
      # TODO(petershaw): Handle case where not all tables are mentioned, i.e.
      # some tables need to be inferred to connect mentioned tables.
      raise UnsupportedSqlError(
          "Couldn't find path between tables %s given relations %s." %
          (table_names, fk_relations))
  # Length of fk_relations will be 1 shorter than visited tables.
  return visited_tables, fk_relations
Returns (List of table names, List of (col name, col name)).
language/xsp/data_preprocessing/abstract_sql.py