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 +4 -4
- data/CHANGELOG.md +19 -1
- data/conceptql.gemspec +1 -1
- data/lib/conceptql/behaviors/dottable.rb +20 -3
- data/lib/conceptql/cli.rb +3 -3
- data/lib/conceptql/graph.rb +1 -1
- data/lib/conceptql/graph_nodifier.rb +3 -2
- data/lib/conceptql/nodes/binary_operator_node.rb +2 -2
- data/lib/conceptql/nodes/casting_node.rb +4 -2
- data/lib/conceptql/nodes/define.rb +11 -20
- data/lib/conceptql/nodes/node.rb +22 -1
- data/lib/conceptql/nodes/recall.rb +6 -3
- data/lib/conceptql/nodifier.rb +2 -2
- data/lib/conceptql/query.rb +6 -2
- data/lib/conceptql/tree.rb +3 -2
- data/lib/conceptql/version.rb +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d18bbb657fb80b014eb554e98b1329f98ecb64f
|
4
|
+
data.tar.gz: 80564c67d29d44af5c91cae68a0096eac546116b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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.
|
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,
|
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
|
data/lib/conceptql/graph.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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 =>
|
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
|
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
|
-
|
55
|
-
|
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
|
data/lib/conceptql/nodes/node.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/conceptql/nodifier.rb
CHANGED
@@ -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
|
data/lib/conceptql/query.rb
CHANGED
@@ -19,7 +19,7 @@ module ConceptQL
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def sql
|
22
|
-
|
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
|
-
|
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
|
data/lib/conceptql/tree.rb
CHANGED
@@ -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
|
data/lib/conceptql/version.rb
CHANGED
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.
|
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-
|
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:
|
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.
|
76
|
-
type: :
|
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.
|
82
|
+
version: '1.2'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: bundler
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '1.
|
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.
|
96
|
+
version: '1.5'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rake
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|