activerecord-cockroachdb-adapter 6.1.0beta1 → 6.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d0954fd425d90342f04c1b6559b78e398be9e523e67779476d81f925a1aa611
4
- data.tar.gz: 1f990c34784394bafa77933eb0d49965a0eac81151f2468c92a66c1bc9beb78a
3
+ metadata.gz: 2d0c9c46ba26129c6660d4c7dcc7fab97e62e6544cf97be3de59876df04b8b49
4
+ data.tar.gz: 35952dc2b491d58a1550a8466a0010ce1530465f7e5c17d3cb1863de9d17c304
5
5
  SHA512:
6
- metadata.gz: 3074426e81a83bb4ae2e50047c6db97dc75d9b8a822c3fd1153fb3403457bb56e7f36acb42802e5dd777c056dd0864db7dc26e875e7a644cb158f0a1c8001f3a
7
- data.tar.gz: 8ff7c637812c1b262452ca1ef6ad8308a3f620a47e3798c6ef7b93096fedb362ce52372f6c0b870af1b475a31cf83f670f4e6d65498c231f5759a475820568af
6
+ metadata.gz: d1d62e4dc3ef136ebb472b4439f0a500cd64e4c16a1d7f6f1f75d7426ddfd85dc871eb26889b3d617dc80816c3d47533c6d46b9dce6fbc42df8049d76f680cf8
7
+ data.tar.gz: 02b1e634681a6e2d25d88d2d78dd0c658bf4125decbce637fa5fa672e3651c099106ee79de86ffa2037ceb3f6fc13e80e8e870b6154e4dbd96f5405b3829003d
data/CHANGELOG.md ADDED
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ ## 6.1.2 - 2021-05-20
4
+
5
+ - Fix a bug where starting the driver can result in a ConnectionNotEstablished error.
6
+
7
+ ## 6.1.1 - 2021-05-14
8
+
9
+ - Fix a bug where starting the driver can result in a NoDatabaseError.
10
+
11
+ ## 6.1.0 - 2021-04-26
12
+
13
+ - Add a telemetry query on start-up. This helps the Cockroach Labs team
14
+ prioritize support for the adapter. It can be disabled by setting the
15
+ `disable_cockroachdb_telemetry` configuration option to false.
16
+
17
+ ## 6.1.0-beta.3 - 2021-04-02
18
+
19
+ - Added a configuration option named `use_follower_reads_for_type_introspection`.
20
+ If true, it improves the speed of type introspection by allowing potentially stale
21
+ type metadata to be read. Defaults to false.
22
+
23
+ ## 6.1.0-beta.2 - 2021-03-06
24
+
25
+ - Improved connection performance by refactoring an introspection
26
+ that loads types.
27
+ - Changed version numbers to semver.
28
+
29
+ ## 6.1.0beta1
30
+
31
+ - Initial support for Rails 6.1.
32
+ - Support for spatial functionality.
data/README.md CHANGED
@@ -1,16 +1,18 @@
1
1
  # ActiveRecord CockroachDB Adapter
2
2
 
3
- CockroachDB adapter for ActiveRecord 4 and 5. This is a lightweight extension of the PostgreSQL adapter that establishes compatibility with [CockroachDB](https://github.com/cockroachdb/cockroach).
3
+ CockroachDB adapter for ActiveRecord 5 and 6. This is a lightweight extension of the PostgreSQL adapter that establishes compatibility with [CockroachDB](https://github.com/cockroachdb/cockroach).
4
4
 
5
5
  ## Installation
6
6
 
7
7
  Add this line to your project's Gemfile:
8
8
 
9
9
  ```ruby
10
- gem 'activerecord-cockroachdb-adapter', '~> 5.2.0'
10
+ gem 'activerecord-cockroachdb-adapter', '~> 6.1.0'
11
11
  ```
12
12
 
13
- If you're using Rails 4.x, use the `0.1.x` versions of this gem.
13
+ If you're using Rails 5.2, use the `5.2.x` versions of this gem.
14
+
15
+ If you're using Rails 6.0, use the `6.0.x` versions of this gem.
14
16
 
15
17
  In `database.yml`, use the following adapter setting:
16
18
 
@@ -22,6 +24,13 @@ development:
22
24
  user: <username>
23
25
  ```
24
26
 
27
+ ## Configuration
28
+
29
+ In addition to the standard adapter settings, CockroachDB also supports the following:
30
+
31
+ - `use_follower_reads_for_type_introspection`: Use follower reads on queries to the `pg_type` catalog when set to `true`. This helps to speed up initialization by reading historical data, but may not find recently created user-defined types.
32
+ - `disable_cockroachdb_telemetry`: Determines if a telemetry call is made to the database when the connection pool is initialized. Setting this to `true` will prevent the call from being made.
33
+
25
34
  ## Working with Spatial Data
26
35
 
27
36
  The adapter uses [RGeo](https://github.com/rgeo/rgeo) and [RGeo-ActiveRecord](https://github.com/rgeo/rgeo-activerecord) to represent geometric and geographic data as Ruby objects and easily interface them with the adapter. The following is a brief introduction to RGeo and tips to help setup your spatial application. More documentation about RGeo can be found in the [YARD Docs](https://rubydoc.info/github/rgeo/rgeo) and [wiki](https://github.com/rgeo/rgeo/wiki).
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "activerecord-cockroachdb-adapter"
7
- spec.version = "6.1.0beta1"
7
+ spec.version = "6.1.2"
8
8
  spec.licenses = ["Apache-2.0"]
9
9
  spec.authors = ["Cockroach Labs"]
10
10
  spec.email = ["cockroach-db@googlegroups.com"]
@@ -11,6 +11,7 @@ connections:
11
11
  user: root
12
12
  requiressl: disable
13
13
  min_messages: warning
14
+ disable_cockroachdb_telemetry: true
14
15
  arunit_without_prepared_statements:
15
16
  database: activerecord_unittest
16
17
  host: localhost
@@ -19,6 +20,7 @@ connections:
19
20
  requiressl: disable
20
21
  min_messages: warning
21
22
  prepared_statements: false
23
+ disable_cockroachdb_telemetry: true
22
24
  arunit2:
23
25
  database: activerecord_unittest2
24
26
  host: localhost
@@ -26,3 +28,4 @@ connections:
26
28
  user: root
27
29
  requiressl: disable
28
30
  min_messages: warning
31
+ disable_cockroachdb_telemetry: true
@@ -0,0 +1,26 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module CockroachDB
4
+ module OID
5
+ module TypeMapInitializer
6
+ # override
7
+ # Replaces the query with a faster version that doesn't rely on the
8
+ # use of 'array_in(cstring,oid,integer)'::regprocedure.
9
+ def query_conditions_for_initial_load
10
+ known_type_names = @store.keys.map { |n| "'#{n}'" }
11
+ known_type_types = %w('r' 'e' 'd')
12
+ <<~SQL % [known_type_names.join(", "), known_type_types.join(", ")]
13
+ WHERE
14
+ t.typname IN (%s)
15
+ OR t.typtype IN (%s)
16
+ OR (t.typarray = 0 AND t.typcategory='A')
17
+ OR t.typelem != 0
18
+ SQL
19
+ end
20
+ end
21
+
22
+ PostgreSQL::OID::TypeMapInitializer.prepend(TypeMapInitializer)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -13,6 +13,7 @@ require "active_record/connection_adapters/cockroachdb/attribute_methods"
13
13
  require "active_record/connection_adapters/cockroachdb/column"
14
14
  require "active_record/connection_adapters/cockroachdb/spatial_column_info"
15
15
  require "active_record/connection_adapters/cockroachdb/setup"
16
+ require "active_record/connection_adapters/cockroachdb/oid/type_map_initializer"
16
17
  require "active_record/connection_adapters/cockroachdb/oid/spatial"
17
18
  require "active_record/connection_adapters/cockroachdb/oid/interval"
18
19
  require "active_record/connection_adapters/cockroachdb/arel_tosql"
@@ -55,6 +56,35 @@ end
55
56
 
56
57
  module ActiveRecord
57
58
  module ConnectionAdapters
59
+ module CockroachDBConnectionPool
60
+ def initialize(pool_config)
61
+ super(pool_config)
62
+ disable_telemetry = pool_config.db_config.configuration_hash[:disable_cockroachdb_telemetry]
63
+ adapter = pool_config.db_config.configuration_hash[:adapter]
64
+ return if disable_telemetry || adapter != "cockroachdb"
65
+
66
+
67
+ begin
68
+ with_connection do |conn|
69
+ if conn.active?
70
+ begin
71
+ query = "SELECT crdb_internal.increment_feature_counter('ActiveRecord %d.%d')"
72
+ conn.execute(query % [ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR])
73
+ rescue ActiveRecord::StatementInvalid
74
+ # The increment_feature_counter built-in is not supported on this
75
+ # CockroachDB version. Ignore.
76
+ rescue StandardError => e
77
+ conn.logger.warn "Unexpected error when incrementing feature counter: #{e}"
78
+ end
79
+ end
80
+ end
81
+ rescue StandardError
82
+ # Prevent failures on db creation and parallel testing.
83
+ end
84
+ end
85
+ end
86
+ ConnectionPool.prepend(CockroachDBConnectionPool)
87
+
58
88
  class CockroachDBAdapter < PostgreSQLAdapter
59
89
  ADAPTER_NAME = "CockroachDB".freeze
60
90
  DEFAULT_PRIMARY_KEY = "rowid"
@@ -73,7 +103,7 @@ module ActiveRecord
73
103
  st_polygon: {},
74
104
  }
75
105
 
76
- # http://postgis.17.x6.nabble.com/Default-SRID-td5001115.html
106
+ # http://postgis.17.x6.nabble.com/Default-SRID-td5001115.html
77
107
  DEFAULT_SRID = 0
78
108
 
79
109
  include CockroachDB::SchemaStatements
@@ -172,6 +202,10 @@ module ActiveRecord
172
202
  @crdb_version >= 202
173
203
  end
174
204
 
205
+ def supports_partitioned_indexes?
206
+ false
207
+ end
208
+
175
209
  # This is hardcoded to 63 (as previously was in ActiveRecord 5.0) to aid in
176
210
  # migration from PostgreSQL to CockroachDB. In practice, this limitation
177
211
  # is arbitrary since CockroachDB supports index name lengths and table alias
@@ -189,6 +223,7 @@ module ActiveRecord
189
223
 
190
224
  def initialize(connection, logger, conn_params, config)
191
225
  super(connection, logger, conn_params, config)
226
+
192
227
  crdb_version_string = query_value("SHOW crdb_version")
193
228
  if crdb_version_string.include? "v1."
194
229
  version_num = 1
@@ -242,12 +277,9 @@ module ActiveRecord
242
277
  precision = extract_precision(sql_type)
243
278
  scale = extract_scale(sql_type)
244
279
 
245
- # TODO(#178) this should never use DecimalWithoutScale since scale
246
- # is assumed to be 0 if it is not explicitly defined.
247
- #
248
280
  # If fmod is -1, that means that precision is defined but not
249
281
  # scale, or neither is defined.
250
- if fmod && fmod == -1
282
+ if fmod && fmod == -1 && !precision.nil?
251
283
  # Below comment is from ActiveRecord
252
284
  # FIXME: Remove this class, and the second argument to
253
285
  # lookups on PG
@@ -360,7 +392,7 @@ module ActiveRecord
360
392
  # In general, it is hard to parse that, but it is easy to handle the common
361
393
  # case of an empty array.
362
394
  def extract_empty_array_from_default(default)
363
- return unless supports_string_to_array_coercion?
395
+ return unless supports_string_to_array_coercion?
364
396
  return unless default =~ /\AARRAY\[\]\z/
365
397
  return "{}"
366
398
  end
@@ -439,6 +471,97 @@ module ActiveRecord
439
471
  false
440
472
  end
441
473
 
474
+ # override
475
+ # This method loads info about data types from the database to
476
+ # populate the TypeMap.
477
+ #
478
+ # Currently, querying from the pg_type catalog can be slow due to geo-partitioning
479
+ # so this modified query uses AS OF SYSTEM TIME '-10s' to read historical data.
480
+ def load_additional_types(oids = nil)
481
+ if @config[:use_follower_reads_for_type_introspection]
482
+ initializer = OID::TypeMapInitializer.new(type_map)
483
+
484
+ query = <<~SQL
485
+ SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
486
+ FROM pg_type as t
487
+ LEFT JOIN pg_range as r ON oid = rngtypid AS OF SYSTEM TIME '-10s'
488
+ SQL
489
+
490
+ if oids
491
+ query += "WHERE t.oid IN (%s)" % oids.join(", ")
492
+ else
493
+ query += initializer.query_conditions_for_initial_load
494
+ end
495
+
496
+ execute_and_clear(query, "SCHEMA", []) do |records|
497
+ initializer.run(records)
498
+ end
499
+ else
500
+ super
501
+ end
502
+ rescue ActiveRecord::StatementInvalid => e
503
+ raise e unless e.cause.is_a? PG::InvalidCatalogName
504
+ # use original if database is younger than 10s
505
+ super
506
+ end
507
+
508
+ # override
509
+ # This method maps data types to their proper decoder.
510
+ #
511
+ # Currently, querying from the pg_type catalog can be slow due to geo-partitioning
512
+ # so this modified query uses AS OF SYSTEM TIME '-10s' to read historical data.
513
+ def add_pg_decoders
514
+ if @config[:use_follower_reads_for_type_introspection]
515
+ @default_timezone = nil
516
+ @timestamp_decoder = nil
517
+
518
+ coders_by_name = {
519
+ "int2" => PG::TextDecoder::Integer,
520
+ "int4" => PG::TextDecoder::Integer,
521
+ "int8" => PG::TextDecoder::Integer,
522
+ "oid" => PG::TextDecoder::Integer,
523
+ "float4" => PG::TextDecoder::Float,
524
+ "float8" => PG::TextDecoder::Float,
525
+ "numeric" => PG::TextDecoder::Numeric,
526
+ "bool" => PG::TextDecoder::Boolean,
527
+ "timestamp" => PG::TextDecoder::TimestampUtc,
528
+ "timestamptz" => PG::TextDecoder::TimestampWithTimeZone,
529
+ }
530
+
531
+ known_coder_types = coders_by_name.keys.map { |n| quote(n) }
532
+ query = <<~SQL % known_coder_types.join(", ")
533
+ SELECT t.oid, t.typname
534
+ FROM pg_type as t AS OF SYSTEM TIME '-10s'
535
+ WHERE t.typname IN (%s)
536
+ SQL
537
+
538
+ coders = execute_and_clear(query, "SCHEMA", []) do |result|
539
+ result
540
+ .map { |row| construct_coder(row, coders_by_name[row["typname"]]) }
541
+ .compact
542
+ end
543
+
544
+ map = PG::TypeMapByOid.new
545
+ coders.each { |coder| map.add_coder(coder) }
546
+ @connection.type_map_for_results = map
547
+
548
+ @type_map_for_results = PG::TypeMapByOid.new
549
+ @type_map_for_results.default_type_map = map
550
+ @type_map_for_results.add_coder(PG::TextDecoder::Bytea.new(oid: 17, name: "bytea"))
551
+ @type_map_for_results.add_coder(MoneyDecoder.new(oid: 790, name: "money"))
552
+
553
+ # extract timestamp decoder for use in update_typemap_for_default_timezone
554
+ @timestamp_decoder = coders.find { |coder| coder.name == "timestamp" }
555
+ update_typemap_for_default_timezone
556
+ else
557
+ super
558
+ end
559
+ rescue ActiveRecord::StatementInvalid => e
560
+ raise e unless e.cause.is_a? PG::InvalidCatalogName
561
+ # use original if database is younger than 10s
562
+ super
563
+ end
564
+
442
565
  def arel_visitor
443
566
  Arel::Visitors::CockroachDB.new(self)
444
567
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-cockroachdb-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.0beta1
4
+ version: 6.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cockroach Labs
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-10 00:00:00.000000000 Z
11
+ date: 2021-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -62,6 +62,7 @@ extra_rdoc_files: []
62
62
  files:
63
63
  - ".gitignore"
64
64
  - ".gitmodules"
65
+ - CHANGELOG.md
65
66
  - CONTRIBUTING.md
66
67
  - Gemfile
67
68
  - LICENSE
@@ -83,6 +84,7 @@ files:
83
84
  - lib/active_record/connection_adapters/cockroachdb/database_tasks.rb
84
85
  - lib/active_record/connection_adapters/cockroachdb/oid/interval.rb
85
86
  - lib/active_record/connection_adapters/cockroachdb/oid/spatial.rb
87
+ - lib/active_record/connection_adapters/cockroachdb/oid/type_map_initializer.rb
86
88
  - lib/active_record/connection_adapters/cockroachdb/quoting.rb
87
89
  - lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb
88
90
  - lib/active_record/connection_adapters/cockroachdb/schema_statements.rb
@@ -109,9 +111,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
109
111
  version: '0'
110
112
  required_rubygems_version: !ruby/object:Gem::Requirement
111
113
  requirements:
112
- - - ">"
114
+ - - ">="
113
115
  - !ruby/object:Gem::Version
114
- version: 1.3.1
116
+ version: '0'
115
117
  requirements: []
116
118
  rubygems_version: 3.0.3
117
119
  signing_key: