33import logging
44from modules .ColumnTypeResolver import ColumnTypeResolver
55
6- from sqlalchemy import MetaData , DateTime , Boolean
6+ from sqlalchemy import MetaData , DateTime , Boolean , BigInteger
77from sqlalchemy .schema import Column , Table
88from sqlalchemy .sql import func
99
1010
1111class DestinationTableManager (object ):
1212 TIMESTAMP_COLUMN_NAME = "data_pipeline_timestamp"
1313 IS_DELETED_COLUMN_NAME = "data_pipeline_is_deleted"
14+ CHANGE_VERSION_COLUMN_NAME = "data_pipeline_change_version"
15+ NEXT_CHANGE_MINIMUM_VERSION_COLUMN_NAME = "data_pipeline_next_change_minimum_version"
1416
1517 def __init__ (self , target_engine , logger = None ):
1618 self .logger = logger or logging .getLogger (__name__ )
@@ -52,9 +54,11 @@ def create_table(self, schema_name, table_name, columns_configuration, drop_firs
5254 table .append_column (
5355 Column (self .IS_DELETED_COLUMN_NAME , Boolean , server_default = 'f' , default = False ))
5456
57+ table .append_column (
58+ Column (self .CHANGE_VERSION_COLUMN_NAME , BigInteger ))
5559
56-
57-
60+ table . append_column (
61+ Column ( self . NEXT_CHANGE_MINIMUM_VERSION_COLUMN_NAME , BigInteger ))
5862
5963 if drop_first :
6064 self .logger .debug (
@@ -63,16 +67,29 @@ def create_table(self, schema_name, table_name, columns_configuration, drop_firs
6367 self .logger .debug (
6468 "Dropped table {0}.{1}" .format (schema_name , table_name ))
6569
70+
6671 self .logger .debug ("Creating table {0}.{1}" .format (schema_name , table_name ))
6772 table .create (self .target_engine , checkfirst = False )
6873 self .logger .debug ("Created table {0}.{1}" .format (schema_name , table_name ))
74+
6975 return
7076
7177 def create_column (self , configuration ):
7278 return Column (configuration ['name' ], self .column_type_resolver .resolve_postgres_type (configuration ),
7379 primary_key = configuration .get ("primary_key" , False ),
7480 nullable = configuration ['nullable' ])
7581
82+ # TODO: this should come from a different log table which is only written to at the end of a successful load load.
83+ def get_last_sync_version (self , schema_name , table_name ):
84+ sql = "SELECT max({0}) as version FROM {1}.{2}" .format (self .NEXT_CHANGE_MINIMUM_VERSION_COLUMN_NAME , schema_name , table_name )
85+
86+ result = self .target_engine .execute (sql )
87+ row = result .fetchone ()
88+ if row ["version" ] is None :
89+ return 0
90+ return row ["version" ]
91+
92+
7693 def rename_table (self , schema_name , source_table_name , target_table_name ):
7794
7895 # Steps to efficiently rename a table.
@@ -116,6 +133,10 @@ def upsert_table(self, schema_name, source_table_name, target_table_name, column
116133 column_array = list (map (lambda column : column ['destination' ]['name' ], columns_configuration ))
117134 column_list = ',' .join (map (str , column_array ))
118135 column_list = column_list + ",{0}" .format (self .TIMESTAMP_COLUMN_NAME )
136+ column_list = column_list + ",{0}" .format (self .IS_DELETED_COLUMN_NAME )
137+ column_list = column_list + ",{0}" .format (self .CHANGE_VERSION_COLUMN_NAME )
138+ column_list = column_list + ",{0}" .format (self .NEXT_CHANGE_MINIMUM_VERSION_COLUMN_NAME )
139+
119140
120141 primary_key_column_array = [column_configuration ['destination' ]['name' ] for column_configuration in columns_configuration if 'primary_key' in column_configuration ['destination' ] and column_configuration ['destination' ]['primary_key' ]]
121142
@@ -132,7 +153,14 @@ def upsert_table(self, schema_name, source_table_name, target_table_name, column
132153 sql_builder .write ("{0} = EXCLUDED.{0}," .format (column_configuratiomn ['destination' ]['name' ]))
133154 sql_builder .write (os .linesep )
134155
135- sql_builder .write ("{0} = EXCLUDED.{0}" .format (self .TIMESTAMP_COLUMN_NAME ))
156+ sql_builder .write ("{0} = EXCLUDED.{0}," .format (self .TIMESTAMP_COLUMN_NAME ))
157+ sql_builder .write (os .linesep )
158+ sql_builder .write ("{0} = EXCLUDED.{0}," .format (self .IS_DELETED_COLUMN_NAME ))
159+ sql_builder .write (os .linesep )
160+ sql_builder .write ("{0} = EXCLUDED.{0}," .format (self .CHANGE_VERSION_COLUMN_NAME ))
161+ sql_builder .write (os .linesep )
162+ sql_builder .write ("{0} = EXCLUDED.{0}" .format (self .NEXT_CHANGE_MINIMUM_VERSION_COLUMN_NAME ))
163+ sql_builder .write (os .linesep )
136164
137165 self .logger .debug ("Upsert executing {0}" .format (sql_builder .getvalue ()))
138166 self .target_engine .execute (sql_builder .getvalue ())
0 commit comments