def _find_recursive_dependencies(sql, values, code, resolved_vars, resolving_vars=None):
    """ Recursive helper method for expanding variables including transitive dependencies.

    Placeholders in SQL are represented as $<name>. If '$' must appear within
    the SQL statement literally, then it can be escaped as '$$'.

    Args:
      sql: the raw SQL statement with named placeholders.
      values: the user-supplied dictionary of name/value pairs to use for placeholder values.
      code: an array of referenced UDFs found during expansion.
      resolved_vars: a ref parameter for the variable references completely resolved so far.
      resolving_vars: a ref parameter for the variable(s) we are currently resolving; if we see
          a dependency again that is in this set we know we have a circular reference.
    Returns:
      The formatted SQL statement with placeholders replaced with their values.
    Raises:
      Exception if a placeholder was found in the SQL statement, but did not
      have a corresponding argument value.
    """

    # Get the set of $var references in this SQL.
    dependencies = SqlStatement._get_dependencies(sql)
    for dependency in dependencies:
      # Now we check each dependency. If it is in complete - i.e., we have an expansion
      # for it already - we just continue.
      if dependency in resolved_vars:
        continue
      # Look it up in our resolution namespace dictionary.
      dep = datalab.utils.get_item(values, dependency)
      # If it is a SQL module, get the main/last query from the module, so users can refer
      # to $module. Useful especially if final query in module has no DEFINE QUERY <name> part.
      if isinstance(dep, types.ModuleType):
        dep = _utils.get_default_query_from_module(dep)
      # If we can't resolve the $name, give up.
      if dep is None:
        raise Exception("Unsatisfied dependency $%s" % dependency)
      # If it is a SqlStatement, it may have its own $ references in turn; check to make
      # sure we don't have circular references, and if not, recursively expand it and add
      # it to the set of complete dependencies.
      if isinstance(dep, SqlStatement):
        if resolving_vars is None:
          resolving_vars = []
        elif dependency in resolving_vars:
          # Circular dependency
          raise Exception("Circular dependency in $%s" % dependency)
        resolving_vars.append(dependency)
        SqlStatement._find_recursive_dependencies(dep._sql, values, code, resolved_vars,
                                                  resolving_vars)
        resolving_vars.pop()
        resolved_vars[dependency] = SqlStatement(dep._sql)
      else:
        resolved_vars[dependency] = dep