def execute(self, context): self.log.info('Executing: %s', self.sql) hook = MsSqlHook(mssql_conn_id=self.mssql_conn_id, schema=self.database) hook.run(self.sql, autocommit=self.autocommit, parameters=self.parameters)
def execute_from_file(connection_name, query): try: logging.info('Executing: ' + str(query)) hook = MsSqlHook(mssql_conn_id=connection_name) hook.run(str(query)) except Exception as e: raise AirflowException(e)
def execute(self, context): _log.info('Executing: ' + str(self.sql)) hook = MsSqlHook(mssql_conn_id=self.mssql_conn_id) hook.run(self.sql, autocommit=self.autocommit, parameters=self.parameters)
def execute(self, context): logging.info('Executing: ' + str(self.sql)) hook = MsSqlHook(mssql_conn_id=self.mssql_conn_id) hook.run(self.sql, parameters=self.parameters)
def sync_db_2_db(source_conn_id: str, destination_conn_id: str, table: str, date_column: str, key_column: str, source_schema: str, destination_schema: str, increment_schema: str, sync_exclusions: bool = False, source_exc_schema: str = None, source_exc_table: str = None, source_exc_column: str = None, chunksize: int = 1000) -> None: """ Realiza a atualização incremental de uma tabela. A sincronização é realizada em 3 etapas. 1-Envia s alterações necessárias para uma tabela intermediária localizada no esquema `increment_schema`. 2-Realiza os Updates. 3-Realiza os Insertes. Apenas as colunas que existam na tabela no BD destino serão sincronizadas. Funciona com Postgres na origem e MsSql no destino. O algoritmo também realiza sincronização de exclusões. Exemplo: sync_db_2_db(source_conn_id=SOURCE_CONN_ID, destination_conn_id=DEST_CONN_ID, table=table, date_column=date_column, key_column=key_column, source_schema=SOURCE_SCHEMA, destination_schema=STG_SCHEMA, chunksize=CHUNK_SIZE) Args: source_conn_id (str): string de conexão airflow do DB origem destination_conn_id (str): string de conexão airflow do DB destino table (str): tabela a ser sincronizada date_column (str): nome da coluna a ser utilizado para identificação dos registros atualizados na origem. key_column (str): nome da coluna a ser utilizado como chave na etapa de atualização dos registros antigos que sofreram atualizações na origem. source_eschema (str): esquema do BD na origem destination_schema (str): esquema do BD no destino increment_schema (str): Esquema no banco utilizado para tabelas temporárias. Caso esta variável seja None, esta tabela será criada no mesmo schema com sufixo '_alteracoes' sync_exclusions (bool): opção de sincronizar exclusões. Default = False. source_exc_schema (str): esquema da tabela na origem onde estão registradas exclusões source_exc_table (str): tabela na origem onde estão registradas exclusões source_exc_column (str): coluna na tabela na origem onde estão registradas exclusões chunksize (int): tamanho do bloco de leitura na origem. Default = 1000 linhas Return: None Todo: * Automatizar a criação da tabela gêmea e remoção ao final * Transformar em Airflow Operator * Possibilitar ler de MsSql e escrever em Postgres * Possibilitar inserir data da carga na tabela de destino * Criar testes """ source_table_name = f"{source_schema}.{table}" dest_table_name = f"{destination_schema}.{table}" if increment_schema: inc_table_name = f"{increment_schema}.{table}" else: inc_table_name = f"{destination_schema}.{table}_alteracoes" source_hook = PostgresHook(postgres_conn_id=source_conn_id, autocommit=True) dest_hook = MsSqlHook(mssql_conn_id=destination_conn_id, autocommit=True) col_list = get_table_cols_name(destination_conn_id, destination_schema, table) dest_rows_count = _table_rows_count(dest_hook, dest_table_name) print(f"Total de linhas atualmente na tabela destino: {dest_rows_count}.") # If de tabela vazia separado para evitar erro na _build_filter_condition() if dest_rows_count == 0: raise Exception("Tabela destino vazia! Utilize carga full!") ref_value, where_condition = _build_filter_condition( dest_hook, dest_table_name, date_column, key_column) new_rows_count = _table_rows_count(source_hook, source_table_name, where_condition) print(f"Total de linhas novas ou modificadas: {new_rows_count}.") worth_increment = (new_rows_count / dest_rows_count) < 0.3 if not worth_increment: raise Exception("Muitas linhas a inserir! Utilize carga full!") # Guarda as alterações e inclusões necessárias select_sql = build_select_sql(f"{source_table_name}", col_list) select_diff = f"{select_sql} WHERE {where_condition}" print(f"SELECT para espelhamento: {select_diff}") copy_db_to_db(destination_table=f"{inc_table_name}", source_conn_id=source_conn_id, source_provider='PG', destination_conn_id=destination_conn_id, destination_provider='MSSQL', source_table=None, select_sql=select_diff, destination_truncate=True, chunksize=chunksize) # Reconstrói índices sql = f"ALTER INDEX ALL ON {inc_table_name} REBUILD" dest_hook.run(sql) print(f"Iniciando carga incremental na tabela {dest_table_name}.") updates_sql, inserts_sql = _build_incremental_sqls( dest_table=f"{dest_table_name}", source_table=f"{inc_table_name}", key_column=key_column, column_list=col_list) # Realiza updates dest_hook.run(updates_sql) # Realiza inserts de novas linhas dest_hook.run(inserts_sql) # Se precisar aplicar as exclusões da origem no destino: if sync_exclusions: source_exc_sql = f"""SELECT {key_column} FROM {source_exc_schema}.{source_exc_table} WHERE {source_exc_column} > '{ref_value}' """ rows = source_hook.get_records(source_exc_sql) ids_to_del = [row[0] for row in rows] if ids_to_del: ids = ", ".join(str(id) for id in ids_to_del) sql = f""" DELETE FROM {dest_table_name} WHERE {key_column} IN ({ids}) """ dest_hook.run(sql) print("Quantidade de linhas possivelmente excluídas:", len(ids_to_del))