class FlattenDB::MySQL

Constants

JOIN_KEY

Attributes

builder[R]
name[R]
tables[R]
type[R]

Public Class Methods

new(options) click to toggle source
Calls superclass method FlattenDB::Base.new
# File lib/flattendb/types/mysql.rb, line 43
def initialize(options)
  super

  @type = options[:type] || :xml
  @name, @tables = parse
end

Public Instance Methods

flatten!(options = {}) click to toggle source
# File lib/flattendb/types/mysql.rb, line 54
def flatten!(options = {})
  flatten_tables!(tables, root, config)
  self
end
parse(tables = {}) click to toggle source
# File lib/flattendb/types/mysql.rb, line 50
def parse(tables = {})
  [send("parse_#{type}", tables) || 'root', tables]
end
to_xml(output = output, builder_options = {}) click to toggle source
# File lib/flattendb/types/mysql.rb, line 59
def to_xml(output = output, builder_options = {})
  initialize_builder(:xml, output, builder_options)

  builder.instruct!

  if tables.size > 1
    builder.tag!(name) {
      tables.sort.each { |table, rows| table_to_xml(table, rows, builder) }
    }
  else
    table_to_xml(name, tables.values.first, builder)
  end

  self
end

Private Instance Methods

field_to_xml(field, value, builder) click to toggle source
# File lib/flattendb/types/mysql.rb, line 199
def field_to_xml(field, value, builder)
  case value
    when String, Numeric, true, false, nil
      builder.tag!(column_to_element(field), value)
    when Array
      value.each { |item| field_to_xml(field, item, builder) }
    when Hash
      row_to_xml(field, value, builder)
    else
      raise ArgumentError,
        "don't know how to handle value of type #{value.class}"
  end
end
flatten_tables!(tables, primary_table, config) click to toggle source
# File lib/flattendb/types/mysql.rb, line 122
def flatten_tables!(tables, primary_table, config)
  config.each { |foreign_table, spec|
    case spec
      when String
        inject_foreign(tables, primary_table, foreign_table, spec)
      when Array
        inject_foreign(tables, primary_table, foreign_table, *spec)
      when Hash
        unless spec.has_key?(JOIN_KEY)
          raise ArgumentError,
            "invalid join table spec, #{JOIN_KEY.inspect} missing"
        end

        unless (join_key_spec = spec.delete(JOIN_KEY)).is_a?(Hash)
          join_key_spec = { foreign_table => join_key_spec }
        end

        foreign_tables = Marshal.load(Marshal.dump(tables))
        flatten_tables!(foreign_tables, foreign_table, spec)

        join_key_spec.each { |foreign_table_name, join_key|
          local_key, foreign_key = join_key

          inject_foreign(
            tables, primary_table, foreign_table,
            local_key, foreign_key || local_key,
            foreign_tables, foreign_table_name
          )
        }
      else
        raise ArgumentError,
          "don't know how to handle spec of type #{spec.class}"
    end
  } if config

  tables.delete_if { |table, _| table != primary_table }
end
inject_foreign( tables, primary_table, foreign_table, local_key, foreign_key = local_key, foreign_tables = tables, foreign_table_name = foreign_table ) click to toggle source
# File lib/flattendb/types/mysql.rb, line 160
def inject_foreign(
  tables, primary_table, foreign_table,
  local_key, foreign_key = local_key,
  foreign_tables = tables, foreign_table_name = foreign_table
)
  unless tables.has_key?(primary_table)
    raise ArgumentError, "no such primary table: #{primary_table}"
  end

  unless foreign_tables.has_key?(foreign_table)
    raise ArgumentError, "no such foreign table: #{foreign_table}"
  end

  foreign_rows = Hash.new { |h, k| h[k] = [] }

  foreign_tables[foreign_table].each { |foreign_row|
    foreign_rows[foreign_row[foreign_key]] << foreign_row
  }

  tables[primary_table].each { |row|
    if row.has_key?(local_key)
      rows = foreign_rows[row[local_key]]
      row[foreign_table_name] = rows unless rows.empty?
    end
  }
end
parse_sql(tables) click to toggle source
# File lib/flattendb/types/mysql.rb, line 98
def parse_sql(tables)
  name = nil

  Nuggets::MySQL::Parser.parse(input) { |event, *args|
    case event
      when :use
        raise 'dump file contains more than one database' if name
        name = args.first
      when :insert
        fields, _, table, columns, values = {}, *args

        values.each_with_index { |value, index|
          if column = columns[index]
            fields[column] = value.to_s
          end
        }

        (tables[table] ||= []) << fields
    end
  }

  name
end
parse_xml(tables) click to toggle source
# File lib/flattendb/types/mysql.rb, line 77
def parse_xml(tables)
  document = LibXML::XML::Document.io(input)
  database = document.root.find_first('database[@name]')

  database.find('table_data[@name]').each { |table|
    rows = tables[table[:name]] ||= []

    table.find('row').each { |row|
      fields = {}

      row.find('field[@name]').each { |field|
        fields[field[:name]] = field.content
      }

      rows << fields
    }
  }

  database[:name]
end
row_to_xml(name, row, builder) click to toggle source
# File lib/flattendb/types/mysql.rb, line 193
def row_to_xml(name, row, builder)
  builder.tag!(name) {
    row.sort.each { |field, value| field_to_xml(field, value, builder) }
  }
end
table_to_xml(table, rows, builder) click to toggle source
# File lib/flattendb/types/mysql.rb, line 187
def table_to_xml(table, rows, builder)
  builder.tag!(table) {
    rows.each { |row| row_to_xml('row', row, builder) } if rows
  }
end