pg_online_schema_change 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b06d39169d55c016d78969968c71cac7f0c49a3c716d0bc8c5004905ef820fb0
4
- data.tar.gz: 78fcc0a928a5efa645ec201cfca093f4ef078b8d683f0776a7f9ad91bb11ef99
3
+ metadata.gz: 8ef1069f7d159544838ec27cf518f98eb31609a0a2e1878ebd40246b10a6b534
4
+ data.tar.gz: 8e83cbac78164fb10870537bf4867020eae7cf06f4cd91930a2c8846fbc76c7c
5
5
  SHA512:
6
- metadata.gz: 179fcaf09bcc36b69186ba48494835841a88c095e010756f0e6f322a146279d0790403f2c195f23f483e89a1cb74c10b50a3ceee26ad6d311e3d9977af1b8c07
7
- data.tar.gz: 157255f9d901ec2cb980d84bd664cc0eaae32854bdd79ebd262b2112eef965f8dc2d123277a35446fefd6ecdac4a4ba4c94769589461053241d1eedbe40efa52
6
+ metadata.gz: 2657c94b3b07730aa3bb282f34cd1ee95f0549d3649b39a61be3ce1b6d2ba5832a1914b6a9788778c912464cbd9773b5e967ed4e6c896127d60e62a0daa76c99
7
+ data.tar.gz: 4788523d691c25045b7f3c539f9743d880fabcbb01887ae34ec55a6c8a829804a9f4d43f619e79e0c44b1c9fff6ea88361fb5ac1111bc1f491aa17e6e43336d0
data/.rubocop.yml CHANGED
@@ -1,3 +1,5 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
1
3
  require:
2
4
  - rubocop-rspec
3
5
  - rubocop-packaging
@@ -14,71 +16,70 @@ AllCops:
14
16
  - "vendor/**/*"
15
17
 
16
18
  Layout/HashAlignment:
17
- EnforcedColonStyle:
18
- - table
19
- - key
20
- EnforcedHashRocketStyle:
21
- - table
22
- - key
19
+ EnforcedColonStyle: key
20
+ EnforcedHashRocketStyle: key
23
21
 
24
22
  Layout/SpaceAroundEqualsInParameterDefault:
25
- EnforcedStyle: no_space
23
+ EnforcedStyle: space
26
24
 
27
25
  Metrics/AbcSize:
28
- Max: 20
26
+ Enabled: true
27
+ Max: 40
29
28
  Exclude:
30
- - "test/**/*"
29
+ - "spec/**/*"
31
30
 
32
31
  Metrics/BlockLength:
32
+ Max: 100
33
33
  Exclude:
34
34
  - "*.gemspec"
35
35
  - "Rakefile"
36
+ - "spec/**/*"
36
37
 
37
38
  Metrics/ClassLength:
38
39
  Exclude:
39
40
  - "test/**/*"
40
41
 
41
42
  Metrics/MethodLength:
42
- Max: 18
43
+ Max: 30
43
44
  Exclude:
44
45
  - "test/**/*"
45
46
 
46
47
  Metrics/ParameterLists:
47
- Max: 6
48
+ Max: 5
48
49
 
49
50
  Naming/MemoizedInstanceVariableName:
50
- Enabled: false
51
+ Enabled: true
51
52
 
52
53
  Naming/VariableNumber:
53
- Enabled: false
54
-
55
- Rake/Desc:
56
- Enabled: false
54
+ Enabled: true
57
55
 
58
56
  Style/BarePercentLiterals:
59
57
  EnforcedStyle: percent_q
60
58
 
61
59
  Style/ClassAndModuleChildren:
62
- Enabled: false
60
+ Enabled: true
63
61
 
64
62
  Style/Documentation:
65
63
  Enabled: false
66
64
 
67
65
  Style/DoubleNegation:
68
- Enabled: false
66
+ Enabled: true
69
67
 
70
68
  Style/EmptyMethod:
71
- Enabled: false
69
+ Enabled: true
72
70
 
73
71
  Style/FrozenStringLiteralComment:
74
- Enabled: false
72
+ Enabled: true
75
73
 
76
74
  Style/NumericPredicate:
77
- Enabled: false
75
+ Enabled: true
78
76
 
79
77
  Style/StringLiterals:
80
78
  EnforcedStyle: double_quotes
81
79
 
80
+ Style/StringLiteralsInInterpolation:
81
+ EnforcedStyle: double_quotes
82
+
82
83
  Style/TrivialAccessors:
83
84
  AllowPredicates: true
84
85
 
@@ -91,9 +92,41 @@ Style/TrailingCommaInArrayLiteral:
91
92
  Style/TrailingCommaInHashLiteral:
92
93
  EnforcedStyleForMultiline: comma
93
94
 
94
- Style/SpaceAroundEqualsInParameterDefault:
95
- EnforcedStyle: space
95
+ Layout/MultilineArrayBraceLayout:
96
+ Enabled: true
97
+ EnforcedStyle: symmetrical
96
98
 
97
- Style/MultilineHashBraceLayout:
99
+ Layout/MultilineHashBraceLayout:
98
100
  Enabled: true
99
101
  EnforcedStyle: symmetrical
102
+
103
+ Layout/MultilineAssignmentLayout:
104
+ Enabled: true
105
+ EnforcedStyle: same_line
106
+
107
+ Layout/FirstArrayElementIndentation:
108
+ Enabled: true
109
+ EnforcedStyle: consistent
110
+
111
+ Layout/FirstHashElementIndentation:
112
+ Enabled: true
113
+ EnforcedStyle: consistent
114
+
115
+ Layout/MultilineHashKeyLineBreaks:
116
+ Enabled: true
117
+
118
+ Layout/LineLength:
119
+ Enabled: true
120
+ Max: 250
121
+
122
+ Style/FormatStringToken:
123
+ Enabled: true
124
+ EnforcedStyle: template
125
+
126
+ RSpec/MessageSpies:
127
+ Enabled: true
128
+ EnforcedStyle: receive
129
+
130
+ RSpec/FilePath:
131
+ Enabled: true
132
+ SpecSuffixOnly: true
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,44 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2022-02-21 22:46:44 UTC using RuboCop version 1.23.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 2
10
+ # Configuration parameters: CountComments, CountAsOne.
11
+ Metrics/ClassLength:
12
+ Max: 233
13
+
14
+ # Offense count: 2
15
+ # Configuration parameters: IgnoredMethods.
16
+ Metrics/CyclomaticComplexity:
17
+ Max: 15
18
+
19
+ # Offense count: 2
20
+ # Configuration parameters: IgnoredMethods.
21
+ Metrics/PerceivedComplexity:
22
+ Max: 13
23
+
24
+ # Offense count: 1
25
+ Packaging/GemspecGit:
26
+ Exclude:
27
+ - 'pg_online_schema_change.gemspec'
28
+
29
+ # Offense count: 62
30
+ # Configuration parameters: CountAsOne.
31
+ RSpec/ExampleLength:
32
+ Max: 55
33
+
34
+ # Offense count: 38
35
+ RSpec/MultipleExpectations:
36
+ Max: 14
37
+
38
+ # Offense count: 6
39
+ # Configuration parameters: AllowedMethods.
40
+ # AllowedMethods: respond_to_missing?
41
+ Style/OptionalBooleanParameter:
42
+ Exclude:
43
+ - 'lib/pg_online_schema_change/query.rb'
44
+ - 'lib/pg_online_schema_change/replay.rb'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [0.3.0] - 2022-02-21
2
+
3
+ - Explicitly call dependencies and bump dependencies by @shayonj https://github.com/shayonj/pg-osc/pull/44
4
+ - Introduce Dockerfile and release process https://github.com/shayonj/pg-osc/pull/45
5
+
1
6
  ## [0.2.0] - 2022-02-17
2
7
 
3
8
  - Use ISOLATION LEVEL SERIALIZABLE ([#42](https://github.com/shayonj/pg-osc/pull/42)) (props to @jfrost)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pg_online_schema_change (0.2.0)
4
+ pg_online_schema_change (0.3.0)
5
5
  ougai (~> 2.0.0)
6
6
  pg (~> 1.3.2)
7
7
  pg_query (~> 2.1.3)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "thor"
2
4
 
3
5
  module PgOnlineSchemaChange
@@ -25,7 +27,7 @@ module PgOnlineSchemaChange
25
27
  def perform
26
28
  client_options = Struct.new(*options.keys.map(&:to_sym)).new(*options.values)
27
29
 
28
- PgOnlineSchemaChange.logger = client_options.verbose
30
+ PgOnlineSchemaChange.logger(verbose: client_options.verbose)
29
31
  PgOnlineSchemaChange::Orchestrate.run!(client_options)
30
32
  end
31
33
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "pg"
2
4
 
3
5
  module PgOnlineSchemaChange
@@ -16,7 +18,9 @@ module PgOnlineSchemaChange
16
18
  @drop = options.drop
17
19
  @kill_backends = options.kill_backends
18
20
  @wait_time_for_lock = options.wait_time_for_lock
21
+
19
22
  handle_copy_statement(options.copy_statement)
23
+ handle_validations
20
24
 
21
25
  @connection = PG.connect(
22
26
  dbname: @dbname,
@@ -26,17 +30,19 @@ module PgOnlineSchemaChange
26
30
  port: @port,
27
31
  )
28
32
 
29
- raise Error, "Not a valid ALTER statement: #{@alter_statement}" unless Query.alter_statement?(@alter_statement)
30
-
31
- unless Query.same_table?(@alter_statement)
32
- raise Error "All statements should belong to the same table: #{@alter_statement}"
33
- end
34
-
35
33
  @table = Query.table(@alter_statement)
36
34
 
37
35
  PgOnlineSchemaChange.logger.debug("Connection established")
38
36
  end
39
37
 
38
+ def handle_validations
39
+ raise Error, "Not a valid ALTER statement: #{@alter_statement}" unless Query.alter_statement?(@alter_statement)
40
+
41
+ return if Query.same_table?(@alter_statement)
42
+
43
+ raise Error "All statements should belong to the same table: #{@alter_statement}"
44
+ end
45
+
40
46
  def handle_copy_statement(statement)
41
47
  return if statement.nil? || statement == ""
42
48
 
@@ -1,4 +1,6 @@
1
- FUNC_FIX_SERIAL_SEQUENCE = <<~SQL.freeze
1
+ # frozen_string_literal: true
2
+
3
+ FUNC_FIX_SERIAL_SEQUENCE = <<~SQL
2
4
  CREATE OR REPLACE FUNCTION fix_serial_sequence(_table regclass, _newtable text)
3
5
  RETURNS void AS
4
6
  $func$
@@ -35,7 +37,7 @@ FUNC_FIX_SERIAL_SEQUENCE = <<~SQL.freeze
35
37
  $func$ LANGUAGE plpgsql VOLATILE;
36
38
  SQL
37
39
 
38
- FUNC_CREATE_TABLE_ALL = <<~SQL.freeze
40
+ FUNC_CREATE_TABLE_ALL = <<~SQL
39
41
  CREATE OR REPLACE FUNCTION create_table_all(source_table text, newsource_table text)
40
42
  RETURNS void language plpgsql
41
43
  as $$
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PgOnlineSchemaChange
2
4
  module Helper
3
5
  def primary_key
@@ -15,7 +17,14 @@ module PgOnlineSchemaChange
15
17
  result = Store.send(:get, method)
16
18
  return result if result
17
19
 
18
- raise ArgumentError, "Method `#{method}` doesn't exist."
20
+ super
21
+ end
22
+
23
+ def respond_to_missing?(method_name, *args)
24
+ result = Store.send(:get, method)
25
+ return true if result
26
+
27
+ super
19
28
  end
20
29
  end
21
30
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "securerandom"
2
4
 
3
5
  module PgOnlineSchemaChange
4
6
  class Orchestrate
5
- SWAP_STATEMENT_TIMEOUT = "5s".freeze
7
+ SWAP_STATEMENT_TIMEOUT = "5s"
6
8
 
7
9
  extend Helper
8
10
 
@@ -21,12 +23,20 @@ module PgOnlineSchemaChange
21
23
  Query.run(client.connection, FUNC_FIX_SERIAL_SEQUENCE)
22
24
  Query.run(client.connection, FUNC_CREATE_TABLE_ALL)
23
25
 
26
+ setup_store
27
+ end
28
+
29
+ def setup_store
24
30
  # Set this early on to ensure their creation and cleanup (unexpected)
25
31
  # happens at all times. IOW, the calls from Store.get always return
26
32
  # the same value.
27
33
  Store.set(:old_primary_table, "pgosc_op_table_#{client.table}")
28
- Store.set(:audit_table, "pgosc_at_#{client.table}_#{random_string}")
29
- Store.set(:shadow_table, "pgosc_st_#{client.table}_#{random_string}")
34
+ Store.set(:audit_table, "pgosc_at_#{client.table}_#{pgosc_identifier}")
35
+ Store.set(:operation_type_column, "operation_type_#{pgosc_identifier}")
36
+ Store.set(:trigger_time_column, "trigger_time_#{pgosc_identifier}")
37
+ Store.set(:audit_table_pk, "at_#{pgosc_identifier}_id")
38
+ Store.set(:audit_table_pk_sequence, "#{audit_table}_#{audit_table_pk}_seq")
39
+ Store.set(:shadow_table, "pgosc_st_#{client.table}_#{pgosc_identifier}")
30
40
  end
31
41
 
32
42
  def run!(options)
@@ -70,7 +80,7 @@ module PgOnlineSchemaChange
70
80
  reader = setup_signals!
71
81
  signal = reader.gets.chomp
72
82
 
73
- while !reader.closed? && IO.select([reader])
83
+ while !reader.closed? && IO.select([reader]) # rubocop:disable Lint/UnreachableLoop
74
84
  logger.info "Signal #{signal} received, cleaning up"
75
85
 
76
86
  client.connection.cancel
@@ -85,7 +95,7 @@ module PgOnlineSchemaChange
85
95
  logger.info("Setting up audit table", { audit_table: audit_table })
86
96
 
87
97
  sql = <<~SQL
88
- CREATE TABLE #{audit_table} (operation_type text, trigger_time timestamp, LIKE #{client.table});
98
+ CREATE TABLE #{audit_table} (#{audit_table_pk} SERIAL PRIMARY KEY, #{operation_type_column} text, #{trigger_time_column} timestamp, LIKE #{client.table});
89
99
  SQL
90
100
 
91
101
  Query.run(client.connection, sql)
@@ -109,13 +119,13 @@ module PgOnlineSchemaChange
109
119
  $$
110
120
  BEGIN
111
121
  IF ( TG_OP = 'INSERT') THEN
112
- INSERT INTO \"#{audit_table}\" select 'INSERT', now(), NEW.* ;
122
+ INSERT INTO \"#{audit_table}\" select nextval(\'#{audit_table_pk_sequence}\'), 'INSERT', clock_timestamp(), NEW.* ;
113
123
  RETURN NEW;
114
124
  ELSIF ( TG_OP = 'UPDATE') THEN
115
- INSERT INTO \"#{audit_table}\" select 'UPDATE', now(), NEW.* ;
125
+ INSERT INTO \"#{audit_table}\" select nextval(\'#{audit_table_pk_sequence}\'), 'UPDATE', clock_timestamp(), NEW.* ;
116
126
  RETURN NEW;
117
127
  ELSIF ( TG_OP = 'DELETE') THEN
118
- INSERT INTO \"#{audit_table}\" select 'DELETE', now(), OLD.* ;
128
+ INSERT INTO \"#{audit_table}\" select nextval(\'#{audit_table_pk_sequence}\'), 'DELETE', clock_timestamp(), OLD.* ;
119
129
  RETURN NEW;
120
130
  END IF;
121
131
  END;
@@ -153,7 +163,7 @@ module PgOnlineSchemaChange
153
163
  # re-uses transaction with serializable
154
164
  # Disabling vacuum to avoid any issues during the process
155
165
  result = Query.storage_parameters_for(client, client.table, true) || ""
156
- primary_table_storage_parameters = Store.set(:primary_table_storage_parameters, result)
166
+ Store.set(:primary_table_storage_parameters, result)
157
167
 
158
168
  logger.debug("Disabling vacuum on shadow and audit table",
159
169
  { shadow_table: shadow_table, audit_table: audit_table })
@@ -185,8 +195,7 @@ module PgOnlineSchemaChange
185
195
  # Begin the process to copy data into copy table
186
196
  # depending on the size of the table, this can be a time
187
197
  # taking operation.
188
- logger.info("Clearing contents of audit table before copy..",
189
- { shadow_table: shadow_table, parent_table: client.table })
198
+ logger.info("Clearing contents of audit table before copy..", { shadow_table: shadow_table, parent_table: client.table })
190
199
  Query.run(client.connection, "DELETE FROM #{audit_table}", true)
191
200
 
192
201
  logger.info("Copying contents..", { shadow_table: shadow_table, parent_table: client.table })
@@ -272,8 +281,10 @@ module PgOnlineSchemaChange
272
281
  Query.run(client.connection, sql)
273
282
  end
274
283
 
275
- private def random_string
276
- @random_string ||= SecureRandom.hex(3)
284
+ private
285
+
286
+ def pgosc_identifier
287
+ @pgosc_identifier ||= SecureRandom.hex(3)
277
288
  end
278
289
  end
279
290
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "pg_query"
2
4
  require "pg"
3
5
 
@@ -5,7 +7,7 @@ module PgOnlineSchemaChange
5
7
  class Query
6
8
  extend Helper
7
9
 
8
- INDEX_SUFFIX = "_pgosc".freeze
10
+ INDEX_SUFFIX = "_pgosc"
9
11
  DROPPED_COLUMN_TYPE = :AT_DropColumn
10
12
  RENAMED_COLUMN_TYPE = :AT_RenameColumn
11
13
  LOCK_ATTEMPT = 4
@@ -15,28 +17,28 @@ module PgOnlineSchemaChange
15
17
  PgQuery.parse(query).tree.stmts.all? do |statement|
16
18
  statement.stmt.alter_table_stmt.instance_of?(PgQuery::AlterTableStmt) || statement.stmt.rename_stmt.instance_of?(PgQuery::RenameStmt)
17
19
  end
18
- rescue PgQuery::ParseError => e
20
+ rescue PgQuery::ParseError
19
21
  false
20
22
  end
21
23
 
22
24
  def same_table?(query)
23
- tables = PgQuery.parse(query).tree.stmts.map do |statement|
25
+ tables = PgQuery.parse(query).tree.stmts.filter_map do |statement|
24
26
  if statement.stmt.alter_table_stmt.instance_of?(PgQuery::AlterTableStmt)
25
27
  statement.stmt.alter_table_stmt.relation.relname
26
28
  elsif statement.stmt.rename_stmt.instance_of?(PgQuery::RenameStmt)
27
29
  statement.stmt.rename_stmt.relation.relname
28
30
  end
29
- end.compact
31
+ end
30
32
 
31
33
  tables.uniq.count == 1
32
- rescue PgQuery::ParseError => e
34
+ rescue PgQuery::ParseError
33
35
  false
34
36
  end
35
37
 
36
38
  def table(query)
37
- from_rename_statement = PgQuery.parse(query).tree.stmts.map do |statement|
39
+ from_rename_statement = PgQuery.parse(query).tree.stmts.filter_map do |statement|
38
40
  statement.stmt.rename_stmt&.relation&.relname
39
- end.compact[0]
41
+ end[0]
40
42
  PgQuery.parse(query).tables[0] || from_rename_statement
41
43
  end
42
44
 
@@ -48,7 +50,7 @@ module PgOnlineSchemaChange
48
50
  connection.async_exec("BEGIN;")
49
51
 
50
52
  result = connection.async_exec(query, &block)
51
- rescue Exception
53
+ rescue Exception # rubocop:disable Lint/RescueException
52
54
  connection.cancel if connection.transaction_status != PG::PQTRANS_IDLE
53
55
  connection.block
54
56
  logger.info("Exception raised, rolling back query", { rollback: true, query: query })
@@ -144,11 +146,11 @@ module PgOnlineSchemaChange
144
146
  end
145
147
 
146
148
  references.map do |row|
147
- if row["definition"].end_with?("NOT VALID")
148
- add_statement = "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]};"
149
- else
150
- add_statement = "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]} NOT VALID;"
151
- end
149
+ add_statement = if row["definition"].end_with?("NOT VALID")
150
+ "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]};"
151
+ else
152
+ "ALTER TABLE #{row["table_on"]} ADD CONSTRAINT #{row["constraint_name"]} #{row["definition"]} NOT VALID;"
153
+ end
152
154
 
153
155
  drop_statement = "ALTER TABLE #{row["table_on"]} DROP CONSTRAINT #{row["constraint_name"]};"
154
156
 
@@ -291,7 +293,7 @@ module PgOnlineSchemaChange
291
293
  client.connection.quote_ident(select_column)
292
294
  end
293
295
 
294
- sql = <<~SQL
296
+ <<~SQL
295
297
  INSERT INTO #{shadow_table}(#{insert_into_columns.join(", ")})
296
298
  SELECT #{select_columns.join(", ")}
297
299
  FROM ONLY #{client.table}
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
4
+
1
5
  module PgOnlineSchemaChange
2
6
  class Replay
3
7
  extend Helper
@@ -5,7 +9,6 @@ module PgOnlineSchemaChange
5
9
  class << self
6
10
  PULL_BATCH_COUNT = 1000
7
11
  DELTA_COUNT = 20
8
- RESERVED_COLUMNS = %w[operation_type trigger_time].freeze
9
12
 
10
13
  # This, picks PULL_BATCH_COUNT rows by primary key from audit_table,
11
14
  # replays it on the shadow_table. Once the batch is done,
@@ -25,7 +28,7 @@ module PgOnlineSchemaChange
25
28
 
26
29
  def rows_to_play(reuse_trasaction = false)
27
30
  select_query = <<~SQL
28
- SELECT * FROM #{audit_table} ORDER BY #{primary_key} LIMIT #{PULL_BATCH_COUNT};
31
+ SELECT * FROM #{audit_table} ORDER BY #{audit_table_pk} LIMIT #{PULL_BATCH_COUNT};
29
32
  SQL
30
33
 
31
34
  rows = []
@@ -34,6 +37,10 @@ module PgOnlineSchemaChange
34
37
  rows
35
38
  end
36
39
 
40
+ def reserved_columns
41
+ @reserved_columns ||= [trigger_time_column, operation_type_column, audit_table_pk]
42
+ end
43
+
37
44
  def play!(rows, reuse_trasaction = false)
38
45
  logger.info("Replaying rows, count: #{rows.size}")
39
46
 
@@ -44,7 +51,7 @@ module PgOnlineSchemaChange
44
51
 
45
52
  # Remove audit table cols, since we will be
46
53
  # re-mapping them for inserts and updates
47
- RESERVED_COLUMNS.each do |col|
54
+ reserved_columns.each do |col|
48
55
  new_row.delete(col)
49
56
  end
50
57
 
@@ -73,7 +80,7 @@ module PgOnlineSchemaChange
73
80
  client.connection.escape_string(value)
74
81
  end
75
82
 
76
- case row["operation_type"]
83
+ case row[operation_type_column]
77
84
  when "INSERT"
78
85
  values = new_row.map { |_, val| "'#{val}'" }.join(",")
79
86
 
@@ -110,13 +117,15 @@ module PgOnlineSchemaChange
110
117
  Query.run(client.connection, to_be_replayed.join, reuse_trasaction)
111
118
 
112
119
  # Delete items from the audit now that are replayed
113
- if to_be_deleted_rows.count >= 1
114
- delete_query = <<~SQL
115
- DELETE FROM #{audit_table} WHERE #{primary_key} IN (#{to_be_deleted_rows.join(",")})
116
- SQL
117
- Query.run(client.connection, delete_query, reuse_trasaction)
118
- end
120
+ return unless to_be_deleted_rows.count >= 1
121
+
122
+ delete_query = <<~SQL
123
+ DELETE FROM #{audit_table} WHERE #{primary_key} IN (#{to_be_deleted_rows.join(",")})
124
+ SQL
125
+ Query.run(client.connection, delete_query, reuse_trasaction)
119
126
  end
120
127
  end
121
128
  end
122
129
  end
130
+
131
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
@@ -1,17 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "pg_query"
2
4
  require "pg"
3
5
 
4
6
  module PgOnlineSchemaChange
5
7
  class Store
6
8
  class << self
7
- @@object = {}
9
+ @object = {}
8
10
 
9
11
  def get(key)
10
- @@object[key.to_s] || @@object[key.to_sym]
12
+ @object ||= {}
13
+ @object[key.to_s] || @object[key.to_sym]
11
14
  end
12
15
 
13
16
  def set(key, value)
14
- @@object[key.to_sym] = value
17
+ @object ||= {}
18
+ @object[key.to_sym] = value
15
19
  end
16
20
  end
17
21
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgOnlineSchemaChange
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -18,16 +18,12 @@ module PgOnlineSchemaChange
18
18
  class CountBelowDelta < StandardError; end
19
19
  class AccessExclusiveLockNotAcquired < StandardError; end
20
20
 
21
- def self.logger=(verbose)
22
- @@logger ||= begin
23
- logger = Ougai::Logger.new($stdout)
24
- logger.level = verbose ? Ougai::Logger::TRACE : Ougai::Logger::INFO
25
- logger.with_fields = { version: PgOnlineSchemaChange::VERSION }
26
- logger
27
- end
28
- end
29
-
30
- def self.logger
31
- @@logger
21
+ def self.logger(verbose: false)
22
+ @logger ||= begin
23
+ logger = Ougai::Logger.new($stdout)
24
+ logger.level = verbose ? Ougai::Logger::TRACE : Ougai::Logger::INFO
25
+ logger.with_fields = { version: PgOnlineSchemaChange::VERSION }
26
+ logger
27
+ end
32
28
  end
33
29
  end
data/scripts/release.sh CHANGED
@@ -11,8 +11,11 @@ gem build pg_online_schema_change.gemspec
11
11
  echo "=== Pushing gem ===="
12
12
  gem push pg_online_schema_change-$VERSION.gem
13
13
 
14
+ echo "=== Sleeping for 5s ===="
15
+ sleep 5
16
+
14
17
  echo "=== Building Image ===="
15
- docker build . --build-arg VERSION=$VERSION -t pg-osc
18
+ docker build . --build-arg VERSION=$VERSION -t shayonj/pg-osc:$VERSION
16
19
 
17
20
  echo "=== Tagging Image ===="
18
21
  docker image tag shayonj/pg-osc:$VERSION shayonj/pg-osc:latest
@@ -20,3 +23,6 @@ docker image tag shayonj/pg-osc:$VERSION shayonj/pg-osc:latest
20
23
  echo "=== Pushing Image ===="
21
24
  docker push shayonj/pg-osc:$VERSION
22
25
  docker push shayonj/pg-osc:latest
26
+
27
+ echo "=== Cleaning up ===="
28
+ rm pg_online_schema_change-$VERSION.gem
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_online_schema_change
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shayon Mukherjee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-21 00:00:00.000000000 Z
11
+ date: 2022-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ougai
@@ -191,6 +191,7 @@ extra_rdoc_files: []
191
191
  files:
192
192
  - ".rspec"
193
193
  - ".rubocop.yml"
194
+ - ".rubocop_todo.yml"
194
195
  - ".ruby-version"
195
196
  - CHANGELOG.md
196
197
  - CODE_OF_CONDUCT.md