dbee-active_record 1.1.0 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f116ae2834ca7c1bb8401f58d6eb0a45464f44eb6d972267e9c8d66374c825c1
4
- data.tar.gz: 8b4b89ed376d95c61cfb093ee6966bd958a53afacbfaf385011f6dfa6cfddcae
3
+ metadata.gz: a19e2929826b2291f8309610e4740340a887deead5ad1a19a9a54b49d5e1fb12
4
+ data.tar.gz: aa96b0004e4a7d7c11c161088d6edaafe9d21099df94d20beed8df0dc0676b84
5
5
  SHA512:
6
- metadata.gz: 63c5e3440f06afab714dd1591a00d1da4ee42df659d35edf96f927528d9413ac1773414ba61973bb20c489e75491e6bc5bbd378fc3e2972b6b9843ae2087663a
7
- data.tar.gz: b60502a160fe716ab7b32fcf3e474ae56a7552772a0fc7e54105139ded1128c6a334e81fa90ea12d71f9d6af63736b620705c78ccc5b1542382f47ac31eb8556
6
+ metadata.gz: 87eaf4667b57c442f8f08923c96f2ba9428acff018b6e4f5f44becfe7e4fca41031f93a19f35935a46fc2277bbc0484f48807bf483a06c5fcd06d7616009f165
7
+ data.tar.gz: 67838d5d7d683ce91bfbebbed17dce20d50cd640af580c0f816a8e5989bd2cc46fa4eff356226bc84af66a689200c9c63790693c465727fde3abea3f919ab3ed
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 1.2.0 (August 29th, 2019)
2
+
3
+ * Add support for Dbee partitioners
4
+ * Only support Dbee version 1.2.0 and above
5
+
1
6
  # 1.1.0 (August 27th, 2019)
2
7
 
3
8
  * Only support Dbee version 1.1.0 and above
@@ -34,7 +34,7 @@ Gem::Specification.new do |s|
34
34
  end
35
35
 
36
36
  s.add_dependency('activerecord', activerecord_version)
37
- s.add_dependency('dbee', '~>1', '>=1.1.0')
37
+ s.add_dependency('dbee', '~>1', '>=1.2.0')
38
38
 
39
39
  s.add_development_dependency('guard-rspec', '~>4.7')
40
40
  s.add_development_dependency('mysql2', '~>0.5')
@@ -13,6 +13,8 @@ module Dbee
13
13
  class ExpressionBuilder
14
14
  # Can derive constraints for Arel table JOIN statements.
15
15
  class ConstraintMaker
16
+ include Singleton
17
+
16
18
  CONCAT_METHOD = lambda do |on, arel_column, value|
17
19
  on ? on.and(arel_column.eq(value)) : arel_column.eq(value)
18
20
  end
@@ -13,6 +13,8 @@ module Dbee
13
13
  class ExpressionBuilder
14
14
  # Derives Arel#order predicates.
15
15
  class OrderMaker
16
+ include Singleton
17
+
16
18
  SORTER_EVALUATORS = {
17
19
  Query::Sorters::Ascending => ->(column) { column },
18
20
  Query::Sorters::Descending => ->(column) { column.desc }
@@ -13,6 +13,8 @@ module Dbee
13
13
  class ExpressionBuilder
14
14
  # Derives Arel#project predicates.
15
15
  class SelectMaker
16
+ include Singleton
17
+
16
18
  def make(column, arel_column, alias_maker)
17
19
  column_alias = quote(alias_maker.make(column.display))
18
20
 
@@ -13,6 +13,8 @@ module Dbee
13
13
  class ExpressionBuilder
14
14
  # Derives Arel#where predicates.
15
15
  class WhereMaker
16
+ include Singleton
17
+
16
18
  FILTER_EVALUATORS = {
17
19
  Query::Filters::Contains => ->(column, val) { column.matches("%#{val}%") },
18
20
  Query::Filters::Equals => ->(column, val) { column.eq(val) },
@@ -28,10 +28,15 @@ module Dbee
28
28
  @table_alias_maker = table_alias_maker
29
29
  @column_alias_maker = column_alias_maker
30
30
 
31
- @base_table = Arel::Table.new(model.table)
32
- @base_table.table_alias = table_alias_maker.make(model.name)
31
+ clear
32
+ end
33
+
34
+ def clear
35
+ @base_table = make_table(model.table, model.name)
33
36
 
34
- @statement = base_table
37
+ build(base_table)
38
+
39
+ add_partitioners(base_table, model.partitioners)
35
40
  end
36
41
 
37
42
  def add(query)
@@ -60,31 +65,14 @@ module Dbee
60
65
  @key_paths_to_arel_columns ||= {}
61
66
  end
62
67
 
63
- def where_maker
64
- @where_maker ||= WhereMaker.new
65
- end
66
-
67
- def order_maker
68
- @order_maker ||= OrderMaker.new
69
- end
70
-
71
- def select_maker
72
- @select_maker ||= SelectMaker.new
73
- end
74
-
75
- def constraint_maker
76
- @constraint_maker ||= ConstraintMaker.new
77
- end
78
-
79
68
  def add_filter(filter)
80
69
  add_key_path(filter.key_path)
81
70
 
82
71
  key_path = filter.key_path
83
72
  arel_column = key_paths_to_arel_columns[key_path]
73
+ predicate = WhereMaker.instance.make(filter, arel_column)
84
74
 
85
- predicate = where_maker.make(filter, arel_column)
86
-
87
- @statement = statement.where(predicate)
75
+ build(statement.where(predicate))
88
76
 
89
77
  self
90
78
  end
@@ -92,12 +80,11 @@ module Dbee
92
80
  def add_sorter(sorter)
93
81
  add_key_path(sorter.key_path)
94
82
 
95
- key_path = sorter.key_path
83
+ key_path = sorter.key_path
96
84
  arel_column = key_paths_to_arel_columns[key_path]
85
+ predicate = OrderMaker.instance.make(sorter, arel_column)
97
86
 
98
- predicate = order_maker.make(sorter, arel_column)
99
-
100
- @statement = statement.order(predicate)
87
+ build(statement.order(predicate))
101
88
 
102
89
  self
103
90
  end
@@ -105,34 +92,45 @@ module Dbee
105
92
  def add_field(field)
106
93
  add_key_path(field.key_path)
107
94
 
108
- key_path = field.key_path
95
+ key_path = field.key_path
109
96
  arel_column = key_paths_to_arel_columns[key_path]
97
+ predicate = SelectMaker.instance.make(field, arel_column, column_alias_maker)
110
98
 
111
- predicate = select_maker.make(field, arel_column, column_alias_maker)
112
-
113
- @statement = statement.project(predicate)
99
+ build(statement.project(predicate))
114
100
 
115
101
  self
116
102
  end
117
103
 
118
104
  def add_limit(limit)
119
- @limit = limit ? limit.to_i : nil
105
+ limit = limit ? limit.to_i : nil
106
+
107
+ build(statement.take(limit))
120
108
 
121
- @statement = @statement.take(limit) if limit
109
+ self
110
+ end
111
+
112
+ def add_partitioners(table, partitioners)
113
+ partitioners.each do |partitioner|
114
+ arel_column = table[partitioner.name]
115
+ predicate = arel_column.eq(partitioner.value)
116
+
117
+ build(statement.where(predicate))
118
+ end
122
119
 
123
120
  self
124
121
  end
125
122
 
126
123
  def table(name, model, previous_table)
127
- table = Arel::Table.new(model.table)
128
- table.table_alias = table_alias_maker.make(name)
124
+ table = make_table(model.table, name)
129
125
 
130
- on = constraint_maker.make(model.constraints, table, previous_table)
126
+ on = ConstraintMaker.instance.make(model.constraints, table, previous_table)
131
127
 
132
128
  raise MissingConstraintError, "for: #{name}" unless on
133
129
 
134
- @statement = statement.join(table, ::Arel::Nodes::OuterJoin)
135
- @statement = statement.on(on)
130
+ build(statement.join(table, ::Arel::Nodes::OuterJoin))
131
+ build(statement.on(on))
132
+
133
+ add_partitioners(table, model.partitioners)
136
134
 
137
135
  tables[name] = table
138
136
  end
@@ -146,7 +144,7 @@ module Dbee
146
144
  def add_key_path(key_path)
147
145
  return if key_paths_to_arel_columns.key?(key_path)
148
146
 
149
- ancestors = model.ancestors(key_path.ancestor_names)
147
+ ancestors = model.ancestors!(key_path.ancestor_names)
150
148
 
151
149
  table = traverse_ancestors(ancestors)
152
150
 
@@ -155,6 +153,16 @@ module Dbee
155
153
 
156
154
  self
157
155
  end
156
+
157
+ def build(new_expression)
158
+ @statement = new_expression
159
+ end
160
+
161
+ def make_table(table_name, alias_name)
162
+ Arel::Table.new(table_name).tap do |table|
163
+ table.table_alias = table_alias_maker.make(alias_name)
164
+ end
165
+ end
158
166
  end
159
167
  end
160
168
  end
@@ -12,8 +12,10 @@ module Dbee
12
12
  class ActiveRecordProvider
13
13
  # This class can be used when readable alias names are expected.
14
14
  class SafeAliasMaker
15
- def make(name)
16
- name.to_s.tr('.', '_')
15
+ def make(*parts)
16
+ parts.flatten
17
+ .join('_')
18
+ .tr('.', '_')
17
19
  end
18
20
  end
19
21
  end
@@ -10,7 +10,7 @@
10
10
  module Dbee
11
11
  module Providers
12
12
  class ActiveRecordProvider
13
- VERSION = '1.1.0'
13
+ VERSION = '1.2.0'
14
14
  end
15
15
  end
16
16
  end
data/spec/db_helper.rb CHANGED
@@ -53,10 +53,17 @@ def load_schema
53
53
  t.timestamps
54
54
  end
55
55
 
56
+ create_table :owners do |t|
57
+ t.column :name, :string
58
+ t.timestamps
59
+ end
60
+
56
61
  create_table :animals do |t|
62
+ t.column :owner_id, :integer
57
63
  t.column :toy_id, :integer
58
64
  t.column :type, :string
59
65
  t.column :name, :string
66
+ t.column :deleted, :boolean
60
67
  t.timestamps
61
68
  end
62
69
 
@@ -0,0 +1,27 @@
1
+ model_name: Partitioner Example 1
2
+ query:
3
+ fields:
4
+ - key_path: id
5
+ sqlite_readable: |+
6
+ SELECT "dogs"."id" AS 'id'
7
+ FROM "animals" "dogs"
8
+ WHERE "dogs"."type" = 'Dog' AND
9
+ "dogs"."deleted" = 'f'
10
+ sqlite_not_readable: |+
11
+ SELECT
12
+ "t0"."id" AS 'c0'
13
+ FROM "animals" "t0"
14
+ WHERE "t0"."type" = 'Dog' AND
15
+ "t0"."deleted" = 'f'
16
+ mysql_readable: |+
17
+ SELECT
18
+ `dogs`.`id` AS 'id'
19
+ FROM `animals` `dogs`
20
+ WHERE `dogs`.`type` = 'Dog' AND
21
+ `dogs`.`deleted` = FALSE
22
+ mysql_not_readable: |+
23
+ SELECT
24
+ `t0`.`id` AS 'c0'
25
+ FROM `animals` `t0`
26
+ WHERE `t0`.`type` = 'Dog' AND
27
+ `t0`.`deleted` = FALSE
@@ -0,0 +1,37 @@
1
+ model_name: Partitioner Example 2
2
+ query:
3
+ fields:
4
+ - key_path: id
5
+ - key_path: dogs.id
6
+ sqlite_readable: |+
7
+ SELECT
8
+ "owners"."id" AS 'id',
9
+ "dogs"."id" AS 'dogs_id'
10
+ FROM "owners" "owners"
11
+ LEFT OUTER JOIN "animals" "dogs" ON "dogs"."owner_id" = "owners"."id"
12
+ WHERE "dogs"."type" = 'Dog' AND
13
+ "dogs"."deleted" = 'f'
14
+ sqlite_not_readable: |+
15
+ SELECT
16
+ "t0"."id" AS 'c0',
17
+ "t1"."id" AS 'c1'
18
+ FROM "owners" "t0"
19
+ LEFT OUTER JOIN "animals" "t1" ON "t1"."owner_id" = "t0"."id"
20
+ WHERE "t1"."type" = 'Dog' AND
21
+ "t1"."deleted" = 'f'
22
+ mysql_readable: |+
23
+ SELECT
24
+ `owners`.`id` AS 'id',
25
+ `dogs`.`id` AS 'dogs_id'
26
+ FROM `owners` `owners`
27
+ LEFT OUTER JOIN `animals` `dogs` ON `dogs`.`owner_id` = `owners`.`id`
28
+ WHERE `dogs`.`type` = 'Dog' AND
29
+ `dogs`.`deleted` = FALSE
30
+ mysql_not_readable: |+
31
+ SELECT
32
+ `t0`.`id` AS 'c0',
33
+ `t1`.`id` AS 'c1'
34
+ FROM `owners` `t0`
35
+ LEFT OUTER JOIN `animals` `t1` ON `t1`.`owner_id` = `t0`.`id`
36
+ WHERE `t1`.`type` = 'Dog' AND
37
+ `t1`.`deleted` = FALSE
@@ -80,3 +80,26 @@ Reverse Polymorphic Example:
80
80
  - type: static
81
81
  parent: type
82
82
  value: Cat
83
+
84
+ Partitioner Example 1:
85
+ name: dogs
86
+ table: animals
87
+ partitioners:
88
+ - name: type
89
+ value: Dog
90
+ - name: deleted
91
+ value: false
92
+
93
+ Partitioner Example 2:
94
+ name: owners
95
+ models:
96
+ - name: dogs
97
+ table: animals
98
+ constraints:
99
+ - name: owner_id
100
+ parent: id
101
+ partitioners:
102
+ - name: type
103
+ value: Dog
104
+ - name: deleted
105
+ value: false
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbee-active_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-28 00:00:00.000000000 Z
11
+ date: 2019-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -39,7 +39,7 @@ dependencies:
39
39
  version: '1'
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 1.1.0
42
+ version: 1.2.0
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,7 +49,7 @@ dependencies:
49
49
  version: '1'
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 1.1.0
52
+ version: 1.2.0
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: guard-rspec
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -219,6 +219,8 @@ files:
219
219
  - spec/fixtures/active_record_snapshots/one_table_query_with_filters.yaml
220
220
  - spec/fixtures/active_record_snapshots/one_table_query_with_limit.yaml
221
221
  - spec/fixtures/active_record_snapshots/one_table_query_with_multiple_sorts.yaml
222
+ - spec/fixtures/active_record_snapshots/partitioner_example_1_query.yaml
223
+ - spec/fixtures/active_record_snapshots/partitioner_example_2_query.yaml
222
224
  - spec/fixtures/active_record_snapshots/reverse_polymorphic_query.yaml
223
225
  - spec/fixtures/active_record_snapshots/two_table_query.yaml
224
226
  - spec/fixtures/models.yaml
@@ -258,6 +260,8 @@ test_files:
258
260
  - spec/fixtures/active_record_snapshots/one_table_query_with_filters.yaml
259
261
  - spec/fixtures/active_record_snapshots/one_table_query_with_limit.yaml
260
262
  - spec/fixtures/active_record_snapshots/one_table_query_with_multiple_sorts.yaml
263
+ - spec/fixtures/active_record_snapshots/partitioner_example_1_query.yaml
264
+ - spec/fixtures/active_record_snapshots/partitioner_example_2_query.yaml
261
265
  - spec/fixtures/active_record_snapshots/reverse_polymorphic_query.yaml
262
266
  - spec/fixtures/active_record_snapshots/two_table_query.yaml
263
267
  - spec/fixtures/models.yaml