composite_primary_keys 7.0.15 → 7.0.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.rdoc +4 -0
- data/lib/composite_primary_keys.rb +5 -0
- data/lib/composite_primary_keys/arel/visitors/to_sql.rb +20 -0
- data/lib/composite_primary_keys/associations/join_dependency/join_association.rb +22 -22
- data/lib/composite_primary_keys/associations/preloader/belongs_to.rb +19 -19
- data/lib/composite_primary_keys/composite_predicates.rb +50 -50
- data/lib/composite_primary_keys/composite_relation.rb +48 -48
- data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +60 -46
- data/lib/composite_primary_keys/fixtures.rb +22 -22
- data/lib/composite_primary_keys/locking/optimistic.rb +55 -55
- data/lib/composite_primary_keys/relation/query_methods.rb +40 -40
- data/lib/composite_primary_keys/version.rb +1 -1
- data/tasks/databases/oracle.rake +25 -25
- data/test/connections/databases.ci.yml +15 -15
- data/test/connections/native_oracle/connection.rb +11 -11
- data/test/connections/native_oracle_enhanced/connection.rb +16 -16
- data/test/fixtures/comment.rb +7 -7
- data/test/fixtures/db_definitions/db2-create-tables.sql +126 -126
- data/test/fixtures/db_definitions/db2-drop-tables.sql +18 -18
- data/test/fixtures/db_definitions/oracle.drop.sql +45 -45
- data/test/fixtures/db_definitions/oracle.sql +223 -223
- data/test/fixtures/dorm.rb +2 -2
- data/test/fixtures/membership.rb +6 -6
- data/test/fixtures/membership_statuses.yml +16 -16
- data/test/fixtures/memberships.yml +10 -10
- data/test/fixtures/product_tariffs.yml +14 -14
- data/test/fixtures/reference_code.rb +7 -7
- data/test/fixtures/restaurants_suburb.rb +2 -2
- data/test/fixtures/suburb.rb +5 -5
- data/test/fixtures/topic.rb +5 -5
- data/test/fixtures/topic_source.rb +6 -6
- data/test/fixtures/topic_sources.yml +3 -3
- data/test/fixtures/topics.yml +8 -8
- data/test/fixtures/users.yml +10 -10
- data/test/test_attribute_methods.rb +63 -63
- data/test/test_calculations.rb +42 -42
- data/test/test_callbacks.rb +99 -99
- data/test/test_delete_all.rb +5 -0
- data/test/test_dumpable.rb +15 -15
- data/test/test_nested_attributes.rb +124 -124
- data/test/test_optimistic.rb +18 -18
- data/test/test_predicates.rb +40 -40
- data/test/test_santiago.rb +23 -23
- data/test/test_suite.rb +34 -34
- data/test/test_touch.rb +23 -23
- data/test/test_update.rb +71 -71
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3eaf57bc39ed46c4a72d72d5340f36e808066af
|
4
|
+
data.tar.gz: 34c682ff2f92cfa89c1f198b33101b4a9f255cdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f807e7a2cd19630d36813aaebc4ada9c08d386c66723f01d3d66b51d220c586c1f94145c26192a5968a7f1b2c0261f8486e78882b09099e93f6609505877bab1
|
7
|
+
data.tar.gz: 6b1b0a788652b9912159ba9f6529778688275cf3648055e73b2f51239a2604c27f7527d92d86468b1d2c05adc4dad6942ef454b2bf4d0c43ce6a607dff51ffc8
|
data/History.rdoc
CHANGED
@@ -30,6 +30,9 @@ unless defined?(ActiveRecord)
|
|
30
30
|
require 'active_record'
|
31
31
|
end
|
32
32
|
|
33
|
+
# Arel files we override
|
34
|
+
require 'arel/visitors/to_sql'
|
35
|
+
|
33
36
|
# AR files we override
|
34
37
|
require 'active_record/counter_cache'
|
35
38
|
require 'active_record/fixtures'
|
@@ -66,6 +69,8 @@ require 'active_record/relation/query_methods'
|
|
66
69
|
require 'active_record/validations/uniqueness'
|
67
70
|
|
68
71
|
# CPK files
|
72
|
+
require 'composite_primary_keys/arel/visitors/to_sql'
|
73
|
+
|
69
74
|
require 'composite_primary_keys/persistence'
|
70
75
|
require 'composite_primary_keys/base'
|
71
76
|
require 'composite_primary_keys/core'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Arel
|
2
|
+
module Visitors
|
3
|
+
class ToSql
|
4
|
+
def visit_Arel_Nodes_In o, a
|
5
|
+
if Array === o.right && o.right.empty?
|
6
|
+
'1=0'
|
7
|
+
else
|
8
|
+
a = o.left if Arel::Attributes::Attribute === o.left
|
9
|
+
# CPK
|
10
|
+
#"#{visit o.left, a} IN (#{visit o.right, a})"
|
11
|
+
if o.left.name.is_a?(Array)
|
12
|
+
"(#{visit o.left, a}) IN (#{visit o.right, a})"
|
13
|
+
else
|
14
|
+
"#{visit o.left, a} IN (#{visit o.right, a})"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,22 +1,22 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Associations
|
3
|
-
class JoinDependency
|
4
|
-
class JoinAssociation
|
5
|
-
def build_constraint(klass, table, key, foreign_table, foreign_key)
|
6
|
-
# CPK
|
7
|
-
# constraint = table[key].eq(foreign_table[foreign_key])
|
8
|
-
constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
|
9
|
-
|
10
|
-
if klass.finder_needs_type_condition?
|
11
|
-
constraint = table.create_and([
|
12
|
-
constraint,
|
13
|
-
klass.send(:type_condition, table)
|
14
|
-
])
|
15
|
-
end
|
16
|
-
|
17
|
-
constraint
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Associations
|
3
|
+
class JoinDependency
|
4
|
+
class JoinAssociation
|
5
|
+
def build_constraint(klass, table, key, foreign_table, foreign_key)
|
6
|
+
# CPK
|
7
|
+
# constraint = table[key].eq(foreign_table[foreign_key])
|
8
|
+
constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
|
9
|
+
|
10
|
+
if klass.finder_needs_type_condition?
|
11
|
+
constraint = table.create_and([
|
12
|
+
constraint,
|
13
|
+
klass.send(:type_condition, table)
|
14
|
+
])
|
15
|
+
end
|
16
|
+
|
17
|
+
constraint
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,19 +1,19 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Associations
|
3
|
-
class Preloader
|
4
|
-
class BelongsTo
|
5
|
-
def query_scope(ids)
|
6
|
-
# CPK
|
7
|
-
# scope.where(association_key.in(ids))
|
8
|
-
|
9
|
-
if association_key_name.is_a?(Array)
|
10
|
-
predicate = cpk_in_predicate(table, association_key_name, ids)
|
11
|
-
scope.where(predicate)
|
12
|
-
else
|
13
|
-
scope.where(association_key.in(ids))
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Associations
|
3
|
+
class Preloader
|
4
|
+
class BelongsTo
|
5
|
+
def query_scope(ids)
|
6
|
+
# CPK
|
7
|
+
# scope.where(association_key.in(ids))
|
8
|
+
|
9
|
+
if association_key_name.is_a?(Array)
|
10
|
+
predicate = cpk_in_predicate(table, association_key_name, ids)
|
11
|
+
scope.where(predicate)
|
12
|
+
else
|
13
|
+
scope.where(association_key.in(ids))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,51 +1,51 @@
|
|
1
|
-
module CompositePrimaryKeys
|
2
|
-
module Predicates
|
3
|
-
def cpk_and_predicate(predicates)
|
4
|
-
if predicates.length == 1
|
5
|
-
predicates.first
|
6
|
-
else
|
7
|
-
Arel::Nodes::And.new(predicates)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def cpk_or_predicate(predicates)
|
12
|
-
or_predicate = predicates.map do |predicate|
|
13
|
-
::Arel::Nodes::Grouping.new(predicate)
|
14
|
-
end.inject do |memo, node|
|
15
|
-
::Arel::Nodes::Or.new(memo, node)
|
16
|
-
end
|
17
|
-
::Arel::Nodes::Grouping.new(or_predicate)
|
18
|
-
end
|
19
|
-
|
20
|
-
def cpk_id_predicate(table, keys, values)
|
21
|
-
eq_predicates = keys.zip(values).map do |key, value|
|
22
|
-
table[key].eq(value)
|
23
|
-
end
|
24
|
-
cpk_and_predicate(eq_predicates)
|
25
|
-
end
|
26
|
-
|
27
|
-
def cpk_join_predicate(table1, key1, table2, key2)
|
28
|
-
key1_fields = Array(key1).map {|key| table1[key]}
|
29
|
-
key2_fields = Array(key2).map {|key| table2[key]}
|
30
|
-
|
31
|
-
eq_predicates = key1_fields.zip(key2_fields).map do |key_field1, key_field2|
|
32
|
-
key_field1.eq(key_field2)
|
33
|
-
end
|
34
|
-
cpk_and_predicate(eq_predicates)
|
35
|
-
end
|
36
|
-
|
37
|
-
def cpk_in_predicate(table, primary_keys, ids)
|
38
|
-
and_predicates = ids.map do |id|
|
39
|
-
cpk_id_predicate(table, primary_keys, id)
|
40
|
-
end
|
41
|
-
cpk_or_predicate(and_predicates)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
ActiveRecord::Associations::AssociationScope.send(:include, CompositePrimaryKeys::Predicates)
|
47
|
-
ActiveRecord::Associations::JoinDependency::JoinAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
48
|
-
ActiveRecord::Associations::Preloader::Association.send(:include, CompositePrimaryKeys::Predicates)
|
49
|
-
ActiveRecord::Associations::HasManyThroughAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
50
|
-
ActiveRecord::Relation.send(:include, CompositePrimaryKeys::Predicates)
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
module Predicates
|
3
|
+
def cpk_and_predicate(predicates)
|
4
|
+
if predicates.length == 1
|
5
|
+
predicates.first
|
6
|
+
else
|
7
|
+
Arel::Nodes::And.new(predicates)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def cpk_or_predicate(predicates)
|
12
|
+
or_predicate = predicates.map do |predicate|
|
13
|
+
::Arel::Nodes::Grouping.new(predicate)
|
14
|
+
end.inject do |memo, node|
|
15
|
+
::Arel::Nodes::Or.new(memo, node)
|
16
|
+
end
|
17
|
+
::Arel::Nodes::Grouping.new(or_predicate)
|
18
|
+
end
|
19
|
+
|
20
|
+
def cpk_id_predicate(table, keys, values)
|
21
|
+
eq_predicates = keys.zip(values).map do |key, value|
|
22
|
+
table[key].eq(value)
|
23
|
+
end
|
24
|
+
cpk_and_predicate(eq_predicates)
|
25
|
+
end
|
26
|
+
|
27
|
+
def cpk_join_predicate(table1, key1, table2, key2)
|
28
|
+
key1_fields = Array(key1).map {|key| table1[key]}
|
29
|
+
key2_fields = Array(key2).map {|key| table2[key]}
|
30
|
+
|
31
|
+
eq_predicates = key1_fields.zip(key2_fields).map do |key_field1, key_field2|
|
32
|
+
key_field1.eq(key_field2)
|
33
|
+
end
|
34
|
+
cpk_and_predicate(eq_predicates)
|
35
|
+
end
|
36
|
+
|
37
|
+
def cpk_in_predicate(table, primary_keys, ids)
|
38
|
+
and_predicates = ids.map do |id|
|
39
|
+
cpk_id_predicate(table, primary_keys, id)
|
40
|
+
end
|
41
|
+
cpk_or_predicate(and_predicates)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
ActiveRecord::Associations::AssociationScope.send(:include, CompositePrimaryKeys::Predicates)
|
47
|
+
ActiveRecord::Associations::JoinDependency::JoinAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
48
|
+
ActiveRecord::Associations::Preloader::Association.send(:include, CompositePrimaryKeys::Predicates)
|
49
|
+
ActiveRecord::Associations::HasManyThroughAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
50
|
+
ActiveRecord::Relation.send(:include, CompositePrimaryKeys::Predicates)
|
51
51
|
ActiveRecord::PredicateBuilder.send(:extend, CompositePrimaryKeys::Predicates)
|
@@ -1,48 +1,48 @@
|
|
1
|
-
module CompositePrimaryKeys
|
2
|
-
module CompositeRelation
|
3
|
-
include CompositePrimaryKeys::ActiveRecord::Batches
|
4
|
-
include CompositePrimaryKeys::ActiveRecord::Calculations
|
5
|
-
include CompositePrimaryKeys::ActiveRecord::FinderMethods
|
6
|
-
include CompositePrimaryKeys::ActiveRecord::QueryMethods
|
7
|
-
|
8
|
-
def delete(id_or_array)
|
9
|
-
# CPK
|
10
|
-
if self.composite?
|
11
|
-
id_or_array = if id_or_array.is_a?(CompositePrimaryKeys::CompositeKeys)
|
12
|
-
[id_or_array]
|
13
|
-
else
|
14
|
-
Array(id_or_array)
|
15
|
-
end
|
16
|
-
|
17
|
-
id_or_array.each do |id|
|
18
|
-
# Is the passed in id actually a record?
|
19
|
-
id = id.kind_of?(::ActiveRecord::Base) ? id.id : id
|
20
|
-
where(cpk_id_predicate(table, self.primary_key, id)).delete_all
|
21
|
-
end
|
22
|
-
else
|
23
|
-
where(primary_key => id_or_array).delete_all
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def destroy(id_or_array)
|
28
|
-
# Without CPK:
|
29
|
-
#if id.is_a?(Array)
|
30
|
-
# id.map { |one_id| destroy(one_id) }
|
31
|
-
#else
|
32
|
-
# find(id).destroy
|
33
|
-
#end
|
34
|
-
|
35
|
-
id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
|
36
|
-
[id_or_array]
|
37
|
-
else
|
38
|
-
Array(id_or_array)
|
39
|
-
end
|
40
|
-
|
41
|
-
id_or_array.each do |id|
|
42
|
-
where(cpk_id_predicate(table, self.primary_key, id)).each do |record|
|
43
|
-
record.destroy
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
module CompositeRelation
|
3
|
+
include CompositePrimaryKeys::ActiveRecord::Batches
|
4
|
+
include CompositePrimaryKeys::ActiveRecord::Calculations
|
5
|
+
include CompositePrimaryKeys::ActiveRecord::FinderMethods
|
6
|
+
include CompositePrimaryKeys::ActiveRecord::QueryMethods
|
7
|
+
|
8
|
+
def delete(id_or_array)
|
9
|
+
# CPK
|
10
|
+
if self.composite?
|
11
|
+
id_or_array = if id_or_array.is_a?(CompositePrimaryKeys::CompositeKeys)
|
12
|
+
[id_or_array]
|
13
|
+
else
|
14
|
+
Array(id_or_array)
|
15
|
+
end
|
16
|
+
|
17
|
+
id_or_array.each do |id|
|
18
|
+
# Is the passed in id actually a record?
|
19
|
+
id = id.kind_of?(::ActiveRecord::Base) ? id.id : id
|
20
|
+
where(cpk_id_predicate(table, self.primary_key, id)).delete_all
|
21
|
+
end
|
22
|
+
else
|
23
|
+
where(primary_key => id_or_array).delete_all
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy(id_or_array)
|
28
|
+
# Without CPK:
|
29
|
+
#if id.is_a?(Array)
|
30
|
+
# id.map { |one_id| destroy(one_id) }
|
31
|
+
#else
|
32
|
+
# find(id).destroy
|
33
|
+
#end
|
34
|
+
|
35
|
+
id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
|
36
|
+
[id_or_array]
|
37
|
+
else
|
38
|
+
Array(id_or_array)
|
39
|
+
end
|
40
|
+
|
41
|
+
id_or_array.each do |id|
|
42
|
+
where(cpk_id_predicate(table, self.primary_key, id)).each do |record|
|
43
|
+
record.destroy
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,46 +1,60 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module ConnectionAdapters
|
3
|
-
class PostgreSQLAdapter
|
4
|
-
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
5
|
-
unless pk
|
6
|
-
# Extract the table from the insert sql. Yuck.
|
7
|
-
table_ref = extract_table_ref_from_insert_sql(sql)
|
8
|
-
pk = primary_key(table_ref) if table_ref
|
9
|
-
end
|
10
|
-
|
11
|
-
if pk
|
12
|
-
# CPK
|
13
|
-
# select_value("#{sql} RETURNING #{quote_column_name(pk)}")
|
14
|
-
select_value("#{sql} RETURNING #{quote_column_names(pk)}")
|
15
|
-
else
|
16
|
-
super
|
17
|
-
end
|
18
|
-
end
|
19
|
-
alias :create :insert
|
20
|
-
|
21
|
-
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
22
|
-
unless pk
|
23
|
-
# Extract the table from the insert sql. Yuck.
|
24
|
-
table_ref = extract_table_ref_from_insert_sql(sql)
|
25
|
-
pk = primary_key(table_ref) if table_ref
|
26
|
-
end
|
27
|
-
|
28
|
-
# CPK
|
29
|
-
# sql = "#{sql} RETURNING #{quote_column_name(pk)}" if pk
|
30
|
-
sql = "#{sql} RETURNING #{quote_column_names(pk)}" if pk
|
31
|
-
|
32
|
-
[sql, binds]
|
33
|
-
end
|
34
|
-
|
35
|
-
# Returns a single value if query returns a single element
|
36
|
-
# otherwise returns an array coresponding to the composite keys
|
37
|
-
#
|
38
|
-
def last_inserted_id(result)
|
39
|
-
row = result && result.rows.first
|
40
|
-
if Array === row
|
41
|
-
row.size == 1 ? row[0] : row
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
|
46
|
-
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class PostgreSQLAdapter
|
4
|
+
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
5
|
+
unless pk
|
6
|
+
# Extract the table from the insert sql. Yuck.
|
7
|
+
table_ref = extract_table_ref_from_insert_sql(sql)
|
8
|
+
pk = primary_key(table_ref) if table_ref
|
9
|
+
end
|
10
|
+
|
11
|
+
if pk
|
12
|
+
# CPK
|
13
|
+
# select_value("#{sql} RETURNING #{quote_column_name(pk)}")
|
14
|
+
select_value("#{sql} RETURNING #{quote_column_names(pk)}")
|
15
|
+
else
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
alias :create :insert
|
20
|
+
|
21
|
+
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
22
|
+
unless pk
|
23
|
+
# Extract the table from the insert sql. Yuck.
|
24
|
+
table_ref = extract_table_ref_from_insert_sql(sql)
|
25
|
+
pk = primary_key(table_ref) if table_ref
|
26
|
+
end
|
27
|
+
|
28
|
+
# CPK
|
29
|
+
# sql = "#{sql} RETURNING #{quote_column_name(pk)}" if pk
|
30
|
+
sql = "#{sql} RETURNING #{quote_column_names(pk)}" if pk
|
31
|
+
|
32
|
+
[sql, binds]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a single value if query returns a single element
|
36
|
+
# otherwise returns an array coresponding to the composite keys
|
37
|
+
#
|
38
|
+
def last_inserted_id(result)
|
39
|
+
row = result && result.rows.first
|
40
|
+
if Array === row
|
41
|
+
row.size == 1 ? row[0] : row
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module Quoting
|
46
|
+
def quote_column_name(name) #:nodoc:
|
47
|
+
# CPK
|
48
|
+
# PGconn.quote_ident(name.to_s)
|
49
|
+
if name.is_a?(Array)
|
50
|
+
name.map do |column|
|
51
|
+
PGconn.quote_ident(column.to_s)
|
52
|
+
end.join(', ')
|
53
|
+
else
|
54
|
+
PGconn.quote_ident(name.to_s)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|