class Blufin::YmlSqlStructureWriter
Public Class Methods
new(site, schema_data)
click to toggle source
# File lib/core/yml_writers/yml_sql_structure_writer.rb, line 5 def initialize(site, schema_data) @schema_data = schema_data raise RuntimeError, 'Could not find valid @schema_data.' if @schema_data.nil? || !@schema_data.is_a?(Hash) @site = Blufin::SiteResolver::validate_site(site) @site_name = Blufin::SiteResolver::get_site_name(@site) @site_domain = Blufin::SiteResolver::get_site_domain(@site) @site_location = "#{Blufin::SiteResolver::get_site_location(@site)}/" @yml_enum_scanner = Blufin::ScannerJavaEnums.new(@site) end
Public Instance Methods
write()
click to toggle source
# File lib/core/yml_writers/yml_sql_structure_writer.rb, line 20 def write # Remove ALL previous structure files. Blufin::YmlSchemaValidator::VALID_SCHEMAS_GENERATE.each do |schema| sfs = get_structure_files(schema) next if sfs.nil? # Skip if user doesn't have the PATH_TO_RUBY config value. structure_file = sfs[0] foreign_key_file = sfs[1] Blufin::Files::delete_file(structure_file) Blufin::Files::delete_file(foreign_key_file) end @schema_data.each do |schema, schema_data| # This filters out the "mock" schema used for testing. next if schema == Blufin::YmlSchemaValidator::MOCK fk_count = 0 idx_count = 0 @structure = [] @alter_table_lines = [] @fks = [] @link_tables = [] schema_data.each_with_index do |(table, table_data), idx| if table_data.length > 0 primary_key = nil indexes = [] indexes_unique = [] indexes_fulltext = [] foreign_keys = [] @structure << "-- Create #{table} table" @structure << "CREATE TABLE `#{table}` (" table_data.each do |column_name, column_data| # Skip Placeholders next if column_name =~ /\A(#{Blufin::YmlSchemaValidator::VALID_SCHEMAS_REGEX})\.[a-z_]+\[\]\z/ || column_name =~ /\A(#{Blufin::YmlSchemaValidator::VALID_SCHEMAS_REGEX})\.[a-z_]+\z/ @type = column_data[Blufin::YmlSchemaValidator::TYPE] @fkey = !column_data[Blufin::YmlSchemaValidator::FKEY].nil? # Skip Transient Objects. next if [Blufin::ScannerJavaEmbeddedObjects::OBJECT].include?(@type) # Create FKEY LINK tables if column_name =~ /\A[a-z_.]+\[#{Blufin::YmlSchemaValidator::LINK}\]/ @link_tables << [ "#{schema}.#{table}", column_name.dup.gsub("[#{Blufin::YmlSchemaValidator::LINK}]", '') ] next end # Get the flags and check for indexes. if column_data[Blufin::YmlSchemaValidator::FLAG].nil? @flags = nil indexes << " INDEX `#{schema}_#{table}_#{column_name}_idx` (`#{column_name}`)," if @type =~ Blufin::YmlSchemaValidator::REGEX_ENUM else @flags = Blufin::YmlCommon::extract_flags(column_data[Blufin::YmlSchemaValidator::FLAG])[0] # See if this is a PRIMARY KEY primary_key = column_name if @flags.primary_key # See if there are any INDEXES if @flags.index if [Blufin::YmlSchemaValidator::TYPE_TEXT, Blufin::YmlSchemaValidator::TYPE_TEXT_LONG].include?(@type) indexes_fulltext << " FULLTEXT `#{schema}_#{table}_#{column_name}_idx_fulltext` (`#{column_name}`)," else indexes << " INDEX `#{schema}_#{table}_#{column_name}_idx` (`#{column_name}`)," if @flags.unique.nil? indexes_unique << " UNIQUE INDEX `#{schema}_#{table}_#{column_name}_uniq_idx` (`#{column_name}`)," if @flags.unique end end end # Check for FKs unless column_data[Blufin::YmlSchemaValidator::FKEY].nil? fk_count = fk_count + 1 fk_ref = column_data[Blufin::YmlSchemaValidator::FKEY].split('.') # The target in form -> app.ebay_user.id foreign_key_lines = [] foreign_key_lines << "ADD CONSTRAINT `fk_#{fk_count}`" foreign_key_lines << " FOREIGN KEY (`#{column_name}`)" foreign_key_lines << " REFERENCES `#{fk_ref[1]}` (`#{fk_ref[2]}`)" foreign_key_lines << ' ON DELETE RESTRICT' foreign_key_lines << ' ON UPDATE CASCADE,' foreign_keys << foreign_key_lines end column_definition = " `#{column_name}`" determine_type(column_definition, column_data) determine_not_null(column_definition, column_data) determine_auto_increment(column_definition) determine_comment(column_data[Blufin::YmlSchemaValidator::DESCRIPTION], column_definition) @structure << "#{column_definition}," end # Add primary key (if any) .. @structure << " PRIMARY KEY (`#{primary_key}`)," if primary_key != nil # Add indexes (if any) .. indexes_fulltext.each { |index_fulltext| @structure << index_fulltext } if indexes_fulltext.any? indexes_unique.each { |index_unique| @structure << index_unique } if indexes_unique.any? indexes.each { |index| @structure << index } if indexes.any? # Add FKs (if any) .. if foreign_keys.any? @alter_table_lines << "-- Add #{table} FKs" @alter_table_lines << "ALTER TABLE `#{table}`" foreign_keys.each do |foreign_key_lines| foreign_key_lines.each do |foreign_key_line| @alter_table_lines << foreign_key_line end end @alter_table_lines[@alter_table_lines.length - 1] = @alter_table_lines[@alter_table_lines.length - 1][0...-1] @alter_table_lines[@alter_table_lines.length - 1] << ";\n" end @structure[@structure.length - 1] = @structure[@structure.length - 1][0...-1] @structure << ") ENGINE = InnoDB;#{idx == (schema_data.length - 1) ? '' : "\n"}" end end # Add LINK tables (if any) .. if @link_tables.any? @link_tables.each_with_index do |link_data, idx| source_table = link_data[0].split('.') target_table = link_data[1].split('.') link_table_name = Blufin::YmlCommon::get_link_table_name(source_table[1], link_data[1]) # Create structure. @structure << "-- Add table to link '#{source_table[1]}' with '#{target_table[1]}'" @structure << "CREATE TABLE `#{link_table_name}` (" @structure << " `#{source_table[1]}_id` INT NOT NULL," @structure << " `#{target_table[1]}_id` INT NOT NULL" @structure << ") ENGINE = InnoDB;#{idx == (@link_tables.length - 1) ? '' : "\n"}" # Create FKs and indexes. @fks << "ALTER TABLE `#{link_table_name}`" idx_count = idx_count + 1 @fks << " ADD INDEX `idx_#{idx_count}` (`#{source_table[1]}_id` DESC)," idx_count = idx_count + 1 @fks << " ADD INDEX `idx_#{idx_count}` (`#{target_table[1]}_id` DESC)," @fks << " ADD UNIQUE INDEX `#{source_table[1]}_to_#{target_table[1]}_uniq_idx` (`#{source_table[1]}_id` DESC, `#{target_table[1]}_id` DESC)," fk_count = fk_count + 1 @fks << " ADD CONSTRAINT `fk_#{fk_count}`" @fks << " FOREIGN KEY (`#{source_table[1]}_id`)" @fks << " REFERENCES `#{source_table[1]}` (`id`)" @fks << ' ON DELETE RESTRICT' @fks << ' ON UPDATE RESTRICT,' fk_count = fk_count + 1 @fks << " ADD CONSTRAINT `fk_#{fk_count}`" @fks << " FOREIGN KEY (`#{target_table[1]}_id`)" @fks << " REFERENCES `#{target_table[1]}` (`id`)" @fks << ' ON DELETE RESTRICT' @fks << ' ON UPDATE RESTRICT;' @fks << '' unless idx == @link_tables.length - 1 end end sfs = get_structure_files(schema) next if sfs.nil? # Skip if user doesn't have the PATH_TO_RUBY config value. structure_file = sfs[0] foreign_key_file = sfs[1] Blufin::Files.write_file(structure_file, @structure).gsub(@site_location, '') if @structure.any? Blufin::Files.write_file(foreign_key_file, @alter_table_lines + @fks).gsub(@site_location, '') if @alter_table_lines.any? || @fks.any? end end
Private Instance Methods
determine_auto_increment(column_definition)
click to toggle source
@return void
# File lib/core/yml_writers/yml_sql_structure_writer.rb, line 254 def determine_auto_increment(column_definition) column_definition << ' AUTO_INCREMENT' if @type == Blufin::YmlSchemaValidator::TYPE_INT_AUTO end
determine_comment(description, column_definition)
click to toggle source
@return void
# File lib/core/yml_writers/yml_sql_structure_writer.rb, line 259 def determine_comment(description, column_definition) if description != nil desc = description else desc = '' end desc = Blufin::YmlCommon::description_without_formatting(desc) if @type =~ Blufin::YmlSchemaValidator::REGEX_ENUM desc << " \xe2\x80\x94 " unless desc == '' || desc.nil? desc << '[' Blufin::YmlCommon::enum_value_extractor(@type, @site).each do |enum_value| desc << "#{enum_value}|" end desc = desc[0...-1] desc << ']' end column_definition << " COMMENT '#{desc.gsub("'", %q(\\\'))}'" if desc != nil && desc.to_s != '' end
determine_not_null(column_definition, column_data)
click to toggle source
@return void
# File lib/core/yml_writers/yml_sql_structure_writer.rb, line 246 def determine_not_null(column_definition, column_data) ((@flags != nil && @flags.nullable) || column_data.has_key?(Blufin::YmlSchemaValidator::REQUIRED_IF)) ? column_definition << ' NULL' : column_definition << ' NOT NULL' end
determine_type(column_definition, column_data)
click to toggle source
@return void
# File lib/core/yml_writers/yml_sql_structure_writer.rb, line 201 def determine_type(column_definition, column_data) if @type == Blufin::YmlSchemaValidator::TYPE_DATE # Must come before DATETIME_TYPES.include? column_definition << ' DATE' elsif Blufin::YmlSchemaValidator::DATETIME_TYPES.include?(@type) column_definition << ' DATETIME(3)' elsif @type == Blufin::YmlSchemaValidator::TYPE_INT_TINY column_definition << ' TINYINT' elsif @type == Blufin::YmlSchemaValidator::TYPE_INT_SMALL column_definition << ' SMALLINT' elsif @type == Blufin::YmlSchemaValidator::TYPE_INT_BIG column_definition << ' BIGINT' elsif Blufin::YmlSchemaValidator::INT_TYPES.include?(@type) column_definition << ' INT' elsif @type == Blufin::YmlSchemaValidator::TYPE_BOOLEAN column_definition << ' TINYINT(1)' elsif @type == Blufin::YmlSchemaValidator::TYPE_TEXT column_definition << ' TEXT' elsif @type == Blufin::YmlSchemaValidator::TYPE_TEXT_LONG column_definition << ' LONGTEXT' elsif @type =~ Blufin::YmlSchemaValidator::REGEX_DECIMAL || @type =~ Blufin::YmlSchemaValidator::REGEX_VARCHAR if column_data[Blufin::YmlSchemaValidator::ENCRYPTED].nil? column_definition << " #{@type}" else # Encrypted VARCHAR(30) would become VARCHAR(60). varchar_amount = Blufin::Strings::extract_using_regex(@type, /\(\d+\)\z/, %w{( )}) column_definition << " #{Blufin::YmlSchemaValidator::TYPE_VARCHAR}(#{varchar_amount.to_i * 2})" end elsif @type =~ Blufin::YmlSchemaValidator::REGEX_ENUM enum_values = Blufin::YmlCommon::enum_value_extractor(@type, @site) column_definition << " VARCHAR(#{enum_values.max_by(&:length).length})" elsif @type =~ Blufin::YmlSchemaValidator::REGEX_ENUM_CUSTOM enum_values = @yml_enum_scanner.get_enum_custom_values_for(Blufin::YmlCommon::enum_name_extractor(@type)) column_definition << " VARCHAR(#{enum_values.max_by(&:length).length})" elsif @type =~ Blufin::YmlSchemaValidator::REGEX_ENUM_SYSTEM enum_values = @yml_enum_scanner.get_enum_system_values_for(Blufin::YmlCommon::enum_name_extractor(@type)) column_definition << " VARCHAR(#{enum_values.max_by(&:length).length})" else raise RuntimeError, "Unrecognized type in #{__FILE__}: #{@type}" end end
get_structure_files(schema)
click to toggle source
@return Array
# File lib/core/yml_writers/yml_sql_structure_writer.rb, line 284 def get_structure_files(schema) if schema == Blufin::YmlSchemaValidator::CONFIG path_to_blufin_ruby = Blufin::Config::get_path('Paths', 'BlufinRuby') return nil if path_to_blufin_ruby.nil? structure_file = "#{path_to_blufin_ruby}/#{App::Opt::BLUFIN}#{App::Opt::OPT_PATH_SQL}/structure/#{App::MySQL::CONFIG_FILENAME_STRUCTURE}" foreign_key_file = "#{path_to_blufin_ruby}/#{App::Opt::BLUFIN}#{App::Opt::OPT_PATH_SQL}/structure/#{App::MySQL::CONFIG_FILENAME_STRUCTURE_FKS}" elsif schema == Blufin::YmlSchemaValidator::MOCK path_to_blufin_ruby = Blufin::Config::get_path('Paths', 'BlufinRuby') return nil if path_to_blufin_ruby.nil? structure_file = "#{path_to_blufin_ruby}/#{App::Opt::BLUFIN}#{App::Opt::OPT_PATH_SQL}/structure/#{App::MySQL::MOCK_FILENAME_STRUCTURE}" foreign_key_file = "#{path_to_blufin_ruby}/#{App::Opt::BLUFIN}#{App::Opt::OPT_PATH_SQL}/structure/#{App::MySQL::MOCK_FILENAME_STRUCTURE_FKS}" else structure_file = "#{get_base_path(@site)}/#{Blufin::Site::PATH_TO_SQL_STRUCTURE}/#{Blufin::SiteResolver::get_site_name(@site)}-#{schema}.sql" foreign_key_file = "#{get_base_path(@site)}/#{Blufin::Site::PATH_TO_SQL_STRUCTURE}/#{Blufin::SiteResolver::get_site_name(@site)}-fks-#{schema}.sql" end [structure_file, foreign_key_file] end