conceptql 0.0.5 → 0.0.6

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
  SHA1:
3
- metadata.gz: 18f492f915df9764cef2f0e323377b3f332775e2
4
- data.tar.gz: c1d56957e335c2ce0cf3b210e87fc7076ea3dd5c
3
+ metadata.gz: 5d18bbb657fb80b014eb554e98b1329f98ecb64f
4
+ data.tar.gz: 80564c67d29d44af5c91cae68a0096eac546116b
5
5
  SHA512:
6
- metadata.gz: c24acf0374cc97a6fac1c09dbbf2e9b5a58904c12221e26f24c39a554c34aba425f0751519e40ba89de2e909e7f04fece936f612cc6556e2884dab87a5493c2e
7
- data.tar.gz: e0e7b23651b543f13720fe89bff326a37c0d33f429ca7164d64d587532037c140763d7bc1fc9de7ce454cd3ceff15b50a9cadc3592d7d2a71aa48172ae26b6fb
6
+ metadata.gz: 2bfa1b9efeae75d2d96c3565cc9ffe38398667e5d15afbf8c9c4d5d835c48da685eb74561262db103f86d8f880e4957ac3bd53ffc26816c5ceec73b065a09457
7
+ data.tar.gz: 11a3813fdd1450c70b4f6aa866dffba16f2e22376ec6a625a77ef6840aeb777dbc8099ab3f40b78feae2080706ebdf40b0609d2cea017f89af5e67faee1823e0
data/CHANGELOG.md CHANGED
@@ -1,6 +1,25 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## 0.0.6 - 2014-08-23
5
+
6
+ ### Added
7
+ - Tree#defined to pass type information between Define and Recall.
8
+ - Node#sql to produce SQL for each node.
9
+ - Graph includes row count on each edge in the diagram.
10
+
11
+ ### Deprecated
12
+ - Nothing.
13
+
14
+ ### Removed
15
+ - Nothing.
16
+
17
+ ### Fixed
18
+ - Bug in CastingNode that generate SQL returning multiple columns in a subquery.
19
+ - Made ruby-graphviz a dependency so calling programs don't bomb out.
20
+ - Define now passes rows on through like any other node!
21
+
22
+
4
23
  ## 0.0.5 - 2014-08-19
5
24
 
6
25
  ### Added
@@ -16,7 +35,6 @@ All notable changes to this project will be documented in this file.
16
35
  - Bug in GraphNodifier not displaying types for `recall` nodes.
17
36
 
18
37
 
19
-
20
38
  ## 0.0.4 - 2014-08-19
21
39
 
22
40
  ### Added
data/conceptql.gemspec CHANGED
@@ -22,8 +22,8 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency 'sequelizer', '~> 0.0'
23
23
  spec.add_dependency 'thor', '~> 0.19'
24
24
  spec.add_dependency 'pg', '~> 0.17'
25
+ spec.add_dependency 'ruby-graphviz', '~> 1.2'
25
26
  spec.add_development_dependency 'bundler', '~> 1.5'
26
- spec.add_development_dependency 'ruby-graphviz', '~> 1.2'
27
27
  spec.add_development_dependency 'rake', '~> 10.3'
28
28
  spec.add_development_dependency 'minitest', '~> 5.4'
29
29
  spec.add_development_dependency 'guard-minitest', '~> 2.3'
@@ -49,9 +49,18 @@ module ConceptQL
49
49
  end
50
50
  end
51
51
 
52
- def link_to(g, dest_node)
52
+ def link_to(g, dest_node, db = nil)
53
+ edge_options = {}
54
+
53
55
  types.each do |type|
54
- e = g.add_edges(graph_node(g), dest_node)
56
+ if db
57
+ my_n = my_n(db, type)
58
+ label = [' rows=' + my_count(db, type).to_s + ' ']
59
+ label << ' n=' + my_n.to_s + ' '
60
+ edge_options[:label] = label.join("\n")
61
+ edge_options[:style] = 'dashed' if my_n.zero?
62
+ end
63
+ e = g.add_edges(graph_node(g), dest_node, edge_options)
55
64
  e[:color] = type_color(type)
56
65
  end
57
66
  end
@@ -63,9 +72,17 @@ module ConceptQL
63
72
  end
64
73
  graph_node(g)
65
74
  children.each do |child|
66
- child.link_to(g, graph_node(g))
75
+ child.link_to(g, graph_node(g), db)
67
76
  end
68
77
  end
78
+
79
+ def my_count(db, type)
80
+ evaluate(db).from_self.where(criterion_type: type.to_s).count
81
+ end
82
+
83
+ def my_n(db, type)
84
+ evaluate(db).from_self.where(criterion_type: type.to_s).select_group(:person_id).count
85
+ end
69
86
  end
70
87
  end
71
88
  end
data/lib/conceptql/cli.rb CHANGED
@@ -37,7 +37,7 @@ module ConceptQL
37
37
  desc 'run_statement statement_file', 'Reads the ConceptQL statement from the statement file and executes it against the DB'
38
38
  def run_statement(statement_file)
39
39
  q = ConceptQL::Query.new(db(options), criteria_from_file(statement_file))
40
- puts q.query.sql
40
+ puts q.sql
41
41
  puts q.statement.to_yaml
42
42
  pp q.execute
43
43
  end
@@ -102,13 +102,13 @@ module ConceptQL
102
102
  puts results.length
103
103
  end
104
104
 
105
- def graph_it(statement, db = nil, title = nil)
105
+ def graph_it(statement, title = nil)
106
106
  require_relative 'graph'
107
107
  require_relative 'tree'
108
108
  ConceptQL::Graph.new(statement,
109
109
  dangler: true,
110
110
  title: title,
111
- db: db
111
+ db: db(options)
112
112
  ).graph_it('/tmp/graph')
113
113
  system('open /tmp/graph.pdf')
114
114
  end
@@ -42,7 +42,7 @@ module ConceptQL
42
42
  blank_node[:height] = 0
43
43
  blank_node[:label] = ''
44
44
  blank_node[:fixedsize] = true
45
- last_node.link_to(g, blank_node)
45
+ last_node.link_to(g, blank_node, db)
46
46
  end
47
47
  end
48
48
  end
@@ -59,7 +59,7 @@ module ConceptQL
59
59
  attr :values, :name
60
60
  def initialize(name, values)
61
61
  @name = name.to_s
62
- super(values)
62
+ super(nil, values)
63
63
  end
64
64
 
65
65
  def display_name
@@ -171,7 +171,8 @@ module ConceptQL
171
171
  def types
172
172
  @types ||= {}
173
173
  end
174
- def create(type, values)
174
+
175
+ def create(type, values, tree)
175
176
  if BINARY_OPERATOR_TYPES.include?(type)
176
177
  return BinaryOperatorNode.new(type, values)
177
178
  elsif type == :define
@@ -17,8 +17,8 @@ module ConceptQL
17
17
  sub.send("#{cluster_name}_left").send('[]', shape: 'point', color: type_color(types))
18
18
  sub.send("#{cluster_name}_right").send('[]', shape: 'point')
19
19
  end
20
- left.link_to(g, me.send("#{cluster_name}_left"))
21
- right.link_to(g, me.send("#{cluster_name}_right"))
20
+ left.link_to(g, me.send("#{cluster_name}_left"), db)
21
+ right.link_to(g, me.send("#{cluster_name}_right"), db)
22
22
  @__graph_node = me.send("#{cluster_name}_left")
23
23
  end
24
24
 
@@ -67,7 +67,7 @@ module ConceptQL
67
67
  # For each castable type in the stream, setup a query that
68
68
  # casts each type to a set of IDs, union those IDs and fetch
69
69
  # them from the source table
70
- castable_type_queries = to_me_types.map do |source_type|
70
+ castable_type_query = to_me_types.map do |source_type|
71
71
  source_ids = db.from(stream_query)
72
72
  .where(criterion_type: source_type.to_s)
73
73
  .select_group(:criterion_id)
@@ -77,8 +77,10 @@ module ConceptQL
77
77
  db.from(source_table)
78
78
  .where(source_type_id => source_ids)
79
79
  .select(destination_type_id)
80
+ end.inject do |union_query, q|
81
+ union_query.union(q)
80
82
  end
81
- wheres << Sequel.expr(destination_type_id => castable_type_queries)
83
+ wheres << Sequel.expr(destination_type_id => castable_type_query)
82
84
  end
83
85
 
84
86
  unless from_me_types.empty?
@@ -13,6 +13,10 @@ module ConceptQL
13
13
  # and then insert that variable into the concept as needed.
14
14
  # run the query once and subsequent calls
15
15
  class Define < Node
16
+ def initialize(*args)
17
+ super
18
+ tree.defined[table_name] = self
19
+ end
16
20
  # Create a temporary table and store the stream of results in that table.
17
21
  # This "caches" the results so we only have to execute stream's query
18
22
  # once.
@@ -39,35 +43,22 @@ module ConceptQL
39
43
  # Also, things will blow up if you try to use a variable that hasn't been
40
44
  # defined yet.
41
45
  def query(db)
42
- table_name = namify(arguments.first)
43
- stash_types(db, table_name, types)
44
46
  db.create_table!(table_name, temp: true, as: stream.evaluate(db))
45
- db[db.send(:create_table_as_sql, table_name, stream.evaluate(db).sql, temp: true)]
47
+ db.from(table_name)
46
48
  end
47
49
 
48
50
  def types
49
51
  stream.types
50
52
  end
51
53
 
54
+ def sql(db)
55
+ db[db.send(:create_table_as_sql, table_name, stream.evaluate(db).sql, temp: true)].sql
56
+ end
57
+
52
58
  private
53
59
 
54
- # TODO: Fix this. This is shameful.
55
- # In order to remember which types a table is storing, we need to preserve
56
- # the type information outside of the "define" statement because the "recall"
57
- # statement most likely doesn't have a reference to this node (that's the
58
- # whole point).
59
- #
60
- # There is only one object shared between all the nodes: the database
61
- # connection. We'll do something terrible and piggyback the type
62
- # information about this variable on the database connection so that
63
- # the "recall" node can pull that information back out.
64
- #
65
- # Ugh.
66
- def stash_types(db, name, types)
67
- def db.types
68
- @types ||= {}
69
- end
70
- db.types[name] = types
60
+ def table_name
61
+ @table_name ||= namify(arguments.first)
71
62
  end
72
63
  end
73
64
  end
@@ -3,7 +3,8 @@ module ConceptQL
3
3
  module Nodes
4
4
  class Node
5
5
  attr :values, :options
6
- def initialize(*args)
6
+ def initialize(tree, *args)
7
+ @tree = tree
7
8
  args.flatten!
8
9
  if args.last.is_a?(Hash)
9
10
  @options = args.pop.symbolize_keys
@@ -16,6 +17,10 @@ module ConceptQL
16
17
  select_it(query(db))
17
18
  end
18
19
 
20
+ def sql(db)
21
+ evaluate(db).sql
22
+ end
23
+
19
24
  def select_it(query, specific_type = nil)
20
25
  specific_type = type if specific_type.nil? && respond_to?(:type)
21
26
  query.select(*columns(specific_type))
@@ -48,6 +53,22 @@ module ConceptQL
48
53
  end
49
54
 
50
55
  private
56
+ # There have been a few times now that I've wanted a node to be able
57
+ # to pass information to another node that is not directly a child
58
+ #
59
+ # Since tree is only object that touches each node in a statement,
60
+ # I'm going to employ tree as a way to communicate between nodes
61
+ #
62
+ # This is an ugly hack, but the use case for this hack is I'm changing
63
+ # the way `define` and `recall` nodes pass type information between
64
+ # each other. They used to take the type information onto the
65
+ # database connection, but there were issues where sometimes the
66
+ # type information was needed before we passed around the database
67
+ # connection.
68
+ #
69
+ # At least this way we don't have timing issues when reading types
70
+ attr :tree
71
+
51
72
  def criterion_id
52
73
  :criterion_id
53
74
  end
@@ -20,13 +20,16 @@ module ConceptQL
20
20
  # before we call #query. Probably time to reevaluate how we're caching
21
21
  # the type information.
22
22
  def query(db)
23
- table_name = namify(arguments.first)
24
- @types = db.types[table_name]
25
23
  db.from(table_name)
26
24
  end
27
25
 
28
26
  def types
29
- @types
27
+ tree.defined[table_name].types
28
+ end
29
+
30
+ private
31
+ def table_name
32
+ @table_name ||= namify(arguments.first)
30
33
  end
31
34
  end
32
35
  end
@@ -1,9 +1,9 @@
1
1
  require 'active_support/inflector'
2
2
  module ConceptQL
3
3
  class Nodifier
4
- def create(type, values)
4
+ def create(type, values, tree)
5
5
  require_relative "nodes/#{type}"
6
- "conceptQL/nodes/#{type}".camelize.constantize.new(values)
6
+ "conceptQL/nodes/#{type}".camelize.constantize.new(tree, values)
7
7
  end
8
8
  end
9
9
  end
@@ -19,7 +19,7 @@ module ConceptQL
19
19
  end
20
20
 
21
21
  def sql
22
- queries.map(&:sql).join(";\n") + ';'
22
+ nodes.map { |node| node.sql(db) }.join(";\n") + ';'
23
23
  end
24
24
 
25
25
  # To avoid a performance penalty, only execute the last
@@ -37,7 +37,11 @@ module ConceptQL
37
37
  attr :yaml, :tree, :db
38
38
 
39
39
  def build_query(db)
40
- tree.root(self).map { |n| n.evaluate(db) }
40
+ nodes.map { |n| n.evaluate(db) }
41
+ end
42
+
43
+ def nodes
44
+ @nodes ||= tree.root(self)
41
45
  end
42
46
  end
43
47
  end
@@ -3,10 +3,11 @@ require 'active_support/core_ext/hash'
3
3
 
4
4
  module ConceptQL
5
5
  class Tree
6
- attr :nodifier, :behavior
6
+ attr :nodifier, :behavior, :defined
7
7
  def initialize(opts = {})
8
8
  @nodifier = opts.fetch(:nodifier, Nodifier.new)
9
9
  @behavior = opts.fetch(:behavior, nil)
10
+ @defined = {}
10
11
  end
11
12
 
12
13
  def root(*queries)
@@ -23,7 +24,7 @@ module ConceptQL
23
24
  end
24
25
  type = obj.keys.first
25
26
  values = traverse(obj[type])
26
- obj = nodifier.create(type, values)
27
+ obj = nodifier.create(type, values, self)
27
28
  obj.extend(behavior) if behavior
28
29
  obj
29
30
  when Array
@@ -1,3 +1,3 @@
1
1
  module ConceptQL
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conceptql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Duryea
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-20 00:00:00.000000000 Z
11
+ date: 2014-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -67,33 +67,33 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.17'
69
69
  - !ruby/object:Gem::Dependency
70
- name: bundler
70
+ name: ruby-graphviz
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.5'
76
- type: :development
75
+ version: '1.2'
76
+ type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.5'
82
+ version: '1.2'
83
83
  - !ruby/object:Gem::Dependency
84
- name: ruby-graphviz
84
+ name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '1.2'
89
+ version: '1.5'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '1.2'
96
+ version: '1.5'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rake
99
99
  requirement: !ruby/object:Gem::Requirement