Class: ChronoModel::Adapter
- Inherits:
-
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
- Object
- ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
- ChronoModel::Adapter
- Includes:
- DDL, Indexes, Migrations, Upgrade
- Defined in:
- lib/chrono_model/adapter.rb,
lib/chrono_model/adapter/ddl.rb,
lib/chrono_model/adapter/indexes.rb,
lib/chrono_model/adapter/upgrade.rb,
lib/chrono_model/adapter/migrations.rb,
lib/chrono_model/adapter/migrations_modules/stable.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, MigrationsModules, 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.
-
#initialize ⇒ Adapter
constructor
A new instance of Adapter.
-
#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
schema
search 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.
- #valid_table_definition_options ⇒ Object
Methods included from Upgrade
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, #change_column, #change_column_default, #change_column_null, #change_table, #create_table, #drop_table, #remove_column, #rename_column, #rename_table
Methods included from MigrationsModules::Stable
Constructor Details
#initialize ⇒ Adapter
Returns a new instance of Adapter.
30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/chrono_model/adapter.rb', line 30 def initialize(*) super connect! unless chrono_supported? raise ChronoModel::Error, 'Your database server is not supported by ChronoModel. ' \ 'Currently, only PostgreSQL >= 9.3 is supported.' end chrono_setup! end |
Instance Method Details
#chrono_metadata_for(view_name) ⇒ Object
Reads the Gem metadata from the COMMENT set on the given PostgreSQL view name.
159 160 161 162 163 164 165 166 |
# File 'lib/chrono_model/adapter.rb', line 159 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.
170 171 172 173 174 |
# File 'lib/chrono_model/adapter.rb', line 170 def (view_name, ) comment = MultiJson.dump() execute %( COMMENT ON VIEW #{view_name} IS #{quote(comment)} ) end |
#chrono_setup! ⇒ Object
53 54 55 56 57 |
# File 'lib/chrono_model/adapter.rb', line 53 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 (90300 in PostgreSQL’s ‘PG_VERSION_NUM` numeric format).
49 50 51 |
# File 'lib/chrono_model/adapter.rb', line 49 def chrono_supported? postgresql_version >= 90300 # rubocop:disable Style/NumericLiterals 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.
93 |
# File 'lib/chrono_model/adapter.rb', line 93 def column_definitions; end |
#is_chrono?(table) ⇒ Boolean
Returns true if the given name references a temporal table.
151 152 153 154 |
# File 'lib/chrono_model/adapter.rb', line 151 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.
109 110 111 |
# File 'lib/chrono_model/adapter.rb', line 109 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.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/chrono_model/adapter.rb', line 120 def on_schema(schema, recurse: :follow) old_path = schema_search_path count_recursions do if (recurse == :follow) || (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 = chrono_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.
103 104 105 |
# File 'lib/chrono_model/adapter.rb', line 103 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.
73 |
# File 'lib/chrono_model/adapter.rb', line 73 def primary_key(table_name); end |
#valid_table_definition_options ⇒ Object
176 177 178 |
# File 'lib/chrono_model/adapter.rb', line 176 def super + %i[temporal journal no_journal full_journal] end |