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.
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