Source code for airflow.providers.google.cloud.transfers.postgres_to_gcs
## Licensed to the Apache Software Foundation (ASF) under one# or more contributor license agreements. See the NOTICE file# distributed with this work for additional information# regarding copyright ownership. The ASF licenses this file# to you under the Apache License, Version 2.0 (the# "License"); you may not use this file except in compliance# with the License. You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing,# software distributed under the License is distributed on an# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY# KIND, either express or implied. See the License for the# specific language governing permissions and limitations# under the License."""PostgreSQL to GCS operator."""importdatetimeimportjsonimporttimeimportuuidfromdecimalimportDecimalfromtypingimportDictimportpendulumfromairflow.providers.google.cloud.transfers.sql_to_gcsimportBaseSQLToGCSOperatorfromairflow.providers.postgres.hooks.postgresimportPostgresHookclass_PostgresServerSideCursorDecorator:""" Inspired by `_PrestoToGCSPrestoCursorAdapter` to keep this consistent. Decorator for allowing description to be available for postgres cursor in case server side cursor is used. It doesn't provide other methods except those needed in BaseSQLToGCSOperator, which is more of a safety feature. """def__init__(self,cursor):self.cursor=cursorself.rows=[]self.initialized=Falsedef__iter__(self):returnselfdef__next__(self):ifself.rows:returnself.rows.pop()else:self.initialized=Truereturnnext(self.cursor)@propertydefdescription(self):"""Fetch first row to initialize cursor description when using server side cursor."""ifnotself.initialized:element=self.cursor.fetchone()ifelementisnotNone:self.rows.append(element)self.initialized=Truereturnself.cursor.description
[docs]classPostgresToGCSOperator(BaseSQLToGCSOperator):""" Copy data from Postgres to Google Cloud Storage in JSON or CSV format. :param postgres_conn_id: Reference to a specific Postgres hook. :param use_server_side_cursor: If server-side cursor should be used for querying postgres. For detailed info, check https://www.psycopg.org/docs/usage.html#server-side-cursors :param cursor_itersize: How many records are fetched at a time in case of server-side cursor. """
[docs]defquery(self):"""Queries Postgres and returns a cursor to the results."""hook=PostgresHook(postgres_conn_id=self.postgres_conn_id)conn=hook.get_conn()cursor=conn.cursor(name=self._unique_name())cursor.execute(self.sql,self.parameters)ifself.use_server_side_cursor:cursor.itersize=self.cursor_itersizereturn_PostgresServerSideCursorDecorator(cursor)returncursor
[docs]defconvert_type(self,value,schema_type,stringify_dict=True):""" Takes a value from Postgres, and converts it to a value that's safe for JSON/Google Cloud Storage/BigQuery. Timezone aware Datetime are converted to UTC seconds. Unaware Datetime, Date and Time are converted to ISO formatted strings. Decimals are converted to floats. :param value: Postgres column value. :param schema_type: BigQuery data type. :param stringify_dict: Specify whether to convert dict to string. """ifisinstance(value,datetime.datetime):iso_format_value=value.isoformat()ifvalue.tzinfoisNone:returniso_format_valuereturnpendulum.parse(iso_format_value).float_timestampifisinstance(value,datetime.date):returnvalue.isoformat()ifisinstance(value,datetime.time):formatted_time=time.strptime(str(value),"%H:%M:%S")time_delta=datetime.timedelta(hours=formatted_time.tm_hour,minutes=formatted_time.tm_min,seconds=formatted_time.tm_sec)returnstr(time_delta)ifstringify_dictandisinstance(value,dict):returnjson.dumps(value)ifisinstance(value,Decimal):returnfloat(value)returnvalue