chrono_model 1.2.1 → 2.0.0
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 +65 -40
- data/lib/active_record/connection_adapters/chronomodel_adapter.rb +17 -11
- data/lib/active_record/tasks/chronomodel_database_tasks.rb +64 -23
- 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/legacy.rb +41 -0
- 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 +97 -99
- data/lib/chrono_model/adapter.rb +64 -31
- data/lib/chrono_model/chrono.rb +17 -0
- data/lib/chrono_model/conversions.rb +15 -9
- data/lib/chrono_model/db_console.rb +9 -0
- data/lib/chrono_model/json.rb +9 -6
- data/lib/chrono_model/patches/as_of_time_holder.rb +2 -2
- data/lib/chrono_model/patches/as_of_time_relation.rb +2 -2
- data/lib/chrono_model/patches/association.rb +15 -12
- data/lib/chrono_model/patches/batches.rb +17 -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 +53 -8
- data/lib/chrono_model/patches.rb +3 -1
- data/lib/chrono_model/railtie.rb +29 -24
- 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 +66 -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 +39 -136
- 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 -24
- 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/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: e9dc931f360178771e212906ec3a02d1ff49ffc2393b457a7f531b101bc1e8ce
|
|
4
|
+
data.tar.gz: 7606b75d5eaf453e0d0f90c760607af50bdf862744f7048cc2c8061f41018bc5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e64bea647172199e03703f0f4be8538d48276a8cb02fedb2309a68913ed6dad910d01f9ed4498fe345119ff1a12e25a0dda16f2b5976a0cb1b587dc4548eef4a
|
|
7
|
+
data.tar.gz: e326f5fce5a0fc94df9e23618840edb6baeaf307e85bbb3449fad7540cd85863be533caca5e30d073fc880a2759ce21ceed74f471dbba4959ead30e9ce43e5b5
|
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-2022 Marcello Barnaba <m.barnaba@ifad.org>
|
|
4
|
+
Copyright (c) 2012-2022 Peter J. Brindisi <p.brindisi@ifad.org>
|
|
5
|
+
Copyright (c) 2012-2022 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
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# Temporal database system on PostgreSQL using [updatable views][pg-updatable-views], [table inheritance][pg-table-inheritance] and [INSTEAD OF triggers][pg-instead-of-triggers].
|
|
2
2
|
|
|
3
3
|
[![Build Status][build-status-badge]][build-status]
|
|
4
|
+
[![Legacy Build Status][legacy-build-status-badge]][build-status]
|
|
4
5
|
[![Code Climate][code-analysis-badge]][code-analysis]
|
|
5
6
|
[![Test Coverage][test-coverage-badge]][test-coverage]
|
|
7
|
+
[![Gem Version][gem-version-badge]][gem-version]
|
|
6
8
|
[![Inlinedocs][docs-analysis-badge]][docs-analysis]
|
|
7
9
|
|
|
8
|
-
![
|
|
10
|
+
![A Delorean that we all love][delorean-image]
|
|
9
11
|
|
|
10
12
|
ChronoModel implements what Oracle sells as "Flashback Queries", with standard
|
|
11
13
|
SQL on free PostgreSQL. Academically speaking, ChronoModel implements a
|
|
@@ -61,8 +63,8 @@ All timestamps are _forcibly_ stored in as UTC, bypassing the
|
|
|
61
63
|
|
|
62
64
|
## Requirements
|
|
63
65
|
|
|
64
|
-
* Ruby >= 2.
|
|
65
|
-
* Active Record >= 5.0. See the [detailed supported versions matrix on
|
|
66
|
+
* Ruby >= 2.2.2
|
|
67
|
+
* Active Record >= 5.0. See the [detailed supported versions matrix on Ruby GitHub Actions workflows](https://github.com/ifad/chronomodel/blob/master/.github/workflows)
|
|
66
68
|
* PostgreSQL >= 9.4 (legacy support for 9.3)
|
|
67
69
|
* The `btree_gist` PostgreSQL extension
|
|
68
70
|
|
|
@@ -95,6 +97,13 @@ development:
|
|
|
95
97
|
username: ...
|
|
96
98
|
```
|
|
97
99
|
|
|
100
|
+
Configure Active Record in your `config/application.rb` to use the `:sql` schema
|
|
101
|
+
format:
|
|
102
|
+
|
|
103
|
+
```rb
|
|
104
|
+
config.active_record.schema_format = :sql
|
|
105
|
+
```
|
|
106
|
+
|
|
98
107
|
## Schema creation
|
|
99
108
|
|
|
100
109
|
ChronoModel hooks all `ActiveRecord::Migration` methods to make them temporal
|
|
@@ -140,7 +149,7 @@ validity from midnight, January 1st, 1 CE. You can set a specific validity with
|
|
|
140
149
|
the `:validity` option:
|
|
141
150
|
|
|
142
151
|
```ruby
|
|
143
|
-
change_table :your_table, :
|
|
152
|
+
change_table :your_table, temporal: true, copy_data: true, validity: '1977-01-01'
|
|
144
153
|
```
|
|
145
154
|
|
|
146
155
|
Please note that `change_table` requires you to use *old_style* `up` and
|
|
@@ -155,9 +164,9 @@ history.
|
|
|
155
164
|
You can also choose which fields are to be journaled, passing the following
|
|
156
165
|
options to `create_table`:
|
|
157
166
|
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
167
|
+
* `journal: %w( fld1 fld2 .. .. )` - record changes in the history only when changing specified fields
|
|
168
|
+
* `no_journal: %w( fld1 fld2 .. )` - do not record changes to the specified fields
|
|
169
|
+
* `full_journal: true` - record changes to *all* fields, including `updated_at`.
|
|
161
170
|
|
|
162
171
|
These options are stored as JSON in the [COMMENT][pg-comment] area of the
|
|
163
172
|
public view, alongside with the ChronoModel version that created them.
|
|
@@ -194,7 +203,7 @@ to your `create_table`. Example:
|
|
|
194
203
|
Include the `ChronoModel::TimeMachine` module in your model.
|
|
195
204
|
|
|
196
205
|
```ruby
|
|
197
|
-
|
|
206
|
+
class Country < ActiveRecord::Base
|
|
198
207
|
include ChronoModel::TimeMachine
|
|
199
208
|
|
|
200
209
|
has_many :compositions
|
|
@@ -333,7 +342,7 @@ ChronoModel::Json.create
|
|
|
333
342
|
## Caveats
|
|
334
343
|
|
|
335
344
|
* Rails 4+ support requires disabling tsrange parsing support, as it
|
|
336
|
-
[is broken][r4-tsrange-broken] and
|
|
345
|
+
[is broken][r4-tsrange-broken] and [incomplete][r4-tsrange-incomplete]
|
|
337
346
|
as of now, mainly due to a [design clash with ruby][pg-tsrange-and-ruby].
|
|
338
347
|
|
|
339
348
|
* The triggers and temporal indexes cannot be saved in schema.rb. The AR
|
|
@@ -344,14 +353,24 @@ ChronoModel::Json.create
|
|
|
344
353
|
`db:structure:load`.
|
|
345
354
|
Two helper tasks are also added, `db:data:dump` and `db:data:load`.
|
|
346
355
|
|
|
347
|
-
* The choice of using subqueries instead of [Common Table Expressions]
|
|
348
|
-
|
|
349
|
-
|
|
356
|
+
* The choice of using subqueries instead of [Common Table Expressions][pg-ctes]
|
|
357
|
+
was dictated by the fact that CTEs [currently act as an optimization
|
|
358
|
+
fence][pg-cte-optimization-fence].
|
|
350
359
|
If it will be possible [to opt-out of the fence][pg-cte-opt-out-fence]
|
|
351
360
|
in the future, they will be probably be used again as they were [in the
|
|
352
361
|
past][cm-cte-impl], because the resulting queries were more readable,
|
|
353
362
|
and do not inhibit using `.from()` on the `AR::Relation`.
|
|
354
363
|
|
|
364
|
+
* Foreign keys are not supported. [See issue #174][gh-issue-174]
|
|
365
|
+
|
|
366
|
+
* There may be unexpected results when combining eager loading and joins.
|
|
367
|
+
[See issue #186][gh-issue-186]
|
|
368
|
+
|
|
369
|
+
* Global ID ignores historical objects. [See issue #192][gh-issue-192]
|
|
370
|
+
|
|
371
|
+
* Different historical objects are considered the identical. [See issue
|
|
372
|
+
#206][gh-issue-206]
|
|
373
|
+
|
|
355
374
|
|
|
356
375
|
## Contributing
|
|
357
376
|
|
|
@@ -375,39 +394,41 @@ while using it in many important projects.
|
|
|
375
394
|
This software is Made in Italy :it: :smile:.
|
|
376
395
|
|
|
377
396
|
|
|
378
|
-
[build-status]: https://
|
|
379
|
-
[build-status-badge]: https://
|
|
380
|
-
[code-analysis]: https://codeclimate.com/github/ifad/chronomodel
|
|
381
|
-
[code-analysis-badge]: https://codeclimate.com/
|
|
382
|
-
[docs-analysis]:
|
|
383
|
-
[docs-analysis-badge]:
|
|
397
|
+
[build-status]: https://github.com/ifad/chronomodel/actions
|
|
398
|
+
[build-status-badge]: https://github.com/ifad/chronomodel/actions/workflows/ruby.yml/badge.svg
|
|
399
|
+
[code-analysis]: https://codeclimate.com/github/ifad/chronomodel/maintainability
|
|
400
|
+
[code-analysis-badge]: https://api.codeclimate.com/v1/badges/cdee7327938dc2eaff99/maintainability
|
|
401
|
+
[docs-analysis]: https://inch-ci.org/github/ifad/chronomodel
|
|
402
|
+
[docs-analysis-badge]: https://inch-ci.org/github/ifad/chronomodel.svg?branch=master
|
|
403
|
+
[gem-version]: https://rubygems.org/gems/chrono_model
|
|
404
|
+
[gem-version-badge]: https://badge.fury.io/rb/chrono_model.svg
|
|
405
|
+
[legacy-build-status-badge]: https://github.com/ifad/chronomodel/actions/workflows/legacy_ruby.yml/badge.svg
|
|
384
406
|
[test-coverage]: https://codeclimate.com/github/ifad/chronomodel
|
|
385
407
|
[test-coverage-badge]: https://codeclimate.com/github/ifad/chronomodel/badges/coverage.svg
|
|
386
408
|
|
|
387
409
|
[delorean-image]: https://i.imgur.com/DD77F4s.jpg
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
[wp-scd-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
[pg-
|
|
394
|
-
[pg-
|
|
395
|
-
[pg-
|
|
396
|
-
[pg-
|
|
397
|
-
[pg-
|
|
398
|
-
[pg-
|
|
399
|
-
[pg-partitioning]:
|
|
400
|
-
[pg-
|
|
401
|
-
[pg-
|
|
402
|
-
[pg-
|
|
403
|
-
[pg-
|
|
404
|
-
[pg-comment]: http://www.postgresql.org/docs/9.4/static/sql-comment.html
|
|
410
|
+
|
|
411
|
+
[wp-scd-2]: https://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_2
|
|
412
|
+
[wp-scd-4]: https://en.wikipedia.org/wiki/Slowly_changing_dimension#Type_4
|
|
413
|
+
|
|
414
|
+
[pg-updatable-views]: https://www.postgresql.org/docs/9.4/sql-createview.html#SQL-CREATEVIEW-UPDATABLE-VIEWS
|
|
415
|
+
[pg-table-inheritance]: https://www.postgresql.org/docs/9.4/ddl-inherit.html
|
|
416
|
+
[pg-instead-of-triggers]: https://www.postgresql.org/docs/9.4/sql-createtrigger.html
|
|
417
|
+
[pg-triggers]: https://www.postgresql.org/docs/9.4/trigger-definition.html
|
|
418
|
+
[pg-schema]: https://www.postgresql.org/docs/9.4/ddl-schemas.html
|
|
419
|
+
[pg-current-timestamp]: https://www.postgresql.org/docs/9.4/functions-datetime.html#FUNCTIONS-DATETIME-TABLE
|
|
420
|
+
[pg-partitioning]: https://www.postgresql.org/docs/9.4/ddl-partitioning.html
|
|
421
|
+
[pg-partitioning-excl-constraints]: https://www.postgresql.org/docs/9.4/ddl-partitioning.html#DDL-PARTITIONING-CONSTRAINT-EXCLUSION
|
|
422
|
+
[pg-gist-indexes]: https://www.postgresql.org/docs/9.4/gist.html
|
|
423
|
+
[pg-exclusion-constraints]: https://www.postgresql.org/docs/9.4/sql-createtable.html#SQL-CREATETABLE-EXCLUDE
|
|
424
|
+
[pg-btree-gist]: https://www.postgresql.org/docs/9.4/btree-gist.html
|
|
425
|
+
[pg-comment]: https://www.postgresql.org/docs/9.4/sql-comment.html
|
|
405
426
|
[pg-tsrange-and-ruby]: https://bugs.ruby-lang.org/issues/6864
|
|
406
|
-
[pg-ctes]:
|
|
407
|
-
[pg-cte-optimization-fence]:
|
|
408
|
-
[pg-cte-opt-out-fence]:
|
|
409
|
-
[pg-json-type]:
|
|
410
|
-
[pg-json-func]:
|
|
427
|
+
[pg-ctes]: https://www.postgresql.org/docs/9.4/queries-with.html
|
|
428
|
+
[pg-cte-optimization-fence]: https://www.postgresql.org/message-id/201209191305.44674.db@kavod.com
|
|
429
|
+
[pg-cte-opt-out-fence]: https://www.postgresql.org/message-id/CAHyXU0zpM5+Dsb_pKxDmm-ZoWUAt=SkHHaiK_DBqcmtxTas6Nw@mail.gmail.com
|
|
430
|
+
[pg-json-type]: https://www.postgresql.org/docs/9.4/datatype-json.html
|
|
431
|
+
[pg-json-func]: https://www.postgresql.org/docs/9.4/functions-json.html
|
|
411
432
|
[pg-json-opclass]: https://github.com/ifad/chronomodel/blob/master/sql/json_ops.sql
|
|
412
433
|
|
|
413
434
|
[r4-tsrange-broken]: https://github.com/rails/rails/pull/13793#issuecomment-34608093
|
|
@@ -418,3 +439,7 @@ This software is Made in Italy :it: :smile:.
|
|
|
418
439
|
[cm-cte-impl]: https://github.com/ifad/chronomodel/commit/18f4c4b
|
|
419
440
|
|
|
420
441
|
[gh-pzac]: https://github.com/pzac
|
|
442
|
+
[gh-issue-174]: https://github.com/ifad/chronomodel/issues/174
|
|
443
|
+
[gh-issue-186]: https://github.com/ifad/chronomodel/issues/186
|
|
444
|
+
[gh-issue-192]: https://github.com/ifad/chronomodel/issues/192
|
|
445
|
+
[gh-issue-206]: https://github.com/ifad/chronomodel/issues/206
|
|
@@ -1,13 +1,21 @@
|
|
|
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:
|
|
17
|
+
return chronomodel_adapter_class.new(config) if ActiveRecord::VERSION::STRING >= '7.1'
|
|
18
|
+
|
|
11
19
|
conn_params = config.symbolize_keys
|
|
12
20
|
|
|
13
21
|
conn_params.delete_if { |_, v| v.nil? }
|
|
@@ -20,24 +28,22 @@ module ActiveRecord
|
|
|
20
28
|
valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
|
|
21
29
|
conn_params.slice!(*valid_conn_param_keys)
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
adapter = ChronoModel::Adapter.new(
|
|
31
|
+
conn = PG.connect(conn_params) if ActiveRecord::VERSION::MAJOR >= 6
|
|
32
|
+
|
|
33
|
+
adapter = ChronoModel::Adapter.new(conn, logger, conn_params, config)
|
|
26
34
|
|
|
27
35
|
unless adapter.chrono_supported?
|
|
28
|
-
raise ChronoModel::Error,
|
|
29
|
-
|
|
36
|
+
raise ChronoModel::Error, 'Your database server is not supported by ChronoModel. ' \
|
|
37
|
+
'Currently, only PostgreSQL >= 9.3 is supported.'
|
|
30
38
|
end
|
|
31
39
|
|
|
32
40
|
adapter.chrono_setup!
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
adapter
|
|
43
|
+
rescue ::PG::Error => e
|
|
44
|
+
raise ActiveRecord::NoDatabaseError if e.message.include?(conn_params[:dbname])
|
|
36
45
|
|
|
37
|
-
|
|
38
|
-
ChronoModelAdapter = ::ChronoModel::Adapter
|
|
46
|
+
raise
|
|
39
47
|
end
|
|
40
|
-
|
|
41
48
|
end
|
|
42
49
|
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
|
|
@@ -18,55 +25,82 @@ module ActiveRecord
|
|
|
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
27
|
|
|
21
|
-
remove_sql_header_comments(filename)
|
|
28
|
+
remove_sql_header_comments(filename) if ActiveRecord::VERSION::STRING < '5.1'
|
|
22
29
|
end
|
|
23
30
|
|
|
24
31
|
def data_dump(target)
|
|
25
|
-
|
|
32
|
+
psql_env
|
|
26
33
|
|
|
27
|
-
args = ['-c', '-f', target]
|
|
28
|
-
args <<
|
|
34
|
+
args = ['-c', '-f', target.to_s]
|
|
35
|
+
args << chronomodel_configuration[:database]
|
|
29
36
|
|
|
30
|
-
run_cmd
|
|
37
|
+
run_cmd 'pg_dump', args, 'dumping data'
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
def data_load(source)
|
|
34
|
-
|
|
41
|
+
psql_env
|
|
35
42
|
|
|
36
43
|
args = ['-f', source]
|
|
37
|
-
args <<
|
|
44
|
+
args << chronomodel_configuration[:database]
|
|
38
45
|
|
|
39
|
-
run_cmd
|
|
46
|
+
run_cmd 'psql', args, 'loading data'
|
|
40
47
|
end
|
|
41
48
|
|
|
42
49
|
private
|
|
43
50
|
|
|
51
|
+
# In Rails 6.1.x the configuration instance variable is not available
|
|
52
|
+
# and it's been replaced by @configuration_hash (which is frozen).
|
|
53
|
+
def chronomodel_configuration
|
|
54
|
+
@chronomodel_configuration ||=
|
|
55
|
+
if defined?(@configuration_hash)
|
|
56
|
+
@configuration_hash
|
|
57
|
+
else
|
|
58
|
+
configuration.with_indifferent_access
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
44
62
|
# If a schema search path is defined in the configuration file, it will
|
|
45
63
|
# be used by the database tasks class to dump only the specified search
|
|
46
64
|
# path. Here we add also ChronoModel's temporal and history schemas to
|
|
47
65
|
# the search path and yield.
|
|
48
66
|
#
|
|
49
67
|
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
|
|
68
|
+
patch_configuration!
|
|
58
69
|
|
|
59
70
|
yield
|
|
60
|
-
|
|
61
71
|
ensure
|
|
62
|
-
|
|
72
|
+
reset_configuration!
|
|
63
73
|
end
|
|
64
74
|
|
|
65
|
-
|
|
75
|
+
def patch_configuration!
|
|
76
|
+
@original_schema_search_path = schema_search_path
|
|
77
|
+
|
|
78
|
+
chronomodel_schema_search_path = "#{schema_search_path},#{CHRONOMODEL_SCHEMAS.join(',')}"
|
|
79
|
+
|
|
80
|
+
if defined?(@configuration_hash)
|
|
81
|
+
@configuration_hash = @configuration_hash.dup
|
|
82
|
+
@configuration_hash[:schema_search_path] = chronomodel_schema_search_path
|
|
83
|
+
@configuration_hash.freeze
|
|
84
|
+
else
|
|
85
|
+
configuration['schema_search_path'] = chronomodel_schema_search_path
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def reset_configuration!
|
|
90
|
+
if defined?(@configuration_hash)
|
|
91
|
+
@configuration_hash = @configuration_hash.dup
|
|
92
|
+
@configuration_hash[:schema_search_path] = @original_schema_search_path
|
|
93
|
+
@configuration_hash.freeze
|
|
94
|
+
else
|
|
95
|
+
configuration['schema_search_path'] = @original_schema_search_path
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
unless private_instance_methods.include?(:remove_sql_header_comments)
|
|
66
100
|
def remove_sql_header_comments(filename)
|
|
67
101
|
sql_comment_begin = '--'
|
|
68
102
|
removing_comments = true
|
|
69
|
-
tempfile = Tempfile.open(
|
|
103
|
+
tempfile = Tempfile.open('uncommented_structure.sql')
|
|
70
104
|
begin
|
|
71
105
|
File.foreach(filename) do |line|
|
|
72
106
|
unless removing_comments && (line.start_with?(sql_comment_begin) || line.blank?)
|
|
@@ -81,6 +115,13 @@ module ActiveRecord
|
|
|
81
115
|
end
|
|
82
116
|
end
|
|
83
117
|
|
|
118
|
+
unless private_instance_methods.include?(:psql_env)
|
|
119
|
+
alias psql_env set_psql_env
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def schema_search_path
|
|
123
|
+
@schema_search_path ||= chronomodel_configuration[:schema_search_path]
|
|
124
|
+
end
|
|
84
125
|
end
|
|
85
126
|
end
|
|
86
127
|
end
|