conceptql 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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