dbee-active_record 2.0.3 → 2.1.2
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 +4 -4
- data/.rubocop.yml +13 -12
- data/.ruby-version +1 -1
- data/.travis.yml +3 -10
- data/CHANGELOG.md +24 -1
- data/README.md +1 -1
- data/dbee-active_record.gemspec +17 -8
- data/exe/.gitkeep +0 -0
- data/lib/dbee/providers/active_record_provider/expression_builder.rb +55 -24
- data/lib/dbee/providers/active_record_provider/maker.rb +37 -0
- data/lib/dbee/providers/active_record_provider/{expression_builder/constraint_maker.rb → makers/constraint.rb} +12 -12
- data/lib/dbee/providers/active_record_provider/{expression_builder/order_maker.rb → makers/order.rb} +9 -9
- data/lib/dbee/providers/active_record_provider/makers/select.rb +81 -0
- data/lib/dbee/providers/active_record_provider/makers/where.rb +111 -0
- data/lib/dbee/providers/active_record_provider/version.rb +1 -1
- data/spec/db_helper.rb +134 -14
- data/spec/dbee/providers/active_record_provider/expression_builder_spec.rb +117 -0
- data/spec/dbee/providers/active_record_provider/makers/where_spec.rb +260 -0
- data/spec/dbee/providers/active_record_provider_spec.rb +101 -3
- data/spec/fixtures/active_record_snapshots/one_table_empty_query.yaml +10 -0
- data/spec/fixtures/active_record_snapshots/one_table_query_with_filters.yaml +24 -16
- data/spec/fixtures/active_record_snapshots/two_table_query_with_aggregation.yaml +71 -0
- data/spec/fixtures/active_record_snapshots/two_table_query_with_pivoting.yaml +88 -0
- data/spec/fixtures/models.yaml +20 -0
- data/spec/spec_helper.rb +5 -1
- metadata +51 -19
- data/lib/dbee/providers/active_record_provider/expression_builder/select_maker.rb +0 -33
- data/lib/dbee/providers/active_record_provider/expression_builder/where_maker.rb +0 -56
@@ -11,8 +11,6 @@ require 'spec_helper'
|
|
11
11
|
require 'db_helper'
|
12
12
|
|
13
13
|
describe Dbee::Providers::ActiveRecordProvider do
|
14
|
-
let(:models) { yaml_fixture('models.yaml') }
|
15
|
-
|
16
14
|
describe '#sql' do
|
17
15
|
before(:all) do
|
18
16
|
connect_to_db(:sqlite)
|
@@ -79,7 +77,7 @@ describe Dbee::Providers::ActiveRecordProvider do
|
|
79
77
|
end
|
80
78
|
end
|
81
79
|
|
82
|
-
context '
|
80
|
+
context 'Shallow SQL Execution' do
|
83
81
|
%w[sqlite].each do |dbms|
|
84
82
|
context dbms do
|
85
83
|
before(:all) do
|
@@ -108,4 +106,104 @@ describe Dbee::Providers::ActiveRecordProvider do
|
|
108
106
|
end
|
109
107
|
end
|
110
108
|
end
|
109
|
+
|
110
|
+
describe 'Deep SQL execution' do
|
111
|
+
before(:all) do
|
112
|
+
connect_to_db(:sqlite)
|
113
|
+
load_schema
|
114
|
+
load_data
|
115
|
+
end
|
116
|
+
|
117
|
+
describe 'pivoting' do
|
118
|
+
let(:snapshot_path) do
|
119
|
+
%w[
|
120
|
+
spec
|
121
|
+
fixtures
|
122
|
+
active_record_snapshots
|
123
|
+
two_table_query_with_pivoting.yaml
|
124
|
+
]
|
125
|
+
end
|
126
|
+
|
127
|
+
let(:snapshot) { yaml_file_read(*snapshot_path) }
|
128
|
+
let(:query) { Dbee::Query.make(snapshot['query']) }
|
129
|
+
let(:model) { Dbee::Model.make(models['Patients']) }
|
130
|
+
|
131
|
+
it 'pivots table rows into columns' do
|
132
|
+
sql = described_class.new.sql(model, query)
|
133
|
+
|
134
|
+
results = ActiveRecord::Base.connection.execute(sql)
|
135
|
+
|
136
|
+
expect(results[0]).to include(
|
137
|
+
'First Name' => 'Bozo',
|
138
|
+
'Date of Birth' => '1904-04-04',
|
139
|
+
'Drivers License #' => '82-54-hut-hut-hike!',
|
140
|
+
'Demographic Notes' => 'The patient is funny!',
|
141
|
+
'Contact Notes' => 'Do not call this patient at night!'
|
142
|
+
)
|
143
|
+
|
144
|
+
expect(results[1]).to include(
|
145
|
+
'First Name' => 'Frank',
|
146
|
+
'Date of Birth' => nil,
|
147
|
+
'Drivers License #' => nil,
|
148
|
+
'Demographic Notes' => nil,
|
149
|
+
'Contact Notes' => nil
|
150
|
+
)
|
151
|
+
|
152
|
+
expect(results[2]).to include(
|
153
|
+
'First Name' => 'Bugs',
|
154
|
+
'Date of Birth' => '2040-01-01',
|
155
|
+
'Drivers License #' => nil,
|
156
|
+
'Demographic Notes' => nil,
|
157
|
+
'Contact Notes' => 'Call anytime!!'
|
158
|
+
)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe 'aggregation' do
|
163
|
+
let(:snapshot_path) do
|
164
|
+
%w[
|
165
|
+
spec
|
166
|
+
fixtures
|
167
|
+
active_record_snapshots
|
168
|
+
two_table_query_with_aggregation.yaml
|
169
|
+
]
|
170
|
+
end
|
171
|
+
|
172
|
+
let(:snapshot) { yaml_file_read(*snapshot_path) }
|
173
|
+
let(:query) { Dbee::Query.make(snapshot['query']) }
|
174
|
+
let(:model) { Dbee::Model.make(models['Patients']) }
|
175
|
+
|
176
|
+
it 'executes correct SQL aggregate functions' do
|
177
|
+
sql = described_class.new.sql(model, query)
|
178
|
+
results = ActiveRecord::Base.connection.execute(sql)
|
179
|
+
|
180
|
+
expect(results[0]).to include(
|
181
|
+
'First Name' => 'Bozo',
|
182
|
+
'Ave Payment' => 10,
|
183
|
+
'Number of Payments' => 3,
|
184
|
+
'Max Payment' => 15,
|
185
|
+
'Min Payment' => 5,
|
186
|
+
'Total Paid' => 30
|
187
|
+
)
|
188
|
+
|
189
|
+
expect(results[1]).to include(
|
190
|
+
'First Name' => 'Frank',
|
191
|
+
'Ave Payment' => 100,
|
192
|
+
'Number of Payments' => 2,
|
193
|
+
'Max Payment' => 150,
|
194
|
+
'Min Payment' => 50,
|
195
|
+
'Total Paid' => 200
|
196
|
+
)
|
197
|
+
|
198
|
+
expect(results[2]).to include(
|
199
|
+
'First Name' => 'Bugs',
|
200
|
+
'Ave Payment' => nil,
|
201
|
+
'Number of Payments' => 0,
|
202
|
+
'Max Payment' => nil,
|
203
|
+
'Min Payment' => nil,
|
204
|
+
'Total Paid' => nil
|
205
|
+
)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
111
209
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
model_name: Patients
|
2
|
+
query:
|
3
|
+
sqlite_readable: |+
|
4
|
+
SELECT "patients".* FROM "patients" "patients"
|
5
|
+
sqlite_not_readable: |+
|
6
|
+
SELECT "t0".* FROM "patients" "t0"
|
7
|
+
mysql_readable: |+
|
8
|
+
SELECT `patients`.* FROM `patients` `patients`
|
9
|
+
mysql_not_readable: |+
|
10
|
+
SELECT `t0`.* FROM `patients` `t0`
|
@@ -45,6 +45,10 @@ query:
|
|
45
45
|
- 'Netflix'
|
46
46
|
- 'Hulu'
|
47
47
|
key_path: name
|
48
|
+
- type: not_equals
|
49
|
+
value:
|
50
|
+
- 'YouTube Super Video'
|
51
|
+
key_path: name
|
48
52
|
- type: not_contain
|
49
53
|
value:
|
50
54
|
- 'tfli'
|
@@ -59,67 +63,71 @@ sqlite_readable: |+
|
|
59
63
|
SELECT "theaters"."id" AS 'ID #',
|
60
64
|
"theaters"."name" AS 'name'
|
61
65
|
FROM "theaters" "theaters"
|
62
|
-
WHERE
|
66
|
+
WHERE "theaters"."name" IN ('AMC', 'Regal') AND
|
63
67
|
"theaters"."name" LIKE 'A%' AND
|
64
68
|
"theaters"."name" LIKE '%m%' AND
|
65
69
|
"theaters"."active" = 'false' AND
|
66
|
-
(
|
67
|
-
(
|
70
|
+
("theaters"."active" IS NULL OR "theaters"."active" IN ('t', 'f')) AND
|
71
|
+
("theaters"."inspected" IS NULL OR "theaters"."inspected" IN ('f', 't')) AND
|
68
72
|
"theaters"."created_at" <= '2019-03-04' AND
|
69
73
|
"theaters"."created_at" < '2018-03-04' AND
|
70
74
|
"theaters"."created_at" >= '2001-03-04' AND
|
71
75
|
"theaters"."created_at" > '2002-03-04' AND
|
72
|
-
|
76
|
+
"theaters"."name" NOT IN ('Netflix', 'Hulu') AND
|
77
|
+
"theaters"."name" != 'YouTube Super Video' AND
|
73
78
|
("theaters"."name" NOT LIKE '%tfli%' OR "theaters"."name" NOT LIKE '%ul%') AND
|
74
79
|
("theaters"."name" NOT LIKE 'netf%' OR "theaters"."name" NOT LIKE 'hu%')
|
75
80
|
sqlite_not_readable: |+
|
76
81
|
SELECT "t0"."id" AS 'c0',
|
77
82
|
"t0"."name" AS 'c1'
|
78
83
|
FROM "theaters" "t0"
|
79
|
-
WHERE
|
84
|
+
WHERE "t0"."name" IN ('AMC', 'Regal') AND
|
80
85
|
"t0"."name" LIKE 'A%' AND
|
81
86
|
"t0"."name" LIKE '%m%' AND
|
82
87
|
"t0"."active" = 'false' AND
|
83
|
-
(
|
84
|
-
(
|
88
|
+
("t0"."active" IS NULL OR "t0"."active" IN ('t', 'f')) AND
|
89
|
+
("t0"."inspected" IS NULL OR "t0"."inspected" IN ('f', 't')) AND
|
85
90
|
"t0"."created_at" <= '2019-03-04' AND
|
86
91
|
"t0"."created_at" < '2018-03-04' AND
|
87
92
|
"t0"."created_at" >= '2001-03-04' AND
|
88
93
|
"t0"."created_at" > '2002-03-04' AND
|
89
|
-
|
94
|
+
"t0"."name" NOT IN ('Netflix', 'Hulu') AND
|
95
|
+
"t0"."name" != 'YouTube Super Video' AND
|
90
96
|
("t0"."name" NOT LIKE '%tfli%' OR "t0"."name" NOT LIKE '%ul%') AND
|
91
97
|
("t0"."name" NOT LIKE 'netf%' OR "t0"."name" NOT LIKE 'hu%')
|
92
98
|
mysql_readable: |+
|
93
99
|
SELECT `theaters`.`id` AS 'ID #',
|
94
100
|
`theaters`.`name` AS 'name'
|
95
101
|
FROM `theaters` `theaters`
|
96
|
-
WHERE
|
102
|
+
WHERE `theaters`.`name` IN ('AMC', 'Regal') AND
|
97
103
|
`theaters`.`name` LIKE 'A%' AND
|
98
104
|
`theaters`.`name` LIKE '%m%' AND
|
99
105
|
`theaters`.`active` = 'false' AND
|
100
|
-
(
|
101
|
-
(
|
106
|
+
(`theaters`.`active` IS NULL OR `theaters`.`active` IN (TRUE, FALSE)) AND
|
107
|
+
(`theaters`.`inspected` IS NULL OR `theaters`.`inspected` IN (FALSE, TRUE)) AND
|
102
108
|
`theaters`.`created_at` <= '2019-03-04' AND
|
103
109
|
`theaters`.`created_at` < '2018-03-04' AND
|
104
110
|
`theaters`.`created_at` >= '2001-03-04' AND
|
105
111
|
`theaters`.`created_at` > '2002-03-04' AND
|
106
|
-
|
112
|
+
`theaters`.`name` NOT IN ('Netflix', 'Hulu') AND
|
113
|
+
`theaters`.`name` != 'YouTube Super Video' AND
|
107
114
|
(`theaters`.`name` NOT LIKE '%tfli%' OR `theaters`.`name` NOT LIKE '%ul%') AND
|
108
115
|
(`theaters`.`name` NOT LIKE 'netf%' OR `theaters`.`name` NOT LIKE 'hu%')
|
109
116
|
mysql_not_readable: |+
|
110
117
|
SELECT `t0`.`id` AS 'c0',
|
111
118
|
`t0`.`name` AS 'c1'
|
112
119
|
FROM `theaters` `t0`
|
113
|
-
WHERE
|
120
|
+
WHERE `t0`.`name` IN ('AMC', 'Regal') AND
|
114
121
|
`t0`.`name` LIKE 'A%' AND
|
115
122
|
`t0`.`name` LIKE '%m%' AND
|
116
123
|
`t0`.`active` = 'false' AND
|
117
|
-
(
|
118
|
-
(
|
124
|
+
(`t0`.`active` IS NULL OR `t0`.`active` IN (TRUE, FALSE)) AND
|
125
|
+
(`t0`.`inspected` IS NULL OR `t0`.`inspected` IN (FALSE, TRUE)) AND
|
119
126
|
`t0`.`created_at` <= '2019-03-04' AND
|
120
127
|
`t0`.`created_at` < '2018-03-04' AND
|
121
128
|
`t0`.`created_at` >= '2001-03-04' AND
|
122
129
|
`t0`.`created_at` > '2002-03-04' AND
|
123
|
-
|
130
|
+
`t0`.`name` NOT IN ('Netflix', 'Hulu') AND
|
131
|
+
`t0`.`name` != 'YouTube Super Video' AND
|
124
132
|
(`t0`.`name` NOT LIKE '%tfli%' OR `t0`.`name` NOT LIKE '%ul%') AND
|
125
133
|
(`t0`.`name` NOT LIKE 'netf%' OR `t0`.`name` NOT LIKE 'hu%')
|
@@ -0,0 +1,71 @@
|
|
1
|
+
model_name: Patients
|
2
|
+
query:
|
3
|
+
fields:
|
4
|
+
- key_path: id
|
5
|
+
display: 'ID #'
|
6
|
+
- key_path: first
|
7
|
+
display: First Name
|
8
|
+
- key_path: patient_payments.amount
|
9
|
+
display: Ave Payment
|
10
|
+
aggregator: ave
|
11
|
+
- key_path: patient_payments.amount
|
12
|
+
display: Number of Payments
|
13
|
+
aggregator: count
|
14
|
+
- key_path: patient_payments.amount
|
15
|
+
display: Max Payment
|
16
|
+
aggregator: max
|
17
|
+
- key_path: patient_payments.amount
|
18
|
+
display: Min Payment
|
19
|
+
aggregator: min
|
20
|
+
- key_path: patient_payments.amount
|
21
|
+
display: Total Paid
|
22
|
+
aggregator: sum
|
23
|
+
|
24
|
+
sqlite_readable: |+
|
25
|
+
SELECT
|
26
|
+
"patients"."id" AS 'ID #',
|
27
|
+
"patients"."first" AS 'First Name',
|
28
|
+
AVG("patient_payments"."amount") AS 'Ave Payment',
|
29
|
+
COUNT("patient_payments"."amount") AS 'Number of Payments',
|
30
|
+
MAX("patient_payments"."amount") AS 'Max Payment',
|
31
|
+
MIN("patient_payments"."amount") AS 'Min Payment',
|
32
|
+
SUM("patient_payments"."amount") AS 'Total Paid'
|
33
|
+
FROM "patients" "patients"
|
34
|
+
LEFT OUTER JOIN "patient_payments" "patient_payments" ON "patient_payments"."patient_id" = "patients"."id"
|
35
|
+
GROUP BY "patients"."id", "patients"."first"
|
36
|
+
sqlite_not_readable: |+
|
37
|
+
SELECT
|
38
|
+
"t0"."id" AS 'c0',
|
39
|
+
"t0"."first" AS 'c1',
|
40
|
+
AVG("t1"."amount") AS 'c2',
|
41
|
+
COUNT("t1"."amount") AS 'c3',
|
42
|
+
MAX("t1"."amount") AS 'c4',
|
43
|
+
MIN("t1"."amount") AS 'c5',
|
44
|
+
SUM("t1"."amount") AS 'c6'
|
45
|
+
FROM "patients" "t0"
|
46
|
+
LEFT OUTER JOIN "patient_payments" "t1" ON "t1"."patient_id" = "t0"."id"
|
47
|
+
GROUP BY "t0"."id", "t0"."first"
|
48
|
+
mysql_readable: |+
|
49
|
+
SELECT
|
50
|
+
`patients`.`id` AS 'ID #',
|
51
|
+
`patients`.`first` AS 'First Name',
|
52
|
+
AVG(`patient_payments`.`amount`) AS 'Ave Payment',
|
53
|
+
COUNT(`patient_payments`.`amount`) AS 'Number of Payments',
|
54
|
+
MAX(`patient_payments`.`amount`) AS 'Max Payment',
|
55
|
+
MIN(`patient_payments`.`amount`) AS 'Min Payment',
|
56
|
+
SUM(`patient_payments`.`amount`) AS 'Total Paid'
|
57
|
+
FROM `patients` `patients`
|
58
|
+
LEFT OUTER JOIN `patient_payments` `patient_payments` ON `patient_payments`.`patient_id` = `patients`.`id`
|
59
|
+
GROUP BY `patients`.`id`, `patients`.`first`
|
60
|
+
mysql_not_readable: |+
|
61
|
+
SELECT
|
62
|
+
`t0`.`id` AS 'c0',
|
63
|
+
`t0`.`first` AS 'c1',
|
64
|
+
AVG(`t1`.`amount`) AS 'c2',
|
65
|
+
COUNT(`t1`.`amount`) AS 'c3',
|
66
|
+
MAX(`t1`.`amount`) AS 'c4',
|
67
|
+
MIN(`t1`.`amount`) AS 'c5',
|
68
|
+
SUM(`t1`.`amount`) AS 'c6'
|
69
|
+
FROM `patients` `t0`
|
70
|
+
LEFT OUTER JOIN `patient_payments` `t1` ON `t1`.`patient_id` = `t0`.`id`
|
71
|
+
GROUP BY `t0`.`id`, `t0`.`first`
|
@@ -0,0 +1,88 @@
|
|
1
|
+
model_name: Patients
|
2
|
+
query:
|
3
|
+
fields:
|
4
|
+
- key_path: id
|
5
|
+
display: 'ID #'
|
6
|
+
- key_path: first
|
7
|
+
display: First Name
|
8
|
+
- key_path: patient_field_values.value
|
9
|
+
display: Date of Birth
|
10
|
+
aggregator: max
|
11
|
+
filters:
|
12
|
+
- key_path: patient_field_values.fields.section
|
13
|
+
value: demographics
|
14
|
+
- key_path: patient_field_values.fields.key
|
15
|
+
value: dob
|
16
|
+
- key_path: patient_field_values.value
|
17
|
+
display: Demographic Notes
|
18
|
+
aggregator: max
|
19
|
+
filters:
|
20
|
+
- key_path: patient_field_values.fields.section
|
21
|
+
value: demographics
|
22
|
+
- key_path: patient_field_values.fields.key
|
23
|
+
value: notes
|
24
|
+
- key_path: patient_field_values.value
|
25
|
+
display: 'Drivers License #'
|
26
|
+
aggregator: max
|
27
|
+
filters:
|
28
|
+
- key_path: patient_field_values.fields.section
|
29
|
+
value: demographics
|
30
|
+
- key_path: patient_field_values.fields.key
|
31
|
+
value: drivers_license
|
32
|
+
- key_path: patient_field_values.value
|
33
|
+
display: Contact Notes
|
34
|
+
aggregator: max
|
35
|
+
filters:
|
36
|
+
- key_path: patient_field_values.fields.section
|
37
|
+
value: contact
|
38
|
+
- key_path: patient_field_values.fields.key
|
39
|
+
value: notes
|
40
|
+
|
41
|
+
sqlite_readable: |+
|
42
|
+
SELECT
|
43
|
+
"patients"."id" AS 'ID #',
|
44
|
+
"patients"."first" AS 'First Name',
|
45
|
+
MAX(CASE WHEN "patient_field_values_fields"."section" = 'demographics' AND "patient_field_values_fields"."key" = 'dob' THEN "patient_field_values"."value" END) AS 'Date of Birth',
|
46
|
+
MAX(CASE WHEN "patient_field_values_fields"."section" = 'demographics' AND "patient_field_values_fields"."key" = 'notes' THEN "patient_field_values"."value" END) AS 'Demographic Notes',
|
47
|
+
MAX(CASE WHEN "patient_field_values_fields"."section" = 'demographics' AND "patient_field_values_fields"."key" = 'drivers_license' THEN "patient_field_values"."value" END) AS 'Drivers License #',
|
48
|
+
MAX(CASE WHEN "patient_field_values_fields"."section" = 'contact' AND "patient_field_values_fields"."key" = 'notes' THEN "patient_field_values"."value" END) AS 'Contact Notes'
|
49
|
+
FROM "patients" "patients"
|
50
|
+
LEFT OUTER JOIN "patient_field_values" "patient_field_values" ON "patient_field_values"."patient_id" = "patients"."id"
|
51
|
+
LEFT OUTER JOIN "fields" "patient_field_values_fields" ON "patient_field_values_fields"."id" = "patient_field_values"."field_id"
|
52
|
+
GROUP BY "patients"."id", "patients"."first"
|
53
|
+
sqlite_not_readable: |+
|
54
|
+
SELECT
|
55
|
+
"t0"."id" AS 'c0',
|
56
|
+
"t0"."first" AS 'c1',
|
57
|
+
MAX(CASE WHEN "t2"."section" = 'demographics' AND "t2"."key" = 'dob' THEN "t1"."value" END) AS 'c2',
|
58
|
+
MAX(CASE WHEN "t2"."section" = 'demographics' AND "t2"."key" = 'notes' THEN "t1"."value" END) AS 'c3',
|
59
|
+
MAX(CASE WHEN "t2"."section" = 'demographics' AND "t2"."key" = 'drivers_license' THEN "t1"."value" END) AS 'c4',
|
60
|
+
MAX(CASE WHEN "t2"."section" = 'contact' AND "t2"."key" = 'notes' THEN "t1"."value" END) AS 'c5'
|
61
|
+
FROM "patients" "t0"
|
62
|
+
LEFT OUTER JOIN "patient_field_values" "t1" ON "t1"."patient_id" = "t0"."id"
|
63
|
+
LEFT OUTER JOIN "fields" "t2" ON "t2"."id" = "t1"."field_id"
|
64
|
+
GROUP BY "t0"."id", "t0"."first"
|
65
|
+
mysql_readable: |+
|
66
|
+
SELECT
|
67
|
+
`patients`.`id` AS 'ID #',
|
68
|
+
`patients`.`first` AS 'First Name',
|
69
|
+
MAX(CASE WHEN `patient_field_values_fields`.`section` = 'demographics' AND `patient_field_values_fields`.`key` = 'dob' THEN `patient_field_values`.`value` END) AS 'Date of Birth',
|
70
|
+
MAX(CASE WHEN `patient_field_values_fields`.`section` = 'demographics' AND `patient_field_values_fields`.`key` = 'notes' THEN `patient_field_values`.`value` END) AS 'Demographic Notes',
|
71
|
+
MAX(CASE WHEN `patient_field_values_fields`.`section` = 'demographics' AND `patient_field_values_fields`.`key` = 'drivers_license' THEN `patient_field_values`.`value` END) AS 'Drivers License #',
|
72
|
+
MAX(CASE WHEN `patient_field_values_fields`.`section` = 'contact' AND `patient_field_values_fields`.`key` = 'notes' THEN `patient_field_values`.`value` END) AS 'Contact Notes'
|
73
|
+
FROM `patients` `patients`
|
74
|
+
LEFT OUTER JOIN `patient_field_values` `patient_field_values` ON `patient_field_values`.`patient_id` = `patients`.`id`
|
75
|
+
LEFT OUTER JOIN `fields` `patient_field_values_fields` ON `patient_field_values_fields`.`id` = `patient_field_values`.`field_id`
|
76
|
+
GROUP BY `patients`.`id`, `patients`.`first`
|
77
|
+
mysql_not_readable: |+
|
78
|
+
SELECT
|
79
|
+
`t0`.`id` AS 'c0',
|
80
|
+
`t0`.`first` AS 'c1',
|
81
|
+
MAX(CASE WHEN `t2`.`section` = 'demographics' AND `t2`.`key` = 'dob' THEN `t1`.`value` END) AS 'c2',
|
82
|
+
MAX(CASE WHEN `t2`.`section` = 'demographics' AND `t2`.`key` = 'notes' THEN `t1`.`value` END) AS 'c3',
|
83
|
+
MAX(CASE WHEN `t2`.`section` = 'demographics' AND `t2`.`key` = 'drivers_license' THEN `t1`.`value` END) AS 'c4',
|
84
|
+
MAX(CASE WHEN `t2`.`section` = 'contact' AND `t2`.`key` = 'notes' THEN `t1`.`value` END) AS 'c5'
|
85
|
+
FROM `patients` `t0`
|
86
|
+
LEFT OUTER JOIN `patient_field_values` `t1` ON `t1`.`patient_id` = `t0`.`id`
|
87
|
+
LEFT OUTER JOIN `fields` `t2` ON `t2`.`id` = `t1`.`field_id`
|
88
|
+
GROUP BY `t0`.`id`, `t0`.`first`
|
data/spec/fixtures/models.yaml
CHANGED
@@ -103,3 +103,23 @@ Partitioner Example 2:
|
|
103
103
|
value: Dog
|
104
104
|
- name: deleted
|
105
105
|
value: false
|
106
|
+
|
107
|
+
Patients:
|
108
|
+
name: patients
|
109
|
+
models:
|
110
|
+
- name: patient_payments
|
111
|
+
constraints:
|
112
|
+
- type: reference
|
113
|
+
parent: id
|
114
|
+
name: patient_id
|
115
|
+
- name: patient_field_values
|
116
|
+
constraints:
|
117
|
+
- type: reference
|
118
|
+
parent: id
|
119
|
+
name: patient_id
|
120
|
+
models:
|
121
|
+
- name: fields
|
122
|
+
constraints:
|
123
|
+
- type: reference
|
124
|
+
parent: field_id
|
125
|
+
name: id
|
data/spec/spec_helper.rb
CHANGED
@@ -35,7 +35,7 @@ def fixture(*filename)
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def yaml_fixture_files(*directory)
|
38
|
-
Dir[File.join('spec', 'fixtures', *directory, '*.yaml')].map do |filename|
|
38
|
+
Dir[File.join('spec', 'fixtures', *directory, '**', '*.yaml')].map do |filename|
|
39
39
|
[
|
40
40
|
filename,
|
41
41
|
yaml_file_read(filename)
|
@@ -50,3 +50,7 @@ end
|
|
50
50
|
def file_read(*filename)
|
51
51
|
File.open(File.join(*filename), 'r:bom|utf-8').read
|
52
52
|
end
|
53
|
+
|
54
|
+
def models
|
55
|
+
yaml_fixture('models.yaml')
|
56
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbee-active_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
8
|
+
- Craig Kattner
|
8
9
|
autorequire:
|
9
|
-
bindir:
|
10
|
+
bindir: exe
|
10
11
|
cert_chain: []
|
11
|
-
date: 2020-
|
12
|
+
date: 2020-10-15 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: activerecord
|
@@ -39,7 +40,7 @@ dependencies:
|
|
39
40
|
version: '2'
|
40
41
|
- - ">="
|
41
42
|
- !ruby/object:Gem::Version
|
42
|
-
version: 2.
|
43
|
+
version: 2.1.1
|
43
44
|
type: :runtime
|
44
45
|
prerelease: false
|
45
46
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -49,7 +50,7 @@ dependencies:
|
|
49
50
|
version: '2'
|
50
51
|
- - ">="
|
51
52
|
- !ruby/object:Gem::Version
|
52
|
-
version: 2.
|
53
|
+
version: 2.1.1
|
53
54
|
- !ruby/object:Gem::Dependency
|
54
55
|
name: guard-rspec
|
55
56
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,6 +93,20 @@ dependencies:
|
|
92
93
|
- - "~>"
|
93
94
|
- !ruby/object:Gem::Version
|
94
95
|
version: '0'
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: pry-byebug
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
95
110
|
- !ruby/object:Gem::Dependency
|
96
111
|
name: rake
|
97
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,42 +141,42 @@ dependencies:
|
|
126
141
|
requirements:
|
127
142
|
- - "~>"
|
128
143
|
- !ruby/object:Gem::Version
|
129
|
-
version: 0.
|
144
|
+
version: 0.90.0
|
130
145
|
type: :development
|
131
146
|
prerelease: false
|
132
147
|
version_requirements: !ruby/object:Gem::Requirement
|
133
148
|
requirements:
|
134
149
|
- - "~>"
|
135
150
|
- !ruby/object:Gem::Version
|
136
|
-
version: 0.
|
151
|
+
version: 0.90.0
|
137
152
|
- !ruby/object:Gem::Dependency
|
138
153
|
name: simplecov
|
139
154
|
requirement: !ruby/object:Gem::Requirement
|
140
155
|
requirements:
|
141
156
|
- - "~>"
|
142
157
|
- !ruby/object:Gem::Version
|
143
|
-
version: 0.
|
158
|
+
version: 0.19.0
|
144
159
|
type: :development
|
145
160
|
prerelease: false
|
146
161
|
version_requirements: !ruby/object:Gem::Requirement
|
147
162
|
requirements:
|
148
163
|
- - "~>"
|
149
164
|
- !ruby/object:Gem::Version
|
150
|
-
version: 0.
|
165
|
+
version: 0.19.0
|
151
166
|
- !ruby/object:Gem::Dependency
|
152
167
|
name: simplecov-console
|
153
168
|
requirement: !ruby/object:Gem::Requirement
|
154
169
|
requirements:
|
155
170
|
- - "~>"
|
156
171
|
- !ruby/object:Gem::Version
|
157
|
-
version: 0.
|
172
|
+
version: 0.7.0
|
158
173
|
type: :development
|
159
174
|
prerelease: false
|
160
175
|
version_requirements: !ruby/object:Gem::Requirement
|
161
176
|
requirements:
|
162
177
|
- - "~>"
|
163
178
|
- !ruby/object:Gem::Version
|
164
|
-
version: 0.
|
179
|
+
version: 0.7.0
|
165
180
|
- !ruby/object:Gem::Dependency
|
166
181
|
name: sqlite3
|
167
182
|
requirement: !ruby/object:Gem::Requirement
|
@@ -180,8 +195,8 @@ description: " By default Dbee ships with no underlying SQL generator. This
|
|
180
195
|
will plug in ActiveRecord into Dbee and Dbee will use it for SQL generation.\n"
|
181
196
|
email:
|
182
197
|
- mruggio@bluemarblepayroll.com
|
183
|
-
|
184
|
-
|
198
|
+
- ckattner@bluemarblepayroll.com
|
199
|
+
executables: []
|
185
200
|
extensions: []
|
186
201
|
extra_rdoc_files: []
|
187
202
|
files:
|
@@ -199,20 +214,25 @@ files:
|
|
199
214
|
- Rakefile
|
200
215
|
- bin/console
|
201
216
|
- dbee-active_record.gemspec
|
217
|
+
- exe/.gitkeep
|
202
218
|
- lib/dbee/providers/active_record_provider.rb
|
203
219
|
- lib/dbee/providers/active_record_provider/expression_builder.rb
|
204
|
-
- lib/dbee/providers/active_record_provider/
|
205
|
-
- lib/dbee/providers/active_record_provider/
|
206
|
-
- lib/dbee/providers/active_record_provider/
|
207
|
-
- lib/dbee/providers/active_record_provider/
|
220
|
+
- lib/dbee/providers/active_record_provider/maker.rb
|
221
|
+
- lib/dbee/providers/active_record_provider/makers/constraint.rb
|
222
|
+
- lib/dbee/providers/active_record_provider/makers/order.rb
|
223
|
+
- lib/dbee/providers/active_record_provider/makers/select.rb
|
224
|
+
- lib/dbee/providers/active_record_provider/makers/where.rb
|
208
225
|
- lib/dbee/providers/active_record_provider/obfuscated_alias_maker.rb
|
209
226
|
- lib/dbee/providers/active_record_provider/safe_alias_maker.rb
|
210
227
|
- lib/dbee/providers/active_record_provider/version.rb
|
211
228
|
- spec/config/database.yaml.ci
|
212
229
|
- spec/db_helper.rb
|
230
|
+
- spec/dbee/providers/active_record_provider/expression_builder_spec.rb
|
231
|
+
- spec/dbee/providers/active_record_provider/makers/where_spec.rb
|
213
232
|
- spec/dbee/providers/active_record_provider_spec.rb
|
214
233
|
- spec/fixtures/active_record_snapshots/five_table_query.yaml
|
215
234
|
- spec/fixtures/active_record_snapshots/multiple_same_table_query_with_static_constraints.yaml
|
235
|
+
- spec/fixtures/active_record_snapshots/one_table_empty_query.yaml
|
216
236
|
- spec/fixtures/active_record_snapshots/one_table_query.yaml
|
217
237
|
- spec/fixtures/active_record_snapshots/one_table_query_with_ascending_sort.yaml
|
218
238
|
- spec/fixtures/active_record_snapshots/one_table_query_with_descending_sort.yaml
|
@@ -223,12 +243,19 @@ files:
|
|
223
243
|
- spec/fixtures/active_record_snapshots/partitioner_example_2_query.yaml
|
224
244
|
- spec/fixtures/active_record_snapshots/reverse_polymorphic_query.yaml
|
225
245
|
- spec/fixtures/active_record_snapshots/two_table_query.yaml
|
246
|
+
- spec/fixtures/active_record_snapshots/two_table_query_with_aggregation.yaml
|
247
|
+
- spec/fixtures/active_record_snapshots/two_table_query_with_pivoting.yaml
|
226
248
|
- spec/fixtures/models.yaml
|
227
249
|
- spec/spec_helper.rb
|
228
250
|
homepage: https://github.com/bluemarblepayroll/dbee-active_record
|
229
251
|
licenses:
|
230
252
|
- MIT
|
231
|
-
metadata:
|
253
|
+
metadata:
|
254
|
+
bug_tracker_uri: https://github.com/bluemarblepayroll/dbee-active_record/issues
|
255
|
+
changelog_uri: https://github.com/bluemarblepayroll/dbee-active_record/blob/master/CHANGELOG.md
|
256
|
+
documentation_uri: https://www.rubydoc.info/gems/dbee-active_record
|
257
|
+
homepage_uri: https://github.com/bluemarblepayroll/dbee-active_record
|
258
|
+
source_code_uri: https://github.com/bluemarblepayroll/dbee-active_record
|
232
259
|
post_install_message:
|
233
260
|
rdoc_options: []
|
234
261
|
require_paths:
|
@@ -237,7 +264,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
237
264
|
requirements:
|
238
265
|
- - ">="
|
239
266
|
- !ruby/object:Gem::Version
|
240
|
-
version: 2.
|
267
|
+
version: '2.5'
|
241
268
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
242
269
|
requirements:
|
243
270
|
- - ">="
|
@@ -251,9 +278,12 @@ summary: Plugs in ActiveRecord so Dbee can use Arel for SQL generation.
|
|
251
278
|
test_files:
|
252
279
|
- spec/config/database.yaml.ci
|
253
280
|
- spec/db_helper.rb
|
281
|
+
- spec/dbee/providers/active_record_provider/expression_builder_spec.rb
|
282
|
+
- spec/dbee/providers/active_record_provider/makers/where_spec.rb
|
254
283
|
- spec/dbee/providers/active_record_provider_spec.rb
|
255
284
|
- spec/fixtures/active_record_snapshots/five_table_query.yaml
|
256
285
|
- spec/fixtures/active_record_snapshots/multiple_same_table_query_with_static_constraints.yaml
|
286
|
+
- spec/fixtures/active_record_snapshots/one_table_empty_query.yaml
|
257
287
|
- spec/fixtures/active_record_snapshots/one_table_query.yaml
|
258
288
|
- spec/fixtures/active_record_snapshots/one_table_query_with_ascending_sort.yaml
|
259
289
|
- spec/fixtures/active_record_snapshots/one_table_query_with_descending_sort.yaml
|
@@ -264,5 +294,7 @@ test_files:
|
|
264
294
|
- spec/fixtures/active_record_snapshots/partitioner_example_2_query.yaml
|
265
295
|
- spec/fixtures/active_record_snapshots/reverse_polymorphic_query.yaml
|
266
296
|
- spec/fixtures/active_record_snapshots/two_table_query.yaml
|
297
|
+
- spec/fixtures/active_record_snapshots/two_table_query_with_aggregation.yaml
|
298
|
+
- spec/fixtures/active_record_snapshots/two_table_query_with_pivoting.yaml
|
267
299
|
- spec/fixtures/models.yaml
|
268
300
|
- spec/spec_helper.rb
|