# Path: graphscale/kvetch/dbshard.py
# class KvetchDbShard(KvetchShard):
#     def __init__(self, *, pool: KvetchDbSingleConnectionPool) -> None:
#         self._pool = pool
# 
#     def create_safe_conn(
#         self
#     ) -> Any:  # ContextManager:  # should be context manager typing module imports it conditionally
#         return self._pool.create_safe_conn()
# 
#     async def gen_object(self, obj_id: UUID) -> KvetchData:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_get_object(conn, obj_id)
# 
#     async def gen_objects(self, ids: List[UUID]) -> Dict[UUID, KvetchData]:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_get_objects(conn, ids)
# 
#     async def gen_objects_of_type(self, type_id: int, after: UUID=None,
#                                   first: int=None) -> Dict[UUID, KvetchData]:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_get_objects_by_type(conn, type_id, after, first)
# 
#     async def gen_insert_index_entry(
#         self, index: IndexDefinition, index_value: Any, target_id: UUID
#     ) -> None:
#         attr = index.indexed_attr
#         with self.create_safe_conn() as conn:
#             _kv_shard_insert_index_entry(
#                 shard_conn=conn,
#                 index_name=index.index_name,
#                 index_column=attr,
#                 index_value=index_value,
#                 target_id=target_id,
#             )
# 
#     async def gen_delete_index_entry(
#         self, index: IndexDefinition, index_value: Any, target_id: UUID
#     ) -> None:
#         attr = index.indexed_attr
#         with self.create_safe_conn() as conn:
#             _kv_shard_delete_index_entry(
#                 shard_conn=conn,
#                 index_name=index.index_name,
#                 index_column=attr,
#                 index_value=index_value,
#                 target_id=target_id,
#             )
# 
#     async def gen_insert_edge(
#         self,
#         edge_definition: StoredIdEdgeDefinition,
#         from_id: UUID,
#         to_id: UUID,
#         data: KvetchData=None
#     ):
#         data = data or {}
#         with self.create_safe_conn() as conn:
#             _kv_shard_insert_edge(conn, edge_definition.edge_id, from_id, to_id, data)
# 
#     async def gen_insert_object(self, new_id: UUID, type_id: int, data: KvetchData) -> UUID:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_insert_object(conn, new_id, type_id, data)
# 
#     async def gen_insert_objects(self, new_ids: List[UUID], type_id: int,
#                                  datas: List[KvetchData]) -> List[UUID]:
#         with self.create_safe_conn() as conn:
#             _kv_shard_insert_objects(conn, new_ids, type_id, datas)
#         return new_ids
# 
#     async def gen_update_object(self, obj_id: UUID, data: KvetchData) -> None:
#         old_object = await self.gen_object(obj_id)
#         for key, val in data.items():
#             old_object[key] = val
#         with self.create_safe_conn() as conn:
#             _kv_shard_replace_object(conn, obj_id, old_object)
# 
#     async def gen_delete_object(self, obj_id: UUID) -> None:
#         with self.create_safe_conn() as conn:
#             _kv_shard_delete_object(conn, obj_id)
# 
#     async def gen_edges(
#         self,
#         edge_definition: StoredIdEdgeDefinition,
#         from_id: UUID,
#         after: UUID=None,
#         first: int=None
#     ) -> List[EdgeData]:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_get_edges(conn, edge_definition.edge_id, from_id, after, first)
# 
#     async def gen_edge_ids(
#         self,
#         edge_definition: StoredIdEdgeDefinition,
#         from_id: UUID,
#         after: UUID=None,
#         first: int=None
#     ) -> List[UUID]:
#         edges = await self.gen_edges(edge_definition, from_id, after, first)
#         return [edge.to_id for edge in edges]
# 
#     async def gen_index_entries(self, index: IndexDefinition, value: Any) -> List[IndexEntry]:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_get_index_entries(
#                 shard_conn=conn,
#                 index_name=index.index_name,
#                 index_column=index.indexed_attr,
#                 index_value=value
#             )
# 
# Path: graphscale/kvetch/kvetch.py
# class IndexDefinition(NamedTuple):
#     index_name: str
#     indexed_type: str
#     indexed_attr: str
#     index_type: IndexType
# 
# class IndexType(Enum):
#     STRING = auto()
#     INT = auto()


import contextlib
import pymysql
from typing import Iterator, List
from warnings import filterwarnings, resetwarnings
from .dbshard import KvetchDbShard
from .kvetch import IndexDefinition, IndexType




@contextlib.contextmanager
def disable_pymysql_warnings() -> Iterator:
    filterwarnings('ignore', category=pymysql.Warning)  # type: ignore
    yield
    resetwarnings()


def execute_ddl(shard: KvetchDbShard, ddl: str) -> str:
    with disable_pymysql_warnings():
        with shard.create_safe_conn() as conn:
            with conn.cursor() as cursor:
                cursor.execute(ddl)
    return ddl


def create_kvetch_objects_table_sql() -> str:
    return """CREATE TABLE IF NOT EXISTS kvetch_objects (
    row_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    obj_id BINARY(16) NOT NULL,
    type_id INT NOT NULL,
    created DATETIME NOT NULL,
    updated DATETIME NOT NULL,
    body MEDIUMBLOB,
    UNIQUE KEY (obj_id),
    UNIQUE KEY (type_id, obj_id),

# Path: graphscale/kvetch/dbshard.py
# class KvetchDbShard(KvetchShard):
#     def __init__(self, *, pool: KvetchDbSingleConnectionPool) -> None:
#         self._pool = pool
# 
#     def create_safe_conn(
#         self
#     ) -> Any:  # ContextManager:  # should be context manager typing module imports it conditionally
#         return self._pool.create_safe_conn()
# 
#     async def gen_object(self, obj_id: UUID) -> KvetchData:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_get_object(conn, obj_id)
# 
#     async def gen_objects(self, ids: List[UUID]) -> Dict[UUID, KvetchData]:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_get_objects(conn, ids)
# 
#     async def gen_objects_of_type(self, type_id: int, after: UUID=None,
#                                   first: int=None) -> Dict[UUID, KvetchData]:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_get_objects_by_type(conn, type_id, after, first)
# 
#     async def gen_insert_index_entry(
#         self, index: IndexDefinition, index_value: Any, target_id: UUID
#     ) -> None:
#         attr = index.indexed_attr
#         with self.create_safe_conn() as conn:
#             _kv_shard_insert_index_entry(
#                 shard_conn=conn,
#                 index_name=index.index_name,
#                 index_column=attr,
#                 index_value=index_value,
#                 target_id=target_id,
#             )
# 
#     async def gen_delete_index_entry(
#         self, index: IndexDefinition, index_value: Any, target_id: UUID
#     ) -> None:
#         attr = index.indexed_attr
#         with self.create_safe_conn() as conn:
#             _kv_shard_delete_index_entry(
#                 shard_conn=conn,
#                 index_name=index.index_name,
#                 index_column=attr,
#                 index_value=index_value,
#                 target_id=target_id,
#             )
# 
#     async def gen_insert_edge(
#         self,
#         edge_definition: StoredIdEdgeDefinition,
#         from_id: UUID,
#         to_id: UUID,
#         data: KvetchData=None
#     ):
#         data = data or {}
#         with self.create_safe_conn() as conn:
#             _kv_shard_insert_edge(conn, edge_definition.edge_id, from_id, to_id, data)
# 
#     async def gen_insert_object(self, new_id: UUID, type_id: int, data: KvetchData) -> UUID:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_insert_object(conn, new_id, type_id, data)
# 
#     async def gen_insert_objects(self, new_ids: List[UUID], type_id: int,
#                                  datas: List[KvetchData]) -> List[UUID]:
#         with self.create_safe_conn() as conn:
#             _kv_shard_insert_objects(conn, new_ids, type_id, datas)
#         return new_ids
# 
#     async def gen_update_object(self, obj_id: UUID, data: KvetchData) -> None:
#         old_object = await self.gen_object(obj_id)
#         for key, val in data.items():
#             old_object[key] = val
#         with self.create_safe_conn() as conn:
#             _kv_shard_replace_object(conn, obj_id, old_object)
# 
#     async def gen_delete_object(self, obj_id: UUID) -> None:
#         with self.create_safe_conn() as conn:
#             _kv_shard_delete_object(conn, obj_id)
# 
#     async def gen_edges(
#         self,
#         edge_definition: StoredIdEdgeDefinition,
#         from_id: UUID,
#         after: UUID=None,
#         first: int=None
#     ) -> List[EdgeData]:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_get_edges(conn, edge_definition.edge_id, from_id, after, first)
# 
#     async def gen_edge_ids(
#         self,
#         edge_definition: StoredIdEdgeDefinition,
#         from_id: UUID,
#         after: UUID=None,
#         first: int=None
#     ) -> List[UUID]:
#         edges = await self.gen_edges(edge_definition, from_id, after, first)
#         return [edge.to_id for edge in edges]
# 
#     async def gen_index_entries(self, index: IndexDefinition, value: Any) -> List[IndexEntry]:
#         with self.create_safe_conn() as conn:
#             return _kv_shard_get_index_entries(
#                 shard_conn=conn,
#                 index_name=index.index_name,
#                 index_column=index.indexed_attr,
#                 index_value=value
#             )
# 
# Path: graphscale/kvetch/kvetch.py
# class IndexDefinition(NamedTuple):
#     index_name: str
#     indexed_type: str
#     indexed_attr: str
#     index_type: IndexType
# 
# class IndexType(Enum):
#     STRING = auto()
#     INT = auto()


# Path: graphscale/kvetch/dbschema.py
import contextlib
import pymysql
from typing import Iterator, List
from warnings import filterwarnings, resetwarnings
from .dbshard import KvetchDbShard
from .kvetch import IndexDefinition, IndexType





@contextlib.contextmanager
def disable_pymysql_warnings() -> Iterator:
    filterwarnings('ignore', category=pymysql.Warning)  # type: ignore
    yield
    resetwarnings()


def execute_ddl(shard: KvetchDbShard, ddl: str) -> str:
    with disable_pymysql_warnings():
        with shard.create_safe_conn() as conn:
            with conn.cursor() as cursor:
                cursor.execute(ddl)
    return ddl


def create_kvetch_objects_table_sql() -> str:
    return """CREATE TABLE IF NOT EXISTS kvetch_objects (
    row_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    obj_id BINARY(16) NOT NULL,
    type_id INT NOT NULL,
    created DATETIME NOT NULL,
    updated DATETIME NOT NULL,
    body MEDIUMBLOB,
    UNIQUE KEY (obj_id),
    UNIQUE KEY (type_id, obj_id),

    KEY (updated)