# Path: simplesqlite/_common.py
# def extract_table_metadata(
#     con: "SimpleSQLite", table_name: str
# ) -> Tuple[Optional[str], List[str], Dict[str, TypeHint]]:
#     primary_key = None
#     index_attrs = []
#     type_hints = OrderedDict()
# 
#     for attr in con.schema_extractor.fetch_table_schema(table_name).as_dict()[table_name]:
#         attr_name = attr[SchemaHeader.ATTR_NAME]
# 
#         if attr[SchemaHeader.KEY] == "PRI":
#             primary_key = attr_name
#         elif attr[SchemaHeader.INDEX]:
#             index_attrs.append(attr_name)
# 
#         type_hints[attr_name] = _sqlitetype_to_typepy.get(attr[SchemaHeader.DATA_TYPE])
# 
#     return (primary_key, index_attrs, type_hints)
# 
# Path: simplesqlite/_validator.py
# def validate_sqlite_attr_name(name: str) -> None:
#     """
#     :param str name: Name to validate.
#     :raises pathvalidate.ValidationError:
#         - If the ``name`` includes unprintable character(s).
#         - |raises_sqlite_keywords|
#     """
# 
#     if not name:
#         raise ValidationError(["null name"], reason=ErrorReason.NULL_NAME)
# 
#     if __RE_INVALID_CHARS.search(name):
#         raise ValidationError(["unprintable character found"], reason=ErrorReason.INVALID_CHARACTER)
# 
#     name = name.upper()
# 
#     if name in __SQLITE_INVALID_RESERVED_KEYWORDS_ATTR:
#         raise ValidationError(
#             [f"'{name}' is a reserved keyword by sqlite"],
#             reason=ErrorReason.RESERVED_NAME,
#             reusable_name=False,
#         )
# 
#     if name in __SQLITE_VALID_RESERVED_KEYWORDS_ATTR:
#         raise ValidationError(
#             [f"'{name}' is a reserved keyword by sqlite"],
#             reason=ErrorReason.RESERVED_NAME,
#             reusable_name=True,
#         )
# 
# def validate_sqlite_table_name(name: str) -> None:
#     """
#     :param str name: Name to validate.
#     :raises pathvalidate.ValidationError:
#         - If the ``name`` includes unprintable character(s).
#         - |raises_sqlite_keywords|
#     """
# 
#     if not name:
#         raise ValidationError(["null name"], reason=ErrorReason.NULL_NAME)
# 
#     if __RE_INVALID_CHARS.search(name):
#         raise ValidationError(["unprintable character found"], reason=ErrorReason.INVALID_CHARACTER)
# 
#     name = name.upper()
# 
#     if name in __SQLITE_INVALID_RESERVED_KEYWORDS_TABLE:
#         raise ValidationError(
#             [f"'{name}' is a reserved keyword by sqlite"],
#             reason=ErrorReason.RESERVED_NAME,
#             reusable_name=False,
#         )
# 
#     if name in __SQLITE_VALID_RESERVED_KEYWORDS_TABLE:
#         raise ValidationError(
#             [f"'{name}' is a reserved keyword by sqlite"],
#             reason=ErrorReason.RESERVED_NAME,
#             reusable_name=True,
#         )
# 
# Path: simplesqlite/error.py
# class DatabaseError(sqlite3.DatabaseError):
# class NullDatabaseConnectionError(DatabaseError):
# class TableNotFoundError(DatabaseError):
# class AttributeNotFoundError(DatabaseError):
# class SqlSyntaxError(Exception):
# class OperationalError(sqlite3.OperationalError):
#     def message(self) -> Optional[str]:
#     def __init__(self, *args, **kwargs) -> None:


from textwrap import dedent
from typing import TYPE_CHECKING
from pathvalidate.error import ErrorReason, ValidationError
from ._common import extract_table_metadata
from ._logger import logger
from ._validator import validate_sqlite_attr_name, validate_sqlite_table_name
from .error import NameValidationError
    from simplesqlite import SimpleSQLite  # noqa
    :return: |True| if the copy operation succeed.
    :rtype: bool
    :raises simplesqlite.TableNotFoundError:
        |raises_verify_table_existence|
    :raises ValueError:
        If attributes of the table are different from each other.
    """

    logger.debug(
        "copy table: src={src_db}.{src_tbl}, dst={dst_db}.{dst_tbl}".format(
            src_db=src_con.database_path,
            src_tbl=src_table_name,
            dst_db=dst_con.database_path,
            dst_tbl=dst_table_name,
        )
    )

    src_con.verify_table_existence(src_table_name)
    dst_con.validate_access_permission(["w", "a"])

    if dst_con.has_table(dst_table_name):
        if is_overwrite:
            dst_con.drop_table(dst_table_name)
        else:
            logger.error(
                "failed to copy table: the table already exists "
                "(src_table={}, dst_table={})".format(src_table_name, dst_table_name)
            )
            return False


# Path: simplesqlite/_common.py
# def extract_table_metadata(
#     con: "SimpleSQLite", table_name: str
# ) -> Tuple[Optional[str], List[str], Dict[str, TypeHint]]:
#     primary_key = None
#     index_attrs = []
#     type_hints = OrderedDict()
# 
#     for attr in con.schema_extractor.fetch_table_schema(table_name).as_dict()[table_name]:
#         attr_name = attr[SchemaHeader.ATTR_NAME]
# 
#         if attr[SchemaHeader.KEY] == "PRI":
#             primary_key = attr_name
#         elif attr[SchemaHeader.INDEX]:
#             index_attrs.append(attr_name)
# 
#         type_hints[attr_name] = _sqlitetype_to_typepy.get(attr[SchemaHeader.DATA_TYPE])
# 
#     return (primary_key, index_attrs, type_hints)
# 
# Path: simplesqlite/_validator.py
# def validate_sqlite_attr_name(name: str) -> None:
#     """
#     :param str name: Name to validate.
#     :raises pathvalidate.ValidationError:
#         - If the ``name`` includes unprintable character(s).
#         - |raises_sqlite_keywords|
#     """
# 
#     if not name:
#         raise ValidationError(["null name"], reason=ErrorReason.NULL_NAME)
# 
#     if __RE_INVALID_CHARS.search(name):
#         raise ValidationError(["unprintable character found"], reason=ErrorReason.INVALID_CHARACTER)
# 
#     name = name.upper()
# 
#     if name in __SQLITE_INVALID_RESERVED_KEYWORDS_ATTR:
#         raise ValidationError(
#             [f"'{name}' is a reserved keyword by sqlite"],
#             reason=ErrorReason.RESERVED_NAME,
#             reusable_name=False,
#         )
# 
#     if name in __SQLITE_VALID_RESERVED_KEYWORDS_ATTR:
#         raise ValidationError(
#             [f"'{name}' is a reserved keyword by sqlite"],
#             reason=ErrorReason.RESERVED_NAME,
#             reusable_name=True,
#         )
# 
# def validate_sqlite_table_name(name: str) -> None:
#     """
#     :param str name: Name to validate.
#     :raises pathvalidate.ValidationError:
#         - If the ``name`` includes unprintable character(s).
#         - |raises_sqlite_keywords|
#     """
# 
#     if not name:
#         raise ValidationError(["null name"], reason=ErrorReason.NULL_NAME)
# 
#     if __RE_INVALID_CHARS.search(name):
#         raise ValidationError(["unprintable character found"], reason=ErrorReason.INVALID_CHARACTER)
# 
#     name = name.upper()
# 
#     if name in __SQLITE_INVALID_RESERVED_KEYWORDS_TABLE:
#         raise ValidationError(
#             [f"'{name}' is a reserved keyword by sqlite"],
#             reason=ErrorReason.RESERVED_NAME,
#             reusable_name=False,
#         )
# 
#     if name in __SQLITE_VALID_RESERVED_KEYWORDS_TABLE:
#         raise ValidationError(
#             [f"'{name}' is a reserved keyword by sqlite"],
#             reason=ErrorReason.RESERVED_NAME,
#             reusable_name=True,
#         )
# 
# Path: simplesqlite/error.py
# class DatabaseError(sqlite3.DatabaseError):
# class NullDatabaseConnectionError(DatabaseError):
# class TableNotFoundError(DatabaseError):
# class AttributeNotFoundError(DatabaseError):
# class SqlSyntaxError(Exception):
# class OperationalError(sqlite3.OperationalError):
#     def message(self) -> Optional[str]:
#     def __init__(self, *args, **kwargs) -> None:


# Path: simplesqlite/_func.py
from textwrap import dedent
from typing import TYPE_CHECKING
from pathvalidate.error import ErrorReason, ValidationError
from ._common import extract_table_metadata
from ._logger import logger
from ._validator import validate_sqlite_attr_name, validate_sqlite_table_name
from .error import NameValidationError
    from simplesqlite import SimpleSQLite  # noqa

    :return: |True| if the copy operation succeed.
    :rtype: bool
    :raises simplesqlite.TableNotFoundError:
        |raises_verify_table_existence|
    :raises ValueError:
        If attributes of the table are different from each other.
    """

    logger.debug(
        "copy table: src={src_db}.{src_tbl}, dst={dst_db}.{dst_tbl}".format(
            src_db=src_con.database_path,
            src_tbl=src_table_name,
            dst_db=dst_con.database_path,
            dst_tbl=dst_table_name,
        )
    )

    src_con.verify_table_existence(src_table_name)
    dst_con.validate_access_permission(["w", "a"])

    if dst_con.has_table(dst_table_name):
        if is_overwrite:
            dst_con.drop_table(dst_table_name)
        else:
            logger.error(
                "failed to copy table: the table already exists "
                "(src_table={}, dst_table={})".format(src_table_name, dst_table_name)
            )
            return False


    primary_key, index_attrs, _ = extract_table_metadata(src_con, src_table_name)