forked from move-coop/parsons
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DBSync: Create Table from DDL (move-coop#492)
* dbsync: add retries and configurable chunking This commit makes a few fixes to the Parsons DBSync class to improve the performance and stability of the functionality. * Add a `retries` argument to the `DBSync` class to configure the number of times the sync will retry reading / writing data if there is a failure. This should make the sync process less brittle. * Add `read_chunk_size` and `write_chunk_size` arguments to the `DBSync` class to allow users to configure how much data is downloading from the source DB or written to the destination DB at a time. * Added a `strict_length` argument to the Redshift `copy_s3` and all DB `copy` functions that allows users to opt out or into of new functionality when creating tables to use a step function when determining what length to specify on a `varchar` column. * PR comments * Initial poc. * Add in doc strings and Redshift, MySQL. * Lint + Requirements. * Skeleton tests. * Lint. * Lint. Co-authored-by: Eliot Stone <[email protected]>
- Loading branch information
Showing
7 changed files
with
109 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
from sqlalchemy import create_engine, Table, MetaData | ||
import logging | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class Alchemy: | ||
|
||
def generate_engine(self): | ||
""" | ||
Generate a SQL Alchemy engine. | ||
""" | ||
|
||
alchemy_url = self.generate_alchemy_url() | ||
return create_engine(alchemy_url, echo=False, convert_unicode=True) | ||
|
||
def generate_alchemy_url(self): | ||
""" | ||
Generate a SQL Alchemy engine | ||
https://docs.sqlalchemy.org/en/14/core/engines.html# | ||
""" | ||
|
||
if self.dialect == 'redshift' or self.dialect == 'postgres': | ||
connection_schema = 'postgresql+psycopg2' | ||
elif self.dialect == 'mysql': | ||
connection_schema = 'mysql+mysqlconnector' | ||
|
||
params = [(self.username, self.username), | ||
(self.password, f':{self.password}'), | ||
(self.host, f'@{self.host}'), | ||
(self.port, f':{self.port}'), | ||
(self.db, f'/{self.db}')] | ||
|
||
url = f'{connection_schema}://' | ||
|
||
for i in params: | ||
if i[0]: | ||
url += i[1] | ||
|
||
return url | ||
|
||
def get_table_object(self, table_name): | ||
""" | ||
Get a SQL Alchemy table object. | ||
""" | ||
|
||
schema, table_name = self.split_table_name(table_name) | ||
db_meta = MetaData(bind=self.generate_engine(), schema=schema) | ||
return Table(table_name, db_meta, autoload=True) | ||
|
||
def create_table(self, table_object, table_name): | ||
""" | ||
Create a table based on table object data. | ||
""" | ||
|
||
schema, table_name = self.split_table_name(table_name) | ||
|
||
if schema: | ||
table_object.schema = schema | ||
if table_name: | ||
table_object.table_name = table_name | ||
|
||
table_object.metadata.create_all(self.generate_engine()) | ||
|
||
@staticmethod | ||
def split_table_name(full_table_name): | ||
""" | ||
Utility method to parse the schema and table name. | ||
""" | ||
|
||
if "." not in full_table_name: | ||
return "public", full_table_name | ||
|
||
try: | ||
schema, table = full_table_name.split(".") | ||
except ValueError as e: | ||
if "too many values to unpack" in str(e): | ||
raise ValueError(f"Invalid database table {full_table_name}") | ||
|
||
return schema, table |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters