Skip to content

Commit 52f0b23

Browse files
committed
Fix merge conflict in postgresql_adapter_test, update README with new configuration setting
2 parents 17f8d01 + 876afa2 commit 52f0b23

File tree

5 files changed

+118
-2
lines changed

5 files changed

+118
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 6.1.0-beta.3 - 2021-04-02
4+
5+
- Added a configuration option named `use_follower_reads_for_type_introspection`.
6+
If true, it improves the speed of type introspection by allowing potentially stale
7+
type metadata to be read. Defaults to false.
8+
39
## 6.1.0-beta.2 - 2021-03-06
410

511
- Improved connection performance by refactoring an introspection

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ development:
2222
user: <username>
2323
```
2424

25+
## Configuration
26+
27+
In addition to the standard adapter settings, CockroachDB also supports the following:
28+
29+
- `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.
30+
- `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.
31+
2532
## Working with Spatial Data
2633

2734
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).

activerecord-cockroachdb-adapter.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
44

55
Gem::Specification.new do |spec|
66
spec.name = "activerecord-cockroachdb-adapter"
7-
spec.version = "6.1.0-beta.2"
7+
spec.version = "6.1.0-beta.3"
88
spec.licenses = ["Apache-2.0"]
99
spec.authors = ["Cockroach Labs"]
1010
spec.email = ["[email protected]"]

lib/active_record/connection_adapters/cockroachdb_adapter.rb

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,97 @@ def is_cached_plan_failure?(e)
469469
false
470470
end
471471

472+
# override
473+
# This method loads info about data types from the database to
474+
# populate the TypeMap.
475+
#
476+
# Currently, querying from the pg_type catalog can be slow due to geo-partitioning
477+
# so this modified query uses AS OF SYSTEM TIME '-10s' to read historical data.
478+
def load_additional_types(oids = nil)
479+
if @config[:use_follower_reads_for_type_introspection]
480+
initializer = OID::TypeMapInitializer.new(type_map)
481+
482+
query = <<~SQL
483+
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
484+
FROM pg_type as t
485+
LEFT JOIN pg_range as r ON oid = rngtypid AS OF SYSTEM TIME '-10s'
486+
SQL
487+
488+
if oids
489+
query += "WHERE t.oid IN (%s)" % oids.join(", ")
490+
else
491+
query += initializer.query_conditions_for_initial_load
492+
end
493+
494+
execute_and_clear(query, "SCHEMA", []) do |records|
495+
initializer.run(records)
496+
end
497+
else
498+
super
499+
end
500+
rescue ActiveRecord::StatementInvalid => e
501+
raise e unless e.cause.is_a? PG::InvalidCatalogName
502+
# use original if database is younger than 10s
503+
super
504+
end
505+
506+
# override
507+
# This method maps data types to their proper decoder.
508+
#
509+
# Currently, querying from the pg_type catalog can be slow due to geo-partitioning
510+
# so this modified query uses AS OF SYSTEM TIME '-10s' to read historical data.
511+
def add_pg_decoders
512+
if @config[:use_follower_reads_for_type_introspection]
513+
@default_timezone = nil
514+
@timestamp_decoder = nil
515+
516+
coders_by_name = {
517+
"int2" => PG::TextDecoder::Integer,
518+
"int4" => PG::TextDecoder::Integer,
519+
"int8" => PG::TextDecoder::Integer,
520+
"oid" => PG::TextDecoder::Integer,
521+
"float4" => PG::TextDecoder::Float,
522+
"float8" => PG::TextDecoder::Float,
523+
"numeric" => PG::TextDecoder::Numeric,
524+
"bool" => PG::TextDecoder::Boolean,
525+
"timestamp" => PG::TextDecoder::TimestampUtc,
526+
"timestamptz" => PG::TextDecoder::TimestampWithTimeZone,
527+
}
528+
529+
known_coder_types = coders_by_name.keys.map { |n| quote(n) }
530+
query = <<~SQL % known_coder_types.join(", ")
531+
SELECT t.oid, t.typname
532+
FROM pg_type as t AS OF SYSTEM TIME '-10s'
533+
WHERE t.typname IN (%s)
534+
SQL
535+
536+
coders = execute_and_clear(query, "SCHEMA", []) do |result|
537+
result
538+
.map { |row| construct_coder(row, coders_by_name[row["typname"]]) }
539+
.compact
540+
end
541+
542+
map = PG::TypeMapByOid.new
543+
coders.each { |coder| map.add_coder(coder) }
544+
@connection.type_map_for_results = map
545+
546+
@type_map_for_results = PG::TypeMapByOid.new
547+
@type_map_for_results.default_type_map = map
548+
@type_map_for_results.add_coder(PG::TextDecoder::Bytea.new(oid: 17, name: "bytea"))
549+
@type_map_for_results.add_coder(MoneyDecoder.new(oid: 790, name: "money"))
550+
551+
# extract timestamp decoder for use in update_typemap_for_default_timezone
552+
@timestamp_decoder = coders.find { |coder| coder.name == "timestamp" }
553+
update_typemap_for_default_timezone
554+
else
555+
super
556+
end
557+
rescue ActiveRecord::StatementInvalid => e
558+
raise e unless e.cause.is_a? PG::InvalidCatalogName
559+
# use original if database is younger than 10s
560+
super
561+
end
562+
472563
def arel_visitor
473564
Arel::Visitors::CockroachDB.new(self)
474565
end

test/cases/adapters/postgresql/postgresql_adapter_test.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def setup
1616
end
1717

1818
def teardown
19-
# use connection without follower_reads
19+
# use connection without follower_reads and telemetry
2020
database_config = { "adapter" => "cockroachdb", "database" => "activerecord_unittest" }
2121
ar_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
2222
database_config.update(ar_config.configuration_hash)
@@ -50,6 +50,18 @@ def test_using_telemetry_builtin_connects_properly
5050

5151
assert_equal(false, conn_config[:disable_cockroachdb_telemetry])
5252
end
53+
54+
def test_using_follower_reads_connects_properly
55+
database_config = { "use_follower_reads_for_type_introspection": true, "adapter" => "cockroachdb", "database" => "activerecord_unittest" }
56+
ar_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
57+
database_config.update(ar_config.configuration_hash)
58+
59+
ActiveRecord::Base.establish_connection(database_config)
60+
conn = ActiveRecord::Base.connection
61+
conn_config = conn.instance_variable_get("@config")
62+
63+
assert conn_config[:use_follower_reads_for_type_introspection]
64+
end
5365
end
5466
end
5567
end

0 commit comments

Comments
 (0)