Class: Rigrate::ResultSet
- Inherits:
-
Object
- Object
- Rigrate::ResultSet
- Defined in:
- lib/rigrate/interface/result_set.rb
Instance Attribute Summary collapse
-
#column_info ⇒ Object
Returns the value of attribute column_info.
-
#db ⇒ Object
Returns the value of attribute db.
-
#rows ⇒ Object
Returns the value of attribute rows.
-
#target_tbl_name ⇒ Object
Returns the value of attribute target_tbl_name.
Instance Method Summary collapse
- #-(target, opts = {}) ⇒ Object (also: #minus)
- #column_idx(*names) ⇒ Object
- #column_values(row, cols) ⇒ Object
- #convert_to_native_row(row) ⇒ Object
- #default_migration_condition ⇒ Object
- #delete_not_exist_rows(target_rows, source_rows, target_cols_idx, src_cols_idx) ⇒ Object
-
#format_rows(src_rows, tg_width, filled = nil) ⇒ Object
convert source resulset rows to specify width.
- #get_sql(type, condition = nil) ⇒ Object
- #handle_delete!(condition = nil) ⇒ Object
- #handle_insert! ⇒ Object
-
#handle_rows(src_rows_data, mode, src_cols_idx = nil, tg_cols_idx = nil) ⇒ Object
condition => :c_name, :age => :age insert or update or delete.
- #handle_update!(condition = nil) ⇒ Object
- #include?(p_row) ⇒ Boolean
-
#join(source_rs, key_fields = {}) ⇒ Object
join two table by given field { :jc => :job_code }.
-
#migrate_from(src_rs, condition = nil, opts = {}) ⇒ Object
There are three modes :echo is left to right ResultSet, and delete right which is not in left When condition is nil find the primary key as condition 1.
- #op_two_rows(target_rows, target_cols_idx, source_rows, src_cols_idx) ⇒ Object
- #primary_key ⇒ Object
- #save!(condition = nil) ⇒ Object
- #size ⇒ Object
-
#union(target, opts = {}) ⇒ Object
union two result set , columns defination will not change default is union all style.
Instance Attribute Details
#column_info ⇒ Object
Returns the value of attribute column_info.
7 8 9 |
# File 'lib/rigrate/interface/result_set.rb', line 7 def column_info @column_info end |
#db ⇒ Object
Returns the value of attribute db.
5 6 7 |
# File 'lib/rigrate/interface/result_set.rb', line 5 def db @db end |
#rows ⇒ Object
Returns the value of attribute rows.
6 7 8 |
# File 'lib/rigrate/interface/result_set.rb', line 6 def rows @rows end |
#target_tbl_name ⇒ Object
Returns the value of attribute target_tbl_name.
5 6 7 |
# File 'lib/rigrate/interface/result_set.rb', line 5 def target_tbl_name @target_tbl_name end |
Instance Method Details
#-(target, opts = {}) ⇒ Object Also known as: minus
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/rigrate/interface/result_set.rb', line 83 def -(target, opts = {}) src_col_size = column_info.size target_col_size = target.column_info.size # checking type? #columns size must equal if src_col_size != target_col_size raise ResultSetError.new('minus must be used between column size equaled.') end @rows.reject! do |row| target.include? row end self end |
#column_idx(*names) ⇒ Object
335 336 337 338 339 340 341 342 343 |
# File 'lib/rigrate/interface/result_set.rb', line 335 def column_idx(*names) names.inject([]) do |idxes, name| column_info.each_with_index do |col, idx| idxes << idx if col.name.to_s.downcase == name.to_s.downcase end idxes end end |
#column_values(row, cols) ⇒ Object
329 330 331 332 333 |
# File 'lib/rigrate/interface/result_set.rb', line 329 def column_values(row, cols) cols.map do |col| row[col] end end |
#convert_to_native_row(row) ⇒ Object
363 364 365 |
# File 'lib/rigrate/interface/result_set.rb', line 363 def convert_to_native_row(row) @db.to_native_row(row, @column_info) end |
#default_migration_condition ⇒ Object
353 354 355 356 357 358 359 360 361 |
# File 'lib/rigrate/interface/result_set.rb', line 353 def default_migration_condition flag = true cols = @column_info.map { |col| col.name } primary_key.each do |key| flag = false unless cols.include? key end primary_key if flag end |
#delete_not_exist_rows(target_rows, source_rows, target_cols_idx, src_cols_idx) ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/rigrate/interface/result_set.rb', line 192 def delete_not_exist_rows(target_rows, source_rows, target_cols_idx, src_cols_idx) result = [] target_rows.each do |t_row| t_values = t_row.values(*target_cols_idx) fetched = false source_rows.each do |s_row| break fetched = true if s_row.values(*src_cols_idx) == t_values end result << Row.new(t_row.data, RowStatus::DELETE) unless fetched end result end |
#format_rows(src_rows, tg_width, filled = nil) ⇒ Object
convert source resulset rows to specify width
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 |
# File 'lib/rigrate/interface/result_set.rb', line 313 def format_rows(src_rows, tg_width, filled = nil) r_length = src_rows.first.size if r_length > tg_width src_rows.map! do |row| row.data = row[0..tg_width] end elsif r_length < tg_width src_rows.map! do |row| row.fill_with_nil(tg_width - r_length) end end src_rows end |
#get_sql(type, condition = nil) ⇒ Object
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/rigrate/interface/result_set.rb', line 281 def get_sql(type, condition = nil) case type when :insert params_str = column_info.map(&:name).join(',') values_str = Array.new(column_info.size){'?'}.join(',') "insert into #{target_tbl_name} (#{params_str}) values (#{values_str})" when :update condi_fields = condition || primary_key params_str = condi_fields.map do |col| "#{col}=?" end.join(' and ') upd_fields = column_info.reject do |col| condi_fields.include? col.name end setting_str = upd_fields.map do |col| "#{col.name}=?" end.join(',') "update #{target_tbl_name} set #{setting_str} where #{params_str}" when :delete params_str = condition.map do |col| "#{col}=?" end.join(' and ') raise ResultSetError.new("can't get the delete sql") if params_str.to_s.size <= 0 "delete from #{target_tbl_name} where #{params_str}" end end |
#handle_delete!(condition = nil) ⇒ Object
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/rigrate/interface/result_set.rb', line 261 def handle_delete!(condition = nil) temp_primary_key = nil temp_primary_key = primary_key if primary_key.size > 0 condi_fields = condition || temp_primary_key || column_info.map{ |col| col.name } sql = get_sql(:delete, condi_fields) op_rows = @rows.select do |row| row.status == RowStatus::DELETE end params_idx = column_idx(*condi_fields) formated_rows = op_rows.map do |row| row.values(*params_idx) end Rigrate.logger.info("start delete [#{op_rows.size}] rows using sql [#{sql}]") @db.delete sql, *formated_rows if formated_rows.size > 0 end |
#handle_insert! ⇒ Object
227 228 229 230 231 232 233 234 235 236 |
# File 'lib/rigrate/interface/result_set.rb', line 227 def handle_insert!() sql = get_sql(:insert) op_rows = @rows.select do |row| row.status == RowStatus::NEW end Rigrate.logger.info("start insert [#{op_rows.size}] rows using sql [#{sql}]") @db.insert sql, *op_rows if op_rows.size > 0 end |
#handle_rows(src_rows_data, mode, src_cols_idx = nil, tg_cols_idx = nil) ⇒ Object
condition => :c_name, :age => :age insert or update or delete
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/rigrate/interface/result_set.rb', line 143 def handle_rows (src_rows_data, mode, src_cols_idx = nil, tg_cols_idx = nil) new_rows_data = [] # condition parameter is null , so delete all ROWS. and then copy the source rs if src_cols_idx.to_a.size <= 0 && tg_cols_idx.to_a.size <= 0 # TODO check the size if mode == :echo # delete all the dest rs data @rows.each do |row| new_rows_data << Row.new(row.data, RowStatus::DELETE) end end # :echo and :contribute mode format_rows(src_rows_data, width).map do |row| new_rows_data << Row.new(row.data, RowStatus::NEW) end else if mode == :echo new_rows_data += delete_not_exist_rows(@rows, src_rows_data, tg_cols_idx, src_cols_idx) end # :echo and :contribute new_rows_data += op_two_rows(@rows, tg_cols_idx, src_rows_data, src_cols_idx) end new_rows_data end |
#handle_update!(condition = nil) ⇒ Object
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/rigrate/interface/result_set.rb', line 238 def handle_update!(condition = nil) key_fields = (condition || primary_key) sql = get_sql(:update, key_fields) param_fields = column_info.reject do |col| key_fields.include? col.name end.map { |col| col.name } op_rows = rows.select do |row| row.status == RowStatus::UPDATED end key_idx = column_idx(*key_fields) params_idx = column_idx(*param_fields) formated_rows = op_rows.map do |row| key_values = row.values(*key_idx) params_values = row.values(*params_idx) params_values + key_values end Rigrate.logger.info("start update [#{op_rows.size}] rows using sql [#{sql}]") @db.update sql, *formated_rows if formated_rows.size > 0 end |
#include?(p_row) ⇒ Boolean
345 346 347 348 349 350 351 |
# File 'lib/rigrate/interface/result_set.rb', line 345 def include?(p_row) @rows.each do |row| return true if row.data == p_row.data end false end |
#join(source_rs, key_fields = {}) ⇒ Object
join two table by given field { :jc => :job_code }
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/rigrate/interface/result_set.rb', line 10 def join(source_rs, key_fields = {}) if key_fields.size <= 0 raise ResultSetError.new("must specify the join condition.") end # convert condition key and value to string key_fields = key_fields.inject({}) do |h, (k, v)| h[k.to_s.upcase] = v.to_s.upcase h end origin_rs_idx = column_idx(*key_fields.keys) source_rs_idx = source_rs.column_idx(*key_fields.values) ResultSet.new.tap do |rs| # remove duplicate column header, base on column name addtion_column_info = source_rs.column_info.dup.delete_if do |col| key_fields.values.include? col.name.upcase end rs.column_info = @column_info + addtion_column_info rs.rows = @rows.inject([]) do |new_rows, row| origin_rs_key_values = row.values(*origin_rs_idx) selected_source_rs_row = source_rs.rows.select do |r| r.values(*source_rs_idx) == origin_rs_key_values end # remove duplicate data columns selected_source_rs_row.map! do |r| data = [] r.data.each_with_index do |value, idx| data << value unless source_rs_idx.include? idx end Row.new data, RowStatus::NEW end # this is a left join. if selected_source_rs_row.size > 0 selected_source_rs_row.each do |t_row| new_rows << Row.new(row.data + t_row.data, RowStatus::NEW) end else new_rows << row.dup.fill_with_nil(addtion_column_info.size) end new_rows end end end |
#migrate_from(src_rs, condition = nil, opts = {}) ⇒ Object
There are three modes :echo is left to right ResultSet, and delete right which is not in left
+When condition is nil+
find the primary key as condition
1. if primary key can't find in ResultSet then delete all record in right side, and insert
all rows to left side
+When condition is not nil+
1. using condition to update existing row in right side
2. and insert rows which not included in right side
3. then delete rows not in left side
:contribute is left to right, and KEEP the file even it not in left
+When condition is nil+
find the primary key as condition
1. if primary key can't find in Result then insert all rows to left side
+When condition is not nil+
1. using condition to update existing row in right side
2. and insert rows not included in right side
:sync will keep left and right the same TODO
just keep two side the same
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/rigrate/interface/result_set.rb', line 123 def migrate_from(src_rs, condition = nil, opts = {}) Rigrate.logger.info("start migration : source rs [#{src_rs.size}] ->target rs [#{rows.size}]") mode = opts[:mode] condition = eval "{#{condition.to_s.upcase}}" unless condition.nil? if condition src_cols_idx = src_rs.column_idx(*condition.keys) tg_cols_idx = column_idx(*condition.values) else # delete line -> src_cols_idx = src_rs.column_idx(*src_rs.default_migration_condition) # suppose all primary key of target resultset can be found in src result, and in same column idx tg_cols_idx = column_idx(*default_migration_condition) src_cols_idx = tg_cols_idx end @rows = handle_rows(src_rs.rows, mode, src_cols_idx, tg_cols_idx) save!(condition) end |
#op_two_rows(target_rows, target_cols_idx, source_rows, src_cols_idx) ⇒ Object
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/rigrate/interface/result_set.rb', line 170 def op_two_rows(target_rows, target_cols_idx, source_rows, src_cols_idx) result = [] source_rows.each do |s_row| s_values = s_row.values(*src_cols_idx) fetched = false target_rows.each do |t_row| if s_values == t_row.values(*target_cols_idx) fetched = true if s_row.data != t_row.data result << Row.new(s_row.data, RowStatus::UPDATED) else result << Row.new(s_row.data, RowStatus::ORIGIN) end end end result << Row.new(s_row.data, RowStatus::NEW) unless fetched end result end |
#primary_key ⇒ Object
371 372 373 |
# File 'lib/rigrate/interface/result_set.rb', line 371 def primary_key @primary_key ||= @db.primary_key(@target_tbl_name) end |
#save!(condition = nil) ⇒ Object
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/rigrate/interface/result_set.rb', line 207 def save!(condition = nil) begin # convert all to native row @rows.map do |row| convert_to_native_row(row) end @db.transaction if Rigrate.config[:strict] condition = condition.values if condition handle_delete!(condition) handle_insert! handle_update!(condition) @db.commit if @db.transaction_active? rescue Exception => e Rigrate.logger.error("saving resultset [#{rows.size}] error: #{e.message} #{e.backtrace}") raise e @db.rollback if @db.transaction_active? end end |
#size ⇒ Object
367 368 369 |
# File 'lib/rigrate/interface/result_set.rb', line 367 def size @rows.size end |
#union(target, opts = {}) ⇒ Object
union two result set , columns defination will not change default is union all style
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/rigrate/interface/result_set.rb', line 64 def union(target, opts = {}) src_col_size = column_info.size target_col_size = target.column_info.size # TODO need type checking? if src_col_size > target_col_size target.rows = target.rows.map do |row| row.fill_with_nil(src_col_size - target_col_size) end elsif src_col_size < target_col_size target.rows = target.rows.map { |row| row[0...src_col_size] } end @rows += target.rows self end |