chrono_model 0.5.3 → 0.8.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 +7 -0
- data/.rspec +1 -1
- data/.travis.yml +7 -0
- data/Gemfile +10 -1
- data/LICENSE +3 -1
- data/README.md +239 -136
- data/README.sql +108 -94
- data/chrono_model.gemspec +5 -4
- data/lib/active_record/connection_adapters/chronomodel_adapter.rb +42 -0
- data/lib/chrono_model.rb +0 -8
- data/lib/chrono_model/adapter.rb +346 -212
- data/lib/chrono_model/patches.rb +21 -8
- data/lib/chrono_model/railtie.rb +1 -13
- data/lib/chrono_model/time_gate.rb +2 -2
- data/lib/chrono_model/time_machine.rb +153 -87
- data/lib/chrono_model/utils.rb +35 -8
- data/lib/chrono_model/version.rb +1 -1
- data/spec/adapter_spec.rb +154 -14
- data/spec/config.yml.example +1 -0
- data/spec/json_ops_spec.rb +48 -0
- data/spec/support/connection.rb +4 -9
- data/spec/support/helpers.rb +27 -2
- data/spec/support/matchers/column.rb +5 -2
- data/spec/support/matchers/index.rb +4 -0
- data/spec/support/matchers/schema.rb +4 -0
- data/spec/support/matchers/table.rb +94 -21
- data/spec/time_machine_spec.rb +62 -28
- data/spec/time_query_spec.rb +227 -0
- data/sql/json_ops.sql +56 -0
- data/sql/uninstall-json_ops.sql +24 -0
- metadata +44 -18
- data/lib/chrono_model/compatibility.rb +0 -31
data/sql/json_ops.sql
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
-- This is a naive, unoptimized way of checking two
|
2
|
+
-- JSON objects for equality. It uses python's json
|
3
|
+
-- module to load and re-dump the json object while
|
4
|
+
-- sorting its keys, and then calculates the object
|
5
|
+
-- hash from it.
|
6
|
+
--
|
7
|
+
CREATE OR REPLACE FUNCTION json_hash( a json ) RETURNS INTEGER AS $$
|
8
|
+
import json
|
9
|
+
|
10
|
+
# http://www.isthe.com/chongo/tech/comp/fnv/#FNV-1a
|
11
|
+
def fnv1a(str):
|
12
|
+
hval = 2166136261
|
13
|
+
for s in str:
|
14
|
+
hval = hval ^ ord(s)
|
15
|
+
hval = (hval * 16777619) % (2**32)
|
16
|
+
return hval
|
17
|
+
|
18
|
+
hsh = fnv1a(json.dumps(json.loads(a), sort_keys=True, separators=(',', ':')))
|
19
|
+
return hsh - 2**31
|
20
|
+
|
21
|
+
$$ LANGUAGE plpythonu STRICT IMMUTABLE;
|
22
|
+
|
23
|
+
CREATE OR REPLACE FUNCTION json_eq( a json, b json ) RETURNS BOOLEAN AS $$
|
24
|
+
SELECT json_hash(a) = json_hash(b);
|
25
|
+
$$ LANGUAGE SQL STRICT IMMUTABLE;
|
26
|
+
|
27
|
+
DO $$
|
28
|
+
BEGIN
|
29
|
+
|
30
|
+
CREATE OPERATOR = (
|
31
|
+
LEFTARG = json,
|
32
|
+
RIGHTARG = json,
|
33
|
+
PROCEDURE = json_eq
|
34
|
+
);
|
35
|
+
|
36
|
+
RAISE LOG 'Created JSON equality operator';
|
37
|
+
|
38
|
+
EXCEPTION WHEN duplicate_function THEN
|
39
|
+
RAISE NOTICE 'JSON equality operator already exists, skipping';
|
40
|
+
END;
|
41
|
+
$$ LANGUAGE plpgsql;
|
42
|
+
|
43
|
+
DO $$
|
44
|
+
BEGIN
|
45
|
+
|
46
|
+
CREATE OPERATOR CLASS json_ops
|
47
|
+
DEFAULT FOR TYPE JSON USING hash AS
|
48
|
+
OPERATOR 1 = (json, json),
|
49
|
+
FUNCTION 1 json_hash(json);
|
50
|
+
|
51
|
+
RAISE LOG 'Created JSON hash operator class';
|
52
|
+
|
53
|
+
EXCEPTION WHEN duplicate_object THEN
|
54
|
+
RAISE NOTICE 'JSON hash operator class already exists, skipping';
|
55
|
+
END;
|
56
|
+
$$ LANGUAGE plpgsql;
|
@@ -0,0 +1,24 @@
|
|
1
|
+
DO $$
|
2
|
+
BEGIN
|
3
|
+
|
4
|
+
DROP OPERATOR CLASS json_ops using hash;
|
5
|
+
RAISE LOG 'Dropped JSON hash operator class';
|
6
|
+
|
7
|
+
EXCEPTION WHEN undefined_object THEN
|
8
|
+
RAISE NOTICE 'JSON hash operator class does not exist, skipping';
|
9
|
+
END;
|
10
|
+
$$ LANGUAGE plpgsql;
|
11
|
+
|
12
|
+
DO $$
|
13
|
+
BEGIN
|
14
|
+
|
15
|
+
DROP OPERATOR = ( json, json );
|
16
|
+
RAISE LOG 'Dropped JSON equality operator';
|
17
|
+
|
18
|
+
EXCEPTION WHEN undefined_function THEN
|
19
|
+
RAISE NOTICE 'JSON equality operator does not exist, skipping';
|
20
|
+
END;
|
21
|
+
$$ LANGUAGE plpgsql;
|
22
|
+
|
23
|
+
DROP FUNCTION IF EXISTS json_eq( json, json );
|
24
|
+
DROP FUNCTION IF EXISTS json_hash ( json );
|
metadata
CHANGED
@@ -1,42 +1,63 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chrono_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.8.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Marcello Barnaba
|
8
|
+
- Peter Joseph Brindisi
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-03-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
16
|
-
requirement:
|
17
|
-
none: false
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
18
17
|
requirements:
|
19
18
|
- - ~>
|
20
19
|
- !ruby/object:Gem::Version
|
21
|
-
version: '
|
20
|
+
version: '4.0'
|
22
21
|
type: :runtime
|
23
22
|
prerelease: false
|
24
|
-
version_requirements:
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '4.0'
|
25
28
|
- !ruby/object:Gem::Dependency
|
26
29
|
name: pg
|
27
|
-
requirement:
|
28
|
-
none: false
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
29
31
|
requirements:
|
30
|
-
- -
|
32
|
+
- - '>='
|
31
33
|
- !ruby/object:Gem::Version
|
32
34
|
version: '0'
|
33
35
|
type: :runtime
|
34
36
|
prerelease: false
|
35
|
-
version_requirements:
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: multi_json
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
36
56
|
description: Give your models as-of date temporal extensions. Built entirely for PostgreSQL
|
37
57
|
>= 9.0
|
38
58
|
email:
|
39
59
|
- vjt@openssl.it
|
60
|
+
- p.brindisi@ifad.org
|
40
61
|
executables: []
|
41
62
|
extensions: []
|
42
63
|
extra_rdoc_files: []
|
@@ -50,9 +71,9 @@ files:
|
|
50
71
|
- README.sql
|
51
72
|
- Rakefile
|
52
73
|
- chrono_model.gemspec
|
74
|
+
- lib/active_record/connection_adapters/chronomodel_adapter.rb
|
53
75
|
- lib/chrono_model.rb
|
54
76
|
- lib/chrono_model/adapter.rb
|
55
|
-
- lib/chrono_model/compatibility.rb
|
56
77
|
- lib/chrono_model/patches.rb
|
57
78
|
- lib/chrono_model/railtie.rb
|
58
79
|
- lib/chrono_model/schema_format.rake
|
@@ -64,6 +85,7 @@ files:
|
|
64
85
|
- spec/adapter_spec.rb
|
65
86
|
- spec/config.travis.yml
|
66
87
|
- spec/config.yml.example
|
88
|
+
- spec/json_ops_spec.rb
|
67
89
|
- spec/spec_helper.rb
|
68
90
|
- spec/support/connection.rb
|
69
91
|
- spec/support/helpers.rb
|
@@ -73,34 +95,37 @@ files:
|
|
73
95
|
- spec/support/matchers/schema.rb
|
74
96
|
- spec/support/matchers/table.rb
|
75
97
|
- spec/time_machine_spec.rb
|
98
|
+
- spec/time_query_spec.rb
|
99
|
+
- sql/json_ops.sql
|
100
|
+
- sql/uninstall-json_ops.sql
|
76
101
|
homepage: http://github.com/ifad/chronomodel
|
77
102
|
licenses: []
|
103
|
+
metadata: {}
|
78
104
|
post_install_message:
|
79
105
|
rdoc_options: []
|
80
106
|
require_paths:
|
81
107
|
- lib
|
82
108
|
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
-
none: false
|
84
109
|
requirements:
|
85
|
-
- -
|
110
|
+
- - '>='
|
86
111
|
- !ruby/object:Gem::Version
|
87
112
|
version: '0'
|
88
113
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
114
|
requirements:
|
91
|
-
- -
|
115
|
+
- - '>='
|
92
116
|
- !ruby/object:Gem::Version
|
93
117
|
version: '0'
|
94
118
|
requirements: []
|
95
119
|
rubyforge_project:
|
96
|
-
rubygems_version:
|
120
|
+
rubygems_version: 2.0.3
|
97
121
|
signing_key:
|
98
|
-
specification_version:
|
122
|
+
specification_version: 4
|
99
123
|
summary: Temporal extensions (SCD Type II) for Active Record
|
100
124
|
test_files:
|
101
125
|
- spec/adapter_spec.rb
|
102
126
|
- spec/config.travis.yml
|
103
127
|
- spec/config.yml.example
|
128
|
+
- spec/json_ops_spec.rb
|
104
129
|
- spec/spec_helper.rb
|
105
130
|
- spec/support/connection.rb
|
106
131
|
- spec/support/helpers.rb
|
@@ -110,3 +135,4 @@ test_files:
|
|
110
135
|
- spec/support/matchers/schema.rb
|
111
136
|
- spec/support/matchers/table.rb
|
112
137
|
- spec/time_machine_spec.rb
|
138
|
+
- spec/time_query_spec.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
|
3
|
-
module ChronoModel
|
4
|
-
|
5
|
-
# Utility methods added to every ActiveRecord::Base class instance
|
6
|
-
# to check whether ChronoModel is supported and whether a model is
|
7
|
-
# backed by temporal tables or not.
|
8
|
-
#
|
9
|
-
module Compatibility
|
10
|
-
extend ActiveSupport::Concern
|
11
|
-
|
12
|
-
# Returns true if this model is backed by a temporal table,
|
13
|
-
# false otherwise.
|
14
|
-
#
|
15
|
-
def chrono?
|
16
|
-
supports_chrono? && connection.is_chrono?(table_name)
|
17
|
-
end
|
18
|
-
|
19
|
-
# Returns true whether the connection adapter supports our
|
20
|
-
# implementation of temporal tables. Currently, only the
|
21
|
-
# PostgreSQL adapter is supported.
|
22
|
-
#
|
23
|
-
def supports_chrono?
|
24
|
-
connection.respond_to?(:chrono_supported?) &&
|
25
|
-
connection.chrono_supported?
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
ActiveRecord::Base.extend ChronoModel::Compatibility
|