switchman 1.15.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/app/models/switchman/shard.rb +10 -5
  3. data/db/migrate/20130328212039_create_switchman_shards.rb +2 -0
  4. data/db/migrate/20130328224244_create_default_shard.rb +3 -1
  5. data/db/migrate/20161206323434_add_back_default_string_limits_switchman.rb +2 -0
  6. data/db/migrate/20180828183945_add_default_shard_index.rb +2 -0
  7. data/db/migrate/20180828192111_add_timestamps_to_shards.rb +2 -0
  8. data/db/migrate/20190114212900_add_unique_name_indexes.rb +2 -0
  9. data/lib/switchman.rb +3 -1
  10. data/lib/switchman/action_controller/caching.rb +2 -0
  11. data/lib/switchman/active_record/abstract_adapter.rb +6 -4
  12. data/lib/switchman/active_record/association.rb +2 -0
  13. data/lib/switchman/active_record/attribute_methods.rb +2 -0
  14. data/lib/switchman/active_record/base.rb +20 -9
  15. data/lib/switchman/active_record/batches.rb +2 -0
  16. data/lib/switchman/active_record/calculations.rb +2 -0
  17. data/lib/switchman/active_record/connection_handler.rb +8 -14
  18. data/lib/switchman/active_record/connection_pool.rb +2 -12
  19. data/lib/switchman/active_record/finder_methods.rb +2 -0
  20. data/lib/switchman/active_record/log_subscriber.rb +2 -0
  21. data/lib/switchman/active_record/migration.rb +2 -0
  22. data/lib/switchman/active_record/model_schema.rb +2 -0
  23. data/lib/switchman/active_record/persistence.rb +3 -1
  24. data/lib/switchman/active_record/postgresql_adapter.rb +12 -21
  25. data/lib/switchman/active_record/predicate_builder.rb +2 -0
  26. data/lib/switchman/active_record/query_cache.rb +2 -0
  27. data/lib/switchman/active_record/query_methods.rb +2 -0
  28. data/lib/switchman/active_record/reflection.rb +2 -0
  29. data/lib/switchman/active_record/relation.rb +7 -5
  30. data/lib/switchman/active_record/spawn_methods.rb +2 -0
  31. data/lib/switchman/active_record/statement_cache.rb +5 -16
  32. data/lib/switchman/active_record/table_definition.rb +4 -2
  33. data/lib/switchman/active_record/type_caster.rb +2 -0
  34. data/lib/switchman/active_record/where_clause_factory.rb +2 -0
  35. data/lib/switchman/active_support/cache.rb +4 -2
  36. data/lib/switchman/arel.rb +2 -0
  37. data/lib/switchman/call_super.rb +2 -0
  38. data/lib/switchman/connection_pool_proxy.rb +13 -11
  39. data/lib/switchman/database_server.rb +18 -16
  40. data/lib/switchman/default_shard.rb +2 -0
  41. data/lib/switchman/engine.rb +10 -8
  42. data/lib/switchman/environment.rb +2 -0
  43. data/lib/switchman/errors.rb +2 -0
  44. data/lib/switchman/{shackles.rb → guard_rail.rb} +6 -4
  45. data/lib/switchman/{shackles → guard_rail}/relation.rb +7 -5
  46. data/lib/switchman/open4.rb +2 -0
  47. data/lib/switchman/r_spec_helper.rb +7 -5
  48. data/lib/switchman/rails.rb +2 -0
  49. data/lib/switchman/schema_cache.rb +2 -0
  50. data/lib/switchman/sharded_instrumenter.rb +3 -1
  51. data/lib/switchman/standard_error.rb +2 -0
  52. data/lib/switchman/test_helper.rb +5 -3
  53. data/lib/switchman/version.rb +3 -1
  54. data/lib/tasks/switchman.rake +6 -13
  55. metadata +27 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4bfb336093e3167cc3f353d50e6dcb60ec44da9d03fd8b30d1ec51adf570d702
4
- data.tar.gz: ae40dd725814601f125ef10f7c0ae835abc8ae22c38259ec82abb9bfb4046b95
3
+ metadata.gz: 376bc704492af36189c96e77637f3f1e1f8290f25e80a65c5bfe100cd87945d5
4
+ data.tar.gz: 9af4f9c45b7e958ffdfca22cb98a4287c2b2fd35f4cbe7dd80a640df7d25c55c
5
5
  SHA512:
6
- metadata.gz: a8e0dd6e60c8454eb99ad2035b6dfb95a5596c46dbcecf6b77dd422c7a988730ea63f32a78de5d5e742e9aa3caff0f8ff5576af0f3dac92b6b40677f5ca06205
7
- data.tar.gz: 810631877453b90f8cbeda22eb180b50e575b3f49f2965006292e20c0f4f35085417f5ac0f4d0ead2c291abbec82c82943332b46c81669b9068e40a947a03c29
6
+ metadata.gz: 4cdf5640f5128c0d0d8235d2446bf676d7ff25bf934e8f266b98f27a45e397e015750bd4928332514a1202f585d84a70ac0c5a3c92db4a3533cf9fdd5a3619c6
7
+ data.tar.gz: 40de3daa0b556f247243fd6cff2c7fdad620c7e0b74b58d5735dd984919ffbbe48b96412e50ba62ac169bc6d076f055fef1503e0a09f25848beecdae54c1165d
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'switchman/database_server'
2
4
  require 'switchman/default_shard'
3
5
  require 'switchman/environment'
@@ -38,7 +40,10 @@ module Switchman
38
40
  end
39
41
 
40
42
  def default(reload_deprecated = false, reload: false, with_fallback: false)
41
- reload = reload_deprecated if reload_deprecated
43
+ if reload_deprecated
44
+ reload = reload_deprecated
45
+ ::ActiveSupport::Deprecation.warn("positional reload parameter to Switchman::Shard.default is deprecated; use `reload: true`")
46
+ end
42
47
  if !@default || reload
43
48
  # Have to create a dummy object so that several key methods still work
44
49
  # (it's easier to do this in one place here, and just assume that sharding
@@ -351,8 +356,8 @@ module Switchman
351
356
  # prune the prior connection unless it happened to be the same
352
357
  if previous_shard && shard != previous_shard && !previous_shard.database_server.shareable?
353
358
  previous_shard.activate do
354
- ::Shackles.activated_environments.each do |env|
355
- ::Shackles.activate(env) do
359
+ ::GuardRail.activated_environments.each do |env|
360
+ ::GuardRail.activate(env) do
356
361
  if ::ActiveRecord::Base.connected? && ::ActiveRecord::Base.connection.open_transactions == 0
357
362
  ::ActiveRecord::Base.connection_pool.current_pool.disconnect!
358
363
  end
@@ -659,7 +664,7 @@ module Switchman
659
664
  case adapter
660
665
  when 'mysql', 'mysql2'
661
666
  self.activate do
662
- ::Shackles.activate(:deploy) do
667
+ ::GuardRail.activate(:deploy) do
663
668
  drop_statement ||= "DROP DATABASE #{self.name}"
664
669
  Array(drop_statement).each do |stmt|
665
670
  ::ActiveRecord::Base.connection.execute(stmt)
@@ -668,7 +673,7 @@ module Switchman
668
673
  end
669
674
  when 'postgresql'
670
675
  self.activate do
671
- ::Shackles.activate(:deploy) do
676
+ ::GuardRail.activate(:deploy) do
672
677
  # Shut up, Postgres!
673
678
  conn = ::ActiveRecord::Base.connection
674
679
  old_proc = conn.raw_connection.set_notice_processor {}
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreateSwitchmanShards < ActiveRecord::Migration[4.2]
2
4
  def change
3
5
  create_table :switchman_shards do |t|
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreateDefaultShard < ActiveRecord::Migration[4.2]
2
4
  def up
3
5
  unless Switchman::Shard.default.is_a?(Switchman::Shard)
4
6
  Switchman::Shard.reset_column_information
5
7
  Switchman::Shard.create!(:default => true)
6
- Switchman::Shard.default(true)
8
+ Switchman::Shard.default(reload: true)
7
9
  end
8
10
  end
9
11
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddBackDefaultStringLimitsSwitchman < ActiveRecord::Migration[4.2]
2
4
  def up
3
5
  add_string_limit_if_missing :switchman_shards, :name
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddDefaultShardIndex < ActiveRecord::Migration[4.2]
2
4
  def change
3
5
  Switchman::Shard.where(default: nil).update_all(default: false)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddTimestampsToShards < ActiveRecord::Migration[4.2]
2
4
  def change
3
5
  add_timestamps :switchman_shards, null: true
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddUniqueNameIndexes < ActiveRecord::Migration[4.2]
2
4
  def change
3
5
  add_index :switchman_shards, [:database_server_id, :name], unique: true
@@ -1,4 +1,6 @@
1
- require "shackles"
1
+ # frozen_string_literal: true
2
+
3
+ require "guard_rail"
2
4
  require "switchman/open4"
3
5
  require "switchman/engine"
4
6
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActionController
3
5
  module Caching
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'switchman/sharded_instrumenter'
2
4
 
3
5
  module Switchman
4
6
  module ActiveRecord
5
7
  module AbstractAdapter
6
8
  module ForeignKeyCheck
7
- def add_column(table, name, type, options = {})
8
- Engine.foreign_key_check(name, type, options)
9
+ def add_column(table, name, type, limit: nil, **)
10
+ Engine.foreign_key_check(name, type, limit: limit)
9
11
  super
10
12
  end
11
13
  end
@@ -27,8 +29,8 @@ module Switchman
27
29
  quote_table_name(name)
28
30
  end
29
31
 
30
- def use_qualified_names?
31
- false
32
+ def schema_migration
33
+ ::ActiveRecord::SchemaMigration
32
34
  end
33
35
 
34
36
  protected
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module Association
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module AttributeMethods
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module Base
@@ -31,20 +33,20 @@ module Switchman
31
33
  @integral_id
32
34
  end
33
35
 
34
- def transaction(*args)
36
+ def transaction(**)
35
37
  if self != ::ActiveRecord::Base && current_scope
36
38
  current_scope.activate do
37
39
  db = Shard.current(shard_category).database_server
38
- if ::Shackles.environment != db.shackles_environment
39
- db.unshackle { super }
40
+ if ::GuardRail.environment != db.guard_rail_environment
41
+ db.unguard { super }
40
42
  else
41
43
  super
42
44
  end
43
45
  end
44
46
  else
45
47
  db = Shard.current(shard_category).database_server
46
- if ::Shackles.environment != db.shackles_environment
47
- db.unshackle { super }
48
+ if ::GuardRail.environment != db.guard_rail_environment
49
+ db.unguard { super }
48
50
  else
49
51
  super
50
52
  end
@@ -105,12 +107,12 @@ module Switchman
105
107
  end
106
108
  end
107
109
 
108
- def save(*args)
110
+ def save(*, **)
109
111
  @shard_set_in_stone = true
110
112
  (self.class.current_scope || self.class.default_scoped).shard(shard, :implicit).scoping { super }
111
113
  end
112
114
 
113
- def save!(*args)
115
+ def save!(*, **)
114
116
  @shard_set_in_stone = true
115
117
  (self.class.current_scope || self.class.default_scoped).shard(shard, :implicit).scoping { super }
116
118
  end
@@ -128,9 +130,9 @@ module Switchman
128
130
  result
129
131
  end
130
132
 
131
- def transaction(options={}, &block)
133
+ def transaction(**kwargs, &block)
132
134
  shard.activate(self.class.shard_category) do
133
- self.class.transaction(options, &block)
135
+ self.class.transaction(**kwargs, &block)
134
136
  end
135
137
  end
136
138
 
@@ -155,6 +157,15 @@ module Switchman
155
157
  self.class.connection.quote(id)
156
158
  end
157
159
 
160
+ def update_columns(*)
161
+ db = Shard.current(self.class.shard_category).database_server
162
+ if ::GuardRail.environment != db.guard_rail_environment
163
+ return db.unguard { super }
164
+ else
165
+ super
166
+ end
167
+ end
168
+
158
169
  protected
159
170
 
160
171
  # see also AttributeMethods#shard_category_code_for_reflection
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module Batches
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module Calculations
@@ -1,11 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'switchman/connection_pool_proxy'
2
4
 
3
5
  module Switchman
4
6
  module ActiveRecord
5
7
  module ConnectionHandler
6
8
  def self.make_sharing_automagic(config, shard = Shard.current)
7
- key = config[:adapter] == 'postgresql' ? :schema_search_path : :database
8
-
9
9
  # only load the shard name from the db if we have to
10
10
  if !config[:shard_name]
11
11
  # we may not be able to connect to this shard yet, cause it might be an empty database server
@@ -15,12 +15,6 @@ module Switchman
15
15
 
16
16
  config[:shard_name] ||= shard_name
17
17
  end
18
-
19
- if !config[key] || config[key] == shard_name
20
- # this may truncate the schema_search_path if it was not specified in database.yml
21
- # but that's what our old behavior was anyway, so I guess it's okay
22
- config[key] = '%{shard_name}'
23
- end
24
18
  end
25
19
 
26
20
  def establish_connection(spec)
@@ -63,7 +57,7 @@ module Switchman
63
57
  Shard.default.remove_instance_variable(:@name) if Shard.default.instance_variable_defined?(:@name)
64
58
  end
65
59
 
66
- @shard_connection_pools ||= { [:master, Shard.default.database_server.shareable? ? ::Rails.env : Shard.default] => pool}
60
+ @shard_connection_pools ||= { [:primary, Shard.default.database_server.shareable? ? ::Rails.env : Shard.default] => pool}
67
61
 
68
62
  category = pool.spec.name.to_sym
69
63
  proxy = ConnectionPoolProxy.new(category,
@@ -72,13 +66,13 @@ module Switchman
72
66
  owner_to_pool[pool.spec.name] = proxy
73
67
 
74
68
  if first_time
75
- if Shard.default.database_server.config[:prefer_slave]
76
- Shard.default.database_server.shackle!
69
+ if Shard.default.database_server.config[:prefer_secondary]
70
+ Shard.default.database_server.guard!
77
71
  end
78
72
 
79
- if Shard.default.is_a?(DefaultShard) && Shard.default.database_server.config[:slave]
80
- Shard.default.database_server.shackle!
81
- Shard.default(true)
73
+ if Shard.default.is_a?(DefaultShard) && Shard.default.database_server.config[:secondary]
74
+ Shard.default.database_server.guard!
75
+ Shard.default(reload: true)
82
76
  end
83
77
  end
84
78
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'switchman/errors'
2
4
 
3
5
  module Switchman
@@ -84,18 +86,6 @@ module Switchman
84
86
  end
85
87
 
86
88
  spec.config[:shard_name] = self.shard.name
87
- case conn.adapter_name
88
- when 'MySQL', 'Mysql2'
89
- conn.execute("USE #{spec.config[:database]}")
90
- when 'PostgreSQL'
91
- if conn.schema_search_path != spec.config[:schema_search_path]
92
- conn.schema_search_path = spec.config[:schema_search_path]
93
- end
94
- when 'SQLite'
95
- # This is an artifact of the adapter modifying the path to be an absolute path when it is instantiated; just let it slide
96
- else
97
- raise("Cannot switch databases on same DatabaseServer with adapter type: #{conn.adapter_name}. Limit one Shard per DatabaseServer.")
98
- end
99
89
  conn.shard = shard
100
90
  end
101
91
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module FinderMethods
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module LogSubscriber
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module Migration
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module ModelSchema
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module Persistence
4
6
  # touch reads the id attribute directly, so it's not relative to the current shard
5
- def touch(*)
7
+ def touch(*, **)
6
8
  shard.activate(self.class.shard_category) { super }
7
9
  end
8
10
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module PostgreSQLAdapter
@@ -38,23 +40,17 @@ module Switchman
38
40
  select_values("SELECT * FROM unnest(current_schemas(false))")
39
41
  end
40
42
 
41
- def use_qualified_names?
42
- @config[:use_qualified_names]
43
- end
44
-
45
43
  def tables(name = nil)
46
- schema = shard.name if use_qualified_names?
47
-
48
44
  query(<<-SQL, 'SCHEMA').map { |row| row[0] }
49
45
  SELECT tablename
50
46
  FROM pg_tables
51
- WHERE schemaname = #{schema ? "'#{schema}'" : 'ANY (current_schemas(false))'}
47
+ WHERE schemaname = '#{shard.name}'
52
48
  SQL
53
49
  end
54
50
 
55
51
  def extract_schema_qualified_name(string)
56
52
  name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(string.to_s)
57
- if string && !name.schema && use_qualified_names?
53
+ if string && !name.schema
58
54
  name.instance_variable_set(:@schema, shard.name)
59
55
  end
60
56
  [name.schema, name.identifier]
@@ -63,7 +59,7 @@ module Switchman
63
59
  def view_exists?(name)
64
60
  name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
65
61
  return false unless name.identifier
66
- if !name.schema && use_qualified_names?
62
+ if !name.schema
67
63
  name.instance_variable_set(:@schema, shard.name)
68
64
  end
69
65
 
@@ -73,13 +69,11 @@ module Switchman
73
69
  LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
74
70
  WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
75
71
  AND c.relname = '#{name.identifier}'
76
- AND n.nspname = #{name.schema ? "'#{name.schema}'" : 'ANY (current_schemas(false))'}
72
+ AND n.nspname = '#{shard.name}'
77
73
  SQL
78
74
  end
79
75
 
80
76
  def indexes(table_name)
81
- schema = shard.name if use_qualified_names?
82
-
83
77
  result = query(<<-SQL, 'SCHEMA')
84
78
  SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
85
79
  FROM pg_class t
@@ -88,7 +82,7 @@ module Switchman
88
82
  WHERE i.relkind = 'i'
89
83
  AND d.indisprimary = 'f'
90
84
  AND t.relname = '#{table_name}'
91
- AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = #{schema ? "'#{schema}'" : 'ANY (current_schemas(false))'} )
85
+ AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
92
86
  ORDER BY i.relname
93
87
  SQL
94
88
 
@@ -126,8 +120,6 @@ module Switchman
126
120
  end
127
121
 
128
122
  def index_name_exists?(table_name, index_name, _default = nil)
129
- schema = shard.name if use_qualified_names?
130
-
131
123
  exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0
132
124
  SELECT COUNT(*)
133
125
  FROM pg_class t
@@ -136,7 +128,7 @@ module Switchman
136
128
  WHERE i.relkind = 'i'
137
129
  AND i.relname = '#{index_name}'
138
130
  AND t.relname = '#{table_name}'
139
- AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = #{schema ? "'#{schema}'" : 'ANY (current_schemas(false))'} )
131
+ AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
140
132
  SQL
141
133
  end
142
134
 
@@ -150,7 +142,7 @@ module Switchman
150
142
  def quote_table_name(name)
151
143
  return quote_local_table_name(name) if @use_local_table_name
152
144
  name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
153
- if !name.schema && use_qualified_names?
145
+ if !name.schema
154
146
  name.instance_variable_set(:@schema, shard.name)
155
147
  end
156
148
  name.quoted
@@ -165,7 +157,6 @@ module Switchman
165
157
  end
166
158
 
167
159
  def foreign_keys(table_name)
168
- schema = shard.name if use_qualified_names?
169
160
 
170
161
  # mostly copy-pasted from AR - only change is to the nspname condition for qualified names support
171
162
  fk_info = select_all <<-SQL.strip_heredoc
@@ -178,7 +169,7 @@ module Switchman
178
169
  JOIN pg_namespace t3 ON c.connamespace = t3.oid
179
170
  WHERE c.contype = 'f'
180
171
  AND t1.relname = #{quote(table_name)}
181
- AND t3.nspname = #{schema ? "'#{schema}'" : 'ANY (current_schemas(false))'}
172
+ AND t3.nspname = '#{shard.name}'
182
173
  ORDER BY c.conname
183
174
  SQL
184
175
 
@@ -195,7 +186,7 @@ module Switchman
195
186
  # strip the schema name from to_table if it matches
196
187
  to_table = row['to_table']
197
188
  to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(to_table)
198
- if use_qualified_names? && to_table_qualified_name.schema == shard.name
189
+ if to_table_qualified_name.schema == shard.name
199
190
  to_table = to_table_qualified_name.identifier
200
191
  end
201
192
 
@@ -203,7 +194,7 @@ module Switchman
203
194
  end
204
195
  end
205
196
 
206
- def add_index_options(_table_name, _column_name, _options = {})
197
+ def add_index_options(_table_name, _column_name, **)
207
198
  index_name, index_type, index_columns, index_options, algorithm, using = super
208
199
  algorithm = nil if DatabaseServer.creating_new_shard && algorithm == "CONCURRENTLY"
209
200
  [index_name, index_type, index_columns, index_options, algorithm, using]