require 'flydata/source' require 'flydata/source/component' require 'flydata/source/errors' module Flydata module Source class SyncGenerateTableDdl < Component def self.inherited(child_class) Source.register(child_class, self) end def initialize(source, dp, options = {}) super(source, options) @dp = dp end attr_reader :dp # Public Interface: Run compatibility check # # Run whatever check (compatibility, connectivity, privilege, etc) to ensure # that the 'sync:generate_table_ddl' command can run without an issue. # # Raises exception when check fails def run_compatibility_check raise UnsupportedSourceError, "subclass must implement" end def generate_flydata_tabledef(tables, options) prefs = data_entry_prefs reset_uk_as_pk_override(tables, prefs) options = options.merge(prefs) flydata_tabledefs = [] error_list = [] uk_as_pk_override = {} missing_tables = each_source_tabledef(tables, options) do |source_tabledef, error| if error error_list << error.err_hash next end if source_tabledef.converting_uk_to_pk? new_pk_override = source_tabledef.get_pk_override_as_hash uk_as_pk_override.merge!(new_pk_override) end flydata_tabledefs << source_tabledef.to_flydata_tabledef end if missing_tables missing_tables.each {|missing_table| error_list << { error: "Table does not exist in the #{data_source_type_display_name}", table: missing_table } } end [flydata_tabledefs, error_list, uk_as_pk_override] end private # Returns the namne of the data source type. The name will be used in an error message. def data_source_type_display_name raise UnsupportedSourceError, "subclass must implement" end # Returns a data entry preference hash def data_entry_prefs raise UnsupportedSourceError, "subclass must implement" end # Calls `block` with the source tabledef or error for each table. # # tables: An array of table names # # options: A hash including options. It includes the contents of # `data_entry_prefs` and :skip_primary_key_check. When the option is true, # the method must call the `block` for a table which is missing the primary # key. Otherwise, it should call the `block` with an error. # # block: A callback block called for each table with the following # arguments: # source_tabledef: A TableDef object of the source (e.g. MysqlTableDef) # The value will be nil if it failed to create the object. # error: A FlydataCore::TableDefError object. If no error ocurred, # this will be nil. # # Returns an array of tables which do not exist in the source def each_source_tabledef(tables, options, &block) raise UnsupportedSourceError, "subclass must implement" end def reset_uk_as_pk_override(target_tables, prefs) # Reset uk_as_pk_override for target tables. prefs['uk_as_pk_override'].delete_if do |table_name, val| target_tables.include?(table_name) end update_pk_override_pref(prefs) end def update_pk_override_pref(prefs) # pk_override = user_pk_override + uk_as_pk_override # (`user_pk_override` takes precedence) prefs['pk_override'] = prefs['uk_as_pk_override'].merge( prefs['user_pk_override'] ) $log.info "primary key override: #{prefs['pk_override']}" end end end end