activefacts 0.8.9 → 0.8.10
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.
- data/.gemtest +0 -0
- data/Manifest.txt +28 -33
- data/Rakefile +11 -12
- data/bin/cql +90 -46
- data/examples/CQL/Blog.cql +2 -1
- data/examples/CQL/CompanyDirectorEmployee.cql +2 -2
- data/examples/CQL/Death.cql +1 -1
- data/examples/CQL/Diplomacy.cql +9 -9
- data/examples/CQL/Genealogy.cql +3 -2
- data/examples/CQL/Insurance.cql +10 -7
- data/examples/CQL/JoinEquality.cql +2 -2
- data/examples/CQL/Marriage.cql +1 -1
- data/examples/CQL/Metamodel.cql +73 -53
- data/examples/CQL/MetamodelNext.cql +89 -67
- data/examples/CQL/OneToOnes.cql +2 -2
- data/examples/CQL/ServiceDirector.cql +10 -5
- data/examples/CQL/Supervision.cql +3 -3
- data/examples/CQL/Tests.Test5.Load.cql +1 -1
- data/examples/CQL/Warehousing.cql +4 -2
- data/lib/activefacts/cql/CQLParser.treetop +26 -60
- data/lib/activefacts/cql/Context.treetop +12 -2
- data/lib/activefacts/cql/Expressions.treetop +14 -30
- data/lib/activefacts/cql/FactTypes.treetop +165 -110
- data/lib/activefacts/cql/Language/English.treetop +167 -54
- data/lib/activefacts/cql/LexicalRules.treetop +16 -2
- data/lib/activefacts/cql/{Concepts.treetop → ObjectTypes.treetop} +36 -37
- data/lib/activefacts/cql/Terms.treetop +57 -27
- data/lib/activefacts/cql/ValueTypes.treetop +39 -13
- data/lib/activefacts/cql/compiler.rb +5 -3
- data/lib/activefacts/cql/compiler/{reading.rb → clause.rb} +407 -285
- data/lib/activefacts/cql/compiler/constraint.rb +178 -275
- data/lib/activefacts/cql/compiler/entity_type.rb +73 -64
- data/lib/activefacts/cql/compiler/expression.rb +418 -0
- data/lib/activefacts/cql/compiler/fact.rb +146 -145
- data/lib/activefacts/cql/compiler/fact_type.rb +197 -80
- data/lib/activefacts/cql/compiler/join.rb +159 -0
- data/lib/activefacts/cql/compiler/shared.rb +51 -23
- data/lib/activefacts/cql/compiler/value_type.rb +56 -2
- data/lib/activefacts/cql/parser.rb +15 -4
- data/lib/activefacts/generate/absorption.rb +7 -7
- data/lib/activefacts/generate/cql.rb +100 -37
- data/lib/activefacts/generate/oo.rb +28 -51
- data/lib/activefacts/generate/ordered.rb +60 -36
- data/lib/activefacts/generate/ruby.rb +6 -6
- data/lib/activefacts/generate/sql/server.rb +4 -4
- data/lib/activefacts/input/orm.rb +71 -53
- data/lib/activefacts/persistence.rb +1 -1
- data/lib/activefacts/persistence/columns.rb +27 -23
- data/lib/activefacts/persistence/foreignkey.rb +6 -6
- data/lib/activefacts/persistence/index.rb +17 -17
- data/lib/activefacts/persistence/{concept.rb → object_type.rb} +9 -9
- data/lib/activefacts/persistence/reference.rb +61 -36
- data/lib/activefacts/persistence/tables.rb +61 -59
- data/lib/activefacts/support.rb +54 -29
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +99 -54
- data/lib/activefacts/vocabulary/metamodel.rb +43 -37
- data/lib/activefacts/vocabulary/verbaliser.rb +134 -109
- data/spec/absorption_spec.rb +8 -8
- data/spec/cql/comparison_spec.rb +91 -0
- data/spec/cql/contractions_spec.rb +251 -0
- data/spec/cql/entity_type_spec.rb +319 -0
- data/spec/cql/expressions_spec.rb +63 -0
- data/spec/cql/fact_type_matching_spec.rb +283 -0
- data/spec/cql/french_spec.rb +21 -0
- data/spec/cql/parser/bad_literals_spec.rb +86 -0
- data/spec/cql/parser/constraints_spec.rb +19 -0
- data/spec/cql/parser/entity_types_spec.rb +106 -0
- data/spec/cql/parser/expressions_spec.rb +179 -0
- data/spec/cql/parser/fact_types_spec.rb +41 -0
- data/spec/cql/parser/literals_spec.rb +312 -0
- data/spec/cql/parser/pragmas_spec.rb +89 -0
- data/spec/cql/parser/value_types_spec.rb +42 -0
- data/spec/cql/role_matching_spec.rb +147 -0
- data/spec/cql/samples_spec.rb +9 -9
- data/spec/cql_cql_spec.rb +1 -1
- data/spec/cql_dm_spec.rb +116 -0
- data/spec/cql_mysql_spec.rb +1 -1
- data/spec/cql_ruby_spec.rb +1 -1
- data/spec/cql_sql_spec.rb +3 -3
- data/spec/cql_symbol_tables_spec.rb +30 -30
- data/spec/cqldump_spec.rb +4 -4
- data/spec/helpers/array_matcher.rb +32 -27
- data/spec/helpers/diff_matcher.rb +6 -26
- data/spec/helpers/file_matcher.rb +41 -32
- data/spec/helpers/parse_to_ast_matcher.rb +76 -0
- data/spec/helpers/string_matcher.rb +32 -31
- data/spec/norma_cql_spec.rb +1 -1
- data/spec/norma_ruby_spec.rb +1 -1
- data/spec/norma_ruby_sql_spec.rb +1 -1
- data/spec/norma_sql_spec.rb +3 -1
- data/spec/norma_tables_spec.rb +1 -1
- data/spec/ruby_api_spec.rb +23 -0
- data/spec/spec_helper.rb +5 -4
- metadata +66 -66
- data/examples/CQL/OrienteeringER.cql +0 -58
- data/lib/activefacts/api.rb +0 -44
- data/lib/activefacts/api/concept.rb +0 -410
- data/lib/activefacts/api/constellation.rb +0 -128
- data/lib/activefacts/api/entity.rb +0 -256
- data/lib/activefacts/api/instance.rb +0 -60
- data/lib/activefacts/api/instance_index.rb +0 -80
- data/lib/activefacts/api/numeric.rb +0 -167
- data/lib/activefacts/api/role.rb +0 -80
- data/lib/activefacts/api/role_proxy.rb +0 -70
- data/lib/activefacts/api/role_values.rb +0 -117
- data/lib/activefacts/api/standard_types.rb +0 -87
- data/lib/activefacts/api/support.rb +0 -65
- data/lib/activefacts/api/value.rb +0 -135
- data/lib/activefacts/api/vocabulary.rb +0 -82
- data/spec/api/autocounter.rb +0 -82
- data/spec/api/constellation.rb +0 -130
- data/spec/api/entity_type.rb +0 -103
- data/spec/api/instance.rb +0 -461
- data/spec/api/roles.rb +0 -124
- data/spec/api/value_type.rb +0 -112
- data/spec/api_spec.rb +0 -13
- data/spec/cql/matching_spec.rb +0 -517
- data/spec/cql/unit_spec.rb +0 -394
- data/spec/spec.opts +0 -1
data/.gemtest
ADDED
|
File without changes
|
data/Manifest.txt
CHANGED
|
@@ -31,7 +31,6 @@ examples/CQL/OddIdentifier.cql
|
|
|
31
31
|
examples/CQL/OilSupply.cql
|
|
32
32
|
examples/CQL/OneToOnes.cql
|
|
33
33
|
examples/CQL/Orienteering.cql
|
|
34
|
-
examples/CQL/OrienteeringER.cql
|
|
35
34
|
examples/CQL/PersonPlaysGame.cql
|
|
36
35
|
examples/CQL/RedundantDependency.cql
|
|
37
36
|
examples/CQL/SchoolActivities.cql
|
|
@@ -50,37 +49,25 @@ examples/intro.html
|
|
|
50
49
|
examples/local.css
|
|
51
50
|
index.html
|
|
52
51
|
lib/activefacts.rb
|
|
53
|
-
lib/activefacts/api.rb
|
|
54
|
-
lib/activefacts/api/concept.rb
|
|
55
|
-
lib/activefacts/api/constellation.rb
|
|
56
|
-
lib/activefacts/api/entity.rb
|
|
57
|
-
lib/activefacts/api/instance.rb
|
|
58
|
-
lib/activefacts/api/instance_index.rb
|
|
59
|
-
lib/activefacts/api/numeric.rb
|
|
60
|
-
lib/activefacts/api/role.rb
|
|
61
|
-
lib/activefacts/api/role_proxy.rb
|
|
62
|
-
lib/activefacts/api/role_values.rb
|
|
63
|
-
lib/activefacts/api/standard_types.rb
|
|
64
|
-
lib/activefacts/api/support.rb
|
|
65
|
-
lib/activefacts/api/value.rb
|
|
66
|
-
lib/activefacts/api/vocabulary.rb
|
|
67
52
|
lib/activefacts/cql.rb
|
|
68
53
|
lib/activefacts/cql/CQLParser.treetop
|
|
69
|
-
lib/activefacts/cql/Concepts.treetop
|
|
70
54
|
lib/activefacts/cql/Context.treetop
|
|
71
55
|
lib/activefacts/cql/Expressions.treetop
|
|
72
56
|
lib/activefacts/cql/FactTypes.treetop
|
|
73
57
|
lib/activefacts/cql/Language/English.treetop
|
|
74
58
|
lib/activefacts/cql/LexicalRules.treetop
|
|
59
|
+
lib/activefacts/cql/ObjectTypes.treetop
|
|
75
60
|
lib/activefacts/cql/Rakefile
|
|
76
61
|
lib/activefacts/cql/Terms.treetop
|
|
77
62
|
lib/activefacts/cql/ValueTypes.treetop
|
|
78
63
|
lib/activefacts/cql/compiler.rb
|
|
64
|
+
lib/activefacts/cql/compiler/clause.rb
|
|
79
65
|
lib/activefacts/cql/compiler/constraint.rb
|
|
80
66
|
lib/activefacts/cql/compiler/entity_type.rb
|
|
67
|
+
lib/activefacts/cql/compiler/expression.rb
|
|
81
68
|
lib/activefacts/cql/compiler/fact.rb
|
|
82
69
|
lib/activefacts/cql/compiler/fact_type.rb
|
|
83
|
-
lib/activefacts/cql/compiler/
|
|
70
|
+
lib/activefacts/cql/compiler/join.rb
|
|
84
71
|
lib/activefacts/cql/compiler/shared.rb
|
|
85
72
|
lib/activefacts/cql/compiler/value_type.rb
|
|
86
73
|
lib/activefacts/cql/parser.rb
|
|
@@ -97,9 +84,9 @@ lib/activefacts/input/cql.rb
|
|
|
97
84
|
lib/activefacts/input/orm.rb
|
|
98
85
|
lib/activefacts/persistence.rb
|
|
99
86
|
lib/activefacts/persistence/columns.rb
|
|
100
|
-
lib/activefacts/persistence/concept.rb
|
|
101
87
|
lib/activefacts/persistence/foreignkey.rb
|
|
102
88
|
lib/activefacts/persistence/index.rb
|
|
89
|
+
lib/activefacts/persistence/object_type.rb
|
|
103
90
|
lib/activefacts/persistence/reference.rb
|
|
104
91
|
lib/activefacts/persistence/tables.rb
|
|
105
92
|
lib/activefacts/support.rb
|
|
@@ -109,38 +96,46 @@ lib/activefacts/vocabulary/extensions.rb
|
|
|
109
96
|
lib/activefacts/vocabulary/metamodel.rb
|
|
110
97
|
lib/activefacts/vocabulary/verbaliser.rb
|
|
111
98
|
script/txt2html
|
|
99
|
+
spec/cql/comparison_spec.rb
|
|
100
|
+
spec/cql/contractions_spec.rb
|
|
101
|
+
spec/cql/entity_type_spec.rb
|
|
102
|
+
spec/cql/expressions_spec.rb
|
|
103
|
+
spec/cql/french_spec.rb
|
|
104
|
+
spec/cql/role_matching_spec.rb
|
|
105
|
+
spec/ruby_api_spec.rb
|
|
112
106
|
spec/absorption_spec.rb
|
|
113
|
-
spec/api/autocounter.rb
|
|
114
|
-
spec/api/constellation.rb
|
|
115
|
-
spec/api/entity_type.rb
|
|
116
|
-
spec/api/instance.rb
|
|
117
|
-
spec/api/roles.rb
|
|
118
|
-
spec/api/value_type.rb
|
|
119
|
-
spec/api_spec.rb
|
|
120
107
|
spec/cql/context_spec.rb
|
|
121
108
|
spec/cql/deontic_spec.rb
|
|
122
|
-
spec/cql/
|
|
109
|
+
spec/cql/fact_type_matching_spec.rb
|
|
110
|
+
spec/cql/parser/bad_literals_spec.rb
|
|
111
|
+
spec/cql/parser/constraints_spec.rb
|
|
112
|
+
spec/cql/parser/entity_types_spec.rb
|
|
113
|
+
spec/cql/parser/expressions_spec.rb
|
|
114
|
+
spec/cql/parser/fact_types_spec.rb
|
|
115
|
+
spec/cql/parser/literals_spec.rb
|
|
116
|
+
spec/cql/parser/pragmas_spec.rb
|
|
117
|
+
spec/cql/parser/value_types_spec.rb
|
|
123
118
|
spec/cql/samples_spec.rb
|
|
124
|
-
spec/cql/unit_spec.rb
|
|
125
119
|
spec/cql_cql_spec.rb
|
|
120
|
+
spec/cql_dm_spec.rb
|
|
126
121
|
spec/cql_mysql_spec.rb
|
|
127
122
|
spec/cql_parse_spec.rb
|
|
128
123
|
spec/cql_ruby_spec.rb
|
|
129
124
|
spec/cql_sql_spec.rb
|
|
130
125
|
spec/cql_symbol_tables_spec.rb
|
|
131
126
|
spec/cqldump_spec.rb
|
|
127
|
+
spec/norma_cql_spec.rb
|
|
128
|
+
spec/norma_ruby_spec.rb
|
|
129
|
+
spec/norma_ruby_sql_spec.rb
|
|
130
|
+
spec/norma_sql_spec.rb
|
|
131
|
+
spec/norma_tables_spec.rb
|
|
132
132
|
spec/helpers/array_matcher.rb
|
|
133
133
|
spec/helpers/ctrl_c_support.rb
|
|
134
134
|
spec/helpers/diff_matcher.rb
|
|
135
135
|
spec/helpers/file_matcher.rb
|
|
136
|
+
spec/helpers/parse_to_ast_matcher.rb
|
|
136
137
|
spec/helpers/string_matcher.rb
|
|
137
138
|
spec/helpers/test_parser.rb
|
|
138
|
-
spec/norma_cql_spec.rb
|
|
139
|
-
spec/norma_ruby_spec.rb
|
|
140
|
-
spec/norma_ruby_sql_spec.rb
|
|
141
|
-
spec/norma_sql_spec.rb
|
|
142
|
-
spec/norma_tables_spec.rb
|
|
143
|
-
spec/spec.opts
|
|
144
139
|
spec/spec_helper.rb
|
|
145
140
|
status.html
|
|
146
141
|
why.html
|
data/Rakefile
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
%w[rubygems hoe rake rake/clean fileutils newgem rubigen
|
|
1
|
+
%w[rubygems hoe rake rake/clean fileutils newgem thread rubigen].each { |f|
|
|
2
|
+
require f
|
|
3
|
+
}
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
rescue
|
|
8
|
-
HANNA = false
|
|
9
|
-
end
|
|
5
|
+
require 'rspec'
|
|
6
|
+
require 'rspec/core/rake_task'
|
|
7
|
+
|
|
8
|
+
gem "rspec", :require => "spec/rake/spectask"
|
|
10
9
|
|
|
11
10
|
require File.dirname(__FILE__) + '/lib/activefacts'
|
|
12
11
|
|
|
@@ -28,6 +27,7 @@ and object models in SQL, Ruby and other languages.
|
|
|
28
27
|
p.post_install_message = 'For more information on ActiveFacts, see http://dataconstellation.com/ActiveFacts'
|
|
29
28
|
p.rubyforge_name = "cjheath@rubyforge.org"
|
|
30
29
|
p.extra_deps = [
|
|
30
|
+
['activefacts-api','>= 0.8.10'],
|
|
31
31
|
['treetop','>= 1.4.1'],
|
|
32
32
|
['rake','>= 0.8.7'],
|
|
33
33
|
]
|
|
@@ -38,9 +38,8 @@ and object models in SQL, Ruby and other languages.
|
|
|
38
38
|
# Magic Hoe hook to prevent the generation of diagrams:
|
|
39
39
|
ENV['NODOT'] = 'yes'
|
|
40
40
|
p.spec_extras[:rdoc_options] = ['-S'] +
|
|
41
|
-
|
|
41
|
+
# RDoc used to have these options: -A has_one -A one_to_one -A maybe
|
|
42
42
|
%w{
|
|
43
|
-
-A has_one -A one_to_one -A maybe
|
|
44
43
|
-x lib/activefacts/cql/.*.rb
|
|
45
44
|
-x lib/activefacts/vocabulary/.*.rb
|
|
46
45
|
}
|
|
@@ -56,9 +55,9 @@ Dir['tasks/**/*.rake'].each { |t| load t }
|
|
|
56
55
|
# TODO - want other tests/tasks run by default? Add them to the list
|
|
57
56
|
# task :default => [:spec, :features]
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
RSpec::Core::RakeTask.new do |t|
|
|
60
59
|
t.ruby_opts = ['-I', "lib"]
|
|
61
|
-
t.
|
|
60
|
+
# t.pattern = FileList['spec/**/*_spec.rb']
|
|
62
61
|
# t.rcov = true
|
|
63
62
|
# t.rcov_opts = ['--exclude', 'spec,/usr/lib/ruby' ]
|
|
64
63
|
end
|
data/bin/cql
CHANGED
|
@@ -22,22 +22,14 @@ require 'activefacts/cql/compiler'
|
|
|
22
22
|
class InteractiveCQL < ActiveFacts::CQL::Compiler
|
|
23
23
|
def initialize *a
|
|
24
24
|
@show_tree = false # Show the raw Treetop parse tree
|
|
25
|
+
@show_highlight = false # Show the highlighted CQL text from the parse tree
|
|
25
26
|
super *a
|
|
26
27
|
self.root = :definition
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def list_instances name
|
|
30
|
-
if name.
|
|
31
|
-
|
|
32
|
-
else
|
|
33
|
-
if !@vocabulary.constellation.Concept[[[@vocabulary.name], name]]
|
|
34
|
-
puts "Object type '#{name}' does not exist in vocabulary '#{@vocabulary.name}'"
|
|
35
|
-
[]
|
|
36
|
-
else
|
|
37
|
-
@vocabulary.constellation.Instance.values.select{|i| i.concept.supertypes_transitive.detect{|k| k.name == name}}
|
|
38
|
-
end
|
|
39
|
-
end.select do |instance|
|
|
40
|
-
instance.concept.vocabulary == @vocabulary
|
|
31
|
+
if (name.is_a?(ActiveFacts::Metamodel::ObjectType))
|
|
32
|
+
name.all_instance
|
|
41
33
|
end.map do |instance|
|
|
42
34
|
instance.verbalise
|
|
43
35
|
end.sort.each do |verbalisation|
|
|
@@ -52,31 +44,31 @@ class InteractiveCQL < ActiveFacts::CQL::Compiler
|
|
|
52
44
|
end
|
|
53
45
|
|
|
54
46
|
def list_object_types
|
|
55
|
-
|
|
56
|
-
@constellation.
|
|
47
|
+
object_types_by_vocabulary = {}
|
|
48
|
+
@constellation.ObjectType.keys.
|
|
57
49
|
each do |v,t|
|
|
58
|
-
(
|
|
50
|
+
(object_types_by_vocabulary[v[0]] ||= []) << t
|
|
59
51
|
end
|
|
60
|
-
|
|
61
|
-
puts "#{v}:\n\t" +
|
|
52
|
+
object_types_by_vocabulary.keys.sort.each do |v|
|
|
53
|
+
puts "#{v}:\n\t" + object_types_by_vocabulary[v].sort*"\n\t"
|
|
62
54
|
end
|
|
63
55
|
end
|
|
64
56
|
|
|
65
57
|
def list_connotations word
|
|
66
|
-
|
|
67
|
-
unless
|
|
58
|
+
object_type = @constellation.ObjectType[[@vocabulary.identifying_role_values, word]]
|
|
59
|
+
unless object_type
|
|
68
60
|
puts "Object type '#{word}' is unknown in #{@vocabulary.name}"
|
|
69
61
|
return
|
|
70
62
|
end
|
|
71
63
|
puts "Fact types in which '#{word}' plays a part:"
|
|
72
|
-
if
|
|
73
|
-
puts "\t#{
|
|
74
|
-
|
|
75
|
-
puts "#{st.name} is written as #{
|
|
64
|
+
if object_type.is_a?(ActiveFacts::Metamodel::ValueType)
|
|
65
|
+
puts "\t#{object_type.name} is written as #{object_type.supertype.name};" if object_type.supertype
|
|
66
|
+
object_type.all_value_type_as_supertype.each do |st|
|
|
67
|
+
puts "#{st.name} is written as #{object_type.name};"
|
|
76
68
|
end
|
|
77
69
|
end
|
|
78
|
-
|
|
79
|
-
puts "\t
|
|
70
|
+
object_type.all_role.map{|role| role.fact_type}.uniq.each do |fact_type|
|
|
71
|
+
puts "\t" + fact_type.all_reading.map{|r| r.expand}*', '
|
|
80
72
|
end
|
|
81
73
|
end
|
|
82
74
|
|
|
@@ -84,8 +76,6 @@ class InteractiveCQL < ActiveFacts::CQL::Compiler
|
|
|
84
76
|
# meta-commands start with /
|
|
85
77
|
words = line.split
|
|
86
78
|
case cmd = words.shift
|
|
87
|
-
when /(\w*)\?/
|
|
88
|
-
list_instances $1
|
|
89
79
|
when "/trace"
|
|
90
80
|
if words.empty?
|
|
91
81
|
puts debug_keys*", "
|
|
@@ -95,6 +85,12 @@ class InteractiveCQL < ActiveFacts::CQL::Compiler
|
|
|
95
85
|
when "/tree"
|
|
96
86
|
@show_tree = !@show_tree
|
|
97
87
|
puts "Will #{@show_tree ? "" : "not "}show the parse tree"
|
|
88
|
+
when "/highlight"
|
|
89
|
+
@show_highlight = !@show_highlight
|
|
90
|
+
puts "Will #{@show_highlight ? "" : "not "}show the highlighted parse"
|
|
91
|
+
when "/timings"
|
|
92
|
+
$show_timings = !$show_timings
|
|
93
|
+
puts "Will #{$show_timings ? "" : "not "}show command timings"
|
|
98
94
|
when "/root"
|
|
99
95
|
self.root = words[0] && words[0].to_sym || :definition
|
|
100
96
|
puts "Looking for a #{self.root}"
|
|
@@ -131,11 +127,24 @@ class InteractiveCQL < ActiveFacts::CQL::Compiler
|
|
|
131
127
|
end
|
|
132
128
|
end
|
|
133
129
|
|
|
130
|
+
def process_query(join)
|
|
131
|
+
if join.all_join_node.size == 1 and join.all_join_step.size == 0
|
|
132
|
+
list_instances(join.all_join_node.single.object_type)
|
|
133
|
+
else
|
|
134
|
+
# REVISIT: Identify all the unbound Join Nodes, and do a nested-loops iteration checking all Steps
|
|
135
|
+
puts "Can't yet process complex queries (involving #{join.all_join_node.map{|jn|jn.object_type.name}*', '})"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
134
139
|
def process(statement)
|
|
135
140
|
begin
|
|
136
141
|
@results = []
|
|
137
142
|
compile(statement)
|
|
138
|
-
|
|
143
|
+
if @results.size == 1 && @results[0].is_a?(ActiveFacts::Metamodel::Join)
|
|
144
|
+
process_query(@results[0])
|
|
145
|
+
else
|
|
146
|
+
puts(@results.map{|r| "\t"+r.inspect}*"\n")
|
|
147
|
+
end
|
|
139
148
|
rescue => e
|
|
140
149
|
puts e
|
|
141
150
|
puts "\t"+e.backtrace*"\n\t" if ENV["DEBUG"] =~ /exception/
|
|
@@ -145,10 +154,33 @@ class InteractiveCQL < ActiveFacts::CQL::Compiler
|
|
|
145
154
|
def compile_definition ast
|
|
146
155
|
# Accumulate the results:
|
|
147
156
|
p ast if @show_tree
|
|
148
|
-
|
|
157
|
+
puts highlight_tree(ast.tree) if @show_highlight
|
|
158
|
+
result = super
|
|
159
|
+
@results += Array(result)
|
|
149
160
|
result
|
|
150
161
|
end
|
|
151
162
|
|
|
163
|
+
# Return an HTML representation of the source text with classed spans surrounding types of text
|
|
164
|
+
def highlight_tree(ast, prev = nil)
|
|
165
|
+
if ast.node_type == :composite
|
|
166
|
+
wrap = prev != :keyword
|
|
167
|
+
(wrap ? "<span class='keyword'>" : '') +
|
|
168
|
+
(ast.elements.map do |e|
|
|
169
|
+
highlight_tree(e, :keyword)
|
|
170
|
+
end * '').
|
|
171
|
+
gsub(%r{(<span class='([a-z]*)'>[^<]*)</span><span class='\2'>},'\1') +
|
|
172
|
+
(wrap ? "</span>" : '')
|
|
173
|
+
else
|
|
174
|
+
t = ast.text_value.gsub('<', '<').gsub('>', '>')
|
|
175
|
+
if t == ''
|
|
176
|
+
t
|
|
177
|
+
else
|
|
178
|
+
n = ast.node_type
|
|
179
|
+
n == prev ? t : "<span class='#{n}'>#{ast.text_value}</span>"
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
152
184
|
def help words = []
|
|
153
185
|
if words.empty?
|
|
154
186
|
puts %Q{
|
|
@@ -157,9 +189,11 @@ Meta-commands are:
|
|
|
157
189
|
/help\t\t\tThis help message
|
|
158
190
|
/help topic\t\thelp on a specific topic
|
|
159
191
|
/help topics\t\tList the available help topics
|
|
192
|
+
/highlight\t\t\tRe-display the parsed CQL with HTML highlighting markup
|
|
160
193
|
/list\t\t\tList all object type names (terms)
|
|
161
194
|
/load file.cql\tLoad a CQL file
|
|
162
195
|
/root rule\t\tParse just a fragment of a CQL statement, matching syntax rule only
|
|
196
|
+
/timings\t\t\tDisplay the elapsed time to execute each command
|
|
163
197
|
/tree\t\t\tDisplay the abstract syntax tree from each statement parsed
|
|
164
198
|
/trace key\t\tToggle debug tracing key, or list available keys
|
|
165
199
|
}
|
|
@@ -376,25 +410,35 @@ end
|
|
|
376
410
|
|
|
377
411
|
compiler = InteractiveCQL.new
|
|
378
412
|
statement = nil
|
|
413
|
+
loaded_files = false
|
|
379
414
|
ARGV.each do |arg|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
if statement =~ /\s*(.*?)\s*\?\s*$/
|
|
387
|
-
compiler.list_instances $1
|
|
388
|
-
statement = nil
|
|
389
|
-
elsif line =~ %r{\A/}
|
|
390
|
-
compiler.metacommand(line)
|
|
391
|
-
statement = nil
|
|
392
|
-
elsif compiler.root != :definition or
|
|
393
|
-
line.gsub(/(['"])([^\1\\]|\\.)*\1/,'') =~ /[;?]/
|
|
394
|
-
# After stripping string literals the line contains a ';' or /?', we've found the last line of the command:
|
|
395
|
-
compiler.process(statement)
|
|
396
|
-
statement = nil
|
|
415
|
+
if arg =~ /^--(.*)/
|
|
416
|
+
compiler.metacommand('/'+$1)
|
|
417
|
+
else
|
|
418
|
+
loaded_files = false or break if arg == '-'
|
|
419
|
+
compiler.load_file(arg)
|
|
420
|
+
loaded_files = true
|
|
397
421
|
end
|
|
398
422
|
end
|
|
399
|
-
puts
|
|
400
423
|
|
|
424
|
+
if !loaded_files
|
|
425
|
+
puts "Enter / for help on special commands"
|
|
426
|
+
|
|
427
|
+
while line = Readline::readline(statement ? "CQL+ " : "CQL? ", [])
|
|
428
|
+
statement = statement ? statement + "\n"+line : line
|
|
429
|
+
start = Time.now
|
|
430
|
+
case
|
|
431
|
+
when line =~ %r{\A/}
|
|
432
|
+
compiler.metacommand(line)
|
|
433
|
+
statement = nil
|
|
434
|
+
when compiler.root != :definition || line.gsub(/(['"])([^\1\\]|\\.)*\1/,'') =~ /[;?]/
|
|
435
|
+
# After stripping string literals the line contains a ';' or /?', we've found the last line of the command:
|
|
436
|
+
compiler.process(statement)
|
|
437
|
+
statement = nil
|
|
438
|
+
end
|
|
439
|
+
if $show_timings && statement == nil
|
|
440
|
+
puts "Done in #{((Time.now.to_f-start.to_f)*1000000).to_i} usec"
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
puts
|
|
444
|
+
end
|
data/examples/CQL/Blog.cql
CHANGED
|
@@ -31,7 +31,8 @@ Content provides text of Comment,
|
|
|
31
31
|
Comment consists of one text-Content;
|
|
32
32
|
|
|
33
33
|
Post is identified by its Id;
|
|
34
|
-
Post was written by one Author
|
|
34
|
+
Post was written by one Author,
|
|
35
|
+
Author wrote Post;
|
|
35
36
|
|
|
36
37
|
Topic is identified by its Id;
|
|
37
38
|
Post belongs to one Topic,
|
|
@@ -15,7 +15,7 @@ Company is identified by its Name where
|
|
|
15
15
|
Company is called Company Name;
|
|
16
16
|
Company is listed;
|
|
17
17
|
|
|
18
|
-
Meeting is identified by Date and Meeting is board meeting and Company where
|
|
18
|
+
Meeting is independent identified by Date and Meeting is board meeting and Company where
|
|
19
19
|
Meeting is held on one Date,
|
|
20
20
|
Meeting is board meeting,
|
|
21
21
|
Company held Meeting,
|
|
@@ -49,4 +49,4 @@ Manager is ceo;
|
|
|
49
49
|
/*
|
|
50
50
|
* Constraints:
|
|
51
51
|
*/
|
|
52
|
-
either Employee is supervised by Manager(
|
|
52
|
+
either Employee is supervised by Manager(2) or Employee is a Manager(1) that is ceo but not both;
|
data/examples/CQL/Death.cql
CHANGED
data/examples/CQL/Diplomacy.cql
CHANGED
|
@@ -10,17 +10,17 @@ LanguageName is written as String;
|
|
|
10
10
|
/*
|
|
11
11
|
* Entity Types
|
|
12
12
|
*/
|
|
13
|
-
Country is identified by its Name;
|
|
13
|
+
Country is independent identified by its Name;
|
|
14
14
|
|
|
15
15
|
Diplomat is identified by its Name;
|
|
16
16
|
Diplomat represents one Country (as Represented Country);
|
|
17
17
|
Diplomat serves in one Country (as Served Country);
|
|
18
18
|
|
|
19
|
-
Language is identified by its Name;
|
|
19
|
+
Language is independent identified by its Name;
|
|
20
20
|
|
|
21
21
|
LanguageUse is where
|
|
22
22
|
Language is spoken in Country,
|
|
23
|
-
Country uses
|
|
23
|
+
Country uses Language;
|
|
24
24
|
|
|
25
25
|
Ambassador is a kind of Diplomat;
|
|
26
26
|
|
|
@@ -29,8 +29,8 @@ Fluency is where
|
|
|
29
29
|
Language is spoken by Diplomat;
|
|
30
30
|
|
|
31
31
|
Representation is where
|
|
32
|
-
Ambassador is from Country (as Represented Country) to Country
|
|
33
|
-
Represented Country
|
|
32
|
+
Ambassador is from Country (as Represented Country) to Country,
|
|
33
|
+
Represented Country is represented in Country by one Ambassador;
|
|
34
34
|
|
|
35
35
|
/*
|
|
36
36
|
* Constraints:
|
|
@@ -38,11 +38,11 @@ Representation is where
|
|
|
38
38
|
for each Diplomat, Country at most one of these holds:
|
|
39
39
|
Diplomat serves in Country,
|
|
40
40
|
Diplomat represents Country;
|
|
41
|
-
Diplomat is an Ambassador that is from Country(1) to Country(2)
|
|
42
|
-
only if Diplomat represents Country(1);
|
|
43
41
|
Diplomat is an Ambassador that is from Country(2) to Country(1)
|
|
44
|
-
only if Diplomat
|
|
42
|
+
only if Diplomat represents Country(2);
|
|
43
|
+
Diplomat is an Ambassador that is from Country(1) to Country(2)
|
|
44
|
+
only if Diplomat serves in Country(2);
|
|
45
45
|
Diplomat serves in Country
|
|
46
46
|
only if Diplomat speaks Language that is spoken in Country;
|
|
47
47
|
each Ambassador occurs at least one time in
|
|
48
|
-
Ambassador is from Country to Country;
|
|
48
|
+
Ambassador is from Country(1) to Country(2);
|