chrono_model 1.2.2 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|