conceptql 0.2.0 → 0.4.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.
Files changed (242) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +226 -117
  3. data/LICENSE +21 -0
  4. data/README.md +35 -83
  5. data/bin/conceptql +2 -1
  6. data/bin/conceptql_utils +6 -0
  7. data/config/multiple_vocabularies.csv +4 -0
  8. data/config/provenance.yml +489 -0
  9. data/config/race.yml +50 -0
  10. data/config/vocabularies.csv +87 -0
  11. data/lib/conceptql/behaviors/code_lister.rb +23 -0
  12. data/lib/conceptql/behaviors/drugish.rb +17 -0
  13. data/lib/conceptql/behaviors/labish.rb +19 -0
  14. data/lib/conceptql/behaviors/metadatable.rb +226 -73
  15. data/lib/conceptql/behaviors/provenanceable.rb +26 -0
  16. data/lib/conceptql/behaviors/single_event.rb +11 -0
  17. data/lib/conceptql/behaviors/timeless.rb +11 -0
  18. data/lib/conceptql/behaviors/utilizable.rb +206 -0
  19. data/lib/conceptql/behaviors/windowable.rb +27 -0
  20. data/lib/conceptql/cli.rb +117 -108
  21. data/lib/conceptql/columnizer.rb +75 -0
  22. data/lib/conceptql/data_model/base.rb +462 -0
  23. data/lib/conceptql/data_model/gdm.rb +155 -0
  24. data/lib/conceptql/data_model/gdm_wide.rb +42 -0
  25. data/lib/conceptql/data_model/omopv4_plus.rb +12 -0
  26. data/lib/conceptql/data_model.rb +30 -0
  27. data/lib/conceptql/database.rb +214 -0
  28. data/lib/conceptql/date_adjuster.rb +66 -18
  29. data/lib/conceptql/diagram.rb +243 -0
  30. data/lib/conceptql/lexicon/lexicon_gdm.rb +47 -0
  31. data/lib/conceptql/lexicon/lexicon_no_db.rb +49 -0
  32. data/lib/conceptql/lexicon/lexicon_ohdsi.rb +63 -0
  33. data/lib/conceptql/lexicon/lexicon_strategy.rb +116 -0
  34. data/lib/conceptql/lexicon.rb +111 -0
  35. data/lib/conceptql/nodifier.rb +65 -24
  36. data/lib/conceptql/operators/after.rb +34 -14
  37. data/lib/conceptql/operators/any_overlap.rb +8 -6
  38. data/lib/conceptql/operators/before.rb +34 -10
  39. data/lib/conceptql/operators/binary_operator_operator.rb +66 -23
  40. data/lib/conceptql/operators/casting_operator.rb +51 -36
  41. data/lib/conceptql/operators/co_reported.rb +111 -0
  42. data/lib/conceptql/operators/concurrent_within.rb +69 -0
  43. data/lib/conceptql/operators/contains.rb +12 -8
  44. data/lib/conceptql/operators/count.rb +17 -9
  45. data/lib/conceptql/operators/date_range.rb +48 -14
  46. data/lib/conceptql/operators/death.rb +14 -4
  47. data/lib/conceptql/operators/dedup.rb +31 -0
  48. data/lib/conceptql/operators/during.rb +7 -12
  49. data/lib/conceptql/operators/episode.rb +146 -0
  50. data/lib/conceptql/operators/equal.rb +9 -3
  51. data/lib/conceptql/operators/ethnicity.rb +49 -0
  52. data/lib/conceptql/operators/except.rb +19 -12
  53. data/lib/conceptql/operators/filter.rb +23 -8
  54. data/lib/conceptql/operators/first.rb +16 -3
  55. data/lib/conceptql/operators/from.rb +52 -4
  56. data/lib/conceptql/operators/gender.rb +34 -11
  57. data/lib/conceptql/operators/hospice.rb +19 -0
  58. data/lib/conceptql/operators/hospitalization.rb +19 -0
  59. data/lib/conceptql/operators/information_periods.rb +36 -0
  60. data/lib/conceptql/operators/invalid.rb +35 -0
  61. data/lib/conceptql/operators/last.rb +16 -3
  62. data/lib/conceptql/operators/match.rb +91 -0
  63. data/lib/conceptql/operators/multiple_vocabularies.rb +172 -0
  64. data/lib/conceptql/operators/numeric.rb +65 -23
  65. data/lib/conceptql/operators/numeric_filter.rb +68 -0
  66. data/lib/conceptql/operators/occurrence.rb +153 -32
  67. data/lib/conceptql/operators/one_in_two_out.rb +237 -38
  68. data/lib/conceptql/operators/operator.rb +624 -178
  69. data/lib/conceptql/operators/pass_thru.rb +17 -3
  70. data/lib/conceptql/operators/person.rb +18 -6
  71. data/lib/conceptql/operators/person_filter.rb +9 -3
  72. data/lib/conceptql/operators/place_of_service_filter.rb +43 -0
  73. data/lib/conceptql/operators/provenance.rb +55 -0
  74. data/lib/conceptql/operators/provider_filter.rb +62 -0
  75. data/lib/conceptql/operators/race.rb +55 -7
  76. data/lib/conceptql/operators/read.rb +168 -0
  77. data/lib/conceptql/operators/recall.rb +49 -14
  78. data/lib/conceptql/operators/snf.rb +19 -0
  79. data/lib/conceptql/operators/sum.rb +29 -12
  80. data/lib/conceptql/operators/temporal_operator.rb +108 -16
  81. data/lib/conceptql/operators/time_window.rb +20 -32
  82. data/lib/conceptql/operators/trim_date.rb +71 -0
  83. data/lib/conceptql/operators/trim_date_end.rb +28 -40
  84. data/lib/conceptql/operators/trim_date_start.rb +28 -41
  85. data/lib/conceptql/operators/union.rb +67 -6
  86. data/lib/conceptql/operators/vocabulary.rb +151 -0
  87. data/lib/conceptql/paths.rb +41 -0
  88. data/lib/conceptql/query.rb +191 -26
  89. data/lib/conceptql/query_modifiers/gdm/admission_date_query_modifier.rb +46 -0
  90. data/lib/conceptql/query_modifiers/gdm/drug_query_modifier.rb +54 -0
  91. data/lib/conceptql/query_modifiers/gdm/lab_query_modifier.rb +57 -0
  92. data/lib/conceptql/query_modifiers/gdm/pos_query_modifier.rb +46 -0
  93. data/lib/conceptql/query_modifiers/gdm/provenance_query_modifier.rb +45 -0
  94. data/lib/conceptql/query_modifiers/gdm/provider_query_modifier.rb +53 -0
  95. data/lib/conceptql/query_modifiers/gdm_wide/admission_date_query_modifier.rb +42 -0
  96. data/lib/conceptql/query_modifiers/gdm_wide/drug_query_modifier.rb +52 -0
  97. data/lib/conceptql/query_modifiers/gdm_wide/lab_query_modifier.rb +55 -0
  98. data/lib/conceptql/query_modifiers/gdm_wide/pos_query_modifier.rb +37 -0
  99. data/lib/conceptql/query_modifiers/gdm_wide/provenance_query_modifier.rb +38 -0
  100. data/lib/conceptql/query_modifiers/omopv4_plus/admission_date_query_modifier.rb +45 -0
  101. data/lib/conceptql/query_modifiers/omopv4_plus/drug_query_modifier.rb +80 -0
  102. data/lib/conceptql/query_modifiers/omopv4_plus/pos_query_modifier.rb +47 -0
  103. data/lib/conceptql/query_modifiers/omopv4_plus/provenance_query_modifier.rb +45 -0
  104. data/lib/conceptql/query_modifiers/omopv4_plus/provider_query_modifier.rb +26 -0
  105. data/lib/conceptql/query_modifiers/query_modifier.rb +20 -0
  106. data/lib/conceptql/rdbms/duckdb.rb +25 -0
  107. data/lib/conceptql/rdbms/generic.rb +120 -0
  108. data/lib/conceptql/rdbms/postgres.rb +51 -0
  109. data/lib/conceptql/rdbms/spark.rb +22 -0
  110. data/lib/conceptql/rdbms.rb +22 -0
  111. data/lib/conceptql/scope.rb +481 -31
  112. data/lib/conceptql/sql_formatters/formatter.rb +25 -0
  113. data/lib/conceptql/sql_formatters.rb +22 -0
  114. data/lib/conceptql/utils.rb +113 -0
  115. data/lib/conceptql/utils_cli.rb +17 -0
  116. data/lib/conceptql/version.rb +3 -1
  117. data/lib/conceptql/visitors/metadata_extractor.rb +54 -0
  118. data/lib/conceptql/vocabularies/behaviors/costish.rb +24 -0
  119. data/lib/conceptql/vocabularies/behaviors/gdmish.rb +19 -0
  120. data/lib/conceptql/vocabularies/behaviors/omopish.rb +32 -0
  121. data/lib/conceptql/vocabularies/dynamic_vocabularies.rb +63 -0
  122. data/lib/conceptql/vocabularies/entry.rb +138 -0
  123. data/lib/conceptql/vocabularies/vocabulary_class_factory.rb +85 -0
  124. data/lib/conceptql/window/base.rb +26 -0
  125. data/lib/conceptql/window/date_range.rb +25 -0
  126. data/lib/conceptql/window/table.rb +116 -0
  127. data/lib/conceptql/window.rb +72 -0
  128. data/lib/conceptql.rb +65 -2
  129. data/lib/sequel/extensions/pg_ctas_explain.rb +22 -0
  130. data/lib/sequel/extensions/pg_vacuum_table.rb +23 -0
  131. data/schemas/gdm.yml +882 -0
  132. data/schemas/gdm_wide.yml +757 -0
  133. data/schemas/ohdsi_vocabs.yml +143 -0
  134. data/schemas/omopv4_plus.yml +729 -0
  135. data/schemas/omopv4_plus_more_ignorables.tsv +13 -0
  136. metadata +267 -207
  137. data/.gitignore +0 -23
  138. data/Gemfile +0 -4
  139. data/Guardfile +0 -56
  140. data/LICENSE.txt +0 -22
  141. data/Rakefile +0 -1
  142. data/conceptql.gemspec +0 -32
  143. data/doc/ConceptQL Specification (alpha).pdf +0 -0
  144. data/doc/diagram_0.png +0 -0
  145. data/doc/implementation_notes.md +0 -39
  146. data/doc/spec.md +0 -1344
  147. data/lib/conceptql/behaviors/debuggable.rb +0 -70
  148. data/lib/conceptql/behaviors/dottable.rb +0 -103
  149. data/lib/conceptql/behaviors/preppable.rb +0 -20
  150. data/lib/conceptql/converter.rb +0 -65
  151. data/lib/conceptql/debugger.rb +0 -48
  152. data/lib/conceptql/fake_grapher.rb +0 -20
  153. data/lib/conceptql/graph.rb +0 -52
  154. data/lib/conceptql/graph_nodifier.rb +0 -203
  155. data/lib/conceptql/logger.rb +0 -10
  156. data/lib/conceptql/operators/complement.rb +0 -38
  157. data/lib/conceptql/operators/concept.rb +0 -70
  158. data/lib/conceptql/operators/condition_type.rb +0 -71
  159. data/lib/conceptql/operators/cpt.rb +0 -25
  160. data/lib/conceptql/operators/drug_type_concept.rb +0 -21
  161. data/lib/conceptql/operators/from_seer_visits.rb +0 -23
  162. data/lib/conceptql/operators/hcpcs.rb +0 -25
  163. data/lib/conceptql/operators/icd10.rb +0 -28
  164. data/lib/conceptql/operators/icd9.rb +0 -28
  165. data/lib/conceptql/operators/icd9_procedure.rb +0 -25
  166. data/lib/conceptql/operators/intersect.rb +0 -34
  167. data/lib/conceptql/operators/loinc.rb +0 -25
  168. data/lib/conceptql/operators/medcode.rb +0 -28
  169. data/lib/conceptql/operators/medcode_procedure.rb +0 -27
  170. data/lib/conceptql/operators/ndc.rb +0 -29
  171. data/lib/conceptql/operators/observation_by_enttype.rb +0 -29
  172. data/lib/conceptql/operators/observation_period.rb +0 -30
  173. data/lib/conceptql/operators/overlapped_by.rb +0 -23
  174. data/lib/conceptql/operators/overlaps.rb +0 -19
  175. data/lib/conceptql/operators/place_of_service_code.rb +0 -24
  176. data/lib/conceptql/operators/procedure_occurrence.rb +0 -25
  177. data/lib/conceptql/operators/prodcode.rb +0 -29
  178. data/lib/conceptql/operators/rxnorm.rb +0 -24
  179. data/lib/conceptql/operators/snomed.rb +0 -24
  180. data/lib/conceptql/operators/snomed_condition.rb +0 -26
  181. data/lib/conceptql/operators/source_vocabulary_operator.rb +0 -58
  182. data/lib/conceptql/operators/standard_vocabulary_operator.rb +0 -45
  183. data/lib/conceptql/operators/started_by.rb +0 -22
  184. data/lib/conceptql/operators/to_seer_visits.rb +0 -24
  185. data/lib/conceptql/operators/visit.rb +0 -15
  186. data/lib/conceptql/operators/visit_occurrence.rb +0 -30
  187. data/lib/conceptql/tree.rb +0 -53
  188. data/lib/conceptql/utils/temp_table.rb +0 -72
  189. data/spec/conceptql/behaviors/dottable_spec.rb +0 -99
  190. data/spec/conceptql/converter_spec.rb +0 -51
  191. data/spec/conceptql/date_adjuster_spec.rb +0 -68
  192. data/spec/conceptql/operators/after_spec.rb +0 -16
  193. data/spec/conceptql/operators/before_spec.rb +0 -16
  194. data/spec/conceptql/operators/casting_operator_spec.rb +0 -68
  195. data/spec/conceptql/operators/complement_spec.rb +0 -15
  196. data/spec/conceptql/operators/concept_spec.rb +0 -40
  197. data/spec/conceptql/operators/condition_type_spec.rb +0 -128
  198. data/spec/conceptql/operators/contains_spec.rb +0 -19
  199. data/spec/conceptql/operators/cpt_spec.rb +0 -29
  200. data/spec/conceptql/operators/date_range_spec.rb +0 -33
  201. data/spec/conceptql/operators/death_spec.rb +0 -10
  202. data/spec/conceptql/operators/during_spec.rb +0 -30
  203. data/spec/conceptql/operators/except_spec.rb +0 -15
  204. data/spec/conceptql/operators/first_spec.rb +0 -35
  205. data/spec/conceptql/operators/from_spec.rb +0 -13
  206. data/spec/conceptql/operators/gender_spec.rb +0 -27
  207. data/spec/conceptql/operators/hcpcs_spec.rb +0 -29
  208. data/spec/conceptql/operators/icd10_spec.rb +0 -34
  209. data/spec/conceptql/operators/icd9_procedure_spec.rb +0 -29
  210. data/spec/conceptql/operators/icd9_spec.rb +0 -34
  211. data/spec/conceptql/operators/intersect_spec.rb +0 -28
  212. data/spec/conceptql/operators/last_spec.rb +0 -36
  213. data/spec/conceptql/operators/loinc_spec.rb +0 -29
  214. data/spec/conceptql/operators/medcode_procedure_spec.rb +0 -34
  215. data/spec/conceptql/operators/medcode_spec.rb +0 -34
  216. data/spec/conceptql/operators/observation_period_spec.rb +0 -10
  217. data/spec/conceptql/operators/occurrence_spec.rb +0 -87
  218. data/spec/conceptql/operators/overlapped_by_spec.rb +0 -32
  219. data/spec/conceptql/operators/overlaps_spec.rb +0 -21
  220. data/spec/conceptql/operators/person_filter_spec.rb +0 -15
  221. data/spec/conceptql/operators/person_spec.rb +0 -10
  222. data/spec/conceptql/operators/place_of_service_code_spec.rb +0 -24
  223. data/spec/conceptql/operators/procedure_occurrence_spec.rb +0 -10
  224. data/spec/conceptql/operators/prodcode_spec.rb +0 -35
  225. data/spec/conceptql/operators/query_double.rb +0 -20
  226. data/spec/conceptql/operators/query_double_spec.rb +0 -7
  227. data/spec/conceptql/operators/race_spec.rb +0 -21
  228. data/spec/conceptql/operators/rxnorm_spec.rb +0 -29
  229. data/spec/conceptql/operators/snomed_spec.rb +0 -29
  230. data/spec/conceptql/operators/source_vocabulary_operator_spec.rb +0 -35
  231. data/spec/conceptql/operators/standard_vocabulary_operator_spec.rb +0 -35
  232. data/spec/conceptql/operators/started_by_spec.rb +0 -22
  233. data/spec/conceptql/operators/temporal_operator_spec.rb +0 -51
  234. data/spec/conceptql/operators/time_window_spec.rb +0 -77
  235. data/spec/conceptql/operators/union_spec.rb +0 -21
  236. data/spec/conceptql/operators/visit_occurrence_spec.rb +0 -10
  237. data/spec/conceptql/query_spec.rb +0 -22
  238. data/spec/conceptql/tree_spec.rb +0 -50
  239. data/spec/doubles/stream_for_casting_double.rb +0 -9
  240. data/spec/doubles/stream_for_occurrence_double.rb +0 -25
  241. data/spec/doubles/stream_for_temporal_double.rb +0 -6
  242. data/spec/spec_helper.rb +0 -102
data/lib/conceptql/cli.rb CHANGED
@@ -1,156 +1,165 @@
1
- require 'thor'
2
- require 'sequelizer'
3
- require 'psych'
4
- require 'json'
5
- require 'pp'
6
- require_relative 'query'
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH << "lib"
4
+
5
+ require "thor"
6
+ require "sequelizer"
7
+ require "json"
8
+ require "csv"
9
+ require "logger"
10
+ require "conceptql"
11
+ require_relative "query"
7
12
 
8
13
  module ConceptQL
9
14
  class CLI < Thor
10
15
  include Sequelizer
11
16
 
12
17
  class_option :adapter,
13
- aliases: :a,
14
- desc: 'adapter for database'
18
+ aliases: :a,
19
+ desc: "adapter for database"
15
20
  class_option :host,
16
- aliases: :h,
17
- banner: 'localhost',
18
- desc: 'host for database'
21
+ aliases: :h,
22
+ banner: "localhost",
23
+ desc: "host for database"
19
24
  class_option :username,
20
- aliases: :u,
21
- desc: 'username for database'
25
+ aliases: :u,
26
+ desc: "username for database"
22
27
  class_option :password,
23
- aliases: :P,
24
- desc: 'password for database'
28
+ aliases: :P,
29
+ desc: "password for database"
25
30
  class_option :port,
26
- aliases: :p,
27
- type: :numeric,
28
- banner: '5432',
29
- desc: 'port for database'
31
+ aliases: :p,
32
+ type: :numeric,
33
+ banner: "5432",
34
+ desc: "port for database"
30
35
  class_option :database,
31
- aliases: :d,
32
- desc: 'database for database'
36
+ aliases: :d,
37
+ desc: "database for database"
33
38
  class_option :search_path,
34
- aliases: :s,
35
- desc: 'schema for database (PostgreSQL only)'
39
+ aliases: :s,
40
+ desc: "schema for database (PostgreSQL only)"
36
41
 
37
- desc 'run_statement statement_file', 'Reads the ConceptQL statement from the statement file and executes it against the DB'
42
+ desc "run_statement statement_file",
43
+ "Reads the ConceptQL statement from the statement file and executes it against the DB"
38
44
  def run_statement(statement_file)
39
- q = ConceptQL::Query.new(db(options), criteria_from_file(statement_file))
45
+ q = cdb(options).query(criteria_from_file(statement_file))
40
46
  puts q.sql
41
- puts q.statement.to_yaml
42
- pp q.all
47
+ puts JSON.pretty_generate(q.statement)
48
+ pp q.query.all
43
49
  end
44
50
 
45
- desc 'show_graph statement_file', 'Reads the ConceptQL statement from the file and shows the contents as a ConceptQL graph'
46
- option :watch_file
47
- def show_graph(file)
48
- graph_it(criteria_from_file(file))
51
+ desc "analyze statement_file",
52
+ "Reads the ConceptQL statement from the statement file and executes EXPLAIN ANALYZE against the DB"
53
+ def analyze(statement_file)
54
+ q = cdb(options).query(criteria_from_file(statement_file))
55
+ puts JSON.pretty_generate(q.statement)
56
+ puts q.sql(:formatted, :create_tables)
57
+ q.db.logger = db.loggers + [ Logger.new($stdout).tap { |l| l.level = Logger::INFO } ]
58
+ puts q.analyze
49
59
  end
50
60
 
51
- desc 'show_and_tell_file statement_file', 'Reads the ConceptQL statement from the file and shows the contents as a ConceptQL graph, then executes the statement against the DB'
52
- option :full
53
- option :watch_file
54
- def show_and_tell_file(file)
55
- show_and_tell(criteria_from_file(file), options)
61
+ desc "sql statement_file", "Reads the ConceptQL statement from the statement file and prints the SQL out"
62
+ def sql(statement_file)
63
+ q = cdb(options).query(criteria_from_file(statement_file))
64
+ puts q.sql(:formatted, :create_tables)
56
65
  end
57
66
 
58
- desc 'fake_graph file', 'Reads the ConceptQL statement from the file and shows the contents as a ConceptQL graph'
59
- def fake_graph(file)
60
- require_relative 'fake_grapher'
61
- ConceptQL::FakeGrapher.new.graph_it(criteria_from_file(file), '/tmp/graph')
62
- system('open /tmp/graph.pdf')
67
+ desc "code_list statement_file",
68
+ "Reads the ConceptQL statement from the statement file and prints the code list out"
69
+ def code_list(statement_file)
70
+ q = cdb(options).query(criteria_from_file(statement_file))
71
+ puts q.code_list
63
72
  end
64
73
 
65
- desc 'metadata', 'Generates the metadata.js file for the JAM'
66
- def metadata
67
- File.write('/tmp/metadata.js', "var metadata = #{ConceptQL::Nodifier.new.to_metadata.to_json};")
74
+ desc "annotate_statement", "Reads in a statement and annotates it"
75
+ def annotate_statement(statement_file)
76
+ q = ConceptQL::Query.new(cdb(options), criteria_from_file(statement_file))
77
+ pp q.annotate(skip_counts: true)
68
78
  end
69
79
 
70
- desc 'convert', 'Converts from hash-based syntax to list-based syntax'
71
- def convert(file)
72
- require 'conceptql/converter'
73
- require 'json'
74
- begin
75
- puts JSON.pretty_generate(ConceptQL::Converter.new.convert(criteria_from_file(file)))
76
- rescue
77
- puts "Couldn't convert #{file}"
78
- puts $!.message
79
- puts $!.backtrace.join("\n")
80
- end
80
+ desc "scope_annotate", "Reads in a statement and annotates it"
81
+ def scope_annotate(statement_file)
82
+ q = ConceptQL::Query.new(cdb(options), criteria_from_file(statement_file))
83
+ pp q.scope_annotate(skip_counts: true)
81
84
  end
82
85
 
83
- private
84
- desc 'show_and_tell_db conceptql_id', 'Fetches the ConceptQL from a DB and shows the contents as a ConceptQL graph, then executes the statement against our test database'
85
- option :full
86
- option :watch_file
87
- def show_and_tell_db(conceptql_id)
88
- result = fetch_conceptql(conceptql_id, options)
89
- puts "Concept: #{result[:label]}"
90
- show_and_tell(result[:statement].to_hash, options, result[:label])
86
+ desc "render_json STATEMENT_FILE",
87
+ "Prints the statement(s) as a #{ConceptQL::Diagram::FORMAT} render tree (JSON) for the diagram renderer"
88
+ long_desc <<~DESC
89
+ STATEMENT_FILE holds one ConceptQL statement or an array of them (.json, or Ruby for any other extension).
90
+ Prints {"format": "#{ConceptQL::Diagram::FORMAT}", "statements": [<node>, ...]}, one node per statement.
91
+
92
+ Without --counts no claims database is used. With --counts each node gains
93
+ "counts": {<domain>: {"rows": Integer, "n": Integer}}, computed against the database
94
+ given by the connection options (or sequelizer's configuration).
95
+ DESC
96
+ option :counts, type: :boolean, default: false, desc: "annotate with per-domain row/person counts (needs a DB)"
97
+ option :data_model, desc: "data model: gdm, gdm_wide, omopv4_plus (default: $CONCEPTQL_DATA_MODEL or gdm)"
98
+ def render_json(statement_file)
99
+ cdb = if options[:counts]
100
+ ConceptQL::Database.new(db(options.except("counts", "data_model")),
101
+ { data_model: options[:data_model] }.compact)
102
+ else
103
+ ConceptQL::Diagram.default_cdb(options[:data_model])
104
+ end
105
+ doc = ConceptQL::Diagram.render(criteria_from_file(statement_file), cdb: cdb, counts: options[:counts])
106
+ puts JSON.pretty_generate(doc)
91
107
  end
92
108
 
93
- desc 'show_db_graph conceptql_id', 'Shows a graph for the conceptql statement represented by conceptql_id in the db specified by db_url'
94
- def show_db_graph(conceptql_id)
95
- result = fetch_conceptql(conceptql_id, options)
96
- graph_it(result[:statement].to_hash, db, result[:label])
97
- end
109
+ desc "metadata", "Generates the metadata.js file for the JAM"
110
+ def metadata
111
+ json = ConceptQL.metadata(cdb(options), warn: true).to_json
112
+ File.write("metadata.js", "$metadata = #{json};")
113
+ File.write("metadata.json", json)
114
+ return unless system("which", "json_pp", out: File::NULL, err: File::NULL)
98
115
 
99
- def fetch_conceptql(conceptql_id)
100
- my_db = db(options)
101
- my_db.extension(:pg_array, :pg_json)
102
- my_db[:concepts].where(concept_id: conceptql_id).select(:statement, :label).first
116
+ system("cat metadata.json | json_pp", out: "metadata_pp.json")
103
117
  end
104
118
 
105
- def show_and_tell(statement, options, title = nil)
106
- my_db = db(options)
107
- q = ConceptQL::Query.new(my_db, statement)
108
- puts 'YAML'
109
- puts q.statement.to_yaml
110
- puts 'JSON'
111
- puts JSON.pretty_generate(q.statement)
112
- graph_it(statement, title)
113
- STDIN.gets
114
- puts q.sql
115
- STDIN.gets
116
- results = q.all
117
- if options[:full]
118
- pp results
119
- else
120
- pp filtered(results)
121
- end
122
- puts results.length
119
+ desc "simple_visit STATEMENT_FILE",
120
+ "Prints the operators, depth and selection-node count of the statement in STATEMENT_FILE"
121
+ def simple_visit(statement_file)
122
+ pp cdb(options).query(criteria_from_file(statement_file)).extract_metadata
123
123
  end
124
124
 
125
- def graph_it(statement, title = nil)
126
- require_relative 'graph'
127
- require_relative 'tree'
128
- conn = db(options)
129
- ConceptQL::Graph.new(statement,
130
- dangler: true,
131
- title: title,
132
- db: conn
133
- ).graph_it('/tmp/graph')
134
- system('open /tmp/graph.pdf')
135
- if options[:watch_file]
136
- require_relative 'debugger'
137
- debugger = ConceptQL::Debugger.new(statement, db: conn, watch_ids: File.readlines(options[:watch_file]).map(&:to_i))
138
- debugger.capture_results('/tmp/debug.xlsx')
125
+ desc "dumpit", "Dumps out test data into CSVs"
126
+ def dumpit(path)
127
+ path = Pathname.new(path)
128
+ path.mkpath unless path.exist?
129
+ headers_path = path / "headers"
130
+ headers_path.mkpath unless headers_path.exist?
131
+ db.tables.each do |table|
132
+ puts "Dumping #{table}..."
133
+ ds = db[table]
134
+ rows = ds.select_map(ds.columns)
135
+ CSV.open(path + "#{table}.csv", "wb") do |csv|
136
+ rows.each { |row| csv << row }
137
+ end
138
+ CSV.open(headers_path + "#{table}.csv", "wb") do |csv|
139
+ csv << ds.columns
140
+ end
139
141
  end
140
142
  end
141
143
 
144
+ private
145
+
142
146
  def criteria_from_file(file)
143
147
  case File.extname(file)
144
- when '.json'
148
+ when ".json"
145
149
  JSON.parse(File.read(file))
146
150
  else
147
151
  eval(File.read(file))
148
152
  end
149
153
  end
150
154
 
151
- def filtered(results)
152
- results.each { |r| r.delete_if { |k,v| v.nil? } }
155
+ def cdb(options)
156
+ data_db = db(options)
157
+ cdb = ConceptQL::Database.new(data_db)
158
+ # A glob of directories, in search path order: "/data/{wide,slim}".
159
+ if (parquet_dirs = ENV["CONCEPTQL_PARQUET_TEST_DIR"])
160
+ data_db.make_ready(search_path: Dir[parquet_dirs].map { |dir| Pathname.new(dir).glob("*.parquet") })
161
+ end
162
+ cdb
153
163
  end
154
164
  end
155
165
  end
156
-
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConceptQL
4
+ class Columnizer
5
+ class ColumnDefinition
6
+ attr_reader :name, :options
7
+
8
+ def initialize(name, options)
9
+ @name = name
10
+ @options = options
11
+ end
12
+
13
+ def grouped?
14
+ options[:grouped]
15
+ end
16
+
17
+ def sequelized
18
+ col = name
19
+ if (q = options[:qualifier])
20
+ col = Sequel.qualify(q, col)
21
+ end
22
+
23
+ if (fun = options[:function])
24
+ col = Sequel.function(fun, col)
25
+ end
26
+
27
+ unless options[:no_alias]
28
+ n = extract_name(name)
29
+ col = Sequel.expr(col).as(n) if n.present?
30
+ end
31
+
32
+ col
33
+ end
34
+
35
+ def extract_name(name)
36
+ return name if name.is_a?(Symbol)
37
+
38
+ n = nil
39
+ n = name.column if name.respond_to?(:column)
40
+ return n unless n.blank?
41
+
42
+ n = name.table if name.respond_to?(:table)
43
+ return n unless n.blank?
44
+
45
+ extract_name(name.expr) if name.respond_to?(:expr)
46
+ end
47
+ end
48
+
49
+ attr_reader :columns
50
+
51
+ def initialize
52
+ @columns = {}
53
+ end
54
+
55
+ def add_columns(*column_names)
56
+ opts = ConceptQL::Utils.extract_opts!(column_names)
57
+ column_names.each do |column_name|
58
+ columns[column_name] = ColumnDefinition.new(column_name, opts)
59
+ end
60
+ end
61
+
62
+ def apply(query)
63
+ grouped, ungrouped = columns.values.partition(&:grouped?)
64
+ select_method = :select
65
+ unless grouped.empty?
66
+ query = query.select_group(*grouped.map(&:sequelized))
67
+ select_method = :select_append
68
+ end
69
+
70
+ return query if ungrouped.empty?
71
+
72
+ query.send(select_method, *ungrouped.map(&:sequelized))
73
+ end
74
+ end
75
+ end