code: def generate_sql_changes(self):
          
          from_keys = set(self.from_sql_graph.nodes.keys())
          to_keys = set(self.to_sql_graph.nodes.keys())
          new_keys = to_keys - from_keys
          delete_keys = from_keys - to_keys
          changed_keys = set()
          dep_changed_keys = []
  
          for key in from_keys & to_keys:
              old_node = self.from_sql_graph.nodes[key]
              new_node = self.to_sql_graph.nodes[key]
  
              # identify SQL changes -- these will alter database.
              if not is_sql_equal(old_node.sql, new_node.sql):
                  changed_keys.add(key)
  
              # identify dependencies change
              old_deps = self.from_sql_graph.dependencies[key]
              new_deps = self.to_sql_graph.dependencies[key]
              removed_deps = old_deps - new_deps
              added_deps = new_deps - old_deps
              if removed_deps or added_deps:
                  dep_changed_keys.append((key, removed_deps, added_deps))
  
          # we do basic sort here and inject dependency keys here.
          # operations built using these keys will properly set operation dependencies which will
          # enforce django to build/keep a correct order of operations (stable_topological_sort).
          keys = self.assemble_changes(new_keys, changed_keys, self.to_sql_graph)
          delete_keys = self.assemble_changes(delete_keys, set(), self.from_sql_graph)
  
          self._sql_operations = {}
          self._generate_reversed_sql(keys, changed_keys)
          self._generate_sql(keys, changed_keys)
          self._generate_delete_sql(delete_keys)
          self._generate_altered_sql_dependencies(dep_changed_keys)
docs: Starting point of this tool, which identifies changes and generates respective
          operations.