conceptql 0.0.1
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 +7 -0
- data/.gitignore +22 -0
- data/CHANGELOG.md +17 -0
- data/Gemfile +4 -0
- data/Guardfile +28 -0
- data/LICENSE.txt +22 -0
- data/README.md +108 -0
- data/Rakefile +1 -0
- data/bin/conceptql +5 -0
- data/conceptql.gemspec +30 -0
- data/doc/ConceptQL Specification (alpha).pdf +0 -0
- data/doc/diagram_0.png +0 -0
- data/doc/spec.md +1208 -0
- data/lib/conceptql/behaviors/dottable.rb +71 -0
- data/lib/conceptql/cli.rb +135 -0
- data/lib/conceptql/date_adjuster.rb +45 -0
- data/lib/conceptql/graph.rb +49 -0
- data/lib/conceptql/graph_nodifier.rb +123 -0
- data/lib/conceptql/logger.rb +10 -0
- data/lib/conceptql/nodes/after.rb +12 -0
- data/lib/conceptql/nodes/before.rb +11 -0
- data/lib/conceptql/nodes/binary_operator_node.rb +41 -0
- data/lib/conceptql/nodes/casting_node.rb +75 -0
- data/lib/conceptql/nodes/complement.rb +16 -0
- data/lib/conceptql/nodes/concept.rb +38 -0
- data/lib/conceptql/nodes/condition_type.rb +63 -0
- data/lib/conceptql/nodes/cpt.rb +20 -0
- data/lib/conceptql/nodes/date_range.rb +39 -0
- data/lib/conceptql/nodes/death.rb +19 -0
- data/lib/conceptql/nodes/during.rb +16 -0
- data/lib/conceptql/nodes/except.rb +11 -0
- data/lib/conceptql/nodes/first.rb +24 -0
- data/lib/conceptql/nodes/from.rb +15 -0
- data/lib/conceptql/nodes/gender.rb +27 -0
- data/lib/conceptql/nodes/hcpcs.rb +20 -0
- data/lib/conceptql/nodes/icd10.rb +23 -0
- data/lib/conceptql/nodes/icd9.rb +23 -0
- data/lib/conceptql/nodes/icd9_procedure.rb +20 -0
- data/lib/conceptql/nodes/intersect.rb +29 -0
- data/lib/conceptql/nodes/last.rb +24 -0
- data/lib/conceptql/nodes/loinc.rb +20 -0
- data/lib/conceptql/nodes/node.rb +71 -0
- data/lib/conceptql/nodes/occurrence.rb +47 -0
- data/lib/conceptql/nodes/pass_thru.rb +11 -0
- data/lib/conceptql/nodes/person.rb +25 -0
- data/lib/conceptql/nodes/person_filter.rb +12 -0
- data/lib/conceptql/nodes/place_of_service_code.rb +23 -0
- data/lib/conceptql/nodes/procedure_occurrence.rb +21 -0
- data/lib/conceptql/nodes/race.rb +23 -0
- data/lib/conceptql/nodes/rxnorm.rb +20 -0
- data/lib/conceptql/nodes/snomed.rb +19 -0
- data/lib/conceptql/nodes/source_vocabulary_node.rb +54 -0
- data/lib/conceptql/nodes/standard_vocabulary_node.rb +43 -0
- data/lib/conceptql/nodes/started_by.rb +16 -0
- data/lib/conceptql/nodes/temporal_node.rb +25 -0
- data/lib/conceptql/nodes/time_window.rb +54 -0
- data/lib/conceptql/nodes/union.rb +15 -0
- data/lib/conceptql/nodes/visit.rb +11 -0
- data/lib/conceptql/nodes/visit_occurrence.rb +26 -0
- data/lib/conceptql/nodifier.rb +9 -0
- data/lib/conceptql/query.rb +39 -0
- data/lib/conceptql/tree.rb +36 -0
- data/lib/conceptql/version.rb +3 -0
- data/lib/conceptql/view_maker.rb +56 -0
- data/lib/conceptql.rb +7 -0
- data/spec/conceptql/behaviors/dottable_spec.rb +111 -0
- data/spec/conceptql/date_adjuster_spec.rb +68 -0
- data/spec/conceptql/nodes/after_spec.rb +18 -0
- data/spec/conceptql/nodes/before_spec.rb +18 -0
- data/spec/conceptql/nodes/casting_node_spec.rb +73 -0
- data/spec/conceptql/nodes/complement_spec.rb +15 -0
- data/spec/conceptql/nodes/concept_spec.rb +34 -0
- data/spec/conceptql/nodes/condition_type_spec.rb +113 -0
- data/spec/conceptql/nodes/cpt_spec.rb +31 -0
- data/spec/conceptql/nodes/date_range_spec.rb +35 -0
- data/spec/conceptql/nodes/death_spec.rb +12 -0
- data/spec/conceptql/nodes/during_spec.rb +32 -0
- data/spec/conceptql/nodes/except_spec.rb +18 -0
- data/spec/conceptql/nodes/first_spec.rb +37 -0
- data/spec/conceptql/nodes/from_spec.rb +15 -0
- data/spec/conceptql/nodes/gender_spec.rb +29 -0
- data/spec/conceptql/nodes/hcpcs_spec.rb +31 -0
- data/spec/conceptql/nodes/icd10_spec.rb +36 -0
- data/spec/conceptql/nodes/icd9_procedure_spec.rb +31 -0
- data/spec/conceptql/nodes/icd9_spec.rb +36 -0
- data/spec/conceptql/nodes/intersect_spec.rb +33 -0
- data/spec/conceptql/nodes/last_spec.rb +38 -0
- data/spec/conceptql/nodes/loinc_spec.rb +31 -0
- data/spec/conceptql/nodes/occurrence_spec.rb +89 -0
- data/spec/conceptql/nodes/person_filter_spec.rb +18 -0
- data/spec/conceptql/nodes/person_spec.rb +12 -0
- data/spec/conceptql/nodes/place_of_service_code_spec.rb +26 -0
- data/spec/conceptql/nodes/procedure_occurrence_spec.rb +12 -0
- data/spec/conceptql/nodes/query_double.rb +19 -0
- data/spec/conceptql/nodes/race_spec.rb +23 -0
- data/spec/conceptql/nodes/rxnorm_spec.rb +31 -0
- data/spec/conceptql/nodes/snomed_spec.rb +31 -0
- data/spec/conceptql/nodes/source_vocabulary_node_spec.rb +37 -0
- data/spec/conceptql/nodes/standard_vocabulary_node_spec.rb +40 -0
- data/spec/conceptql/nodes/started_by_spec.rb +25 -0
- data/spec/conceptql/nodes/temporal_node_spec.rb +57 -0
- data/spec/conceptql/nodes/time_window_spec.rb +66 -0
- data/spec/conceptql/nodes/union_spec.rb +25 -0
- data/spec/conceptql/nodes/visit_occurrence_spec.rb +12 -0
- data/spec/conceptql/query_spec.rb +20 -0
- data/spec/conceptql/tree_spec.rb +54 -0
- data/spec/doubles/stream_for_casting_double.rb +9 -0
- data/spec/doubles/stream_for_occurrence_double.rb +21 -0
- data/spec/doubles/stream_for_temporal_double.rb +6 -0
- data/spec/spec_helper.rb +74 -0
- metadata +327 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/concept'
|
3
|
+
|
4
|
+
describe ConceptQL::Nodes::Concept do
|
5
|
+
it 'behaves itself' do
|
6
|
+
ConceptQL::Nodes::Concept.new.must_behave_like(:evaluator)
|
7
|
+
end
|
8
|
+
|
9
|
+
class ConceptDouble < ConceptQL::Nodes::Concept
|
10
|
+
def arguments
|
11
|
+
[1]
|
12
|
+
end
|
13
|
+
|
14
|
+
def set_statement(value)
|
15
|
+
# Do Nothing
|
16
|
+
end
|
17
|
+
|
18
|
+
def stream
|
19
|
+
@stream ||= Minitest::Mock.new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#query' do
|
24
|
+
it 'evaluates child' do
|
25
|
+
cd = ConceptDouble.new(1)
|
26
|
+
cd.stream.expect :evaluate, nil, [:db]
|
27
|
+
cd.query(:db)
|
28
|
+
cd.stream.verify
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/condition_type'
|
3
|
+
|
4
|
+
describe ConceptQL::Nodes::ConditionType do
|
5
|
+
it 'behaves itself' do
|
6
|
+
ConceptQL::Nodes::ConditionType.new.must_behave_like(:evaluator)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#query' do
|
10
|
+
it 'works for inpatient_detail_primary' do
|
11
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000183))"
|
12
|
+
ConceptQL::Nodes::ConditionType.new(:inpatient_detail_primary).query(Sequel.mock).sql.must_equal correct_query
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'works for inpatient_detail_1' do
|
16
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000184))"
|
17
|
+
ConceptQL::Nodes::ConditionType.new(:inpatient_detail_1).query(Sequel.mock).sql.must_equal correct_query
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'works for inpatient_detail_2' do
|
21
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000185))"
|
22
|
+
ConceptQL::Nodes::ConditionType.new(:inpatient_detail_2).query(Sequel.mock).sql.must_equal correct_query
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'works for inpatient_header_primary' do
|
26
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000199))"
|
27
|
+
ConceptQL::Nodes::ConditionType.new(:inpatient_header_primary).query(Sequel.mock).sql.must_equal correct_query
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'works for inpatient_header_1' do
|
31
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000200))"
|
32
|
+
ConceptQL::Nodes::ConditionType.new(:inpatient_header_1).query(Sequel.mock).sql.must_equal correct_query
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'works for outpatient_detail_1' do
|
36
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000215))"
|
37
|
+
ConceptQL::Nodes::ConditionType.new(:outpatient_detail_1).query(Sequel.mock).sql.must_equal correct_query
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'works for outpatient_header_1' do
|
41
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000230))"
|
42
|
+
ConceptQL::Nodes::ConditionType.new(:outpatient_header_1).query(Sequel.mock).sql.must_equal correct_query
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'works for ehr_problem_list' do
|
46
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000245))"
|
47
|
+
ConceptQL::Nodes::ConditionType.new(:ehr_problem_list).query(Sequel.mock).sql.must_equal correct_query
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'works for condition_era_0_day_window' do
|
51
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000246))"
|
52
|
+
ConceptQL::Nodes::ConditionType.new(:condition_era_0_day_window).query(Sequel.mock).sql.must_equal correct_query
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'works for condition_era_30_day_window' do
|
56
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000247))"
|
57
|
+
ConceptQL::Nodes::ConditionType.new(:condition_era_30_day_window).query(Sequel.mock).sql.must_equal correct_query
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'with multiple arguments' do
|
61
|
+
it 'works for inpatient_detail_1' do
|
62
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000184, 38000185))"
|
63
|
+
ConceptQL::Nodes::ConditionType.new(:inpatient_detail_1, :inpatient_detail_2).query(Sequel.mock).sql.must_equal correct_query
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'with arguments as strings' do
|
68
|
+
it 'works for inpatient_detail_1' do
|
69
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000184, 38000185))"
|
70
|
+
ConceptQL::Nodes::ConditionType.new('inpatient_detail_1', 'inpatient_detail_2').query(Sequel.mock).sql.must_equal correct_query
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'as category' do
|
75
|
+
it 'works for inpatient_detail' do
|
76
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000183, 38000184, 38000185, 38000186, 38000187, 38000188, 38000189, 38000190, 38000191, 38000192, 38000193, 38000194, 38000195, 38000196, 38000197, 38000198))"
|
77
|
+
ConceptQL::Nodes::ConditionType.new('inpatient_detail').query(Sequel.mock).sql.must_equal correct_query
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'works for inpatient_header' do
|
81
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000199, 38000200, 38000201, 38000202, 38000203, 38000204, 38000205, 38000206, 38000207, 38000208, 38000209, 38000210, 38000211, 38000212, 38000213, 38000214))"
|
82
|
+
ConceptQL::Nodes::ConditionType.new('inpatient_header').query(Sequel.mock).sql.must_equal correct_query
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'works for inpatient' do
|
86
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000183, 38000184, 38000185, 38000186, 38000187, 38000188, 38000189, 38000190, 38000191, 38000192, 38000193, 38000194, 38000195, 38000196, 38000197, 38000198, 38000199, 38000200, 38000201, 38000202, 38000203, 38000204, 38000205, 38000206, 38000207, 38000208, 38000209, 38000210, 38000211, 38000212, 38000213, 38000214))"
|
87
|
+
ConceptQL::Nodes::ConditionType.new('inpatient').query(Sequel.mock).sql.must_equal correct_query
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'works for outpatient_detail' do
|
91
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000215, 38000216, 38000217, 38000218, 38000219, 38000220, 38000221, 38000222, 38000223, 38000224, 38000225, 38000226, 38000227, 38000228, 38000229))"
|
92
|
+
ConceptQL::Nodes::ConditionType.new('outpatient_detail').query(Sequel.mock).sql.must_equal correct_query
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'works for outpatient_header' do
|
96
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000230, 38000231, 38000232, 38000233, 38000234, 38000235, 38000236, 38000237, 38000238, 38000239, 38000240, 38000241, 38000242, 38000243, 38000244))"
|
97
|
+
ConceptQL::Nodes::ConditionType.new('outpatient_header').query(Sequel.mock).sql.must_equal correct_query
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'works for outpatient' do
|
101
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000215, 38000216, 38000217, 38000218, 38000219, 38000220, 38000221, 38000222, 38000223, 38000224, 38000225, 38000226, 38000227, 38000228, 38000229, 38000230, 38000231, 38000232, 38000233, 38000234, 38000235, 38000236, 38000237, 38000238, 38000239, 38000240, 38000241, 38000242, 38000243, 38000244))"
|
102
|
+
ConceptQL::Nodes::ConditionType.new('outpatient').query(Sequel.mock).sql.must_equal correct_query
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'works for condition_era' do
|
106
|
+
correct_query = "SELECT * FROM condition_occurrence_with_dates WHERE (condition_type_concept_id IN (38000246, 38000247))"
|
107
|
+
ConceptQL::Nodes::ConditionType.new('condition_era').query(Sequel.mock).sql.must_equal correct_query
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/cpt'
|
3
|
+
|
4
|
+
describe ConceptQL::Nodes::Cpt do
|
5
|
+
it 'behaves itself' do
|
6
|
+
ConceptQL::Nodes::Cpt.new.must_behave_like(:standard_vocabulary_node)
|
7
|
+
end
|
8
|
+
|
9
|
+
subject do
|
10
|
+
ConceptQL::Nodes::Cpt.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#table' do
|
14
|
+
it 'should be procedure_occurrence' do
|
15
|
+
subject.table.must_equal :procedure_occurrence
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#concept_column' do
|
20
|
+
it 'should be procedure_concept_id' do
|
21
|
+
subject.concept_column.must_equal :procedure_concept_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#vocabulary_id' do
|
26
|
+
it 'should be 4' do
|
27
|
+
subject.vocabulary_id.must_equal 4
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/date_range'
|
3
|
+
|
4
|
+
describe ConceptQL::Nodes::DateRange do
|
5
|
+
it 'behaves itself' do
|
6
|
+
ConceptQL::Nodes::DateRange.new.must_behave_like(:evaluator)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#types' do
|
10
|
+
it 'should be [:date]' do
|
11
|
+
ConceptQL::Nodes::DateRange.new(start: '2004-12-13', end: '2010-03-20').types.must_equal([:person])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#query' do
|
16
|
+
it 'should be dates specified assigned to all persons' do
|
17
|
+
ConceptQL::Nodes::DateRange.new(start: '2004-12-13', end: '2010-03-20').query(Sequel.mock).sql.must_equal("SELECT * FROM (SELECT *, CAST('2004-12-13' AS date) AS start_date, CAST('2010-03-20' AS date) AS end_date FROM person) AS t1")
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should handle strings for option keys' do
|
21
|
+
ConceptQL::Nodes::DateRange.new('start' => '2004-12-13', 'end' => '2010-03-20').query(Sequel.mock).sql.must_equal("SELECT * FROM (SELECT *, CAST('2004-12-13' AS date) AS start_date, CAST('2010-03-20' AS date) AS end_date FROM person) AS t1")
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'handles START as day before first recorded visit_occurrence' do
|
25
|
+
ConceptQL::Nodes::DateRange.new(start: 'START', end: '2010-03-20').query(Sequel.mock).sql.must_equal("SELECT * FROM (SELECT *, CAST((SELECT min(start_date) FROM visit_occurrence_with_dates) AS date) AS start_date, CAST('2010-03-20' AS date) AS end_date FROM person) AS t1")
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'handles END as 2010-12-31' do
|
29
|
+
ConceptQL::Nodes::DateRange.new(start: '2004-12-13', end: 'END').query(Sequel.mock).sql.must_equal("SELECT * FROM (SELECT *, CAST('2004-12-13' AS date) AS start_date, CAST((SELECT max(end_date) FROM visit_occurrence_with_dates) AS date) AS end_date FROM person) AS t1")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/during'
|
3
|
+
require_double('stream_for_temporal')
|
4
|
+
|
5
|
+
describe ConceptQL::Nodes::During do
|
6
|
+
it 'behaves itself' do
|
7
|
+
ConceptQL::Nodes::During.new.must_behave_like(:temporal_node)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'when not inclusive' do
|
11
|
+
subject do
|
12
|
+
ConceptQL::Nodes::During.new(left: StreamForTemporalDouble.new, right: StreamForTemporalDouble.new)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should use proper where clause' do
|
16
|
+
subject.query(Sequel.mock).sql.must_match 'l.end_date <= r.end_date'
|
17
|
+
subject.query(Sequel.mock).sql.must_match 'r.start_date <= l.start_date'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'when inclusive' do
|
22
|
+
subject do
|
23
|
+
ConceptQL::Nodes::During.new(left: StreamForTemporalDouble.new, right: StreamForTemporalDouble.new, inclusive: true)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should use proper where clause' do
|
27
|
+
subject.query(Sequel.mock).sql.must_match '(r.start_date <= l.end_date) AND (l.end_date <= r.end_date)'
|
28
|
+
subject.query(Sequel.mock).sql.must_match '(r.start_date <= l.start_date) AND (l.start_date <= r.end_date)'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/except'
|
3
|
+
require_relative 'query_double'
|
4
|
+
|
5
|
+
describe ConceptQL::Nodes::Except do
|
6
|
+
it 'behaves itself' do
|
7
|
+
ConceptQL::Nodes::Except.new.must_behave_like(:evaluator)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#query' do
|
11
|
+
it 'uses right stream as argument to EXCEPT against left stream' do
|
12
|
+
double1 = QueryDouble.new(1)
|
13
|
+
double2 = QueryDouble.new(2)
|
14
|
+
double1.must_behave_like(:evaluator)
|
15
|
+
ConceptQL::Nodes::Except.new(left: double1, right: double2).query(Sequel.mock).sql.must_equal "SELECT * FROM (SELECT * FROM table1 EXCEPT SELECT * FROM table2) AS t1"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/first'
|
3
|
+
require_double('stream_for_occurrence')
|
4
|
+
|
5
|
+
describe ConceptQL::Nodes::First do
|
6
|
+
it 'behaves itself' do
|
7
|
+
ConceptQL::Nodes::First.new.must_behave_like(:evaluator)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should have occurrence pegged at 1' do
|
11
|
+
ConceptQL::Nodes::First.new.occurrence.must_equal(1)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'occurrence set to 1' do
|
15
|
+
subject do
|
16
|
+
ConceptQL::Nodes::First.new(StreamForOccurrenceDouble.new).query(Sequel.mock).sql
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should order by ascending start_date' do
|
20
|
+
subject.must_match 'ORDER BY start_date ASC'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should partition by person_id' do
|
24
|
+
subject.must_match 'PARTITION BY person_id'
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should assign a row number' do
|
28
|
+
subject.must_match 'row_number()'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should find the all rows with rn = 1' do
|
32
|
+
subject.must_match 'rn = 1'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/from'
|
3
|
+
require_relative 'query_double'
|
4
|
+
|
5
|
+
describe ConceptQL::Nodes::From do
|
6
|
+
it 'behaves itself' do
|
7
|
+
ConceptQL::Nodes::From.new.must_behave_like(:evaluator)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#query' do
|
11
|
+
it 'works for single criteria' do
|
12
|
+
ConceptQL::Nodes::From.new(:table1).query(Sequel.mock).sql.must_equal "SELECT * FROM table1"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/gender'
|
3
|
+
|
4
|
+
describe ConceptQL::Nodes::Gender do
|
5
|
+
it 'behaves itself' do
|
6
|
+
ConceptQL::Nodes::Gender.new.must_behave_like(:evaluator)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#query' do
|
10
|
+
it 'works for male/MALE/Male/M/m' do
|
11
|
+
correct_query = "SELECT * FROM person_with_dates WHERE (gender_concept_id IN (8507))"
|
12
|
+
ConceptQL::Nodes::Gender.new('male').query(Sequel.mock).sql.must_equal correct_query
|
13
|
+
ConceptQL::Nodes::Gender.new('Male').query(Sequel.mock).sql.must_equal correct_query
|
14
|
+
ConceptQL::Nodes::Gender.new('MALE').query(Sequel.mock).sql.must_equal correct_query
|
15
|
+
ConceptQL::Nodes::Gender.new('M').query(Sequel.mock).sql.must_equal correct_query
|
16
|
+
ConceptQL::Nodes::Gender.new('m').query(Sequel.mock).sql.must_equal correct_query
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'works for Female/FEMALE/female/F/f' do
|
20
|
+
correct_query = "SELECT * FROM person_with_dates WHERE (gender_concept_id IN (8532))"
|
21
|
+
ConceptQL::Nodes::Gender.new('female').query(Sequel.mock).sql.must_equal correct_query
|
22
|
+
ConceptQL::Nodes::Gender.new('Female').query(Sequel.mock).sql.must_equal correct_query
|
23
|
+
ConceptQL::Nodes::Gender.new('FEMALE').query(Sequel.mock).sql.must_equal correct_query
|
24
|
+
ConceptQL::Nodes::Gender.new('F').query(Sequel.mock).sql.must_equal correct_query
|
25
|
+
ConceptQL::Nodes::Gender.new('f').query(Sequel.mock).sql.must_equal correct_query
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/hcpcs'
|
3
|
+
|
4
|
+
describe ConceptQL::Nodes::Hcpcs do
|
5
|
+
it 'behaves itself' do
|
6
|
+
ConceptQL::Nodes::Hcpcs.new.must_behave_like(:standard_vocabulary_node)
|
7
|
+
end
|
8
|
+
|
9
|
+
subject do
|
10
|
+
ConceptQL::Nodes::Hcpcs.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#table' do
|
14
|
+
it 'should be procedure_occurrence' do
|
15
|
+
subject.table.must_equal :procedure_occurrence
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#concept_column' do
|
20
|
+
it 'should be procedure_concept_id' do
|
21
|
+
subject.concept_column.must_equal :procedure_concept_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#vocabulary_id' do
|
26
|
+
it 'should be 5' do
|
27
|
+
subject.vocabulary_id.must_equal 5
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/icd10'
|
3
|
+
|
4
|
+
describe ConceptQL::Nodes::Icd10 do
|
5
|
+
it 'behaves itself' do
|
6
|
+
ConceptQL::Nodes::Icd10.new.must_behave_like(:source_vocabulary_node)
|
7
|
+
end
|
8
|
+
|
9
|
+
subject do
|
10
|
+
ConceptQL::Nodes::Icd10.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#table' do
|
14
|
+
it 'should be condition_occurrence' do
|
15
|
+
subject.table.must_equal :condition_occurrence
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#concept_column' do
|
20
|
+
it 'should be condition_concept_id' do
|
21
|
+
subject.concept_column.must_equal :condition_concept_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#source_column' do
|
26
|
+
it 'should be condition_source_valuej' do
|
27
|
+
subject.source_column.must_equal :condition_source_value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#vocabulary_id' do
|
32
|
+
it 'should be 34' do
|
33
|
+
subject.vocabulary_id.must_equal 34
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/icd9_procedure'
|
3
|
+
|
4
|
+
describe ConceptQL::Nodes::Icd9Procedure do
|
5
|
+
it 'behaves itself' do
|
6
|
+
ConceptQL::Nodes::Icd9Procedure.new.must_behave_like(:standard_vocabulary_node)
|
7
|
+
end
|
8
|
+
|
9
|
+
subject do
|
10
|
+
ConceptQL::Nodes::Icd9Procedure.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#table' do
|
14
|
+
it 'should be procedure_occurrence' do
|
15
|
+
subject.table.must_equal :procedure_occurrence
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#concept_column' do
|
20
|
+
it 'should be procedure_concept_id' do
|
21
|
+
subject.concept_column.must_equal :procedure_concept_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#vocabulary_id' do
|
26
|
+
it 'should be 3' do
|
27
|
+
subject.vocabulary_id.must_equal 3
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/icd9'
|
3
|
+
|
4
|
+
describe ConceptQL::Nodes::Icd9 do
|
5
|
+
it 'behaves itself' do
|
6
|
+
ConceptQL::Nodes::Icd9.new.must_behave_like(:source_vocabulary_node)
|
7
|
+
end
|
8
|
+
|
9
|
+
subject do
|
10
|
+
ConceptQL::Nodes::Icd9.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#table' do
|
14
|
+
it 'should be condition_occurrence' do
|
15
|
+
subject.table.must_equal :condition_occurrence
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#concept_column' do
|
20
|
+
it 'should be condition_concept_id' do
|
21
|
+
subject.concept_column.must_equal :condition_concept_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#source_column' do
|
26
|
+
it 'should be condition_source_valuej' do
|
27
|
+
subject.source_column.must_equal :condition_source_value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#vocabulary_id' do
|
32
|
+
it 'should be 2' do
|
33
|
+
subject.vocabulary_id.must_equal 2
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/intersect'
|
3
|
+
require_relative 'query_double'
|
4
|
+
|
5
|
+
describe ConceptQL::Nodes::Intersect do
|
6
|
+
it 'behaves itself' do
|
7
|
+
ConceptQL::Nodes::Intersect.new.must_behave_like(:evaluator)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#query' do
|
11
|
+
it 'works for multiple criteria of same type' do
|
12
|
+
double1 = QueryDouble.new(1)
|
13
|
+
double2 = QueryDouble.new(2)
|
14
|
+
double3 = QueryDouble.new(3)
|
15
|
+
double1.must_behave_like(:evaluator)
|
16
|
+
ConceptQL::Nodes::Intersect.new(double1, double2, double3).query(Sequel.mock).sql.must_equal "SELECT * FROM (SELECT * FROM (SELECT * FROM table1 INTERSECT ALL SELECT * FROM table2) AS t1 INTERSECT ALL SELECT * FROM table3) AS t1"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'works for multiple criteria of different type' do
|
20
|
+
double1 = QueryDouble.new(1)
|
21
|
+
double2 = QueryDouble.new(2, :person)
|
22
|
+
double3 = QueryDouble.new(3)
|
23
|
+
double1.must_behave_like(:evaluator)
|
24
|
+
ConceptQL::Nodes::Intersect.new(double1, double2, double3).query(Sequel.mock).sql.must_equal "SELECT * FROM (SELECT * FROM (SELECT * FROM table1 INTERSECT ALL SELECT * FROM table3) AS t1 UNION ALL SELECT * FROM table2) AS t1"
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'works for single criteria' do
|
28
|
+
double1 = QueryDouble.new(1)
|
29
|
+
double1.must_behave_like(:evaluator)
|
30
|
+
ConceptQL::Nodes::Intersect.new(double1).query(Sequel.mock).sql.must_equal "SELECT * FROM table1"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/last'
|
3
|
+
require_double('stream_for_occurrence')
|
4
|
+
|
5
|
+
describe ConceptQL::Nodes::Last do
|
6
|
+
it 'behaves itself' do
|
7
|
+
ConceptQL::Nodes::Last.new.must_behave_like(:evaluator)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should have occurrence pegged at -1' do
|
11
|
+
ConceptQL::Nodes::Last.new.occurrence.must_equal(-1)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'occurrence set to -1' do
|
15
|
+
subject do
|
16
|
+
ConceptQL::Nodes::Last.new(StreamForOccurrenceDouble.new).query(Sequel.mock).sql
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
it 'should order by descending start_date' do
|
21
|
+
subject.must_match 'ORDER BY start_date DESC'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should partition by person_id' do
|
25
|
+
subject.must_match 'PARTITION BY person_id'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should assign a row number' do
|
29
|
+
subject.must_match 'row_number()'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should find the all rows with rn = 1' do
|
33
|
+
subject.must_match 'rn = 1'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'conceptql/nodes/loinc'
|
3
|
+
|
4
|
+
describe ConceptQL::Nodes::Loinc do
|
5
|
+
it 'behaves itself' do
|
6
|
+
ConceptQL::Nodes::Loinc.new.must_behave_like(:standard_vocabulary_node)
|
7
|
+
end
|
8
|
+
|
9
|
+
subject do
|
10
|
+
ConceptQL::Nodes::Loinc.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#table' do
|
14
|
+
it 'should be observation' do
|
15
|
+
subject.table.must_equal :observation
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#concept_column' do
|
20
|
+
it 'should be procedure_concept_id' do
|
21
|
+
subject.concept_column.must_equal :observation_concept_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#vocabulary_id' do
|
26
|
+
it 'should be 6' do
|
27
|
+
subject.vocabulary_id.must_equal 6
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|