"""Gestion de routines (UDFs y stored procedures) en Google BigQuery.""" from .client import BQClient from google.cloud import bigquery def bq_create_routine( client: BQClient, dataset_id: str, routine_id: str, body: str, routine_type: str = "SCALAR_FUNCTION", language: str = "SQL", arguments: list[dict] | None = None, return_type: str = "", description: str = "", ) -> dict: """Crea una routine (UDF o stored procedure) en BigQuery. Args: client: Cliente autenticado. dataset_id: ID del dataset donde crear la routine. routine_id: ID/nombre de la routine. body: Cuerpo de la routine (SQL, JavaScript o Python). routine_type: Tipo: "SCALAR_FUNCTION", "TABLE_VALUED_FUNCTION", "PROCEDURE". language: Lenguaje: "SQL", "JAVASCRIPT", "PYTHON". arguments: Lista de argumentos, cada uno: {"name": "x", "data_type": "STRING"}. return_type: Tipo de retorno para funciones (ej: "STRING", "INT64"). No aplica a procedures. description: Descripcion opcional. Returns: Dict con: routine_id, dataset_id, project, routine_type, language, body, created, modified. Raises: google.api_core.exceptions.Conflict: Si la routine ya existe. Example: >>> bq_create_routine(client, "analytics", "double_value", ... body="x * 2", ... arguments=[{"name": "x", "data_type": "INT64"}], ... return_type="INT64") """ ref = bigquery.RoutineReference.from_string( f"{client.project_id}.{dataset_id}.{routine_id}" ) routine = bigquery.Routine(ref) routine.type_ = routine_type routine.language = language routine.body = body if description: routine.description = description if arguments: routine.arguments = [ bigquery.RoutineArgument( name=arg["name"], data_type=bigquery.StandardSqlDataType( type_kind=getattr( bigquery.StandardSqlTypeNames, arg["data_type"] ) ), ) for arg in arguments ] if return_type: routine.return_type = bigquery.StandardSqlDataType( type_kind=getattr(bigquery.StandardSqlTypeNames, return_type) ) created = client._client.create_routine(routine) return _routine_to_dict(created) def bq_list_routines(client: BQClient, dataset_id: str) -> list[dict]: """Lista routines de un dataset. Args: client: Cliente autenticado. dataset_id: ID del dataset. Returns: Lista de dicts con: routine_id, dataset_id, project, routine_type, language. Example: >>> routines = bq_list_routines(client, "analytics") >>> for r in routines: ... print(r["routine_id"], r["routine_type"], r["language"]) """ ref = f"{client.project_id}.{dataset_id}" return [ { "routine_id": r.routine_id, "dataset_id": dataset_id, "project": client.project_id, "routine_type": r.type_, "language": r.language, } for r in client._client.list_routines(ref) ] def bq_delete_routine( client: BQClient, dataset_id: str, routine_id: str, ) -> None: """Elimina una routine. Args: client: Cliente autenticado. dataset_id: ID del dataset. routine_id: ID de la routine a eliminar. Raises: google.api_core.exceptions.NotFound: Si la routine no existe. Example: >>> bq_delete_routine(client, "analytics", "double_value") """ ref = f"{client.project_id}.{dataset_id}.{routine_id}" client._client.delete_routine(ref) def _routine_to_dict(routine) -> dict: """Convierte un objeto Routine del SDK a dict plano.""" return { "routine_id": routine.routine_id, "dataset_id": routine.dataset_id, "project": routine.project, "routine_type": routine.type_, "language": routine.language, "body": routine.body, "description": routine.description or "", "created": routine.created.isoformat() if routine.created else None, "modified": routine.modified.isoformat() if routine.modified else None, }