lib/chrono_model/adapter.rb in chrono_model-0.8.2 vs lib/chrono_model/adapter.rb in chrono_model-0.9.0
- old
+ new
@@ -1,8 +1,10 @@
require 'active_record'
require 'active_record/connection_adapters/postgresql_adapter'
+require 'multi_json'
+
module ChronoModel
# This class implements all ActiveRecord::ConnectionAdapters::SchemaStatements
# methods adding support for temporal extensions. It inherits from the Postgres
# adapter for a clean override of its methods using super.
@@ -283,23 +285,36 @@
def remove_column(table_name, *)
return super unless is_chrono?(table_name)
chrono_alter(table_name) { super }
end
- # Runs column_definitions, primary_key and indexes in the temporal schema,
+ # Runs column_definitions in the temporal schema, as the table there
+ # defined is the source for this information.
+ #
+ # The default search path is included however, since the table
+ # may reference types defined in other schemas, which result in their
+ # names becoming schema qualified, which will cause type resolutions to fail.
+ #
+ define_method(:column_definitions) do |table_name|
+ return super(table_name) unless is_chrono?(table_name)
+ on_schema(TEMPORAL_SCHEMA + ',' + self.schema_search_path, false) { super(table_name) }
+ end
+
+ # Runs primary_key, indexes and default_sequence_name in the temporal schema,
# as the table there defined is the source for this information.
#
# Moreover, the PostgreSQLAdapter +indexes+ method uses current_schema(),
# thus this is the only (and cleanest) way to make injection work.
#
# Schema nesting is disabled on these calls, make sure to fetch metadata
# from the first caller's selected schema and not from the current one.
#
- [:column_definitions, :primary_key, :indexes].each do |method|
- define_method(method) do |table_name|
- return super(table_name) unless is_chrono?(table_name)
- _on_temporal_schema(false) { super(table_name) }
+ [:primary_key, :indexes, :default_sequence_name].each do |method|
+ define_method(method) do |*args|
+ table_name = args.first
+ return super(*args) unless is_chrono?(table_name)
+ _on_temporal_schema(false) { super(*args) }
end
end
# Create spatial indexes for timestamp search.
#
@@ -452,10 +467,16 @@
else
klasses.any? { |k| e.message =~ /#{k.name}/ }
end
end
+ def chrono_setup!
+ chrono_create_schemas
+
+ chrono_upgrade_structure!
+ end
+
# HACK: Redefine tsrange parsing support, as it is broken currently.
#
# This self-made API is here because currently AR4 does not support
# open-ended ranges. The reasons are poor support in Ruby:
#
@@ -466,36 +487,41 @@
# https://github.com/rails/rails/issues/13793
# https://github.com/rails/rails/issues/14010
#
# so, for now, we are implementing our own.
#
- class TSRange < OID::Type
- def extract_bounds(value)
- from, to = value[1..-2].split(',')
- {
- from: (value[1] == ',' || from == '-infinity') ? nil : from[1..-2],
- to: (value[-2] == ',' || to == 'infinity') ? nil : to[1..-2],
- #exclude_start: (value[0] == '('),
- #exclude_end: (value[-1] == ')')
- }
- end
+ class TSRange < ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Range
+ OID = 3908
- def type_cast(value)
+ def cast_value(value)
+ return if value == 'empty'
+ return value if value.is_a?(::Array)
+
extracted = extract_bounds(value)
from = Conversions.string_to_utc_time extracted[:from]
to = Conversions.string_to_utc_time extracted[:to ]
[from, to]
end
+
+ def extract_bounds(value)
+ from, to = value[1..-2].split(',')
+ {
+ from: (value[1] == ',' || from == '-infinity') ? nil : from[1..-2],
+ to: (value[-2] == ',' || to == 'infinity') ? nil : to[1..-2],
+ }
+ end
end
- def chrono_setup!
- chrono_create_schemas
- chrono_setup_type_map
+ def initialize_type_map(type_map)
+ super.tap do
+ ar_type = type_map.fetch(TSRange::OID)
+ cm_type = TSRange.new(ar_type.subtype, ar_type.type)
- chrono_upgrade_structure!
+ type_map.register_type TSRange::OID, cm_type
+ end
end
# Copy the indexes from the temporal table to the history table if the indexes
# are not already created with the same name.
#
@@ -525,15 +551,9 @@
#
def chrono_create_schemas
[TEMPORAL_SCHEMA, HISTORY_SCHEMA].each do |schema|
execute "CREATE SCHEMA #{schema}" unless schema_exists?(schema)
end
- end
-
- # Adds the above TSRange class to the PG Adapter OID::TYPE_MAP
- #
- def chrono_setup_type_map
- OID::TYPE_MAP[3908] = TSRange.new
end
# Upgrades existing structure for each table, if required.
# TODO: allow upgrades from pre-0.6 structure with box() and stuff.
#