chrono_model 1.2.2 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +19 -20
- data/README.md +73 -62
- data/lib/active_record/connection_adapters/chronomodel_adapter.rb +14 -14
- data/lib/active_record/tasks/chronomodel_database_tasks.rb +40 -39
- data/lib/chrono_model/adapter/ddl.rb +168 -153
- data/lib/chrono_model/adapter/indexes.rb +99 -94
- data/lib/chrono_model/adapter/migrations.rb +81 -104
- data/lib/chrono_model/adapter/migrations_modules/stable.rb +41 -0
- data/lib/chrono_model/adapter/tsrange.rb +20 -5
- data/lib/chrono_model/adapter/upgrade.rb +89 -91
- data/lib/chrono_model/adapter.rb +59 -31
- data/lib/chrono_model/chrono.rb +17 -0
- data/lib/chrono_model/conversions.rb +14 -8
- data/lib/chrono_model/db_console.rb +5 -0
- data/lib/chrono_model/patches/as_of_time_holder.rb +2 -2
- data/lib/chrono_model/patches/as_of_time_relation.rb +3 -13
- data/lib/chrono_model/patches/association.rb +15 -12
- data/lib/chrono_model/patches/batches.rb +13 -0
- data/lib/chrono_model/patches/db_console.rb +20 -4
- data/lib/chrono_model/patches/join_node.rb +4 -4
- data/lib/chrono_model/patches/preloader.rb +41 -11
- data/lib/chrono_model/patches/relation.rb +51 -8
- data/lib/chrono_model/patches.rb +3 -1
- data/lib/chrono_model/railtie.rb +13 -27
- data/lib/chrono_model/time_gate.rb +3 -3
- data/lib/chrono_model/time_machine/history_model.rb +65 -31
- data/lib/chrono_model/time_machine/time_query.rb +65 -49
- data/lib/chrono_model/time_machine/timeline.rb +52 -28
- data/lib/chrono_model/time_machine.rb +57 -25
- data/lib/chrono_model/utilities.rb +3 -3
- data/lib/chrono_model/version.rb +3 -1
- data/lib/chrono_model.rb +31 -36
- metadata +24 -263
- data/.gitignore +0 -21
- data/.rspec +0 -2
- data/.travis.yml +0 -41
- data/Gemfile +0 -4
- data/README.sql +0 -161
- data/Rakefile +0 -25
- data/chrono_model.gemspec +0 -33
- data/gemfiles/rails_5.0.gemfile +0 -6
- data/gemfiles/rails_5.1.gemfile +0 -6
- data/gemfiles/rails_5.2.gemfile +0 -6
- data/lib/chrono_model/json.rb +0 -28
- data/spec/aruba/dbconsole_spec.rb +0 -25
- data/spec/aruba/fixtures/database_with_default_username_and_password.yml +0 -14
- data/spec/aruba/fixtures/database_without_username_and_password.yml +0 -11
- data/spec/aruba/fixtures/empty_structure.sql +0 -27
- data/spec/aruba/fixtures/migrations/56/20160812190335_create_impressions.rb +0 -10
- data/spec/aruba/fixtures/migrations/56/20171115195229_add_temporal_extension_to_impressions.rb +0 -10
- data/spec/aruba/fixtures/railsapp/config/application.rb +0 -17
- data/spec/aruba/fixtures/railsapp/config/boot.rb +0 -5
- data/spec/aruba/fixtures/railsapp/config/environments/development.rb +0 -38
- data/spec/aruba/migrations_spec.rb +0 -48
- data/spec/aruba/rake_task_spec.rb +0 -71
- data/spec/chrono_model/adapter/base_spec.rb +0 -157
- data/spec/chrono_model/adapter/ddl_spec.rb +0 -243
- data/spec/chrono_model/adapter/indexes_spec.rb +0 -72
- data/spec/chrono_model/adapter/migrations_spec.rb +0 -312
- data/spec/chrono_model/conversions_spec.rb +0 -43
- data/spec/chrono_model/history_models_spec.rb +0 -32
- data/spec/chrono_model/json_ops_spec.rb +0 -59
- data/spec/chrono_model/time_machine/as_of_spec.rb +0 -188
- data/spec/chrono_model/time_machine/changes_spec.rb +0 -50
- data/spec/chrono_model/time_machine/counter_cache_race_spec.rb +0 -46
- data/spec/chrono_model/time_machine/default_scope_spec.rb +0 -37
- data/spec/chrono_model/time_machine/history_spec.rb +0 -104
- data/spec/chrono_model/time_machine/keep_cool_spec.rb +0 -27
- data/spec/chrono_model/time_machine/manipulations_spec.rb +0 -84
- data/spec/chrono_model/time_machine/model_identification_spec.rb +0 -46
- data/spec/chrono_model/time_machine/sequence_spec.rb +0 -74
- data/spec/chrono_model/time_machine/sti_spec.rb +0 -100
- data/spec/chrono_model/time_machine/time_query_spec.rb +0 -261
- data/spec/chrono_model/time_machine/timeline_spec.rb +0 -63
- data/spec/chrono_model/time_machine/timestamps_spec.rb +0 -43
- data/spec/chrono_model/time_machine/transactions_spec.rb +0 -69
- data/spec/config.travis.yml +0 -5
- data/spec/config.yml.example +0 -9
- data/spec/spec_helper.rb +0 -33
- data/spec/support/adapter/helpers.rb +0 -53
- data/spec/support/adapter/structure.rb +0 -44
- data/spec/support/aruba.rb +0 -44
- data/spec/support/connection.rb +0 -70
- data/spec/support/matchers/base.rb +0 -56
- data/spec/support/matchers/column.rb +0 -99
- data/spec/support/matchers/function.rb +0 -79
- data/spec/support/matchers/index.rb +0 -69
- data/spec/support/matchers/schema.rb +0 -39
- data/spec/support/matchers/table.rb +0 -275
- data/spec/support/time_machine/helpers.rb +0 -47
- data/spec/support/time_machine/structure.rb +0 -111
- data/sql/json_ops.sql +0 -56
- data/sql/uninstall-json_ops.sql +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 222db0e6673e7171d44dac2163b5048ebf6b459c18fa2a2609a3051fce8c6591
|
4
|
+
data.tar.gz: 871fdf28717c85267e6b783f1f2d6ba3a24b1261e974e53a25de28d745bc8579
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bf942259052f134ea38de898307a65f20a6b448d8e8ff99a09ae06cd751f9834e1eb22abd4498c880005b8fc91f44ecebea4702be8c174570c50027dce13a75
|
7
|
+
data.tar.gz: 2b894f82a0cb9687d59dca9c3427a854cf6dc02191a08df71a215dfc577a8d1dd58632d44eb179395f097aa7d2391a7c738968d0f4c68f16cc14fffd2d18e034
|
data/LICENSE
CHANGED
@@ -1,24 +1,23 @@
|
|
1
|
-
Copyright (c) 2012-2014 Marcello Barnaba <m.barnaba@ifad.org>
|
2
|
-
Copyright (c) 2012-2014 Peter J. Brindisi <p.brindisi@ifad.org>
|
3
|
-
Copyright (c) 2012-2014 IFAD
|
4
|
-
|
5
1
|
MIT License
|
6
2
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
the
|
3
|
+
Copyright (c) 2012-2024 Marcello Barnaba <m.barnaba@ifad.org>
|
4
|
+
Copyright (c) 2012-2024 Peter J. Brindisi <p.brindisi@ifad.org>
|
5
|
+
Copyright (c) 2012-2024 IFAD
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
9
|
+
in the Software without restriction, including without limitation the rights
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
12
|
+
furnished to do so, subject to the following conditions:
|
14
13
|
|
15
|
-
The above copyright notice and this permission notice shall be
|
16
|
-
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
15
|
+
copies or substantial portions of the Software.
|
17
16
|
|
18
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
OF
|
24
|
-
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
[![Gem Version][gem-version-badge]][gem-version]
|
7
7
|
[![Inlinedocs][docs-analysis-badge]][docs-analysis]
|
8
8
|
|
9
|
-
![
|
9
|
+
![A Delorean that we all love][delorean-image]
|
10
10
|
|
11
11
|
ChronoModel implements what Oracle sells as "Flashback Queries", with standard
|
12
12
|
SQL on free PostgreSQL. Academically speaking, ChronoModel implements a
|
@@ -62,9 +62,9 @@ All timestamps are _forcibly_ stored in as UTC, bypassing the
|
|
62
62
|
|
63
63
|
## Requirements
|
64
64
|
|
65
|
-
* Ruby >=
|
66
|
-
* Active Record >=
|
67
|
-
* PostgreSQL >= 9.4
|
65
|
+
* Ruby >= 3.0
|
66
|
+
* Active Record >= 7.0. See the [detailed supported versions matrix on Ruby GitHub Actions workflows](https://github.com/ifad/chronomodel/blob/master/.github/workflows)
|
67
|
+
* PostgreSQL >= 9.4
|
68
68
|
* The `btree_gist` PostgreSQL extension
|
69
69
|
|
70
70
|
With Homebrew:
|
@@ -96,6 +96,13 @@ development:
|
|
96
96
|
username: ...
|
97
97
|
```
|
98
98
|
|
99
|
+
Configure Active Record in your `config/application.rb` to use the `:sql` schema
|
100
|
+
format:
|
101
|
+
|
102
|
+
```rb
|
103
|
+
config.active_record.schema_format = :sql
|
104
|
+
```
|
105
|
+
|
99
106
|
## Schema creation
|
100
107
|
|
101
108
|
ChronoModel hooks all `ActiveRecord::Migration` methods to make them temporal
|
@@ -141,7 +148,7 @@ validity from midnight, January 1st, 1 CE. You can set a specific validity with
|
|
141
148
|
the `:validity` option:
|
142
149
|
|
143
150
|
```ruby
|
144
|
-
change_table :your_table, :
|
151
|
+
change_table :your_table, temporal: true, copy_data: true, validity: '1977-01-01'
|
145
152
|
```
|
146
153
|
|
147
154
|
Please note that `change_table` requires you to use *old_style* `up` and
|
@@ -156,9 +163,9 @@ history.
|
|
156
163
|
You can also choose which fields are to be journaled, passing the following
|
157
164
|
options to `create_table`:
|
158
165
|
|
159
|
-
*
|
160
|
-
*
|
161
|
-
*
|
166
|
+
* `journal: %w( fld1 fld2 .. .. )` - record changes in the history only when changing specified fields
|
167
|
+
* `no_journal: %w( fld1 fld2 .. )` - do not record changes to the specified fields
|
168
|
+
* `full_journal: true` - record changes to *all* fields, including `updated_at`.
|
162
169
|
|
163
170
|
These options are stored as JSON in the [COMMENT][pg-comment] area of the
|
164
171
|
public view, alongside with the ChronoModel version that created them.
|
@@ -195,7 +202,7 @@ to your `create_table`. Example:
|
|
195
202
|
Include the `ChronoModel::TimeMachine` module in your model.
|
196
203
|
|
197
204
|
```ruby
|
198
|
-
|
205
|
+
class Country < ActiveRecord::Base
|
199
206
|
include ChronoModel::TimeMachine
|
200
207
|
|
201
208
|
has_many :compositions
|
@@ -310,31 +317,19 @@ only against ActiveRecord by using
|
|
310
317
|
|
311
318
|
Ensure to run the full test suite before pushing.
|
312
319
|
|
313
|
-
## Usage with JSON (*not* JSONB) columns
|
314
|
-
|
315
|
-
**DEPRECATED**: Please migrate to JSONB. It has an equality operator built-in,
|
316
|
-
it's faster and stricter, and offers many more indexing abilities and better
|
317
|
-
performance than JSON. It is going to be desupported soon because PostgreSQL 10
|
318
|
-
does not support these anymore.
|
319
|
-
|
320
|
-
The [JSON][pg-json-type] does not provide an [equality operator][pg-json-func].
|
321
|
-
As both unnecessary update suppression and selective journaling require
|
322
|
-
comparing the OLD and NEW rows fields, this fails by default.
|
323
|
-
|
324
|
-
ChronoModel provides a naive and heavyweight JSON equality operator using
|
325
|
-
[pl/python][pg-json-opclass] and associated Postgres objects.
|
326
|
-
|
327
|
-
To set up you can use
|
328
|
-
|
329
|
-
```ruby
|
330
|
-
require 'chrono_model/json'
|
331
|
-
ChronoModel::Json.create
|
332
|
-
```
|
333
|
-
|
334
320
|
## Caveats
|
335
321
|
|
322
|
+
* Considering the nature of modern applications, it's crucial to understand
|
323
|
+
that the database time does not necessarily align with the application time
|
324
|
+
due to the delay introduced by communication between the application and
|
325
|
+
the database server. Consequently, there is no assurance that the application
|
326
|
+
time will always be less than the database time. Therefore, relying solely
|
327
|
+
on `created_at` and `updated_at` fields as timestamps to determine the state
|
328
|
+
of an object at a specific point in time within the application could
|
329
|
+
lead to inaccuracies.
|
330
|
+
|
336
331
|
* Rails 4+ support requires disabling tsrange parsing support, as it
|
337
|
-
[is broken][r4-tsrange-broken] and
|
332
|
+
[is broken][r4-tsrange-broken] and [incomplete][r4-tsrange-incomplete]
|
338
333
|
as of now, mainly due to a [design clash with ruby][pg-tsrange-and-ruby].
|
339
334
|
|
340
335
|
* The triggers and temporal indexes cannot be saved in schema.rb. The AR
|
@@ -345,14 +340,27 @@ ChronoModel::Json.create
|
|
345
340
|
`db:structure:load`.
|
346
341
|
Two helper tasks are also added, `db:data:dump` and `db:data:load`.
|
347
342
|
|
348
|
-
* The choice of using subqueries instead of [Common Table Expressions]
|
349
|
-
|
350
|
-
|
343
|
+
* The choice of using subqueries instead of [Common Table Expressions][pg-ctes]
|
344
|
+
was dictated by the fact that CTEs [currently act as an optimization
|
345
|
+
fence][pg-cte-optimization-fence].
|
351
346
|
If it will be possible [to opt-out of the fence][pg-cte-opt-out-fence]
|
352
347
|
in the future, they will be probably be used again as they were [in the
|
353
348
|
past][cm-cte-impl], because the resulting queries were more readable,
|
354
349
|
and do not inhibit using `.from()` on the `AR::Relation`.
|
355
350
|
|
351
|
+
* Foreign keys are not supported. [See issue #174][gh-issue-174]
|
352
|
+
|
353
|
+
* There may be unexpected results when combining eager loading and joins.
|
354
|
+
[See issue #186][gh-issue-186]
|
355
|
+
|
356
|
+
* Global ID ignores historical objects. [See issue #192][gh-issue-192]
|
357
|
+
|
358
|
+
* Different historical objects are considered the identical. [See issue
|
359
|
+
#206][gh-issue-206]
|
360
|
+
|
361
|
+
* Use with caution when implementing inline editing features, as Chronomodel
|
362
|
+
creates a new record for each modification. This will lead to increased
|
363
|
+
storage requirements and bloated history
|
356
364
|
|
357
365
|
## Contributing
|
358
366
|
|
@@ -376,41 +384,40 @@ while using it in many important projects.
|
|
376
384
|
This software is Made in Italy :it: :smile:.
|
377
385
|
|
378
386
|
|
379
|
-
[build-status]: https://
|
380
|
-
[build-status-badge]: https://
|
381
|
-
[code-analysis]: https://codeclimate.com/github/ifad/chronomodel
|
382
|
-
[code-analysis-badge]: https://codeclimate.com/
|
383
|
-
[docs-analysis]:
|
384
|
-
[docs-analysis-badge]:
|
387
|
+
[build-status]: https://github.com/ifad/chronomodel/actions
|
388
|
+
[build-status-badge]: https://github.com/ifad/chronomodel/actions/workflows/ruby.yml/badge.svg
|
389
|
+
[code-analysis]: https://codeclimate.com/github/ifad/chronomodel/maintainability
|
390
|
+
[code-analysis-badge]: https://api.codeclimate.com/v1/badges/cdee7327938dc2eaff99/maintainability
|
391
|
+
[docs-analysis]: https://inch-ci.org/github/ifad/chronomodel
|
392
|
+
[docs-analysis-badge]: https://inch-ci.org/github/ifad/chronomodel.svg?branch=master
|
385
393
|
[gem-version]: https://rubygems.org/gems/chrono_model
|
386
394
|
[gem-version-badge]: https://badge.fury.io/rb/chrono_model.svg
|
387
395
|
[test-coverage]: https://codeclimate.com/github/ifad/chronomodel
|
388
396
|
[test-coverage-badge]: https://codeclimate.com/github/ifad/chronomodel/badges/coverage.svg
|
389
397
|
|
390
398
|
[delorean-image]: https://i.imgur.com/DD77F4s.jpg
|
391
|
-
|
392
|
-
|
393
|
-
[wp-scd-
|
394
|
-
|
395
|
-
|
396
|
-
[pg-
|
397
|
-
[pg-
|
398
|
-
[pg-
|
399
|
-
[pg-
|
400
|
-
[pg-
|
401
|
-
[pg-
|
402
|
-
[pg-partitioning]:
|
403
|
-
[pg-
|
404
|
-
[pg-
|
405
|
-
[pg-
|
406
|
-
[pg-
|
407
|
-
[pg-comment]: http://www.postgresql.org/docs/9.4/static/sql-comment.html
|
399
|
+
|
400
|
+
[wp-scd-2]: https://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_2
|
401
|
+
[wp-scd-4]: https://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_4
|
402
|
+
|
403
|
+
[pg-updatable-views]: https://www.postgresql.org/docs/9.4/sql-createview.html#SQL-CREATEVIEW-UPDATABLE-VIEWS
|
404
|
+
[pg-table-inheritance]: https://www.postgresql.org/docs/9.4/ddl-inherit.html
|
405
|
+
[pg-instead-of-triggers]: https://www.postgresql.org/docs/9.4/sql-createtrigger.html
|
406
|
+
[pg-triggers]: https://www.postgresql.org/docs/9.4/trigger-definition.html
|
407
|
+
[pg-schema]: https://www.postgresql.org/docs/9.4/ddl-schemas.html
|
408
|
+
[pg-current-timestamp]: https://www.postgresql.org/docs/9.4/functions-datetime.html#FUNCTIONS-DATETIME-TABLE
|
409
|
+
[pg-partitioning]: https://www.postgresql.org/docs/9.4/ddl-partitioning.html
|
410
|
+
[pg-partitioning-excl-constraints]: https://www.postgresql.org/docs/9.4/ddl-partitioning.html#DDL-PARTITIONING-CONSTRAINT-EXCLUSION
|
411
|
+
[pg-gist-indexes]: https://www.postgresql.org/docs/9.4/gist.html
|
412
|
+
[pg-exclusion-constraints]: https://www.postgresql.org/docs/9.4/sql-createtable.html#SQL-CREATETABLE-EXCLUDE
|
413
|
+
[pg-btree-gist]: https://www.postgresql.org/docs/9.4/btree-gist.html
|
414
|
+
[pg-comment]: https://www.postgresql.org/docs/9.4/sql-comment.html
|
408
415
|
[pg-tsrange-and-ruby]: https://bugs.ruby-lang.org/issues/6864
|
409
|
-
[pg-ctes]:
|
410
|
-
[pg-cte-optimization-fence]:
|
411
|
-
[pg-cte-opt-out-fence]:
|
412
|
-
[pg-json-type]:
|
413
|
-
[pg-json-func]:
|
416
|
+
[pg-ctes]: https://www.postgresql.org/docs/9.4/queries-with.html
|
417
|
+
[pg-cte-optimization-fence]: https://www.postgresql.org/message-id/201209191305.44674.db@kavod.com
|
418
|
+
[pg-cte-opt-out-fence]: https://www.postgresql.org/message-id/CAHyXU0zpM5+Dsb_pKxDmm-ZoWUAt=SkHHaiK_DBqcmtxTas6Nw@mail.gmail.com
|
419
|
+
[pg-json-type]: https://www.postgresql.org/docs/9.4/datatype-json.html
|
420
|
+
[pg-json-func]: https://www.postgresql.org/docs/9.4/functions-json.html
|
414
421
|
[pg-json-opclass]: https://github.com/ifad/chronomodel/blob/master/sql/json_ops.sql
|
415
422
|
|
416
423
|
[r4-tsrange-broken]: https://github.com/rails/rails/pull/13793#issuecomment-34608093
|
@@ -421,3 +428,7 @@ This software is Made in Italy :it: :smile:.
|
|
421
428
|
[cm-cte-impl]: https://github.com/ifad/chronomodel/commit/18f4c4b
|
422
429
|
|
423
430
|
[gh-pzac]: https://github.com/pzac
|
431
|
+
[gh-issue-174]: https://github.com/ifad/chronomodel/issues/174
|
432
|
+
[gh-issue-186]: https://github.com/ifad/chronomodel/issues/186
|
433
|
+
[gh-issue-192]: https://github.com/ifad/chronomodel/issues/192
|
434
|
+
[gh-issue-206]: https://github.com/ifad/chronomodel/issues/206
|
@@ -1,16 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'chrono_model'
|
2
4
|
|
3
5
|
module ActiveRecord
|
6
|
+
# TODO: Remove when dropping Rails < 7.2 compatibility
|
4
7
|
module ConnectionHandling
|
8
|
+
def chronomodel_adapter_class
|
9
|
+
ChronoModel::Adapter
|
10
|
+
end
|
5
11
|
|
6
12
|
# Install the new adapter in ActiveRecord. This approach is required because
|
7
13
|
# the PG adapter defines +add_column+ itself, thus making impossible to use
|
8
14
|
# super() in overridden Module methods.
|
9
15
|
#
|
10
16
|
def chronomodel_connection(config) # :nodoc:
|
11
|
-
|
17
|
+
return chronomodel_adapter_class.new(config) if ActiveRecord::VERSION::STRING >= '7.1'
|
12
18
|
|
13
|
-
conn_params
|
19
|
+
conn_params = config.symbolize_keys.compact
|
14
20
|
|
15
21
|
# Map ActiveRecords param names to PGs.
|
16
22
|
conn_params[:user] = conn_params.delete(:username) if conn_params[:username]
|
@@ -20,24 +26,18 @@ module ActiveRecord
|
|
20
26
|
valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
|
21
27
|
conn_params.slice!(*valid_conn_param_keys)
|
22
28
|
|
23
|
-
|
24
|
-
|
25
|
-
adapter = ChronoModel::Adapter.new(
|
29
|
+
conn = PG.connect(conn_params)
|
30
|
+
|
31
|
+
adapter = ChronoModel::Adapter.new(conn, logger, conn_params, config)
|
26
32
|
|
27
33
|
unless adapter.chrono_supported?
|
28
|
-
raise ChronoModel::Error,
|
29
|
-
|
34
|
+
raise ChronoModel::Error, 'Your database server is not supported by ChronoModel. ' \
|
35
|
+
'Currently, only PostgreSQL >= 9.3 is supported.'
|
30
36
|
end
|
31
37
|
|
32
38
|
adapter.chrono_setup!
|
33
39
|
|
34
|
-
|
40
|
+
adapter
|
35
41
|
end
|
36
|
-
|
37
|
-
module Connectionadapters
|
38
|
-
ChronoModelAdapter = ::ChronoModel::Adapter
|
39
|
-
end
|
40
|
-
|
41
42
|
end
|
42
43
|
end
|
43
|
-
|
@@ -1,11 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Tasks
|
3
5
|
class ChronomodelDatabaseTasks < PostgreSQLDatabaseTasks
|
6
|
+
CHRONOMODEL_SCHEMAS = [
|
7
|
+
ChronoModel::Adapter::TEMPORAL_SCHEMA,
|
8
|
+
ChronoModel::Adapter::HISTORY_SCHEMA
|
9
|
+
].freeze
|
4
10
|
|
5
11
|
def structure_dump(*arguments)
|
6
|
-
|
7
|
-
|
8
|
-
|
12
|
+
if schema_search_path.present?
|
13
|
+
with_chronomodel_schema_search_path { super }
|
14
|
+
else
|
15
|
+
super
|
9
16
|
end
|
10
17
|
|
11
18
|
# The structure.sql includes CREATE SCHEMA statements, but as these are executed
|
@@ -17,70 +24,64 @@ module ActiveRecord
|
|
17
24
|
filename = arguments.first
|
18
25
|
sql = File.read(filename).gsub(/CREATE SCHEMA (?!IF NOT EXISTS)/, '\&IF NOT EXISTS ')
|
19
26
|
File.open(filename, 'w') { |file| file << sql }
|
20
|
-
|
21
|
-
remove_sql_header_comments(filename)
|
22
27
|
end
|
23
28
|
|
24
29
|
def data_dump(target)
|
25
|
-
|
30
|
+
psql_env
|
26
31
|
|
27
|
-
args = ['-c', '-f', target]
|
28
|
-
args <<
|
32
|
+
args = ['-c', '-f', target.to_s]
|
33
|
+
args << chronomodel_configuration[:database]
|
29
34
|
|
30
|
-
run_cmd
|
35
|
+
run_cmd 'pg_dump', args, 'dumping data'
|
31
36
|
end
|
32
37
|
|
33
38
|
def data_load(source)
|
34
|
-
|
39
|
+
psql_env
|
35
40
|
|
36
41
|
args = ['-f', source]
|
37
|
-
args <<
|
42
|
+
args << chronomodel_configuration[:database]
|
38
43
|
|
39
|
-
run_cmd
|
44
|
+
run_cmd 'psql', args, 'loading data'
|
40
45
|
end
|
41
46
|
|
42
47
|
private
|
43
48
|
|
49
|
+
def chronomodel_configuration
|
50
|
+
@chronomodel_configuration ||= @configuration_hash
|
51
|
+
end
|
52
|
+
|
44
53
|
# If a schema search path is defined in the configuration file, it will
|
45
54
|
# be used by the database tasks class to dump only the specified search
|
46
55
|
# path. Here we add also ChronoModel's temporal and history schemas to
|
47
56
|
# the search path and yield.
|
48
57
|
#
|
49
58
|
def with_chronomodel_schema_search_path
|
50
|
-
|
51
|
-
|
52
|
-
if original_schema_search_path.present?
|
53
|
-
configuration['schema_search_path'] = original_schema_search_path.split(',').concat([
|
54
|
-
ChronoModel::Adapter::TEMPORAL_SCHEMA,
|
55
|
-
ChronoModel::Adapter::HISTORY_SCHEMA
|
56
|
-
]).join(',')
|
57
|
-
end
|
59
|
+
patch_configuration!
|
58
60
|
|
59
61
|
yield
|
60
|
-
|
61
62
|
ensure
|
62
|
-
|
63
|
+
reset_configuration!
|
63
64
|
end
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
tempfile << line
|
74
|
-
removing_comments = false
|
75
|
-
end
|
76
|
-
end
|
77
|
-
ensure
|
78
|
-
tempfile.close
|
79
|
-
end
|
80
|
-
FileUtils.mv(tempfile.path, filename)
|
81
|
-
end
|
66
|
+
def patch_configuration!
|
67
|
+
@original_schema_search_path = schema_search_path
|
68
|
+
|
69
|
+
chronomodel_schema_search_path = "#{schema_search_path},#{CHRONOMODEL_SCHEMAS.join(',')}"
|
70
|
+
|
71
|
+
@configuration_hash = @configuration_hash.dup
|
72
|
+
@configuration_hash[:schema_search_path] = chronomodel_schema_search_path
|
73
|
+
@configuration_hash.freeze
|
82
74
|
end
|
83
75
|
|
76
|
+
def reset_configuration!
|
77
|
+
@configuration_hash = @configuration_hash.dup
|
78
|
+
@configuration_hash[:schema_search_path] = @original_schema_search_path
|
79
|
+
@configuration_hash.freeze
|
80
|
+
end
|
81
|
+
|
82
|
+
def schema_search_path
|
83
|
+
@schema_search_path ||= chronomodel_configuration[:schema_search_path]
|
84
|
+
end
|
84
85
|
end
|
85
86
|
end
|
86
87
|
end
|