def restore_from_clause(sql_spans, fk_relations):
  """Restores fully-specified FROM clause.

  Args:
    sql_spans: List of SqlSpan tuples with underspecified FROM clause(s).
    fk_relations: List of ForiegnKeyRelation tuples for given schema.

  Returns:
    List of SqlSpan tuples with fully specified FROM clause(s).
  Raises:
    ParseError: If cannot find path between mentioned tables or other parsing
        error.
  """
  # Sort the list to avoid non-determinism.
  table_names = sorted(list(_get_all_table_names(sql_spans)))
  has_nested_from_clause = _has_nested_from_clause(sql_spans)
  restored_sql_spans = []
  in_from_clause = False
  for sql_span in sql_spans:
    if sql_span.nested_statement:
      restored_sql_spans.append(
          make_sql_span(
              nested_statement=restore_from_clause(sql_span.nested_statement,
                                                   fk_relations)))
      continue

    if in_from_clause:
      if not sql_span.table_name:
        in_from_clause = False
    else:
      if sql_span.sql_token and sql_span.sql_token == FROM_CLAUSE_PLACEHOLDER:
        restored_sql_spans.append(make_sql_span(sql_token='from'))
        if not has_nested_from_clause:
          restored_sql_spans.extend(
              _get_from_clause_for_tables(table_names, fk_relations))
          in_from_clause = True
        continue

    if not in_from_clause:
      restored_sql_spans.append(sql_span)
  return restored_sql_spans
Restores fully-specified FROM clause.

  Args:
    sql_spans: List of SqlSpan tuples with underspecified FROM clause(s).
    fk_relations: List of ForiegnKeyRelation tuples for given schema.

  Returns:
    List of SqlSpan tuples with fully specified FROM clause(s).
  Raises:
    ParseError: If cannot find path between mentioned tables or other parsing
        error.
  
language/xsp/data_preprocessing/abstract_sql.py