composite_primary_keys 7.0.15 → 7.0.16

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +4 -0
  3. data/lib/composite_primary_keys.rb +5 -0
  4. data/lib/composite_primary_keys/arel/visitors/to_sql.rb +20 -0
  5. data/lib/composite_primary_keys/associations/join_dependency/join_association.rb +22 -22
  6. data/lib/composite_primary_keys/associations/preloader/belongs_to.rb +19 -19
  7. data/lib/composite_primary_keys/composite_predicates.rb +50 -50
  8. data/lib/composite_primary_keys/composite_relation.rb +48 -48
  9. data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +60 -46
  10. data/lib/composite_primary_keys/fixtures.rb +22 -22
  11. data/lib/composite_primary_keys/locking/optimistic.rb +55 -55
  12. data/lib/composite_primary_keys/relation/query_methods.rb +40 -40
  13. data/lib/composite_primary_keys/version.rb +1 -1
  14. data/tasks/databases/oracle.rake +25 -25
  15. data/test/connections/databases.ci.yml +15 -15
  16. data/test/connections/native_oracle/connection.rb +11 -11
  17. data/test/connections/native_oracle_enhanced/connection.rb +16 -16
  18. data/test/fixtures/comment.rb +7 -7
  19. data/test/fixtures/db_definitions/db2-create-tables.sql +126 -126
  20. data/test/fixtures/db_definitions/db2-drop-tables.sql +18 -18
  21. data/test/fixtures/db_definitions/oracle.drop.sql +45 -45
  22. data/test/fixtures/db_definitions/oracle.sql +223 -223
  23. data/test/fixtures/dorm.rb +2 -2
  24. data/test/fixtures/membership.rb +6 -6
  25. data/test/fixtures/membership_statuses.yml +16 -16
  26. data/test/fixtures/memberships.yml +10 -10
  27. data/test/fixtures/product_tariffs.yml +14 -14
  28. data/test/fixtures/reference_code.rb +7 -7
  29. data/test/fixtures/restaurants_suburb.rb +2 -2
  30. data/test/fixtures/suburb.rb +5 -5
  31. data/test/fixtures/topic.rb +5 -5
  32. data/test/fixtures/topic_source.rb +6 -6
  33. data/test/fixtures/topic_sources.yml +3 -3
  34. data/test/fixtures/topics.yml +8 -8
  35. data/test/fixtures/users.yml +10 -10
  36. data/test/test_attribute_methods.rb +63 -63
  37. data/test/test_calculations.rb +42 -42
  38. data/test/test_callbacks.rb +99 -99
  39. data/test/test_delete_all.rb +5 -0
  40. data/test/test_dumpable.rb +15 -15
  41. data/test/test_nested_attributes.rb +124 -124
  42. data/test/test_optimistic.rb +18 -18
  43. data/test/test_predicates.rb +40 -40
  44. data/test/test_santiago.rb +23 -23
  45. data/test/test_suite.rb +34 -34
  46. data/test/test_touch.rb +23 -23
  47. data/test/test_update.rb +71 -71
  48. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0655d26f0b98d96ce4e4a5e87d1a6cae68391b7d
4
- data.tar.gz: c26046f30f2032540ff93522328a40cdbc735d0a
3
+ metadata.gz: a3eaf57bc39ed46c4a72d72d5340f36e808066af
4
+ data.tar.gz: 34c682ff2f92cfa89c1f198b33101b4a9f255cdb
5
5
  SHA512:
6
- metadata.gz: ecf66e28ac34b92bf9a27a20806bd9fb26e88b1f2b984b2cb43c5e86f325f224f25e5844f4dde8ba8fa80316f85cda8c5d27ae49b616bb48b2bdf6948b56766c
7
- data.tar.gz: cf120e29e8d8c6d38861505f01364e28cf96430d7fcd1c97c24fa7d6077b65a8d18a4aad3a1f1751d22536ac0c65d8859ff97b6d3b67056872b40b22f7904d67
6
+ metadata.gz: f807e7a2cd19630d36813aaebc4ada9c08d386c66723f01d3d66b51d220c586c1f94145c26192a5968a7f1b2c0261f8486e78882b09099e93f6609505877bab1
7
+ data.tar.gz: 6b1b0a788652b9912159ba9f6529778688275cf3648055e73b2f51239a2604c27f7527d92d86468b1d2c05adc4dad6942ef454b2bf4d0c43ce6a607dff51ffc8
@@ -1,3 +1,7 @@
1
+ == 7.0.16 (2015-12-13)
2
+
3
+ * Add support for #delete_all for CPK tables (Charlie Savage)
4
+
1
5
  == 7.0.15 (2015-09-02)
2
6
 
3
7
  * Fix bug in calculations - such as average (Charlie Savage)
@@ -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
- end
45
- end
46
- end
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