active_olap 0.0.2
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/.gitignore +2 -0
- data/MIT-LICENSE +20 -0
- data/README.textile +59 -0
- data/Rakefile +5 -0
- data/active_olap.gemspec +15 -0
- data/init.rb +2 -0
- data/lib/active_olap/aggregate.rb +148 -0
- data/lib/active_olap/category.rb +46 -0
- data/lib/active_olap/configurator.rb +32 -0
- data/lib/active_olap/cube.rb +215 -0
- data/lib/active_olap/dimension.rb +230 -0
- data/lib/active_olap/helpers/chart_helper.rb +99 -0
- data/lib/active_olap/helpers/display_helper.rb +54 -0
- data/lib/active_olap/helpers/form_helper.rb +16 -0
- data/lib/active_olap/helpers/table_helper.rb +92 -0
- data/lib/active_olap/test/assertions.rb +39 -0
- data/lib/active_olap.rb +116 -0
- data/spec/integration/active_olap_spec.rb +1 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/unit/cube_spec.rb +11 -0
- data/tasks/github-gem.rake +312 -0
- data/test/active_olap_test.rb +335 -0
- data/test/helper.rb +115 -0
- data/test/helper_modules_test.rb +65 -0
- metadata +82 -0
@@ -0,0 +1,312 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/tasklib'
|
4
|
+
require 'date'
|
5
|
+
require 'git'
|
6
|
+
|
7
|
+
module GithubGem
|
8
|
+
|
9
|
+
# Detects the gemspc file of this project using heuristics.
|
10
|
+
def self.detect_gemspec_file
|
11
|
+
FileList['*.gemspec'].first
|
12
|
+
end
|
13
|
+
|
14
|
+
# Detects the main include file of this project using heuristics
|
15
|
+
def self.detect_main_include
|
16
|
+
if detect_gemspec_file =~ /^(\.*)\.gemspec$/ && File.exist?("lib/#{$1}.rb")
|
17
|
+
"lib/#{$1}.rb"
|
18
|
+
elsif FileList['lib/*.rb'].length == 1
|
19
|
+
FileList['lib/*.rb'].first
|
20
|
+
else
|
21
|
+
raise "Could not detect main include file!"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class RakeTasks
|
26
|
+
|
27
|
+
attr_reader :gemspec, :modified_files, :git
|
28
|
+
attr_accessor :gemspec_file, :task_namespace, :main_include, :root_dir, :spec_pattern, :test_pattern, :remote, :remote_branch, :local_branch
|
29
|
+
|
30
|
+
# Initializes the settings, yields itself for configuration
|
31
|
+
# and defines the rake tasks based on the gemspec file.
|
32
|
+
def initialize(task_namespace = :gem)
|
33
|
+
@gemspec_file = GithubGem.detect_gemspec_file
|
34
|
+
@task_namespace = task_namespace
|
35
|
+
@main_include = GithubGem.detect_main_include
|
36
|
+
@modified_files = []
|
37
|
+
@root_dir = Dir.pwd
|
38
|
+
@test_pattern = 'test/**/*_test.rb'
|
39
|
+
@spec_pattern = 'spec/**/*_spec.rb'
|
40
|
+
@local_branch = 'master'
|
41
|
+
@remote = 'origin'
|
42
|
+
@remote_branch = 'master'
|
43
|
+
|
44
|
+
yield(self) if block_given?
|
45
|
+
|
46
|
+
@git = Git.open(@root_dir)
|
47
|
+
load_gemspec!
|
48
|
+
define_tasks!
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
# Define Unit test tasks
|
54
|
+
def define_test_tasks!
|
55
|
+
require 'rake/testtask'
|
56
|
+
|
57
|
+
namespace(:test) do
|
58
|
+
Rake::TestTask.new(:basic) do |t|
|
59
|
+
t.pattern = test_pattern
|
60
|
+
t.verbose = true
|
61
|
+
t.libs << 'test'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Run all unit tests for #{gemspec.name}"
|
66
|
+
task(:test => ['test:basic'])
|
67
|
+
end
|
68
|
+
|
69
|
+
# Defines RSpec tasks
|
70
|
+
def define_rspec_tasks!
|
71
|
+
require 'spec/rake/spectask'
|
72
|
+
|
73
|
+
namespace(:spec) do
|
74
|
+
desc "Verify all RSpec examples for #{gemspec.name}"
|
75
|
+
Spec::Rake::SpecTask.new(:basic) do |t|
|
76
|
+
t.spec_files = FileList[spec_pattern]
|
77
|
+
end
|
78
|
+
|
79
|
+
desc "Verify all RSpec examples for #{gemspec.name} and output specdoc"
|
80
|
+
Spec::Rake::SpecTask.new(:specdoc) do |t|
|
81
|
+
t.spec_files = FileList[spec_pattern]
|
82
|
+
t.spec_opts << '--format' << 'specdoc' << '--color'
|
83
|
+
end
|
84
|
+
|
85
|
+
desc "Run RCov on specs for #{gemspec.name}"
|
86
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
87
|
+
t.spec_files = FileList[spec_pattern]
|
88
|
+
t.rcov = true
|
89
|
+
t.rcov_opts = ['--exclude', '"spec/*,gems/*"', '--rails']
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
desc "Verify all RSpec examples for #{gemspec.name} and output specdoc"
|
94
|
+
task(:spec => ['spec:specdoc'])
|
95
|
+
end
|
96
|
+
|
97
|
+
# Defines the rake tasks
|
98
|
+
def define_tasks!
|
99
|
+
|
100
|
+
define_test_tasks! if has_tests?
|
101
|
+
define_rspec_tasks! if has_specs?
|
102
|
+
|
103
|
+
namespace(@task_namespace) do
|
104
|
+
desc "Updates the filelist in the gemspec file"
|
105
|
+
task(:manifest) { manifest_task }
|
106
|
+
|
107
|
+
desc "Builds the .gem package"
|
108
|
+
task(:build => :manifest) { build_task }
|
109
|
+
|
110
|
+
desc "Sets the version of the gem in the gemspec"
|
111
|
+
task(:set_version => [:check_version, :check_current_branch]) { version_task }
|
112
|
+
task(:check_version => :fetch_origin) { check_version_task }
|
113
|
+
|
114
|
+
task(:fetch_origin) { fetch_origin_task }
|
115
|
+
task(:check_current_branch) { check_current_branch_task }
|
116
|
+
task(:check_clean_status) { check_clean_status_task }
|
117
|
+
task(:check_not_diverged => :fetch_origin) { check_not_diverged_task }
|
118
|
+
|
119
|
+
checks = [:check_current_branch, :check_clean_status, :check_not_diverged, :check_version]
|
120
|
+
checks.unshift('spec:basic') if has_specs?
|
121
|
+
checks.unshift('test:basic') if has_tests?
|
122
|
+
checks.push << [:check_rubyforge] if gemspec.rubyforge_project
|
123
|
+
|
124
|
+
desc "Perform all checks that would occur before a release"
|
125
|
+
task(:release_checks => checks)
|
126
|
+
|
127
|
+
release_tasks = [:release_checks, :set_version, :build, :github_release]
|
128
|
+
release_tasks << [:rubyforge_release] if gemspec.rubyforge_project
|
129
|
+
|
130
|
+
desc "Release a new verison of the gem"
|
131
|
+
task(:release => release_tasks) { release_task }
|
132
|
+
|
133
|
+
task(:check_rubyforge) { check_rubyforge_task }
|
134
|
+
task(:rubyforge_release) { rubyforge_release_task }
|
135
|
+
task(:github_release => [:commit_modified_files, :tag_version]) { github_release_task }
|
136
|
+
task(:tag_version) { tag_version_task }
|
137
|
+
task(:commit_modified_files) { commit_modified_files_task }
|
138
|
+
|
139
|
+
desc "Updates the gem release tasks with the latest version on Github"
|
140
|
+
task(:update_tasks) { update_tasks_task }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Updates the files list and test_files list in the gemspec file using the list of files
|
145
|
+
# in the repository and the spec/test file pattern.
|
146
|
+
def manifest_task
|
147
|
+
# Load all the gem's files using "git ls-files"
|
148
|
+
repository_files = git.ls_files.keys
|
149
|
+
test_files = Dir[test_pattern] + Dir[spec_pattern]
|
150
|
+
|
151
|
+
update_gemspec(:files, repository_files)
|
152
|
+
update_gemspec(:test_files, repository_files & test_files)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Builds the gem
|
156
|
+
def build_task
|
157
|
+
sh "gem build -q #{gemspec_file}"
|
158
|
+
Dir.mkdir('pkg') unless File.exist?('pkg')
|
159
|
+
sh "mv #{gemspec.name}-#{gemspec.version}.gem pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
160
|
+
end
|
161
|
+
|
162
|
+
# Updates the version number in the gemspec file, the VERSION constant in the main
|
163
|
+
# include file and the contents of the VERSION file.
|
164
|
+
def version_task
|
165
|
+
update_gemspec(:version, ENV['VERSION']) if ENV['VERSION']
|
166
|
+
update_gemspec(:date, Date.today)
|
167
|
+
|
168
|
+
update_version_file(gemspec.version)
|
169
|
+
update_version_constant(gemspec.version)
|
170
|
+
end
|
171
|
+
|
172
|
+
def check_version_task
|
173
|
+
raise "#{ENV['VERSION']} is not a valid version number!" if ENV['VERSION'] && !Gem::Version.correct?(ENV['VERSION'])
|
174
|
+
proposed_version = Gem::Version.new(ENV['VERSION'] || gemspec.version)
|
175
|
+
# Loads the latest version number using the created tags
|
176
|
+
newest_version = git.tags.map { |tag| tag.name.split('-').last }.compact.map { |v| Gem::Version.new(v) }.max
|
177
|
+
raise "This version (#{proposed_version}) is not higher than the highest tagged version (#{newest_version})" if newest_version && newest_version >= proposed_version
|
178
|
+
end
|
179
|
+
|
180
|
+
# Checks whether the current branch is not diverged from the remote branch
|
181
|
+
def check_not_diverged_task
|
182
|
+
raise "The current branch is diverged from the remote branch!" if git.log.between('HEAD', git.branches["#{remote}/#{remote_branch}"].gcommit).any?
|
183
|
+
end
|
184
|
+
|
185
|
+
# Checks whether the repository status ic clean
|
186
|
+
def check_clean_status_task
|
187
|
+
raise "The current working copy contains modifications" if git.status.changed.any?
|
188
|
+
end
|
189
|
+
|
190
|
+
# Checks whether the current branch is correct
|
191
|
+
def check_current_branch_task
|
192
|
+
raise "Currently not on #{local_branch} branch!" unless git.branch.name == local_branch.to_s
|
193
|
+
end
|
194
|
+
|
195
|
+
# Fetches the latest updates from Github
|
196
|
+
def fetch_origin_task
|
197
|
+
git.fetch('origin')
|
198
|
+
end
|
199
|
+
|
200
|
+
# Commits every file that has been changed by the release task.
|
201
|
+
def commit_modified_files_task
|
202
|
+
if modified_files.any?
|
203
|
+
modified_files.each { |file| git.add(file) }
|
204
|
+
git.commit("Released #{gemspec.name} gem version #{gemspec.version}")
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Adds a tag for the released version
|
209
|
+
def tag_version_task
|
210
|
+
git.add_tag("#{gemspec.name}-#{gemspec.version}")
|
211
|
+
end
|
212
|
+
|
213
|
+
# Pushes the changes and tag to github
|
214
|
+
def github_release_task
|
215
|
+
git.push(remote, remote_branch, true)
|
216
|
+
end
|
217
|
+
|
218
|
+
# Checks whether Rubyforge is configured properly
|
219
|
+
def check_rubyforge_task
|
220
|
+
raise "Could not login on rubyforge!" unless `rubyforge login 2>&1`.strip.empty?
|
221
|
+
output = `rubyforge names`.split("\n")
|
222
|
+
raise "Rubyforge group not found!" unless output.any? { |line| %r[^groups\s*\:.*\b#{Regexp.quote(gemspec.rubyforge_project)}\b.*] =~ line }
|
223
|
+
raise "Rubyforge package not found!" unless output.any? { |line| %r[^packages\s*\:.*\b#{Regexp.quote(gemspec.name)}\b.*] =~ line }
|
224
|
+
end
|
225
|
+
|
226
|
+
# Task to release the .gem file toRubyforge.
|
227
|
+
def rubyforge_release_task
|
228
|
+
sh 'rubyforge', 'add_release', gemspec.rubyforge_project, gemspec.name, gemspec.version.to_s, "pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
229
|
+
end
|
230
|
+
|
231
|
+
# Gem release task.
|
232
|
+
# All work is done by the task's dependencies, so just display a release completed message.
|
233
|
+
def release_task
|
234
|
+
puts
|
235
|
+
puts '------------------------------------------------------------'
|
236
|
+
puts "Released #{gemspec.name} version #{gemspec.version}"
|
237
|
+
end
|
238
|
+
|
239
|
+
private
|
240
|
+
|
241
|
+
# Checks whether this project has any RSpec files
|
242
|
+
def has_specs?
|
243
|
+
FileList[spec_pattern].any?
|
244
|
+
end
|
245
|
+
|
246
|
+
# Checks whether this project has any unit test files
|
247
|
+
def has_tests?
|
248
|
+
FileList[test_pattern].any?
|
249
|
+
end
|
250
|
+
|
251
|
+
# Loads the gemspec file
|
252
|
+
def load_gemspec!
|
253
|
+
@gemspec = eval(File.read(@gemspec_file))
|
254
|
+
end
|
255
|
+
|
256
|
+
# Updates the VERSION file with the new version
|
257
|
+
def update_version_file(version)
|
258
|
+
if File.exists?('VERSION')
|
259
|
+
File.open('VERSION', 'w') { |f| f << version.to_s }
|
260
|
+
modified_files << 'VERSION'
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Updates the VERSION constant in the main include file if it exists
|
265
|
+
def update_version_constant(version)
|
266
|
+
file_contents = File.read(main_include)
|
267
|
+
if file_contents.sub!(/^(\s+VERSION\s*=\s*)[^\s].*$/) { $1 + version.to_s.inspect }
|
268
|
+
File.open(main_include, 'w') { |f| f << file_contents }
|
269
|
+
modified_files << main_include
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# Updates an attribute of the gemspec file.
|
274
|
+
# This function will open the file, and search/replace the attribute using a regular expression.
|
275
|
+
def update_gemspec(attribute, new_value, literal = false)
|
276
|
+
|
277
|
+
unless literal
|
278
|
+
new_value = case new_value
|
279
|
+
when Array then "%w(#{new_value.join(' ')})"
|
280
|
+
when Hash, String then new_value.inspect
|
281
|
+
when Date then new_value.strftime('%Y-%m-%d').inspect
|
282
|
+
else raise "Cannot write value #{new_value.inspect} to gemspec file!"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
spec = File.read(gemspec_file)
|
287
|
+
regexp = Regexp.new('^(\s+\w+\.' + Regexp.quote(attribute.to_s) + '\s*=\s*)[^\s].*$')
|
288
|
+
if spec.sub!(regexp) { $1 + new_value }
|
289
|
+
File.open(gemspec_file, 'w') { |f| f << spec }
|
290
|
+
modified_files << gemspec_file
|
291
|
+
|
292
|
+
# Reload the gemspec so the changes are incorporated
|
293
|
+
load_gemspec!
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
# Updates the tasks file using the latest file found on Github
|
298
|
+
def update_tasks_task
|
299
|
+
require 'net/http'
|
300
|
+
|
301
|
+
server = 'github.com'
|
302
|
+
path = '/wvanbergen/github-gem/raw/master/tasks/github-gem.rake'
|
303
|
+
|
304
|
+
Net::HTTP.start(server) do |http|
|
305
|
+
response = http.get(path)
|
306
|
+
open(__FILE__, "w") { |file| file.write(response.body) }
|
307
|
+
end
|
308
|
+
puts "Updated gem release tasks file with latest version."
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
end
|
@@ -0,0 +1,335 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/helper"
|
2
|
+
|
3
|
+
class ActiveOLAP::QueryTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include ActiveOlapTestHelper
|
6
|
+
|
7
|
+
def setup
|
8
|
+
create_db
|
9
|
+
create_corpus
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
cleanup_db
|
14
|
+
end
|
15
|
+
|
16
|
+
# --- TESTS ---------------------------------
|
17
|
+
|
18
|
+
def test_wrong_overlap_dimension_usage
|
19
|
+
|
20
|
+
begin
|
21
|
+
cube = OlapTest.olap_query :with_overlap, :category
|
22
|
+
assert false, "An exception should have been thrown"
|
23
|
+
rescue
|
24
|
+
assert true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
cube = OlapTest.olap_query :with_overlap, :aggregate => :avg_int_field
|
29
|
+
assert false, "An exception should have been thrown"
|
30
|
+
rescue
|
31
|
+
assert true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_with_associations
|
36
|
+
cube = OlapTest.olap_query :category, :aggregate => [:count_distinct, :total_price]
|
37
|
+
assert_active_olap_cube cube, [5]
|
38
|
+
assert_equal 1, cube[:no_category][:count_distinct]
|
39
|
+
assert_equal 5.7, cube[:no_category][:total_price]
|
40
|
+
assert_equal nil, cube[:first_cat][:total_price]
|
41
|
+
|
42
|
+
cube = OlapTest.olap_query(:in_association)
|
43
|
+
assert_active_olap_cube cube, [3]
|
44
|
+
assert_equal 1, cube[:first]
|
45
|
+
assert_equal 1, cube[:second]
|
46
|
+
assert_equal 4, cube[:other]
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_time_dimension
|
50
|
+
cube = OlapTest.olap_query(:the_time)
|
51
|
+
assert_active_olap_cube cube, [20]
|
52
|
+
|
53
|
+
cube = OlapTest.olap_query([:the_time, {:period_count => 10}])
|
54
|
+
assert_active_olap_cube cube, [10]
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_with_aggregates
|
58
|
+
# defined using a smart symbol
|
59
|
+
cube = OlapTest.olap_query(:category, :aggregate => :sum_int_field)
|
60
|
+
assert_equal 33, cube[:first_cat]
|
61
|
+
assert_equal 77, cube[:second_cat]
|
62
|
+
assert_equal 33, cube[:no_category]
|
63
|
+
assert_equal nil, cube[:third_cat]
|
64
|
+
assert_equal nil, cube[:other]
|
65
|
+
|
66
|
+
# defined using the configurator
|
67
|
+
cube = OlapTest.olap_query(:category, :aggregate => :sum_int)
|
68
|
+
assert_equal 33, cube[:first_cat]
|
69
|
+
assert_equal 77, cube[:second_cat]
|
70
|
+
|
71
|
+
# using an SQL expression
|
72
|
+
cube = OlapTest.olap_query(:category, :aggregate => 'avg(olap_tests.int_field)')
|
73
|
+
assert_equal 33.0, cube[:first_cat]
|
74
|
+
assert_equal (33.0 + 44.0) / 2, cube[:second_cat]
|
75
|
+
assert_equal 33.0, cube[:no_category]
|
76
|
+
assert_equal nil, cube[:third_cat]
|
77
|
+
assert_equal nil, cube[:other]
|
78
|
+
|
79
|
+
# multiple aggregates
|
80
|
+
cube = OlapTest.olap_query(:category, :aggregate => [:count_distinct, 'avg(olap_tests.int_field)', :sum_int ])
|
81
|
+
assert_equal 1, cube.depth
|
82
|
+
assert_equal 5, cube.breadth
|
83
|
+
|
84
|
+
assert_equal 1, cube[:first_cat][:count_distinct]
|
85
|
+
assert_equal 33.0, cube[:first_cat][:sum_int]
|
86
|
+
assert_equal (33.0 + 44.0) / 2, cube[:second_cat]['avg(olap_tests.int_field)']
|
87
|
+
|
88
|
+
# array notation
|
89
|
+
cube = OlapTest.olap_query(:category, :aggregate => [:count_distinct, 'avg(olap_tests.int_field)', :sum_int] )
|
90
|
+
assert_equal 1, cube.depth
|
91
|
+
assert_equal 5, cube.breadth
|
92
|
+
|
93
|
+
assert_equal 1, cube[:first_cat][:count_distinct]
|
94
|
+
assert_equal 33.0, cube[:first_cat][:sum_int]
|
95
|
+
assert_equal (33.0 + 44.0) / 2, cube[:second_cat]['avg(olap_tests.int_field)']
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_with_overlap
|
99
|
+
cube = OlapTest.olap_query(:with_overlap)
|
100
|
+
assert_active_olap_cube cube, [3]
|
101
|
+
|
102
|
+
assert_equal 2, cube[:like_23]
|
103
|
+
assert_equal 3, cube[:starts_with_1]
|
104
|
+
assert_equal 1, cube[:other]
|
105
|
+
|
106
|
+
assert cube.sum > OlapTest.count
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_conditions
|
110
|
+
cube = OlapTest.olap_query(:field => :category_field, :conditions => {:datetime_field => nil})
|
111
|
+
assert_equal 1, cube.depth
|
112
|
+
assert_equal 2, cube.sum
|
113
|
+
|
114
|
+
assert_equal 1, OlapTest.olap_drilldown({:field => :category_field, :conditions => {:datetime_field => nil}} => 'second_cat').count
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_config_with_lambda_trend_and_transpose
|
118
|
+
|
119
|
+
cube = OlapTest.olap_query(:category, :my_trend)
|
120
|
+
assert_equal 5, cube.breadth # 4 + other
|
121
|
+
assert_equal 2, cube.depth
|
122
|
+
assert_equal :first_cat, cube.dimension.categories.first.label
|
123
|
+
|
124
|
+
# switch the dimensions using transpose
|
125
|
+
cube = cube.transpose
|
126
|
+
|
127
|
+
assert_equal 20, cube.breadth # 20 periods
|
128
|
+
assert_equal 2, cube.depth
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_with_config
|
133
|
+
cube = OlapTest.olap_query(:category)
|
134
|
+
assert_equal 1, cube[:first_cat]
|
135
|
+
assert_equal 2, cube[:second_cat]
|
136
|
+
assert_equal 0, cube[:third_cat]
|
137
|
+
assert_equal nil, cube[:fourth_cat]
|
138
|
+
assert_equal 1, cube[:no_category]
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
def test_with_periods
|
143
|
+
dimension_1 = { :trend => { :timestamp_field => :datetime_field, :period_count => 5}}
|
144
|
+
dimension_2 = :category_field
|
145
|
+
|
146
|
+
cube = OlapTest.olap_query(dimension_1, dimension_2)
|
147
|
+
|
148
|
+
assert_active_olap_cube cube, [5, :unknown]
|
149
|
+
|
150
|
+
assert_equal 1, cube[:period_2, 'first_cat']
|
151
|
+
assert_equal 0, cube[:period_2, 'second_cat']
|
152
|
+
assert_equal 0, cube[:period_0, 'first_cat']
|
153
|
+
assert_equal 1, cube[:period_0, 'second_cat']
|
154
|
+
assert_equal 0, cube[:period_3, 'second_cat']
|
155
|
+
assert_equal 0, cube[:period_1, 'first_cat']
|
156
|
+
|
157
|
+
assert_equal 0, OlapTest.olap_drilldown(dimension_1 => :period_4, dimension_2 => 'second_cat').count
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_with_three_dimensions
|
161
|
+
dimension_1 = { :categories => { :datetime_field_set => 'datetime_field IS NOT NULL' } }
|
162
|
+
dimension_2 = :category_field
|
163
|
+
dimension_3 = { :categories => { :string_like_2 => ["string_field LIKE ?", '%2%'] } }
|
164
|
+
|
165
|
+
cube = OlapTest.olap_query(dimension_1, dimension_2, dimension_3)
|
166
|
+
assert_active_olap_cube cube, [2, :unknown, 2]
|
167
|
+
|
168
|
+
# check that every value is set
|
169
|
+
assert_equal 1, cube[:datetime_field_set, 'first_cat',:string_like_2]
|
170
|
+
assert_equal 0, cube[:datetime_field_set, 'first_cat',:other]
|
171
|
+
assert_equal 0, cube[:datetime_field_set, 'second_cat',:string_like_2]
|
172
|
+
assert_equal 1, cube[:datetime_field_set, 'second_cat',:other]
|
173
|
+
assert_equal 0, cube[:datetime_field_set, nil,:string_like_2]
|
174
|
+
assert_equal 0, cube[:datetime_field_set, nil,:other]
|
175
|
+
assert_equal 0, cube[:other, 'first_cat',:string_like_2]
|
176
|
+
assert_equal 0, cube[:other, 'first_cat',:other]
|
177
|
+
assert_equal 1, cube[:other, 'second_cat',:string_like_2]
|
178
|
+
assert_equal 0, cube[:other, 'second_cat',:other]
|
179
|
+
assert_equal 1, cube[:other, nil,:string_like_2]
|
180
|
+
assert_equal 0, cube[:other, nil,:other]
|
181
|
+
|
182
|
+
# checking that drilling down results in cubes as well
|
183
|
+
intermediate_cube = cube[:other]
|
184
|
+
assert_active_olap_cube intermediate_cube, [:unknown, 2]
|
185
|
+
assert_active_olap_cube cube[:other, 'second_cat'], [2]
|
186
|
+
assert_active_olap_cube cube[:other]['second_cat'], [2]
|
187
|
+
|
188
|
+
assert 1, intermediate_cube['second_cat'][:string_like_2]
|
189
|
+
assert 1, cube[:other, 'second_cat'][:string_like_2]
|
190
|
+
|
191
|
+
# check for order preservation
|
192
|
+
found_categories = []
|
193
|
+
intermediate_cube.each do |category, drilled_down_cube|
|
194
|
+
assert_active_olap_cube drilled_down_cube, [2]
|
195
|
+
found_categories << category.label
|
196
|
+
end
|
197
|
+
assert_equal ['first_cat', 'second_cat', nil], found_categories
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_condition_field_with_two_dimensions
|
201
|
+
dimension_1 = { :categories => { :datetime_field_set => 'datetime_field IS NOT NULL' } }
|
202
|
+
dimension_2 = :category_field
|
203
|
+
|
204
|
+
cube = OlapTest.olap_query(dimension_1, dimension_2)
|
205
|
+
assert_active_olap_cube cube, [2, :unknown]
|
206
|
+
|
207
|
+
assert_equal 1, cube[:datetime_field_set, 'first_cat']
|
208
|
+
assert_equal 1, cube[:datetime_field_set, 'second_cat']
|
209
|
+
assert_equal 0, cube[:datetime_field_set, nil]
|
210
|
+
assert_equal 0, cube[:other, 'first_cat']
|
211
|
+
assert_equal 1, cube[:other, 'second_cat']
|
212
|
+
assert_equal 1, cube[:other, nil]
|
213
|
+
|
214
|
+
cube = OlapTest.olap_query(dimension_2, dimension_1)
|
215
|
+
assert_active_olap_cube cube, [:unknown, 2]
|
216
|
+
|
217
|
+
assert_equal 1, cube['first_cat', :datetime_field_set]
|
218
|
+
assert_equal 1, cube['second_cat', :datetime_field_set]
|
219
|
+
assert_equal 1, cube['second_cat', :other]
|
220
|
+
assert_equal 1, cube[nil, :other]
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_condition_field
|
224
|
+
cube = OlapTest.olap_query(:category_field)
|
225
|
+
assert_active_olap_cube cube, [:unknown]
|
226
|
+
|
227
|
+
assert_equal 1, cube['first_cat']
|
228
|
+
assert_equal 2, cube['second_cat']
|
229
|
+
assert_equal nil, cube['third_cat']
|
230
|
+
assert_equal nil, cube['fourth_cat']
|
231
|
+
assert_equal 1, cube[nil]
|
232
|
+
|
233
|
+
assert_equal 1, OlapTest.olap_drilldown(:category_field => nil).count
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_two_dimensions
|
237
|
+
dimension_1 = { :categories => { :datetime_field_not_set => {:datetime_field => nil} } }
|
238
|
+
dimension_2 = { :categories => { :string_like_2 => ["string_field LIKE ?", '%2%'] } }
|
239
|
+
|
240
|
+
cube = OlapTest.olap_query(dimension_1, dimension_2)
|
241
|
+
assert_active_olap_cube cube, [2, 2]
|
242
|
+
|
243
|
+
assert_equal 0, cube[:datetime_field_not_set,:other]
|
244
|
+
assert_equal 2, cube[:datetime_field_not_set,:string_like_2]
|
245
|
+
assert_equal 1, cube[:other,:other]
|
246
|
+
assert_equal 1, cube[:other,:string_like_2]
|
247
|
+
|
248
|
+
assert_equal 0, OlapTest.olap_drilldown(dimension_1 => :datetime_field_not_set, dimension_2 => :other).length
|
249
|
+
assert_equal 2, OlapTest.olap_drilldown(dimension_1 => :datetime_field_not_set, dimension_2 => :string_like_2).length
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
def test_two_dimensions_without_other
|
254
|
+
dimension_1 = { :categories => { :datetime_field_not_set => {:datetime_field => nil }, :other => false} }
|
255
|
+
dimension_2 = { :categories => { :string_like_2 => ["string_field LIKE ?", '%2%'], :other => false } }
|
256
|
+
|
257
|
+
cube = OlapTest.olap_query(dimension_1, dimension_2)
|
258
|
+
assert_active_olap_cube cube, [1, 1]
|
259
|
+
|
260
|
+
assert_nil cube[:other]
|
261
|
+
assert_nil cube[:datetime_field_not_set,:other]
|
262
|
+
assert_equal 2, cube[:datetime_field_not_set,:string_like_2]
|
263
|
+
|
264
|
+
end
|
265
|
+
|
266
|
+
def test_olap_query
|
267
|
+
cube = OlapTest.olap_query :categories => { :datetime_field_not_set => {:datetime_field => nil} }
|
268
|
+
assert_active_olap_cube cube, [2]
|
269
|
+
assert_equal 2, cube[:datetime_field_not_set]
|
270
|
+
assert_equal 2, cube[:other]
|
271
|
+
|
272
|
+
cube = OlapTest.olap_query :categories => { :string_like_2 => ["string_field LIKE ?", '%2%'] }
|
273
|
+
assert_active_olap_cube cube, [2]
|
274
|
+
assert_equal 3, cube[:string_like_2]
|
275
|
+
assert_equal 1, cube[:other]
|
276
|
+
|
277
|
+
found_categories = []
|
278
|
+
cube.each do |category, res|
|
279
|
+
assert_kind_of Numeric, res
|
280
|
+
found_categories << category.label
|
281
|
+
end
|
282
|
+
# cassert the correct order for the categories
|
283
|
+
assert_equal [:string_like_2, :other], found_categories
|
284
|
+
end
|
285
|
+
|
286
|
+
def test_drilldown
|
287
|
+
unsets = OlapTest.olap_drilldown({:categories => {:datetime_field_not_set => {:datetime_field => nil}}} => :datetime_field_not_set)
|
288
|
+
assert_equal 2, unsets.length
|
289
|
+
|
290
|
+
others = OlapTest.olap_drilldown({:categories => {:datetime_field_not_set => {:datetime_field => nil}}} => :other)
|
291
|
+
assert_equal 2, others.length
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_olap_query_within_scope
|
295
|
+
|
296
|
+
assert_active_olap_enabled OlapTest
|
297
|
+
|
298
|
+
assert_equal 3, OlapTest.int_field_33.count
|
299
|
+
cube = OlapTest.int_field_33.olap_query :categories => { :datetime_field_not_set => {:datetime_field => nil} }
|
300
|
+
assert_active_olap_cube cube, [2]
|
301
|
+
assert_equal 1, cube[:datetime_field_not_set]
|
302
|
+
assert_equal 2, cube[:other] # the other record does not fall within the scope int_field_33
|
303
|
+
|
304
|
+
unsets = OlapTest.int_field_33.olap_drilldown({:categories => {:datetime_field_not_set => {:datetime_field => nil}}} => :datetime_field_not_set)
|
305
|
+
assert_equal 1, unsets.length
|
306
|
+
|
307
|
+
others = OlapTest.int_field_33.olap_drilldown({:categories => {:datetime_field_not_set => {:datetime_field => nil}}} => :other)
|
308
|
+
assert_equal 2, others.length
|
309
|
+
end
|
310
|
+
|
311
|
+
# the actual SQL expression strings are connection specific,
|
312
|
+
# For this test, they are in SQLite3 format
|
313
|
+
def test_other_condition
|
314
|
+
dimension = ActiveOLAP::Dimension.create(OlapTest, :categories => { :datetime_field_set => {:datetime_field => nil}})
|
315
|
+
assert_kind_of ActiveOLAP::Dimension, dimension
|
316
|
+
assert_equal '((("olap_tests"."datetime_field" IS NULL)) IS NULL OR NOT(("olap_tests"."datetime_field" IS NULL)))', dimension[:other].to_sanitized_sql
|
317
|
+
|
318
|
+
dimension = { :categories => { :datetime_field_set => {:datetime_field => nil} } }
|
319
|
+
dimension = ActiveOLAP::Dimension.create(OlapTest, dimension)
|
320
|
+
assert_kind_of String, dimension[:other].conditions
|
321
|
+
|
322
|
+
dimension = { :categories => { :other => false, :datetime_field_set => {:datetime_field => nil} } }
|
323
|
+
dimension = ActiveOLAP::Dimension.create(OlapTest, dimension)
|
324
|
+
assert_nil dimension[:other]
|
325
|
+
|
326
|
+
dimension = { :categories => { :other => nil, :datetime_field_set => {:datetime_field => nil} } }
|
327
|
+
dimension = ActiveOLAP::Dimension.create(OlapTest, dimension)
|
328
|
+
assert_nil dimension[:other]
|
329
|
+
|
330
|
+
dimension = { :categories => { :other => ['willem = ?', "grea't"], :datetime_field_set => {:datetime_field => nil} } }
|
331
|
+
dimension = ActiveOLAP::Dimension.create(OlapTest, dimension)
|
332
|
+
assert_equal ["willem = ?", "grea't"], dimension[:other].conditions
|
333
|
+
assert_equal "willem = 'grea''t'", dimension[:other].to_sanitized_sql
|
334
|
+
end
|
335
|
+
end
|