def create_index(
        self,
        columns: Iterable[Union[str, DescIndex]],
        index_name: Optional[str] = None,
        unique: bool = False,
        if_not_exists: bool = False,
        find_unique_name: bool = False,
        analyze: bool = False,
    ):
        """
        Create an index on this table.

        :param columns: A single columns or list of columns to index. These can be strings or,
          to create an index using the column in descending order, ``db.DescIndex(column_name)`` objects.
        :param index_name: The name to use for the new index. Defaults to the column names joined on ``_``.
        :param unique: Should the index be marked as unique, forcing unique values?
        :param if_not_exists: Only create the index if one with that name does not already exist.
        :param find_unique_name: If ``index_name`` is not provided and the automatically derived name
          already exists, keep incrementing a suffix number to find an available name.
        :param analyze: Run ``ANALYZE`` against this index after creating it.

        See :ref:`python_api_create_index`.
        """
        if index_name is None:
            index_name = "idx_{}_{}".format(
                self.name.replace(" ", "_"), "_".join(columns)
            )
        columns_sql = []
        for column in columns:
            if isinstance(column, DescIndex):
                fmt = "[{}] desc"
            else:
                fmt = "[{}]"
            columns_sql.append(fmt.format(column))

        suffix = None
        created_index_name = None
        while True:
            created_index_name = (
                "{}_{}".format(index_name, suffix) if suffix else index_name
            )
            sql = (
                textwrap.dedent(
                    """
                CREATE {unique}INDEX {if_not_exists}[{index_name}]
                    ON [{table_name}] ({columns});
            """
                )
                .strip()
                .format(
                    index_name=created_index_name,
                    table_name=self.name,
                    columns=", ".join(columns_sql),
                    unique="UNIQUE " if unique else "",
                    if_not_exists="IF NOT EXISTS " if if_not_exists else "",
                )
            )
            try:
                self.db.execute(sql)
                break
            except OperationalError as e:
                # find_unique_name=True - try again if 'index ... already exists'
                arg = e.args[0]
                if (
                    find_unique_name
                    and arg.startswith("index ")
                    and arg.endswith(" already exists")
                ):
                    if suffix is None:
                        suffix = 2
                    else:
                        suffix += 1
                    continue
                else:
                    raise e
        if analyze:
            self.db.analyze(created_index_name)
        return self

        Create an index on this table.

        :param columns: A single columns or list of columns to index. These can be strings or,
          to create an index using the column in descending order, ``db.DescIndex(column_name)`` objects.
        :param index_name: The name to use for the new index. Defaults to the column names joined on ``_``.
        :param unique: Should the index be marked as unique, forcing unique values?
        :param if_not_exists: Only create the index if one with that name does not already exist.
        :param find_unique_name: If ``index_name`` is not provided and the automatically derived name
          already exists, keep incrementing a suffix number to find an available name.
        :param analyze: Run ``ANALYZE`` against this index after creating it.

        See :ref:`python_api_create_index`.
        
sqlite_utils/db.py