pg_online_schema_change 0.7.5 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,8 +38,14 @@ module PgOnlineSchemaChange
38
38
  Store.set(:audit_table_pk_sequence, "#{audit_table}_#{audit_table_pk}_seq")
39
39
  Store.set(:shadow_table, "pgosc_st_#{client.table.downcase}_#{pgosc_identifier}")
40
40
 
41
- Store.set(:referential_foreign_key_statements, Query.referential_foreign_keys_to_refresh(client, client.table_name))
42
- Store.set(:self_foreign_key_statements, Query.self_foreign_keys_to_refresh(client, client.table_name))
41
+ Store.set(
42
+ :referential_foreign_key_statements,
43
+ Query.referential_foreign_keys_to_refresh(client, client.table_name),
44
+ )
45
+ Store.set(
46
+ :self_foreign_key_statements,
47
+ Query.self_foreign_keys_to_refresh(client, client.table_name),
48
+ )
43
49
  Store.set(:trigger_statements, Query.get_triggers_for(client, client.table_name))
44
50
  end
45
51
 
@@ -74,9 +80,7 @@ module PgOnlineSchemaChange
74
80
  def setup_signals!
75
81
  reader, writer = IO.pipe
76
82
 
77
- %w[TERM QUIT INT].each do |sig|
78
- trap(sig) { writer.puts sig }
79
- end
83
+ ['TERM', 'QUIT', 'INT'].each { |sig| trap(sig) { writer.puts sig } }
80
84
 
81
85
  reader
82
86
  end
@@ -85,14 +89,14 @@ module PgOnlineSchemaChange
85
89
  reader = setup_signals!
86
90
  signal = reader.gets.chomp
87
91
 
88
- while !reader.closed? && IO.select([reader]) # rubocop:disable Lint/UnreachableLoop
89
- logger.info "Signal #{signal} received, cleaning up"
92
+ while !reader.closed? && reader.wait_readable # rubocop:disable Lint/UnreachableLoop
93
+ logger.info("Signal #{signal} received, cleaning up")
90
94
 
91
95
  client.connection.cancel
92
96
  drop_and_cleanup!
93
97
  reader.close
94
98
 
95
- exit Signal.list[signal]
99
+ exit(Signal.list[signal])
96
100
  end
97
101
  end
98
102
 
@@ -124,13 +128,13 @@ module PgOnlineSchemaChange
124
128
  $$
125
129
  BEGIN
126
130
  IF ( TG_OP = 'INSERT') THEN
127
- INSERT INTO \"#{audit_table}\" select nextval(\'#{audit_table_pk_sequence}\'), 'INSERT', clock_timestamp(), NEW.* ;
131
+ INSERT INTO "#{audit_table}" select nextval('#{audit_table_pk_sequence}'), 'INSERT', clock_timestamp(), NEW.* ;
128
132
  RETURN NEW;
129
133
  ELSIF ( TG_OP = 'UPDATE') THEN
130
- INSERT INTO \"#{audit_table}\" select nextval(\'#{audit_table_pk_sequence}\'), 'UPDATE', clock_timestamp(), NEW.* ;
134
+ INSERT INTO "#{audit_table}" select nextval('#{audit_table_pk_sequence}'), 'UPDATE', clock_timestamp(), NEW.* ;
131
135
  RETURN NEW;
132
136
  ELSIF ( TG_OP = 'DELETE') THEN
133
- INSERT INTO \"#{audit_table}\" select nextval(\'#{audit_table_pk_sequence}\'), 'DELETE', clock_timestamp(), OLD.* ;
137
+ INSERT INTO "#{audit_table}" select nextval('#{audit_table_pk_sequence}'), 'DELETE', clock_timestamp(), OLD.* ;
134
138
  RETURN NEW;
135
139
  END IF;
136
140
  END;
@@ -158,10 +162,18 @@ module PgOnlineSchemaChange
158
162
  Query.run(client.connection, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE", true)
159
163
  logger.info("Setting up shadow table", { shadow_table: shadow_table })
160
164
 
161
- Query.run(client.connection, "SELECT create_table_all('#{client.table_name}', '#{shadow_table}');", true)
165
+ Query.run(
166
+ client.connection,
167
+ "SELECT create_table_all('#{client.table_name}', '#{shadow_table}');",
168
+ true,
169
+ )
162
170
 
163
171
  # update serials
164
- Query.run(client.connection, "SELECT fix_serial_sequence('#{client.table_name}', '#{shadow_table}');", true)
172
+ Query.run(
173
+ client.connection,
174
+ "SELECT fix_serial_sequence('#{client.table_name}', '#{shadow_table}');",
175
+ true,
176
+ )
165
177
  end
166
178
 
167
179
  def disable_vacuum!
@@ -170,8 +182,10 @@ module PgOnlineSchemaChange
170
182
  result = Query.storage_parameters_for(client, client.table_name, true) || ""
171
183
  Store.set(:primary_table_storage_parameters, result)
172
184
 
173
- logger.debug("Disabling vacuum on shadow and audit table",
174
- { shadow_table: shadow_table, audit_table: audit_table })
185
+ logger.debug(
186
+ "Disabling vacuum on shadow and audit table",
187
+ { shadow_table: shadow_table, audit_table: audit_table },
188
+ )
175
189
  sql = <<~SQL
176
190
  ALTER TABLE #{shadow_table} SET (
177
191
  autovacuum_enabled = false, toast.autovacuum_enabled = false
@@ -187,8 +201,10 @@ module PgOnlineSchemaChange
187
201
  def run_alter_statement!
188
202
  # re-uses transaction with serializable
189
203
  statement = Query.alter_statement_for(client, shadow_table)
190
- logger.info("Running alter statement on shadow table",
191
- { shadow_table: shadow_table, parent_table: client.table_name })
204
+ logger.info(
205
+ "Running alter statement on shadow table",
206
+ { shadow_table: shadow_table, parent_table: client.table_name },
207
+ )
192
208
  Query.run(client.connection, statement, true)
193
209
 
194
210
  Store.set(:dropped_columns_list, Query.dropped_columns(client))
@@ -200,10 +216,16 @@ module PgOnlineSchemaChange
200
216
  # Begin the process to copy data into copy table
201
217
  # depending on the size of the table, this can be a time
202
218
  # taking operation.
203
- logger.info("Clearing contents of audit table before copy..", { shadow_table: shadow_table, parent_table: client.table_name })
219
+ logger.info(
220
+ "Clearing contents of audit table before copy..",
221
+ { shadow_table: shadow_table, parent_table: client.table_name },
222
+ )
204
223
  Query.run(client.connection, "DELETE FROM #{audit_table}", true)
205
224
 
206
- logger.info("Copying contents..", { shadow_table: shadow_table, parent_table: client.table_name })
225
+ logger.info(
226
+ "Copying contents..",
227
+ { shadow_table: shadow_table, parent_table: client.table_name },
228
+ )
207
229
  if client.copy_statement
208
230
  query = format(client.copy_statement, shadow_table: shadow_table)
209
231
  return Query.run(client.connection, query, true)
@@ -225,9 +247,6 @@ module PgOnlineSchemaChange
225
247
 
226
248
  def swap!
227
249
  logger.info("Performing swap!")
228
-
229
- storage_params_reset = primary_table_storage_parameters.empty? ? "" : "ALTER TABLE #{client.table_name} SET (#{primary_table_storage_parameters});"
230
-
231
250
  # From here on, all statements are carried out in a single
232
251
  # transaction with access exclusive lock
233
252
 
@@ -235,12 +254,17 @@ module PgOnlineSchemaChange
235
254
 
236
255
  raise AccessExclusiveLockNotAcquired unless opened
237
256
 
238
- Query.run(client.connection, "SET statement_timeout to '#{SWAP_STATEMENT_TIMEOUT}';", opened)
257
+ Query.run(
258
+ client.connection,
259
+ "SET statement_timeout to '#{SWAP_STATEMENT_TIMEOUT}';",
260
+ opened,
261
+ )
239
262
 
240
263
  rows = Replay.rows_to_play(opened)
241
264
  Replay.play!(rows, opened)
242
265
 
243
- query_for_primary_key_refresh = Query.query_for_primary_key_refresh(shadow_table, primary_key, client.table_name, opened)
266
+ query_for_primary_key_refresh =
267
+ Query.query_for_primary_key_refresh(shadow_table, primary_key, client.table_name, opened)
244
268
 
245
269
  sql = <<~SQL
246
270
  #{query_for_primary_key_refresh};
@@ -296,6 +320,17 @@ module PgOnlineSchemaChange
296
320
  def pgosc_identifier
297
321
  @pgosc_identifier ||= SecureRandom.hex(3)
298
322
  end
323
+
324
+ def storage_params_reset
325
+ "ALTER TABLE #{client.table_name} RESET (autovacuum_enabled, toast.autovacuum_enabled);" +
326
+ (
327
+ if primary_table_storage_parameters.empty?
328
+ ""
329
+ else
330
+ "ALTER TABLE #{client.table_name} SET (#{primary_table_storage_parameters});"
331
+ end
332
+ )
333
+ end
299
334
  end
300
335
  end
301
336
  end
@@ -14,21 +14,31 @@ module PgOnlineSchemaChange
14
14
 
15
15
  class << self
16
16
  def alter_statement?(query)
17
- PgQuery.parse(query).tree.stmts.all? do |statement|
18
- statement.stmt.alter_table_stmt.instance_of?(PgQuery::AlterTableStmt) || statement.stmt.rename_stmt.instance_of?(PgQuery::RenameStmt)
19
- end
17
+ PgQuery
18
+ .parse(query)
19
+ .tree
20
+ .stmts
21
+ .all? do |statement|
22
+ statement.stmt.alter_table_stmt.instance_of?(PgQuery::AlterTableStmt) ||
23
+ statement.stmt.rename_stmt.instance_of?(PgQuery::RenameStmt)
24
+ end
20
25
  rescue PgQuery::ParseError
21
26
  false
22
27
  end
23
28
 
24
29
  def same_table?(query)
25
- tables = PgQuery.parse(query).tree.stmts.filter_map do |statement|
26
- if statement.stmt.alter_table_stmt.instance_of?(PgQuery::AlterTableStmt)
27
- statement.stmt.alter_table_stmt.relation.relname
28
- elsif statement.stmt.rename_stmt.instance_of?(PgQuery::RenameStmt)
29
- statement.stmt.rename_stmt.relation.relname
30
- end
31
- end
30
+ tables =
31
+ PgQuery
32
+ .parse(query)
33
+ .tree
34
+ .stmts
35
+ .filter_map do |statement|
36
+ if statement.stmt.alter_table_stmt.instance_of?(PgQuery::AlterTableStmt)
37
+ statement.stmt.alter_table_stmt.relation.relname
38
+ elsif statement.stmt.rename_stmt.instance_of?(PgQuery::RenameStmt)
39
+ statement.stmt.rename_stmt.relation.relname
40
+ end
41
+ end
32
42
 
33
43
  tables.uniq.count == 1
34
44
  rescue PgQuery::ParseError
@@ -36,15 +46,20 @@ module PgOnlineSchemaChange
36
46
  end
37
47
 
38
48
  def table(query)
39
- from_rename_statement = PgQuery.parse(query).tree.stmts.filter_map do |statement|
40
- statement.stmt.rename_stmt&.relation&.relname
41
- end[0]
49
+ from_rename_statement =
50
+ PgQuery
51
+ .parse(query)
52
+ .tree
53
+ .stmts
54
+ .filter_map { |statement| statement.stmt.rename_stmt&.relation&.relname }[
55
+ 0
56
+ ]
42
57
  PgQuery.parse(query).tables[0] || from_rename_statement
43
58
  end
44
59
 
45
60
  def table_name(query, table)
46
61
  table_name = "\"#{table}\""
47
- if table =~ /[A-Z]/ && (query.include? table_name) && table[0] != '"'
62
+ if table =~ /[A-Z]/ && query.include?(table_name) && table[0] != '"'
48
63
  table_name
49
64
  else
50
65
  table
@@ -52,7 +67,9 @@ module PgOnlineSchemaChange
52
67
  end
53
68
 
54
69
  def run(connection, query, reuse_trasaction = false, &block)
55
- connection.cancel if [PG::PQTRANS_INERROR, PG::PQTRANS_UNKNOWN].include?(connection.transaction_status)
70
+ if [PG::PQTRANS_INERROR, PG::PQTRANS_UNKNOWN].include?(connection.transaction_status)
71
+ connection.cancel
72
+ end
56
73
 
57
74
  logger.debug("Running query", { query: query })
58
75
 
@@ -74,18 +91,19 @@ module PgOnlineSchemaChange
74
91
  def table_columns(client, table = nil, reuse_trasaction = false)
75
92
  sql = <<~SQL
76
93
  SELECT attname as column_name, format_type(atttypid, atttypmod) as type, attnum as column_position FROM pg_attribute
77
- WHERE attrelid = \'#{table || client.table_name}\'::regclass AND attnum > 0 AND NOT attisdropped
94
+ WHERE attrelid = '#{table || client.table_name}'::regclass AND attnum > 0 AND NOT attisdropped
78
95
  ORDER BY attnum;
79
96
  SQL
80
97
  mapped_columns = []
81
98
 
82
99
  run(client.connection, sql, reuse_trasaction) do |result|
83
- mapped_columns = result.map do |row|
84
- row["column_name_regular"] = row["column_name"]
85
- row["column_name"] = client.connection.quote_ident(row["column_name"])
86
- row["column_position"] = row["column_position"].to_i
87
- row
88
- end
100
+ mapped_columns =
101
+ result.map do |row|
102
+ row["column_name_regular"] = row["column_name"]
103
+ row["column_name"] = client.connection.quote_ident(row["column_name"])
104
+ row["column_position"] = row["column_position"].to_i
105
+ row
106
+ end
89
107
  end
90
108
 
91
109
  mapped_columns
@@ -95,7 +113,9 @@ module PgOnlineSchemaChange
95
113
  parsed_query = PgQuery.parse(client.alter_statement)
96
114
 
97
115
  parsed_query.tree.stmts.each do |statement|
98
- statement.stmt.alter_table_stmt.relation.relname = shadow_table if statement.stmt.alter_table_stmt
116
+ if statement.stmt.alter_table_stmt
117
+ statement.stmt.alter_table_stmt.relation.relname = shadow_table
118
+ end
99
119
 
100
120
  statement.stmt.rename_stmt.relation.relname = shadow_table if statement.stmt.rename_stmt
101
121
  end
@@ -106,13 +126,11 @@ module PgOnlineSchemaChange
106
126
  query = <<~SQL
107
127
  SELECT indexdef, schemaname
108
128
  FROM pg_indexes
109
- WHERE schemaname = \'#{client.schema}\' AND tablename = \'#{table}\'
129
+ WHERE schemaname = '#{client.schema}' AND tablename = '#{table}'
110
130
  SQL
111
131
 
112
132
  indexes = []
113
- run(client.connection, query) do |result|
114
- indexes = result.map { |row| row["indexdef"] }
115
- end
133
+ run(client.connection, query) { |result| indexes = result.map { |row| row["indexdef"] } }
116
134
 
117
135
  indexes
118
136
  end
@@ -120,13 +138,11 @@ module PgOnlineSchemaChange
120
138
  def get_triggers_for(client, table)
121
139
  query = <<~SQL
122
140
  SELECT pg_get_triggerdef(oid) as tdef FROM pg_trigger
123
- WHERE tgrelid = \'#{client.schema}.#{table}\'::regclass AND tgisinternal = FALSE;
141
+ WHERE tgrelid = '#{client.schema}.#{table}'::regclass AND tgisinternal = FALSE;
124
142
  SQL
125
143
 
126
144
  triggers = []
127
- run(client.connection, query) do |result|
128
- triggers = result.map { |row| "#{row["tdef"]};" }
129
- end
145
+ run(client.connection, query) { |result| triggers = result.map { |row| "#{row["tdef"]};" } }
130
146
 
131
147
  triggers.join(";")
132
148
  end
@@ -144,9 +160,7 @@ module PgOnlineSchemaChange
144
160
  SQL
145
161
 
146
162
  constraints = []
147
- run(client.connection, query) do |result|
148
- constraints = result.map { |row| row }
149
- end
163
+ run(client.connection, query) { |result| constraints = result.map { |row| row } }
150
164
 
151
165
  constraints
152
166
  end
@@ -164,72 +178,93 @@ module PgOnlineSchemaChange
164
178
  end
165
179
 
166
180
  def referential_foreign_keys_to_refresh(client, table)
167
- references = get_all_constraints_for(client).select do |row|
168
- row["table_from"] == table && row["constraint_type"] == "f"
169
- end
181
+ references =
182
+ get_all_constraints_for(client).select do |row|
183
+ row["table_from"] == table && row["constraint_type"] == "f"
184
+ end
170
185
 
171
- references.map do |row|
172
- add_statement = if row["definition"].end_with?("NOT VALID")
173
- "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]};"
174
- else
175
- "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]} NOT VALID;"
176
- end
186
+ references
187
+ .map do |row|
188
+ add_statement =
189
+ if row["definition"].end_with?("NOT VALID")
190
+ "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]};"
191
+ else
192
+ "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]} NOT VALID;"
193
+ end
177
194
 
178
- drop_statement = "ALTER TABLE #{row["table_on"]} DROP CONSTRAINT #{row["constraint_name"]};"
195
+ drop_statement =
196
+ "ALTER TABLE #{row["table_on"]} DROP CONSTRAINT #{row["constraint_name"]};"
179
197
 
180
- "#{drop_statement} #{add_statement}"
181
- end.join
198
+ "#{drop_statement} #{add_statement}"
199
+ end
200
+ .join
182
201
  end
183
202
 
184
203
  def self_foreign_keys_to_refresh(client, table)
185
- references = get_all_constraints_for(client).select do |row|
186
- row["table_on"] == table && row["constraint_type"] == "f"
187
- end
204
+ references =
205
+ get_all_constraints_for(client).select do |row|
206
+ row["table_on"] == table && row["constraint_type"] == "f"
207
+ end
188
208
 
189
- references.map do |row|
190
- add_statement = if row["definition"].end_with?("NOT VALID")
191
- "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]};"
192
- else
193
- "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]} NOT VALID;"
194
- end
195
- add_statement
196
- end.join
209
+ references
210
+ .map do |row|
211
+ add_statement =
212
+ if row["definition"].end_with?("NOT VALID")
213
+ "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]};"
214
+ else
215
+ "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]} NOT VALID;"
216
+ end
217
+ add_statement
218
+ end
219
+ .join
197
220
  end
198
221
 
199
222
  def get_foreign_keys_to_validate(client, table)
200
223
  constraints = get_all_constraints_for(client)
201
- referential_foreign_keys = constraints.select do |row|
202
- row["table_from"] == table && row["constraint_type"] == "f"
203
- end
224
+ referential_foreign_keys =
225
+ constraints.select { |row| row["table_from"] == table && row["constraint_type"] == "f" }
204
226
 
205
- self_foreign_keys = constraints.select do |row|
206
- row["table_on"] == table && row["constraint_type"] == "f"
207
- end
227
+ self_foreign_keys =
228
+ constraints.select { |row| row["table_on"] == table && row["constraint_type"] == "f" }
208
229
 
209
- [referential_foreign_keys, self_foreign_keys].flatten.map do |row|
210
- "ALTER TABLE #{row["table_on"]} VALIDATE CONSTRAINT #{row["constraint_name"]};"
211
- end.join
230
+ [referential_foreign_keys, self_foreign_keys].flatten
231
+ .map do |row|
232
+ "ALTER TABLE #{row["table_on"]} VALIDATE CONSTRAINT #{row["constraint_name"]};"
233
+ end
234
+ .join
212
235
  end
213
236
 
214
237
  def dropped_columns(client)
215
- PgQuery.parse(client.alter_statement).tree.stmts.map do |statement|
216
- next if statement.stmt.alter_table_stmt.nil?
217
-
218
- statement.stmt.alter_table_stmt.cmds.map do |cmd|
219
- cmd.alter_table_cmd.name if cmd.alter_table_cmd.subtype == DROPPED_COLUMN_TYPE
238
+ PgQuery
239
+ .parse(client.alter_statement)
240
+ .tree
241
+ .stmts
242
+ .map do |statement|
243
+ next if statement.stmt.alter_table_stmt.nil?
244
+
245
+ statement.stmt.alter_table_stmt.cmds.map do |cmd|
246
+ cmd.alter_table_cmd.name if cmd.alter_table_cmd.subtype == DROPPED_COLUMN_TYPE
247
+ end
220
248
  end
221
- end.flatten.compact
249
+ .flatten
250
+ .compact
222
251
  end
223
252
 
224
253
  def renamed_columns(client)
225
- PgQuery.parse(client.alter_statement).tree.stmts.map do |statement|
226
- next if statement.stmt.rename_stmt.nil?
227
-
228
- {
229
- old_name: statement.stmt.rename_stmt.subname,
230
- new_name: statement.stmt.rename_stmt.newname,
231
- }
232
- end.flatten.compact
254
+ PgQuery
255
+ .parse(client.alter_statement)
256
+ .tree
257
+ .stmts
258
+ .map do |statement|
259
+ next if statement.stmt.rename_stmt.nil?
260
+
261
+ {
262
+ old_name: statement.stmt.rename_stmt.subname,
263
+ new_name: statement.stmt.rename_stmt.newname,
264
+ }
265
+ end
266
+ .flatten
267
+ .compact
233
268
  end
234
269
 
235
270
  def primary_key_for(client, table)
@@ -238,9 +273,9 @@ module PgOnlineSchemaChange
238
273
  pg_attribute.attname as column_name
239
274
  FROM pg_index, pg_class, pg_attribute, pg_namespace
240
275
  WHERE
241
- pg_class.oid = \'#{table}\'::regclass AND
276
+ pg_class.oid = '#{table}'::regclass AND
242
277
  indrelid = pg_class.oid AND
243
- nspname = \'#{client.schema}\' AND
278
+ nspname = '#{client.schema}' AND
244
279
  pg_class.relnamespace = pg_namespace.oid AND
245
280
  pg_attribute.attrelid = pg_class.oid AND
246
281
  pg_attribute.attnum = any(pg_index.indkey)
@@ -248,16 +283,14 @@ module PgOnlineSchemaChange
248
283
  SQL
249
284
 
250
285
  columns = []
251
- run(client.connection, query) do |result|
252
- columns = result.map { |row| row["column_name"] }
253
- end
286
+ run(client.connection, query) { |result| columns = result.map { |row| row["column_name"] } }
254
287
 
255
288
  columns.first
256
289
  end
257
290
 
258
291
  def storage_parameters_for(client, table, reuse_trasaction = false)
259
292
  query = <<~SQL
260
- SELECT array_to_string(reloptions, ',') as params FROM pg_class WHERE relname=\'#{table}\';
293
+ SELECT array_to_string(reloptions, ',') as params FROM pg_class WHERE relname='#{table}';
261
294
  SQL
262
295
 
263
296
  columns = []
@@ -305,16 +338,17 @@ module PgOnlineSchemaChange
305
338
  logger.info("Terminating other backends")
306
339
 
307
340
  query = <<~SQL
308
- SELECT pg_terminate_backend(pid) FROM pg_locks WHERE locktype = 'relation' AND relation = \'#{table}\'::regclass::oid AND pid <> pg_backend_pid()
341
+ SELECT pg_terminate_backend(pid) FROM pg_locks WHERE locktype = 'relation' AND relation = '#{table}'::regclass::oid AND pid <> pg_backend_pid()
309
342
  SQL
310
343
 
311
344
  run(client.connection, query, true)
312
345
  end
313
346
 
314
347
  def copy_data_statement(client, shadow_table, reuse_trasaction = false)
315
- select_columns = table_columns(client, client.table_name, reuse_trasaction).map do |entry|
316
- entry["column_name_regular"]
317
- end
348
+ select_columns =
349
+ table_columns(client, client.table_name, reuse_trasaction).map do |entry|
350
+ entry["column_name_regular"]
351
+ end
318
352
 
319
353
  select_columns -= dropped_columns_list if dropped_columns_list.any?
320
354
 
@@ -332,9 +366,7 @@ module PgOnlineSchemaChange
332
366
  client.connection.quote_ident(insert_into_column)
333
367
  end
334
368
 
335
- select_columns.map! do |select_column|
336
- client.connection.quote_ident(select_column)
337
- end
369
+ select_columns.map! { |select_column| client.connection.quote_ident(select_column) }
338
370
 
339
371
  <<~SQL
340
372
  INSERT INTO #{shadow_table}(#{insert_into_columns.join(", ")})
@@ -345,14 +377,12 @@ module PgOnlineSchemaChange
345
377
 
346
378
  def primary_key_sequence(shadow_table, primary_key, opened)
347
379
  query = <<~SQL
348
- SELECT pg_get_serial_sequence(\'#{shadow_table}\', \'#{primary_key}\') as sequence_name
380
+ SELECT pg_get_serial_sequence('#{shadow_table}', '#{primary_key}') as sequence_name
349
381
  SQL
350
382
 
351
383
  result = run(client.connection, query, opened)
352
384
 
353
- result.map do |row|
354
- row["sequence_name"]
355
- end&.first
385
+ result.map { |row| row["sequence_name"] }&.first
356
386
  end
357
387
 
358
388
  def query_for_primary_key_refresh(shadow_table, primary_key, table, opened)
@@ -361,7 +391,7 @@ module PgOnlineSchemaChange
361
391
  return "" if sequence_name.nil?
362
392
 
363
393
  <<~SQL
364
- SELECT setval((select pg_get_serial_sequence(\'#{shadow_table}\', \'#{primary_key}\')), (SELECT max(#{primary_key}) FROM #{table}));
394
+ SELECT setval((select pg_get_serial_sequence('#{shadow_table}', '#{primary_key}')), (SELECT max(#{primary_key}) FROM #{table}));
365
395
  SQL
366
396
  end
367
397
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
4
-
5
3
  module PgOnlineSchemaChange
6
4
  class Replay
7
5
  extend Helper
@@ -29,7 +27,9 @@ module PgOnlineSchemaChange
29
27
  SQL
30
28
 
31
29
  rows = []
32
- Query.run(client.connection, select_query, reuse_trasaction) { |result| rows = result.map { |row| row } }
30
+ Query.run(client.connection, select_query, reuse_trasaction) do |result|
31
+ rows = result.map { |row| row }
32
+ end
33
33
 
34
34
  rows
35
35
  end
@@ -48,14 +48,10 @@ module PgOnlineSchemaChange
48
48
 
49
49
  # Remove audit table cols, since we will be
50
50
  # re-mapping them for inserts and updates
51
- reserved_columns.each do |col|
52
- new_row.delete(col)
53
- end
51
+ reserved_columns.each { |col| new_row.delete(col) }
54
52
 
55
53
  if dropped_columns_list.any?
56
- dropped_columns_list.each do |dropped_column|
57
- new_row.delete(dropped_column)
58
- end
54
+ dropped_columns_list.each { |dropped_column| new_row.delete(dropped_column) }
59
55
  end
60
56
 
61
57
  if renamed_columns_list.any?
@@ -69,13 +65,9 @@ module PgOnlineSchemaChange
69
65
 
70
66
  # quote indent column to preserve case insensitivity
71
67
  # ensure rows are escaped
72
- new_row = new_row.transform_keys do |column|
73
- client.connection.quote_ident(column)
74
- end
68
+ new_row = new_row.transform_keys { |column| client.connection.quote_ident(column) }
75
69
 
76
- new_row = new_row.transform_values do |value|
77
- client.connection.escape_string(value)
78
- end
70
+ new_row = new_row.transform_values { |value| client.connection.escape_string(value) }
79
71
 
80
72
  case row[operation_type_column]
81
73
  when "INSERT"
@@ -89,21 +81,19 @@ module PgOnlineSchemaChange
89
81
 
90
82
  to_be_deleted_rows << "'#{row[audit_table_pk]}'"
91
83
  when "UPDATE"
92
- set_values = new_row.map do |column, value|
93
- "#{column} = '#{value}'"
94
- end.join(",")
84
+ set_values = new_row.map { |column, value| "#{column} = '#{value}'" }.join(",")
95
85
 
96
86
  sql = <<~SQL
97
87
  UPDATE #{shadow_table}
98
88
  SET #{set_values}
99
- WHERE #{primary_key}=\'#{row[primary_key]}\';
89
+ WHERE #{primary_key}='#{row[primary_key]}';
100
90
  SQL
101
91
  to_be_replayed << sql
102
92
 
103
93
  to_be_deleted_rows << "'#{row[audit_table_pk]}'"
104
94
  when "DELETE"
105
95
  sql = <<~SQL
106
- DELETE FROM #{shadow_table} WHERE #{primary_key}=\'#{row[primary_key]}\';
96
+ DELETE FROM #{shadow_table} WHERE #{primary_key}='#{row[primary_key]}';
107
97
  SQL
108
98
  to_be_replayed << sql
109
99
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgOnlineSchemaChange
4
- VERSION = "0.7.5"
4
+ VERSION = "0.8.0"
5
5
  end