mondrian-olap 0.8.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Changelog.md +36 -0
- data/LICENSE.txt +1 -1
- data/README.md +5 -2
- data/VERSION +1 -1
- data/lib/mondrian/jars/commons-collections-3.2.2.jar +0 -0
- data/lib/mondrian/jars/commons-lang-2.6.jar +0 -0
- data/lib/mondrian/jars/commons-logging-1.2.jar +0 -0
- data/lib/mondrian/jars/commons-vfs2-2.2.jar +0 -0
- data/lib/mondrian/jars/eigenbase-xom-1.3.5.jar +0 -0
- data/lib/mondrian/jars/log4j.properties +2 -4
- data/lib/mondrian/jars/mondrian-8.3.0.5.jar +0 -0
- data/lib/mondrian/olap/connection.rb +112 -16
- data/lib/mondrian/olap/cube.rb +9 -2
- data/lib/mondrian/olap/error.rb +37 -8
- data/lib/mondrian/olap/query.rb +14 -17
- data/lib/mondrian/olap/result.rb +73 -40
- data/lib/mondrian/olap/schema.rb +1 -0
- data/lib/mondrian/olap/schema_element.rb +20 -4
- data/lib/mondrian/olap/schema_udf.rb +21 -16
- data/spec/connection_role_spec.rb +65 -12
- data/spec/connection_spec.rb +2 -0
- data/spec/cube_cache_control_spec.rb +16 -12
- data/spec/query_spec.rb +157 -21
- data/spec/schema_definition_spec.rb +151 -55
- data/spec/spec_helper.rb +75 -0
- metadata +65 -64
- data/lib/mondrian/jars/commons-collections-3.2.1.jar +0 -0
- data/lib/mondrian/jars/commons-logging-1.1.1.jar +0 -0
- data/lib/mondrian/jars/commons-vfs2-2.1-20150824.jar +0 -0
- data/lib/mondrian/jars/eigenbase-xom-1.3.1.jar +0 -0
- data/lib/mondrian/jars/mondrian-3.12.0.6-237.jar +0 -0
data/lib/mondrian/olap/query.rb
CHANGED
@@ -79,7 +79,7 @@ module Mondrian
|
|
79
79
|
self
|
80
80
|
end
|
81
81
|
|
82
|
-
def filter(condition, options={})
|
82
|
+
def filter(condition, options = {})
|
83
83
|
raise ArgumentError, "cannot use filter method before axis or with_set method" unless @current_set
|
84
84
|
@current_set.replace [:filter, @current_set.clone, condition]
|
85
85
|
@current_set << options[:as] if options[:as]
|
@@ -138,7 +138,7 @@ module Mondrian
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
|
-
def hierarchize(order=nil, all=nil)
|
141
|
+
def hierarchize(order = nil, all = nil)
|
142
142
|
raise ArgumentError, "cannot use hierarchize method before axis or with_set method" unless @current_set
|
143
143
|
order = order && order.to_s.upcase
|
144
144
|
raise ArgumentError, "invalid hierarchize order #{order.inspect}" unless order.nil? || order == 'POST'
|
@@ -152,7 +152,7 @@ module Mondrian
|
|
152
152
|
self
|
153
153
|
end
|
154
154
|
|
155
|
-
def hierarchize_all(order=nil)
|
155
|
+
def hierarchize_all(order = nil)
|
156
156
|
hierarchize(order, :all)
|
157
157
|
end
|
158
158
|
|
@@ -236,19 +236,15 @@ module Mondrian
|
|
236
236
|
end
|
237
237
|
|
238
238
|
def execute(parameters = {})
|
239
|
-
|
240
|
-
@connection.execute to_mdx, parameters
|
241
|
-
end
|
239
|
+
@connection.execute to_mdx, parameters
|
242
240
|
end
|
243
241
|
|
244
242
|
def execute_drill_through(options = {})
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
@connection.execute_drill_through drill_through_mdx
|
251
|
-
end
|
243
|
+
drill_through_mdx = "DRILLTHROUGH "
|
244
|
+
drill_through_mdx << "MAXROWS #{options[:max_rows]} " if options[:max_rows]
|
245
|
+
drill_through_mdx << to_mdx
|
246
|
+
drill_through_mdx << " RETURN #{Array(options[:return]).join(',')}" if options[:return]
|
247
|
+
@connection.execute_drill_through drill_through_mdx
|
252
248
|
end
|
253
249
|
|
254
250
|
private
|
@@ -300,10 +296,10 @@ module Mondrian
|
|
300
296
|
}
|
301
297
|
|
302
298
|
def members_to_mdx(members)
|
303
|
-
# if only one member which does not end with ]
|
299
|
+
# if only one member which does not end with ] or .Item(...)
|
304
300
|
# then assume it is expression which returns set
|
305
301
|
# TODO: maybe always include also single expressions in {...} to avoid some edge cases?
|
306
|
-
if members.length == 1 && members[0]
|
302
|
+
if members.length == 1 && members[0] !~ /(\]|\.Item\(\d+\))\z/i
|
307
303
|
members[0]
|
308
304
|
elsif members[0].is_a?(Symbol)
|
309
305
|
case members[0]
|
@@ -380,8 +376,9 @@ module Mondrian
|
|
380
376
|
end
|
381
377
|
|
382
378
|
def extract_dimension_name(full_name)
|
383
|
-
|
384
|
-
|
379
|
+
# "[Foo [Bar]]].[Baz]" => "Foo [Bar]"
|
380
|
+
if full_name
|
381
|
+
full_name.gsub(/\A\[|\]\z/, '').split('].[').first.try(:gsub, ']]', ']')
|
385
382
|
end
|
386
383
|
end
|
387
384
|
end
|
data/lib/mondrian/olap/result.rb
CHANGED
@@ -3,12 +3,14 @@ require 'bigdecimal'
|
|
3
3
|
module Mondrian
|
4
4
|
module OLAP
|
5
5
|
class Result
|
6
|
-
def initialize(connection, raw_cell_set)
|
6
|
+
def initialize(connection, raw_cell_set, options = {})
|
7
7
|
@connection = connection
|
8
8
|
@raw_cell_set = raw_cell_set
|
9
|
+
@profiling_handler = options[:profiling_handler]
|
10
|
+
@total_duration = options[:total_duration]
|
9
11
|
end
|
10
12
|
|
11
|
-
attr_reader :raw_cell_set
|
13
|
+
attr_reader :raw_cell_set, :profiling_handler, :total_duration
|
12
14
|
|
13
15
|
def axes_count
|
14
16
|
axes.length
|
@@ -105,6 +107,32 @@ module Mondrian
|
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
110
|
+
def profiling_plan
|
111
|
+
if profiling_handler
|
112
|
+
@raw_cell_set.close
|
113
|
+
if plan = profiling_handler.plan
|
114
|
+
plan.gsub("\r\n", "\n")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def profiling_timing
|
120
|
+
if profiling_handler
|
121
|
+
@raw_cell_set.close
|
122
|
+
profiling_handler.timing
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def profiling_mark_full(name, duration)
|
127
|
+
profiling_timing && profiling_timing.markFull(name, duration)
|
128
|
+
end
|
129
|
+
|
130
|
+
def profiling_timing_string
|
131
|
+
if profiling_timing && (timing_string = profiling_timing.toString)
|
132
|
+
timing_string.gsub("\r\n", "\n")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
108
136
|
# Specify drill through cell position, for example, as
|
109
137
|
# :row => 0, :cell => 1
|
110
138
|
# Specify max returned rows with :max_rows parameter
|
@@ -177,7 +205,7 @@ module Mondrian
|
|
177
205
|
if @raw_result_set.next
|
178
206
|
row_values = []
|
179
207
|
column_types.each_with_index do |column_type, i|
|
180
|
-
row_values << Result.java_to_ruby_value(@raw_result_set.getObject(i+1), column_type)
|
208
|
+
row_values << Result.java_to_ruby_value(@raw_result_set.getObject(i + 1), column_type)
|
181
209
|
end
|
182
210
|
row_values
|
183
211
|
else
|
@@ -248,24 +276,28 @@ module Mondrian
|
|
248
276
|
sql_non_extended = rolap_cell.getDrillThroughSQL(return_expressions, false)
|
249
277
|
sql_extended = rolap_cell.getDrillThroughSQL(return_expressions, true)
|
250
278
|
|
251
|
-
if sql_non_extended =~ /\Aselect (.*) from (.*) where (.*) order by (.*)\Z/
|
279
|
+
if sql_non_extended =~ /\Aselect (.*) from (.*) where (.*) order by (.*)\Z/m
|
280
|
+
non_extended_from = $2
|
281
|
+
non_extended_where = $3
|
282
|
+
# the latest Mondrian version sometimes returns sql_non_extended without order by
|
283
|
+
elsif sql_non_extended =~ /\Aselect (.*) from (.*) where (.*)\Z/m
|
252
284
|
non_extended_from = $2
|
253
285
|
non_extended_where = $3
|
254
286
|
# if drill through total measure with just all members selection
|
255
|
-
elsif sql_non_extended =~ /\Aselect (.*) from (.*)\Z/
|
287
|
+
elsif sql_non_extended =~ /\Aselect (.*) from (.*)\Z/m
|
256
288
|
non_extended_from = $2
|
257
289
|
non_extended_where = "1 = 1" # dummy true condition
|
258
290
|
else
|
259
291
|
raise ArgumentError, "cannot parse drill through SQL: #{sql_non_extended}"
|
260
292
|
end
|
261
293
|
|
262
|
-
if sql_extended =~ /\Aselect (.*) from (.*) where (.*) order by (.*)\Z/
|
294
|
+
if sql_extended =~ /\Aselect (.*) from (.*) where (.*) order by (.*)\Z/m
|
263
295
|
extended_select = $1
|
264
296
|
extended_from = $2
|
265
297
|
extended_where = $3
|
266
298
|
extended_order_by = $4
|
267
299
|
# if only measures are selected then there will be no order by
|
268
|
-
elsif sql_extended =~ /\Aselect (.*) from (.*) where (.*)\Z/
|
300
|
+
elsif sql_extended =~ /\Aselect (.*) from (.*) where (.*)\Z/m
|
269
301
|
extended_select = $1
|
270
302
|
extended_from = $2
|
271
303
|
extended_where = $3
|
@@ -282,13 +314,14 @@ module Mondrian
|
|
282
314
|
|
283
315
|
return_fields.size.times do |i|
|
284
316
|
column_alias = return_fields[i][:column_alias]
|
285
|
-
new_select_columns <<
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
317
|
+
new_select_columns <<
|
318
|
+
if column_expression = return_fields[i][:column_expression]
|
319
|
+
new_order_by_columns << column_expression
|
320
|
+
new_group_by_columns << column_expression if group_by && return_fields[i][:type] != :measure
|
321
|
+
"#{column_expression} AS #{column_alias}"
|
322
|
+
else
|
323
|
+
"'' AS #{column_alias}"
|
324
|
+
end
|
292
325
|
end
|
293
326
|
|
294
327
|
new_select = new_select_columns.join(', ')
|
@@ -361,7 +394,7 @@ module Mondrian
|
|
361
394
|
end
|
362
395
|
end
|
363
396
|
|
364
|
-
return_fields.size.times do |
|
397
|
+
return_fields.size.times do |i|
|
365
398
|
member_full_name = return_fields[i][:member_full_name]
|
366
399
|
begin
|
367
400
|
segment_list = Java::MondrianOlap::Util.parseIdentifier(member_full_name)
|
@@ -381,34 +414,34 @@ module Mondrian
|
|
381
414
|
end
|
382
415
|
|
383
416
|
return_fields[i][:column_expression] = case return_fields[i][:type]
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
end
|
417
|
+
when :name
|
418
|
+
if level_or_member.respond_to? :getNameExp
|
419
|
+
level_or_member.getNameExp.getExpression sql_query
|
420
|
+
end
|
421
|
+
when :property
|
422
|
+
if property = level_or_member.getProperties.to_a.detect{|p| p.getName == return_fields[i][:name]}
|
423
|
+
# property.getExp is a protected method therefore
|
424
|
+
# use a workaround to get the value from the field
|
425
|
+
f = property.java_class.declared_field("exp")
|
426
|
+
f.accessible = true
|
427
|
+
if column = f.value(property)
|
428
|
+
column.getExpression sql_query
|
397
429
|
end
|
430
|
+
end
|
431
|
+
else
|
432
|
+
if level_or_member.respond_to? :getKeyExp
|
433
|
+
return_fields[i][:type] = :key
|
434
|
+
level_or_member.getKeyExp.getExpression sql_query
|
398
435
|
else
|
399
|
-
|
400
|
-
|
401
|
-
|
436
|
+
return_fields[i][:type] = :measure
|
437
|
+
column_expression = level_or_member.getMondrianDefExpression.getExpression sql_query
|
438
|
+
if params[:group_by]
|
439
|
+
level_or_member.getAggregator.getExpression column_expression
|
402
440
|
else
|
403
|
-
|
404
|
-
column_expression = level_or_member.getMondrianDefExpression.getExpression sql_query
|
405
|
-
if params[:group_by]
|
406
|
-
level_or_member.getAggregator.getExpression column_expression
|
407
|
-
else
|
408
|
-
column_expression
|
409
|
-
end
|
441
|
+
column_expression
|
410
442
|
end
|
411
443
|
end
|
444
|
+
end
|
412
445
|
|
413
446
|
column_alias = if return_fields[i][:type] == :key
|
414
447
|
"#{return_fields[i][:name]} (Key)"
|
@@ -479,7 +512,7 @@ module Mondrian
|
|
479
512
|
@axes ||= @raw_cell_set.getAxes
|
480
513
|
end
|
481
514
|
|
482
|
-
def axis_positions(map_method, join_with=false)
|
515
|
+
def axis_positions(map_method, join_with = false)
|
483
516
|
axes.map do |axis|
|
484
517
|
axis.getPositions.map do |position|
|
485
518
|
names = position.getMembers.map do |member|
|
@@ -508,7 +541,7 @@ module Mondrian
|
|
508
541
|
:chapters => 4
|
509
542
|
}.freeze
|
510
543
|
|
511
|
-
def recursive_values(value_method, axes_sequence, current_index, cell_params=[])
|
544
|
+
def recursive_values(value_method, axes_sequence, current_index, cell_params = [])
|
512
545
|
if axis_number = axes_sequence[current_index]
|
513
546
|
axis_number = AXIS_SYMBOL_TO_NUMBER[axis_number] if axis_number.is_a?(Symbol)
|
514
547
|
positions_size = axes[axis_number].getPositions.size
|
data/lib/mondrian/olap/schema.rb
CHANGED
@@ -67,14 +67,30 @@ module Mondrian
|
|
67
67
|
attr_reader pluralize(name).to_sym
|
68
68
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
69
69
|
def #{name}(name=nil, attributes = {}, &block)
|
70
|
-
|
70
|
+
new_element = Schema::#{camel_case(name)}.new(name, attributes, self, &block)
|
71
|
+
@#{pluralize(name)} << new_element
|
72
|
+
new_element
|
71
73
|
end
|
72
74
|
RUBY
|
75
|
+
if name == :annotations
|
76
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
77
|
+
def annotations_hash
|
78
|
+
hash = {}
|
79
|
+
@annotationss.each do |annotations|
|
80
|
+
annotations.annotations.each do |annotation|
|
81
|
+
hash[annotation.name] = annotation.content
|
82
|
+
end
|
83
|
+
end
|
84
|
+
hash
|
85
|
+
end
|
86
|
+
RUBY
|
87
|
+
end
|
73
88
|
end
|
74
89
|
end
|
75
90
|
|
76
|
-
def self.content(type=nil)
|
91
|
+
def self.content(type = nil)
|
77
92
|
return @content if type.nil?
|
93
|
+
attr_reader :content
|
78
94
|
@content = type
|
79
95
|
end
|
80
96
|
|
@@ -86,7 +102,7 @@ module Mondrian
|
|
86
102
|
@xml_fragments << string
|
87
103
|
end
|
88
104
|
|
89
|
-
def to_xml(options={})
|
105
|
+
def to_xml(options = {})
|
90
106
|
options[:upcase_data_dictionary] = @upcase_data_dictionary unless @upcase_data_dictionary.nil?
|
91
107
|
Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
|
92
108
|
add_to_xml(xml, options)
|
@@ -125,7 +141,7 @@ module Mondrian
|
|
125
141
|
def xmlized_attributes(options)
|
126
142
|
# data dictionary values should be in uppercase if schema defined with :upcase_data_dictionary => true
|
127
143
|
# or by default when using Oracle or LucidDB driver (can be overridden by :upcase_data_dictionary => false)
|
128
|
-
upcase_attributes = if options[:upcase_data_dictionary].nil? && %w(oracle luciddb).include?(options[:driver]) ||
|
144
|
+
upcase_attributes = if options[:upcase_data_dictionary].nil? && %w(oracle luciddb snowflake).include?(options[:driver]) ||
|
129
145
|
options[:upcase_data_dictionary]
|
130
146
|
self.class.data_dictionary_names
|
131
147
|
else
|
@@ -17,7 +17,7 @@ module Mondrian
|
|
17
17
|
|
18
18
|
def coffeescript_function(arguments_string, text)
|
19
19
|
# construct function to ensure that last expression is returned
|
20
|
-
coffee_text = "#{arguments_string} ->\n" << text.gsub(/^/,' ')
|
20
|
+
coffee_text = "#{arguments_string} ->\n" << text.gsub(/^/, ' ')
|
21
21
|
javascript_text = CoffeeScript.compile(coffee_text, :bare => true)
|
22
22
|
# remove function definition first and last lines
|
23
23
|
javascript_text = javascript_text.strip.lines.to_a[1..-2].join
|
@@ -67,7 +67,7 @@ module Mondrian
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def ruby_formatter_java_class_name(name)
|
70
|
-
"rubyobj.#{self.class.name.gsub('::','.')}.#{ruby_formatter_name_to_class_name(name)}"
|
70
|
+
"rubyobj.#{self.class.name.gsub('::', '.')}.#{ruby_formatter_name_to_class_name(name)}"
|
71
71
|
end
|
72
72
|
|
73
73
|
end
|
@@ -180,19 +180,21 @@ JS
|
|
180
180
|
add_method_signature("getSyntax", [Java::mondrian.olap.Syntax])
|
181
181
|
|
182
182
|
UDF_SCALAR_TYPES = {
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
183
|
+
'Numeric' => Java::mondrian.olap.type.NumericType,
|
184
|
+
'String' => Java::mondrian.olap.type.StringType,
|
185
|
+
'Boolean' => Java::mondrian.olap.type.BooleanType,
|
186
|
+
'DateTime' => Java::mondrian.olap.type.DateTimeType,
|
187
|
+
'Decimal' => Java::mondrian.olap.type.DecimalType,
|
188
|
+
'Scalar' => Java::mondrian.olap.type.ScalarType
|
189
189
|
}
|
190
190
|
UDF_OTHER_TYPES = {
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
191
|
+
'Member' => Java::mondrian.olap.type.MemberType::Unknown,
|
192
|
+
'Tuple' => Java::mondrian.olap.type.TupleType.new([].to_java(Java::mondrian.olap.type.Type)),
|
193
|
+
'Hierarchy' => Java::mondrian.olap.type.HierarchyType.new(nil, nil),
|
194
|
+
'Level' => Java::mondrian.olap.type.LevelType::Unknown
|
195
195
|
}
|
196
|
+
UDF_OTHER_TYPES['Set'] = UDF_OTHER_TYPES['MemberSet'] = Java::mondrian.olap.type.SetType.new(UDF_OTHER_TYPES['Member'])
|
197
|
+
UDF_OTHER_TYPES['TupleSet'] = Java::mondrian.olap.type.SetType.new(UDF_OTHER_TYPES['Tuple'])
|
196
198
|
|
197
199
|
def getParameterTypes
|
198
200
|
@parameterTypes ||= self.class.parameters.map{|p| get_java_type(p)}
|
@@ -214,7 +216,7 @@ JS
|
|
214
216
|
|
215
217
|
def execute(evaluator, arguments)
|
216
218
|
values = []
|
217
|
-
self.class.parameters.each_with_index do |p,i|
|
219
|
+
self.class.parameters.each_with_index do |p, i|
|
218
220
|
value = UDF_SCALAR_TYPES[p] ? arguments[i].evaluateScalar(evaluator) : arguments[i].evaluate(evaluator)
|
219
221
|
values << value
|
220
222
|
end
|
@@ -239,9 +241,12 @@ JS
|
|
239
241
|
end
|
240
242
|
|
241
243
|
def self.stringified_type(type)
|
242
|
-
|
243
|
-
|
244
|
-
|
244
|
+
type_as_string = stringify(type)
|
245
|
+
if UDF_SCALAR_TYPES[type_as_string] || UDF_OTHER_TYPES[type_as_string]
|
246
|
+
type_as_string
|
247
|
+
else
|
248
|
+
raise ArgumentError, "Invalid user defined function type #{type.inspect}"
|
249
|
+
end
|
245
250
|
end
|
246
251
|
|
247
252
|
def self.stringify(arg)
|
@@ -4,15 +4,21 @@ describe "Connection role" do
|
|
4
4
|
|
5
5
|
describe "create connection" do
|
6
6
|
before(:each) do
|
7
|
-
@
|
8
|
-
|
7
|
+
@all_roles = [
|
8
|
+
@role_name = role_name = 'California manager',
|
9
|
+
@role_name2 = role_name2 = 'Dummy, with comma',
|
10
|
+
@simple_role_name = simple_role_name = 'USA manager',
|
11
|
+
@union_role_name = union_role_name = 'Union California manager',
|
12
|
+
@intermediate_union_role_name = intermediate_union_role_name = "Intermediate #{union_role_name}"
|
13
|
+
]
|
14
|
+
|
9
15
|
@schema = Mondrian::OLAP::Schema.define do
|
10
16
|
cube 'Sales' do
|
11
17
|
table 'sales'
|
12
18
|
dimension 'Gender', :foreign_key => 'customer_id' do
|
13
19
|
hierarchy :has_all => true, :primary_key => 'id' do
|
14
20
|
table 'customers'
|
15
|
-
level 'Gender', :column => 'gender', :unique_members => true
|
21
|
+
level 'Gender', :column => 'gender', :unique_members => true, :hide_member_if => 'IfBlankName'
|
16
22
|
end
|
17
23
|
end
|
18
24
|
dimension 'Customers', :foreign_key => 'customer_id' do
|
@@ -49,6 +55,26 @@ describe "Connection role" do
|
|
49
55
|
end
|
50
56
|
role role_name2
|
51
57
|
|
58
|
+
role simple_role_name do
|
59
|
+
schema_grant :access => 'none' do
|
60
|
+
cube_grant :cube => 'Sales', :access => 'all' do
|
61
|
+
hierarchy_grant :hierarchy => '[Customers]', :access => 'custom', :bottom_level => '[Customers].[State Province]' do
|
62
|
+
member_grant :member => '[Customers].[USA]', :access => 'all'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
role intermediate_union_role_name do
|
68
|
+
union do
|
69
|
+
role_usage role_name: simple_role_name
|
70
|
+
end
|
71
|
+
end
|
72
|
+
role union_role_name do
|
73
|
+
union do
|
74
|
+
role_usage role_name: intermediate_union_role_name
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
52
78
|
# to test that Role elements are generated before UserDefinedFunction
|
53
79
|
user_defined_function 'Factorial' do
|
54
80
|
ruby do
|
@@ -63,12 +89,16 @@ describe "Connection role" do
|
|
63
89
|
@olap = Mondrian::OLAP::Connection.create(CONNECTION_PARAMS.merge :schema => @schema)
|
64
90
|
end
|
65
91
|
|
92
|
+
after(:each) do
|
93
|
+
@olap.role_name = nil if @olap
|
94
|
+
end
|
95
|
+
|
66
96
|
it "should connect" do
|
67
97
|
@olap.should be_connected
|
68
98
|
end
|
69
99
|
|
70
100
|
it "should get available role names" do
|
71
|
-
@olap.available_role_names.should ==
|
101
|
+
@olap.available_role_names.sort.should == @all_roles.sort
|
72
102
|
end
|
73
103
|
|
74
104
|
it "should not get role name if not set" do
|
@@ -113,17 +143,40 @@ describe "Connection role" do
|
|
113
143
|
# end
|
114
144
|
|
115
145
|
it "should not get non-visible member when role name set in connection parameters" do
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
@cube.member('[Customers].[USA].[CA].[Los Angeles]').should be_nil
|
146
|
+
olap = Mondrian::OLAP::Connection.create(CONNECTION_PARAMS.merge schema: @schema, role: @role_name)
|
147
|
+
cube = olap.cube('Sales')
|
148
|
+
cube.member('[Customers].[USA].[CA].[Los Angeles]').should be_nil
|
120
149
|
end
|
121
150
|
|
122
151
|
it "should not get non-visible member when several role names set in connection parameters" do
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
152
|
+
olap = Mondrian::OLAP::Connection.create(CONNECTION_PARAMS.merge schema: @schema, roles: [@role_name, @role_name2])
|
153
|
+
cube = olap.cube('Sales')
|
154
|
+
cube.member('[Customers].[USA].[CA].[Los Angeles]').should be_nil
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should see members from ragged dimensions when using single role" do
|
158
|
+
# Workaround for a Mondrian bug which does not allow access to ragged dimensions when using single role.
|
159
|
+
# This syntax will create a union role with one role.
|
160
|
+
@olap.role_names = [@role_name]
|
161
|
+
cube = @olap.cube('Sales')
|
162
|
+
cube.member('[Customers].[USA].[CA].[Los Angeles]').should be_nil
|
163
|
+
cube.member('[Gender].[All Genders]').should_not be_nil
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should see members from ragged dimensions when using multiple roles" do
|
167
|
+
@olap.role_names = [@role_name, @role_name2]
|
168
|
+
cube = @olap.cube('Sales')
|
169
|
+
cube.member('[Customers].[USA].[CA].[Los Angeles]').should be_nil
|
170
|
+
cube.member('[Gender].[All Genders]').should_not be_nil
|
171
|
+
end
|
172
|
+
|
173
|
+
# Test patch for UnionRoleImpl getBottomLevelDepth method
|
174
|
+
it "should see member as drillable when using union of union role" do
|
175
|
+
@olap.role_names = [@union_role_name]
|
176
|
+
cube = @olap.cube('Sales')
|
177
|
+
cube.member('[Customers].[All Customers]').should be_drillable
|
178
|
+
cube.member('[Customers].[All Customers].[USA]').should be_drillable
|
179
|
+
cube.member('[Customers].[All Customers].[USA].[CA]').should_not be_drillable
|
127
180
|
end
|
128
181
|
|
129
182
|
end
|