Class: ActiveRecord::ConnectionAdapters::CockroachDBAdapter

Inherits:
PostgreSQLAdapter
  • Object
show all
Includes:
ActiveRecord::ConnectionAdapters::CockroachDB::DatabaseStatements, ActiveRecord::ConnectionAdapters::CockroachDB::Quoting, ActiveRecord::ConnectionAdapters::CockroachDB::ReferentialIntegrity, ActiveRecord::ConnectionAdapters::CockroachDB::SchemaStatements
Defined in:
lib/active_record/connection_adapters/cockroachdb_adapter.rb

Constant Summary collapse

ADAPTER_NAME =
"CockroachDB"
DEFAULT_PRIMARY_KEY =
"rowid"
SPATIAL_COLUMN_OPTIONS =
{
  geography:           { geographic: true },
  geometry:            {},
  geometry_collection: {},
  line_string:         {},
  multi_line_string:   {},
  multi_point:         {},
  multi_polygon:       {},
  spatial:             {},
  st_point:            {},
  st_polygon:          {},
}
DEFAULT_SRID =
0

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ActiveRecord::ConnectionAdapters::CockroachDB::Quoting

#quote

Methods included from ActiveRecord::ConnectionAdapters::CockroachDB::DatabaseStatements

#insert_fixtures_set

Methods included from ActiveRecord::ConnectionAdapters::CockroachDB::ReferentialIntegrity

#check_all_foreign_keys_valid!, #disable_referential_integrity

Methods included from ActiveRecord::ConnectionAdapters::CockroachDB::SchemaStatements

#add_index, #create_schema_dumper, #create_table_definition, #default_sequence_name, #foreign_key_options, #foreign_keys, #native_database_types, #new_column_from_field, #pk_and_sequence_for, #primary_key, #reset_pk_sequence!, #schema_creation, #schema_names, #spatial_column_info, #type_to_sql

Class Method Details

.initialize_type_map(m = type_map) ⇒ Object



269
270
271
272
273
274
275
276
277
278
279
280
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
311
312
313
314
315
316
317
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 269

def initialize_type_map(m = type_map)
  %w(
    geography
    geometry
    geometry_collection
    line_string
    multi_line_string
    multi_point
    multi_polygon
    st_point
    st_polygon
  ).each do |geo_type|
    m.register_type(geo_type) do |oid, _, sql_type|
      CockroachDB::OID::Spatial.new(oid, sql_type)
    end
  end

  # Belongs after other types are defined because of issues described
  # in this https://github.com/rails/rails/pull/38571
  # Once that PR is merged, we can call super at the top.
  super(m)

  # Override numeric type. This is almost identical to the default,
  # except that the conditional based on the fmod is changed.
  m.register_type "numeric" do |_, fmod, sql_type|
    precision = extract_precision(sql_type)
    scale = extract_scale(sql_type)

    # The type for the numeric depends on the width of the field,
    # so we'll do something special here.
    #
    # When dealing with decimal columns:
    #
    # places after decimal  = fmod - 4 & 0xffff
    # places before decimal = (fmod - 4) >> 16 & 0xffff
    #
    # For older versions of CockroachDB (<v22.1), fmod is -1 for 0 width.
    # If fmod is -1, that means that precision is defined but not
    # scale, or neither is defined.
    if fmod && ((fmod == -1 && !precision.nil?) || (fmod - 4 & 0xffff).zero?)
      # Below comment is from ActiveRecord
      # FIXME: Remove this class, and the second argument to
      # lookups on PG
      Type::DecimalWithoutScale.new(precision: precision)
    else
      ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Decimal.new(precision: precision, scale: scale)
    end
  end
end

.spatial_column_options(key) ⇒ Object



110
111
112
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 110

def self.spatial_column_options(key)
  SPATIAL_COLUMN_OPTIONS[key]
end

Instance Method Details

#check_versionObject

:nodoc:



216
217
218
219
220
221
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 216

def check_version # :nodoc:
  # https://www.cockroachlabs.com/docs/releases/release-support-policy
  if database_version < 23_01_12 # < 23.1.12
    raise "Your version of CockroachDB (#{database_version}) is too old. Active Record supports CockroachDB >= 23.1.12."
  end
end

#configure_connectionObject



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 223

def configure_connection(...)
  super

# This rescue flow appears in new_client, but it is needed here as well
# since Cockroach will sometimes not raise until a query is made.
#
# See https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/337#issuecomment-2328419453
#
# The error conditions used to differ from the ones in new_client, but
# the reasons why are no longer relevant. We keep this in sync with new_client
# even though some conditions might never be checked.
#
# See https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/229
#
# We have to rescue `ActiveRecord::StatementInvalid` instead of `::PG::Error`
# here as the error has already been casted (in `#with_raw_connection` as
# of Rails 7.2.1).
rescue ActiveRecord::StatementInvalid => error
  conn_params = @connection_parameters
  if conn_params && conn_params[:dbname] == "postgres"
    raise ActiveRecord::ConnectionNotEstablished, error.message
  elsif conn_params && conn_params[:dbname] && error.cause.message.include?(conn_params[:dbname])
    raise ActiveRecord::NoDatabaseError.db_error(conn_params[:dbname])
  elsif conn_params && conn_params[:user] && error.cause.message.include?(conn_params[:user])
    raise ActiveRecord::DatabaseConnectionError.username_error(conn_params[:user])
  elsif conn_params && conn_params[:host] && error.cause.message.include?(conn_params[:host])
    raise ActiveRecord::DatabaseConnectionError.hostname_error(conn_params[:host])
  else
    raise ActiveRecord::ConnectionNotEstablished, error.message
  end
end

#create_enum(name, values, **options) ⇒ Object

override The PostgreSQLAdapter uses syntax for an anonymous function (DO $$) that CockroachDB does not support.

Given a name and an array of values, creates an enum type.



260
261
262
263
264
265
266
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 260

def create_enum(name, values, **options)
  sql_values = values.map { |s| quote(s) }.join(", ")
  query = <<~SQL
    CREATE TYPE IF NOT EXISTS #{quote_table_name(name)} AS ENUM (#{sql_values});
  SQL
  internal_exec_query(query).tap { reload_type_map }
end

#debugging?Boolean

Returns:

  • (Boolean)


131
132
133
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 131

def debugging?
  !!ENV["DEBUG_COCKROACHDB_ADAPTER"]
end

#default_sridObject



118
119
120
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 118

def default_srid
  DEFAULT_SRID
end

#get_database_versionObject



139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 139

def get_database_version
  with_raw_connection do |conn|
    conn.async_exec("SHOW crdb_version") do |result|
      major, minor, patch = result
        .getvalue(0, 0)
        .match(/v(\d+).(\d+).(\d+)/)
        .captures
        .map(&:to_i)
      major * 100 * 100 + minor * 100 + patch
    end
  end
end

#max_transaction_retriesObject



135
136
137
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 135

def max_transaction_retries
  @max_transaction_retries ||= @config.fetch(:max_transaction_retries, 3)
end

#postgis_lib_versionObject



114
115
116
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 114

def postgis_lib_version
  @postgis_lib_version ||= select_value("SELECT PostGIS_Lib_Version()")
end

#srs_database_columnsObject



122
123
124
125
126
127
128
129
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 122

def srs_database_columns
  {
    auth_name_column: "auth_name",
    auth_srid_column: "auth_srid",
    proj4text_column: "proj4text",
    srtext_column:    "srtext",
  }
end

#supports_advisory_locks?Boolean

Returns:

  • (Boolean)


195
196
197
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 195

def supports_advisory_locks?
  false
end

#supports_comments_in_create?Boolean

Returns:

  • (Boolean)


191
192
193
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 191

def supports_comments_in_create?
  false
end

#supports_datetime_with_precision?Boolean

Returns:

  • (Boolean)


154
155
156
157
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 154

def supports_datetime_with_precision?
  # https://github.com/cockroachdb/cockroach/pull/111400
  true
end

#supports_ddl_transactions?Boolean

Returns:

  • (Boolean)


164
165
166
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 164

def supports_ddl_transactions?
  false
end

#supports_deferrable_constraints?Boolean

Returns:

  • (Boolean)


211
212
213
214
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 211

def supports_deferrable_constraints?
  # https://go.crdb.dev/issue-v/31632/v23.1
  false
end

#supports_exclusion_constraints?Boolean

Returns:

  • (Boolean)


180
181
182
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 180

def supports_exclusion_constraints?
  false
end

#supports_expression_index?Boolean

Returns:

  • (Boolean)


184
185
186
187
188
189
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 184

def supports_expression_index?
  # Expression indexes are partially supported by CockroachDB v21.2,
  # but activerecord requires "ON CONFLICT expression" support.
  # See https://github.com/cockroachdb/cockroach/issues/67893
  false
end

#supports_extensions?Boolean

Returns:

  • (Boolean)


168
169
170
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 168

def supports_extensions?
  false
end

#supports_index_include?Boolean

Returns:

  • (Boolean)


176
177
178
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 176

def supports_index_include?
  false
end

#supports_materialized_views?Boolean

Returns:

  • (Boolean)


172
173
174
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 172

def supports_materialized_views?
  true
end

#supports_nulls_not_distinct?Boolean

Returns:

  • (Boolean)


159
160
161
162
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 159

def supports_nulls_not_distinct?
  # https://github.com/cockroachdb/cockroach/issues/115836
  false
end

#supports_partitioned_indexes?Boolean

Returns:

  • (Boolean)


207
208
209
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 207

def supports_partitioned_indexes?
  false
end

#supports_string_to_array_coercion?Boolean

Returns:

  • (Boolean)


203
204
205
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 203

def supports_string_to_array_coercion?
  true
end

#supports_virtual_columns?Boolean

Returns:

  • (Boolean)


199
200
201
# File 'lib/active_record/connection_adapters/cockroachdb_adapter.rb', line 199

def supports_virtual_columns?
  true
end