Class: ChronoModel::Adapter
- Inherits:
-
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
- Object
- ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
- ChronoModel::Adapter
- Includes:
- DDL, Indexes, Migrations, TSRange, Upgrade
- Defined in:
- lib/chrono_model/adapter.rb,
lib/chrono_model/adapter/ddl.rb,
lib/chrono_model/adapter/indexes.rb,
lib/chrono_model/adapter/tsrange.rb,
lib/chrono_model/adapter/upgrade.rb,
lib/chrono_model/adapter/migrations.rb
Overview
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.
Defined Under Namespace
Modules: DDL, Indexes, Migrations, TSRange, Upgrade
Constant Summary collapse
- TEMPORAL_SCHEMA =
The schema holding current data
'temporal'- HISTORY_SCHEMA =
The schema holding historical data
'history'
Instance Method Summary collapse
-
#chrono_metadata_for(view_name) ⇒ Object
Reads the Gem metadata from the COMMENT set on the given PostgreSQL view name.
-
#chrono_metadata_set(view_name, metadata) ⇒ Object
Writes Gem metadata on the COMMENT field in the given VIEW name.
- #chrono_setup! ⇒ Object
-
#chrono_supported? ⇒ Boolean
Returns true whether the connection adapter supports our implementation of temporal tables.
-
#column_definitions ⇒ Object
Runs column_definitions in the temporal schema, as the table there defined is the source for this information.
-
#is_chrono?(table) ⇒ Boolean
Returns true if the given name references a temporal table.
-
#on_history_schema(&block) ⇒ Object
Evaluates the given block in the history schema.
-
#on_schema(schema, recurse: :follow) ⇒ Object
Evaluates the given block in the given
schemasearch path. -
#on_temporal_schema(&block) ⇒ Object
Evaluates the given block in the temporal schema.
-
#primary_key(table_name) ⇒ Object
Runs primary_key, indexes and default_sequence_name in the temporal schema, as the table there defined is the source for this information.
Methods included from TSRange
Methods included from Indexes
#add_temporal_indexes, #add_timeline_consistency_constraint, #remove_temporal_indexes, #remove_timeline_consistency_constraint, #timeline_consistency_constraint_name
Methods included from Migrations
#add_column, #add_index, #change_column, #change_column_default, #change_column_null, #change_table, #create_table, #drop_table, #remove_column, #remove_index, #rename_column, #rename_table
Instance Method Details
#chrono_metadata_for(view_name) ⇒ Object
Reads the Gem metadata from the COMMENT set on the given PostgreSQL view name.
143 144 145 146 147 148 149 |
# File 'lib/chrono_model/adapter.rb', line 143 def (view_name) comment = select_value( "SELECT obj_description(#{quote(view_name)}::regclass)", "ChronoModel metadata for #{view_name}") if data_source_exists?(view_name) MultiJson.load(comment || '{}').with_indifferent_access end |
#chrono_metadata_set(view_name, metadata) ⇒ Object
Writes Gem metadata on the COMMENT field in the given VIEW name.
153 154 155 156 157 |
# File 'lib/chrono_model/adapter.rb', line 153 def (view_name, ) comment = MultiJson.dump() execute %[ COMMENT ON VIEW #{view_name} IS #{quote(comment)} ] end |
#chrono_setup! ⇒ Object
36 37 38 39 40 |
# File 'lib/chrono_model/adapter.rb', line 36 def chrono_setup! chrono_ensure_schemas chrono_upgrade_warning end |
#chrono_supported? ⇒ Boolean
Returns true whether the connection adapter supports our implementation of temporal tables. Currently, Chronomodel is supported starting with PostgreSQL 9.3.
32 33 34 |
# File 'lib/chrono_model/adapter.rb', line 32 def chrono_supported? postgresql_version >= 90300 end |
#column_definitions ⇒ Object
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.
NOTE: This method is dynamically defined, see the source.
76 77 |
# File 'lib/chrono_model/adapter.rb', line 76 def column_definitions end |
#is_chrono?(table) ⇒ Boolean
Returns true if the given name references a temporal table.
135 136 137 138 |
# File 'lib/chrono_model/adapter.rb', line 135 def is_chrono?(table) on_temporal_schema { data_source_exists?(table) } && on_history_schema { data_source_exists?(table) } end |
#on_history_schema(&block) ⇒ Object
Evaluates the given block in the history schema.
92 93 94 |
# File 'lib/chrono_model/adapter.rb', line 92 def on_history_schema(&block) on_schema(HISTORY_SCHEMA, &block) end |
#on_schema(schema, recurse: :follow) ⇒ Object
Evaluates the given block in the given schema search path.
Recursion works by saving the old_path the function closure at each recursive call.
See specs for examples and behaviour.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/chrono_model/adapter.rb', line 103 def on_schema(schema, recurse: :follow) old_path = self.schema_search_path count_recursions do if recurse == :follow or Thread.current['recursions'] == 1 self.schema_search_path = schema end yield end ensure # If the transaction is aborted, any execute() call will raise # "transaction is aborted errors" - thus calling the Adapter's # setter won't update the memoized variable. # # Here we reset it to +nil+ to refresh it on the next call, as # there is no way to know which path will be restored when the # transaction ends. # transaction_aborted = @connection.transaction_status == PG::Connection::PQTRANS_INERROR if transaction_aborted && Thread.current['recursions'] == 1 @schema_search_path = nil else self.schema_search_path = old_path end end |
#on_temporal_schema(&block) ⇒ Object
Evaluates the given block in the temporal schema.
86 87 88 |
# File 'lib/chrono_model/adapter.rb', line 86 def on_temporal_schema(&block) on_schema(TEMPORAL_SCHEMA, &block) end |
#primary_key(table_name) ⇒ Object
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.
NOTE: These methods are dynamically defined, see the source.
56 57 |
# File 'lib/chrono_model/adapter.rb', line 56 def primary_key(table_name) end |