Class: MysqlDumpToJson::MySQL::Reader
- Inherits:
-
Object
- Object
- MysqlDumpToJson::MySQL::Reader
- Defined in:
- lib/mysql_dump_to_json/mysql/reader.rb
Instance Attribute Summary collapse
-
#database ⇒ Object
readonly
Returns the value of attribute database.
-
#opts ⇒ Object
readonly
Returns the value of attribute opts.
-
#source_dump ⇒ Object
readonly
Returns the value of attribute source_dump.
-
#statements ⇒ Object
readonly
Returns the value of attribute statements.
Instance Method Summary collapse
-
#build_database ⇒ Object
Creating the database as objects.
-
#compress_sql_into_statements ⇒ Object
Compressing the source into distinct SQL statements.
- #create_table(sql_statement) ⇒ Object
- #create_table_definition(sql_statement) ⇒ Object
- #field_from_line(line) ⇒ Object
- #fields_from_insert(sql_statement) ⇒ Object
- #index_of_closing_quote_value(ary, start_at_index) ⇒ Object
- #ingest(mysql_string) ⇒ Object
-
#initialize(database, opts = {}) ⇒ Reader
constructor
A new instance of Reader.
- #insert_into(sql_statement) ⇒ Object
-
#parse_values_row_with_escape(values_row) ⇒ Object
Simply splitting on commas gets most rows, but fails when there are commas in quoted text.
- #remove_block_comments(str) ⇒ Object
- #remove_quotes_from_values(values) ⇒ Object
- #strip_comments(str) ⇒ Object
- #table_name_from_create(str) ⇒ Object
- #table_name_from_insert(sql_statement) ⇒ Object
- #value_chunks_from_insert(sql_statement) ⇒ Object
- #value_complete_quote?(value) ⇒ Boolean
- #value_not_quoted?(value) ⇒ Boolean
- #value_open_end_quote?(value) ⇒ Boolean
- #value_open_start_quote?(value) ⇒ Boolean
- #value_to_numeric(value) ⇒ Object
Constructor Details
#initialize(database, opts = {}) ⇒ Reader
Returns a new instance of Reader.
12 13 14 15 16 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 12 def initialize(database, opts = {}) @database = database @tables = {} @opts = opts end |
Instance Attribute Details
#database ⇒ Object (readonly)
Returns the value of attribute database.
10 11 12 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 10 def database @database end |
#opts ⇒ Object (readonly)
Returns the value of attribute opts.
10 11 12 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 10 def opts @opts end |
#source_dump ⇒ Object (readonly)
Returns the value of attribute source_dump.
10 11 12 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 10 def source_dump @source_dump end |
#statements ⇒ Object (readonly)
Returns the value of attribute statements.
10 11 12 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 10 def statements @statements end |
Instance Method Details
#build_database ⇒ Object
Creating the database as objects
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 26 def build_database @statements.each_with_index do |sql_statement| case sql_statement when /^CREATE +DATABASE/i, /^USE/i, /^DROP +TABLE/i, /^LOCK TABLES/i, /^UNLOCK TABLES/i, ';' next when /^CREATE +TABLE/i create_table(sql_statement) when /^INSERT +INTO/i insert_into(sql_statement) else warn " !!! SQL statement found that is not handled by this gem: #{sql_statement.split("\n").first}" end end @database end |
#compress_sql_into_statements ⇒ Object
Compressing the source into distinct SQL statements
180 181 182 183 184 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 180 def compress_sql_into_statements str = remove_block_comments(@source_dump) uncommented = strip_comments(str) uncommented.split(/(?<=;)[\r\n]/) end |
#create_table(sql_statement) ⇒ Object
46 47 48 49 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 46 def create_table(sql_statement) table = create_table_definition(sql_statement) @database.create_table(table[:name], table[:fields], table[:keys]) end |
#create_table_definition(sql_statement) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 51 def create_table_definition(sql_statement) table = { name: nil, fields: [], keys: [] } sql_statement.split("\n").each do |line| case line.strip when /^CREATE +TABLE +/i table[:name] = table_name_from_create(line) when /^PRIMARY +KEY/i, /^FOREIGN +KEY/i, /^KEY/i table[:keys] << line.strip.delete_suffix(',') when ');', /ENGINE=/i, /^CONSTRAINT/i, /^ENGINE/i else table[:fields] << field_from_line(line) end end table end |
#field_from_line(line) ⇒ Object
71 72 73 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 71 def field_from_line(line) line.strip.scan(/[a-z0-9_$]+/i).first end |
#fields_from_insert(sql_statement) ⇒ Object
88 89 90 91 92 93 94 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 88 def fields_from_insert(sql_statement) before_values_section = sql_statement.split(/values/i).first field_section = before_values_section.gsub(/^INSERT INTO ['`]?#{table_name_from_insert(sql_statement)}['`]?/i,'').strip return false if field_section.empty? || field_section.nil? sql_statement.split(/[()]/)[1].split(',') end |
#index_of_closing_quote_value(ary, start_at_index) ⇒ Object
168 169 170 171 172 173 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 168 def index_of_closing_quote_value(ary, start_at_index) ary.each_with_index do |value, index| next if index < start_at_index return index if value_open_start_quote?(value) end end |
#ingest(mysql_string) ⇒ Object
18 19 20 21 22 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 18 def ingest(mysql_string) @source_dump = mysql_string @statements = compress_sql_into_statements build_database end |
#insert_into(sql_statement) ⇒ Object
75 76 77 78 79 80 81 82 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 75 def insert_into(sql_statement) table_name = table_name_from_insert(sql_statement) table = @database.tables.fetch(table_name) insert_fields = fields_from_insert(sql_statement) || table.fields value_chunks_from_insert(sql_statement).each do |row_ary| table.add_row(insert_fields, row_ary) end end |
#parse_values_row_with_escape(values_row) ⇒ Object
Simply splitting on commas gets most rows, but fails when there are commas in quoted text. When an opening quote is found, but not a closing quote, look ahead in the array until the closing quote is found to merge those values back together with the consumed comma
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 107 def parse_values_row_with_escape(values_row) simple_split = values_row.split(',') values = [] merged_indexes = [] simple_split.each_with_index do |value, index| next if merged_indexes.include?(index) if value_not_quoted?(value) values << value_to_numeric(value) elsif value_complete_quote?(value) values << value elsif value_open_end_quote?(value) end_of_quote_index = index_of_closing_quote_value(simple_split, index) values << simple_split[index..end_of_quote_index].join(',') merged_indexes |= (index..end_of_quote_index).to_a else binding.pry end end remove_quotes_from_values(values) end |
#remove_block_comments(str) ⇒ Object
194 195 196 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 194 def remove_block_comments(str) str.gsub(/\/\*.*?\*\//m,'') end |
#remove_quotes_from_values(values) ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 129 def remove_quotes_from_values(values) values.map do |value| if value.is_a?(String) value.delete_suffix("'") # Remove the enacapsulating quotes .delete_prefix("'") .gsub("\\'", "'") # Remove the double escaped interior single quotes else value end end end |
#strip_comments(str) ⇒ Object
186 187 188 189 190 191 192 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 186 def strip_comments(str) str.split(/[\n\r]+/).reject do |line| line.nil? || line.empty? || line.start_with?('--') end.join("\n") end |
#table_name_from_create(str) ⇒ Object
67 68 69 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 67 def table_name_from_create(str) str.strip.gsub(/CREATE +TABLE +`?/i,'').delete_suffix("(").strip.delete_suffix('`') end |
#table_name_from_insert(sql_statement) ⇒ Object
84 85 86 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 84 def table_name_from_insert(sql_statement) sql_statement.split(/[ ()`]+/)[2] end |
#value_chunks_from_insert(sql_statement) ⇒ Object
96 97 98 99 100 101 102 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 96 def value_chunks_from_insert(sql_statement) values_str = sql_statement.split(/ VALUES +/i).last values_ary = values_str[1..-3].split(/\)\s*,\s*\(/) values_ary.map do |values_row| parse_values_row_with_escape(values_row.delete_prefix('(').delete_suffix(')')) end end |
#value_complete_quote?(value) ⇒ Boolean
153 154 155 156 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 153 def value_complete_quote?(value) value[0] == "'" && value[-1] == "'" end |
#value_not_quoted?(value) ⇒ Boolean
149 150 151 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 149 def value_not_quoted?(value) value.count("'").zero? end |
#value_open_end_quote?(value) ⇒ Boolean
158 159 160 161 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 158 def value_open_end_quote?(value) value[0] == "'" && value[-1] != "'" end |
#value_open_start_quote?(value) ⇒ Boolean
163 164 165 166 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 163 def value_open_start_quote?(value) value[0] != "'" && value[-1] == "'" end |
#value_to_numeric(value) ⇒ Object
141 142 143 144 145 146 147 |
# File 'lib/mysql_dump_to_json/mysql/reader.rb', line 141 def value_to_numeric(value) return nil if value == 'NULL' return value.to_i if value.to_i.to_s == value return value.to_f if value.to_f.to_s == value binding.pry end |