mondrian-olap 0.3.0 → 0.5.0

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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/Changelog.md +38 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +302 -0
  5. data/VERSION +1 -1
  6. data/lib/mondrian/jars/commons-collections-3.2.jar +0 -0
  7. data/lib/mondrian/jars/commons-logging-1.1.1.jar +0 -0
  8. data/lib/mondrian/jars/commons-math-1.1.jar +0 -0
  9. data/lib/mondrian/jars/eigenbase-properties-1.1.2.jar +0 -0
  10. data/lib/mondrian/jars/eigenbase-resgen-1.3.1.jar +0 -0
  11. data/lib/mondrian/jars/eigenbase-xom-1.3.1.jar +0 -0
  12. data/lib/mondrian/jars/{javacup.jar → javacup-10k.jar} +0 -0
  13. data/lib/mondrian/jars/log4j-1.2.14.jar +0 -0
  14. data/lib/mondrian/jars/mondrian.jar +0 -0
  15. data/lib/mondrian/jars/olap4j-1.0.1.539.jar +0 -0
  16. data/lib/mondrian/olap.rb +2 -1
  17. data/lib/mondrian/olap/connection.rb +163 -32
  18. data/lib/mondrian/olap/cube.rb +163 -24
  19. data/lib/mondrian/olap/error.rb +57 -0
  20. data/lib/mondrian/olap/query.rb +52 -17
  21. data/lib/mondrian/olap/result.rb +298 -6
  22. data/lib/mondrian/olap/schema.rb +220 -29
  23. data/lib/mondrian/olap/schema_element.rb +31 -11
  24. data/lib/mondrian/olap/schema_udf.rb +331 -0
  25. data/lib/mondrian/olap/version.rb +5 -0
  26. data/spec/connection_role_spec.rb +130 -0
  27. data/spec/connection_spec.rb +36 -1
  28. data/spec/cube_spec.rb +137 -7
  29. data/spec/fixtures/MondrianTest.xml +4 -4
  30. data/spec/mondrian_spec.rb +53 -0
  31. data/spec/query_spec.rb +294 -11
  32. data/spec/rake_tasks.rb +8 -8
  33. data/spec/schema_definition_spec.rb +845 -26
  34. data/spec/spec_helper.rb +26 -17
  35. data/spec/support/matchers/be_like.rb +2 -2
  36. metadata +296 -237
  37. data/.rspec +0 -2
  38. data/Gemfile +0 -18
  39. data/README.rdoc +0 -221
  40. data/RUNNING_TESTS.rdoc +0 -66
  41. data/Rakefile +0 -46
  42. data/lib/mondrian/jars/commons-collections-3.1.jar +0 -0
  43. data/lib/mondrian/jars/commons-logging-1.0.4.jar +0 -0
  44. data/lib/mondrian/jars/commons-math-1.0.jar +0 -0
  45. data/lib/mondrian/jars/eigenbase-properties.jar +0 -0
  46. data/lib/mondrian/jars/eigenbase-resgen.jar +0 -0
  47. data/lib/mondrian/jars/eigenbase-xom.jar +0 -0
  48. data/lib/mondrian/jars/log4j-1.2.8.jar +0 -0
  49. data/lib/mondrian/jars/olap4j.jar +0 -0
  50. data/mondrian-olap.gemspec +0 -126
@@ -1,9 +1,7 @@
1
- require 'nokogiri'
2
-
3
1
  module Mondrian
4
2
  module OLAP
5
3
  class SchemaElement
6
- def initialize(name = nil, attributes = {}, &block)
4
+ def initialize(name = nil, attributes = {}, parent = nil, &block)
7
5
  # if just attributes hash provided
8
6
  if name.is_a?(Hash) && attributes == {}
9
7
  attributes = name
@@ -12,7 +10,14 @@ module Mondrian
12
10
  @attributes = {}
13
11
  if name
14
12
  if self.class.content
15
- @content = name
13
+ if attributes.is_a?(Hash)
14
+ @content = name
15
+ else
16
+ # used for Annotation element where both name and content is given as arguments
17
+ @attributes[:name] = name
18
+ @content = attributes
19
+ attributes = {}
20
+ end
16
21
  else
17
22
  @attributes[:name] = name
18
23
  end
@@ -21,8 +26,12 @@ module Mondrian
21
26
  self.class.elements.each do |element|
22
27
  instance_variable_set("@#{pluralize(element)}", [])
23
28
  end
29
+ # extract annotations from options
30
+ if @attributes[:annotations] && self.class.elements.include?(:annotations)
31
+ annotations @attributes.delete(:annotations)
32
+ end
24
33
  @xml_fragments = []
25
- instance_eval &block if block
34
+ instance_eval(&block) if block
26
35
  end
27
36
 
28
37
  def self.attributes(*names)
@@ -54,10 +63,11 @@ module Mondrian
54
63
  @elements.concat(names)
55
64
 
56
65
  names.each do |name|
66
+ next if name == :xml
57
67
  attr_reader pluralize(name).to_sym
58
68
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
59
69
  def #{name}(name=nil, attributes = {}, &block)
60
- @#{pluralize(name)} << Schema::#{camel_case(name)}.new(name, attributes, &block)
70
+ @#{pluralize(name)} << Schema::#{camel_case(name)}.new(name, attributes, self, &block)
61
71
  end
62
72
  RUBY
63
73
  end
@@ -78,7 +88,7 @@ module Mondrian
78
88
 
79
89
  def to_xml(options={})
80
90
  options[:upcase_data_dictionary] = @upcase_data_dictionary unless @upcase_data_dictionary.nil?
81
- Nokogiri::XML::Builder.new do |xml|
91
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
82
92
  add_to_xml(xml, options)
83
93
  end.to_xml
84
94
  end
@@ -90,16 +100,26 @@ module Mondrian
90
100
  xml.send(tag_name(self.class.name), @content, xmlized_attributes(options))
91
101
  else
92
102
  xml.send(tag_name(self.class.name), xmlized_attributes(options)) do
103
+ xml_fragments_added = false
93
104
  self.class.elements.each do |element|
94
- instance_variable_get("@#{pluralize(element)}").each {|item| item.add_to_xml(xml, options)}
95
- end
96
- @xml_fragments.each do |xml_fragment|
97
- xml.send(:insert, Nokogiri::XML::DocumentFragment.parse(xml_fragment))
105
+ if element == :xml
106
+ add_xml_fragments(xml)
107
+ xml_fragments_added = true
108
+ else
109
+ instance_variable_get("@#{pluralize(element)}").each {|item| item.add_to_xml(xml, options)}
110
+ end
98
111
  end
112
+ add_xml_fragments(xml) unless xml_fragments_added
99
113
  end
100
114
  end
101
115
  end
102
116
 
117
+ def add_xml_fragments(xml)
118
+ @xml_fragments.each do |xml_fragment|
119
+ xml.send(:insert, Nokogiri::XML::DocumentFragment.parse(xml_fragment))
120
+ end
121
+ end
122
+
103
123
  private
104
124
 
105
125
  def xmlized_attributes(options)
@@ -0,0 +1,331 @@
1
+ require 'jruby/core_ext'
2
+
3
+ module Mondrian
4
+ module OLAP
5
+ class Schema < SchemaElement
6
+
7
+ def user_defined_cell_formatter(name, &block)
8
+ CellFormatter.new(name, &block)
9
+ end
10
+
11
+ module ScriptElements
12
+ def javascript(text)
13
+ script text, :language => 'JavaScript'
14
+ end
15
+
16
+ private
17
+
18
+ def coffeescript_function(arguments_string, text)
19
+ # construct function to ensure that last expression is returned
20
+ coffee_text = "#{arguments_string} ->\n" << text.gsub(/^/,' ')
21
+ javascript_text = CoffeeScript.compile(coffee_text, :bare => true)
22
+ # remove function definition first and last lines
23
+ javascript_text = javascript_text.strip.lines.to_a[1..-2].join
24
+ javascript javascript_text
25
+ end
26
+
27
+ def ruby(*options, &block)
28
+ udf_class_name = if options.include?(:shared)
29
+ "#{name.capitalize}Udf"
30
+ end
31
+ if udf_class_name && self.class.const_defined?(udf_class_name)
32
+ udf_class = self.class.const_get(udf_class_name)
33
+ else
34
+ udf_class = Class.new(RubyUdfBase)
35
+ self.class.const_set(udf_class_name, udf_class) if udf_class_name
36
+ end
37
+ udf_class.function_name = name
38
+ udf_class.class_eval(&block)
39
+ udf_java_class = udf_class.become_java!(false)
40
+
41
+ class_name udf_java_class.getName
42
+ end
43
+
44
+ def ruby_formatter(options, interface_class, method, signature, &block)
45
+ formatter_class_name = if options.include?(:shared) && @attributes[:name]
46
+ ruby_formatter_name_to_class_name(@attributes[:name])
47
+ end
48
+ if formatter_class_name && self.class.const_defined?(formatter_class_name)
49
+ formatter_class = self.class.const_get(formatter_class_name)
50
+ else
51
+ formatter_class = Class.new
52
+ self.class.const_set(formatter_class_name, formatter_class) if formatter_class_name
53
+ end
54
+
55
+ formatter_class.class_eval do
56
+ include interface_class
57
+ define_method method, &block
58
+ add_method_signature(method, signature)
59
+ end
60
+ formatter_java_class = formatter_class.become_java!(false)
61
+ class_name formatter_java_class.getName
62
+ end
63
+
64
+ def ruby_formatter_name_to_class_name(name)
65
+ # upcase just first character
66
+ "#{name.sub(/\A./){|m| m.upcase}}Udf"
67
+ end
68
+
69
+ def ruby_formatter_java_class_name(name)
70
+ "rubyobj.#{self.class.name.gsub('::','.')}.#{ruby_formatter_name_to_class_name(name)}"
71
+ end
72
+
73
+ end
74
+
75
+ class UserDefinedFunction < SchemaElement
76
+ include ScriptElements
77
+ attributes :name, # Name with which the user-defined function will be referenced in MDX expressions.
78
+ # Name of the class which implemenets this user-defined function.
79
+ # Must implement the mondrian.spi.UserDefinedFunction interface.
80
+ :class_name
81
+ elements :script
82
+
83
+ def coffeescript(text)
84
+ coffee_text = "__udf__ = {\n" << text << "}\n"
85
+ javascript_text = CoffeeScript.compile(coffee_text, :bare => true)
86
+ javascript_text << <<-JS
87
+
88
+ __udf__.parameters || (__udf__.parameters = []);
89
+ __udf__.returns || (__udf__.returns = "Scalar");
90
+ var __scalarTypes__ = {"Numeric":true,"String":true,"Boolean":true,"DateTime":true,"Decimal":true,"Scalar":true};
91
+ function __getType__(type) {
92
+ if (__scalarTypes__[type]) {
93
+ return new mondrian.olap.type[type+"Type"];
94
+ } else if (type === "Member") {
95
+ return mondrian.olap.type.MemberType.Unknown;
96
+ } else {
97
+ return null;
98
+ }
99
+ }
100
+ function getParameterTypes() {
101
+ var parameters = __udf__.parameters || [],
102
+ types = [];
103
+ for (var i = 0, len = parameters.length; i < len; i++) {
104
+ types.push(__getType__(parameters[i]))
105
+ }
106
+ return types;
107
+ }
108
+ function getReturnType(parameterTypes) {
109
+ var returns = __udf__.returns || "Scalar";
110
+ return __getType__(returns);
111
+ }
112
+ if (__udf__.syntax) {
113
+ function getSyntax() {
114
+ return mondrian.olap.Syntax[__udf__.syntax];
115
+ }
116
+ }
117
+ function execute(evaluator, args) {
118
+ var parameters = __udf__.parameters || [],
119
+ values = [],
120
+ value;
121
+ for (var i = 0, len = parameters.length; i < len; i++) {
122
+ if (__scalarTypes__[parameters[i]]) {
123
+ value = args[i].evaluateScalar(evaluator);
124
+ } else {
125
+ value = args[i].evaluate(evaluator);
126
+ }
127
+ values.push(value);
128
+ }
129
+ return __udf__.execute.apply(__udf__, values);
130
+ }
131
+ JS
132
+ javascript javascript_text
133
+ end
134
+
135
+ class RubyUdfBase
136
+ include Java::mondrian.spi.UserDefinedFunction
137
+ def self.function_name=(name); @function_name = name; end
138
+ def self.function_name; @function_name; end
139
+
140
+ def getName
141
+ self.class.function_name
142
+ end
143
+ add_method_signature("getName", [java.lang.String])
144
+
145
+ def getDescription
146
+ getName
147
+ end
148
+ add_method_signature("getDescription", [java.lang.String])
149
+
150
+ def self.parameters(*types)
151
+ if types.empty?
152
+ @parameters || []
153
+ else
154
+ @parameters = types.map{|type| stringified_type(type)}
155
+ end
156
+ end
157
+
158
+ def self.returns(type = nil)
159
+ if type
160
+ @returns = stringified_type(type)
161
+ else
162
+ @returns || 'Scalar'
163
+ end
164
+ end
165
+
166
+ VALID_SYNTAX_TYPES = %w(Function Property Method)
167
+ def self.syntax(type = nil)
168
+ if type
169
+ type = stringify(type)
170
+ raise ArgumentError, "invalid user defined function type #{type.inspect}" unless VALID_SYNTAX_TYPES.include? type
171
+ @syntax = type
172
+ else
173
+ @syntax || 'Function'
174
+ end
175
+ end
176
+
177
+ def getSyntax
178
+ Java::mondrian.olap.Syntax.const_get self.class.syntax
179
+ end
180
+ add_method_signature("getSyntax", [Java::mondrian.olap.Syntax])
181
+
182
+ UDF_SCALAR_TYPES = {
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
+ }
190
+ UDF_OTHER_TYPES = {
191
+ "Member" => Java::mondrian.olap.type.MemberType::Unknown,
192
+ "Set" => Java::mondrian.olap.type.SetType.new(Java::mondrian.olap.type.MemberType::Unknown),
193
+ "Hierarchy" => Java::mondrian.olap.type.HierarchyType.new(nil, nil),
194
+ "Level" => Java::mondrian.olap.type.LevelType::Unknown
195
+ }
196
+
197
+ def getParameterTypes
198
+ @parameterTypes ||= self.class.parameters.map{|p| get_java_type(p)}
199
+ end
200
+ class_loader = JRuby.runtime.jruby_class_loader
201
+ type_array_class = java.lang.Class.forName "[Lmondrian.olap.type.Type;", true, class_loader
202
+ add_method_signature("getParameterTypes", [type_array_class])
203
+
204
+ def getReturnType(parameterTypes)
205
+ @returnType ||= get_java_type self.class.returns
206
+ end
207
+ add_method_signature("getReturnType", [Java::mondrian.olap.type.Type, type_array_class])
208
+
209
+ def getReservedWords
210
+ nil
211
+ end
212
+ string_array_class = java.lang.Class.forName "[Ljava.lang.String;", true, class_loader
213
+ add_method_signature("getReservedWords", [string_array_class])
214
+
215
+ def execute(evaluator, arguments)
216
+ values = []
217
+ self.class.parameters.each_with_index do |p,i|
218
+ value = UDF_SCALAR_TYPES[p] ? arguments[i].evaluateScalar(evaluator) : arguments[i].evaluate(evaluator)
219
+ values << value
220
+ end
221
+ call_with_evaluator(evaluator, *values)
222
+ end
223
+ arguments_array_class = java.lang.Class.forName "[Lmondrian.spi.UserDefinedFunction$Argument;", true, class_loader
224
+ add_method_signature("execute", [java.lang.Object, Java::mondrian.olap.Evaluator, arguments_array_class])
225
+
226
+ # Override this metho if evaluator is needed
227
+ def call_with_evaluator(evaluator, *values)
228
+ call(*values)
229
+ end
230
+
231
+ private
232
+
233
+ def get_java_type(type)
234
+ if type_class = UDF_SCALAR_TYPES[type]
235
+ type_class.new
236
+ else
237
+ UDF_OTHER_TYPES[type]
238
+ end
239
+ end
240
+
241
+ def self.stringified_type(type)
242
+ type = stringify(type)
243
+ raise ArgumentError, "invalid user defined function type #{type.inspect}" unless UDF_SCALAR_TYPES[type] || UDF_OTHER_TYPES[type]
244
+ type
245
+ end
246
+
247
+ def self.stringify(arg)
248
+ arg = arg.to_s.split('_').map{|s| s.capitalize}.join if arg.is_a? Symbol
249
+ arg
250
+ end
251
+ end
252
+
253
+ def ruby(*options, &block)
254
+ udf_class_name = if options.include?(:shared)
255
+ "#{name.capitalize}Udf"
256
+ end
257
+ if udf_class_name && self.class.const_defined?(udf_class_name)
258
+ udf_class = self.class.const_get(udf_class_name)
259
+ else
260
+ udf_class = Class.new(RubyUdfBase)
261
+ self.class.const_set(udf_class_name, udf_class) if udf_class_name
262
+ end
263
+ udf_class.function_name = name
264
+ udf_class.class_eval(&block)
265
+ udf_java_class = udf_class.become_java!(false)
266
+
267
+ class_name udf_java_class.getName
268
+ end
269
+ end
270
+
271
+ class Script < SchemaElement
272
+ attributes :language
273
+ content :text
274
+ end
275
+
276
+ class CellFormatter < SchemaElement
277
+ include ScriptElements
278
+ # Name of a formatter class for the appropriate cell being displayed.
279
+ # The class must implement the mondrian.olap.CellFormatter interface.
280
+ attributes :class_name
281
+ elements :script
282
+
283
+ def initialize(name = nil, attributes = {}, parent = nil, &block)
284
+ super
285
+ if name && !attributes[:class_name] && !block_given?
286
+ # use shared ruby implementation
287
+ @attributes[:class_name] = ruby_formatter_java_class_name(name)
288
+ @attributes.delete(:name)
289
+ end
290
+ end
291
+
292
+ def coffeescript(text)
293
+ coffeescript_function('(value)', text)
294
+ end
295
+
296
+ def ruby(*options, &block)
297
+ ruby_formatter(options, Java::mondrian.spi.CellFormatter, 'formatCell', [java.lang.String, java.lang.Object], &block)
298
+ end
299
+ end
300
+
301
+ class MemberFormatter < SchemaElement
302
+ include ScriptElements
303
+ attributes :class_name
304
+ elements :script
305
+
306
+ def coffeescript(text)
307
+ coffeescript_function('(member)', text)
308
+ end
309
+
310
+ def ruby(*options, &block)
311
+ ruby_formatter(options, Java::mondrian.spi.MemberFormatter, 'formatMember', [java.lang.String, Java::mondrian.olap.Member], &block)
312
+ end
313
+ end
314
+
315
+ class PropertyFormatter < SchemaElement
316
+ include ScriptElements
317
+ attributes :class_name
318
+ elements :script
319
+
320
+ def coffeescript(text)
321
+ coffeescript_function('(member,propertyName,propertyValue)', text)
322
+ end
323
+
324
+ def ruby(*options, &block)
325
+ ruby_formatter(options, Java::mondrian.spi.PropertyFormatter, 'formatProperty', [java.lang.String, Java::mondrian.olap.Member, java.lang.String, java.lang.Object], &block)
326
+ end
327
+ end
328
+
329
+ end
330
+ end
331
+ end
@@ -0,0 +1,5 @@
1
+ module Mondrian
2
+ module OLAP
3
+ VERSION = File.read(File.expand_path('../../../../VERSION', __FILE__)).chomp
4
+ end
5
+ end
@@ -0,0 +1,130 @@
1
+ require "spec_helper"
2
+
3
+ describe "Connection role" do
4
+
5
+ describe "create connection" do
6
+ before(:each) do
7
+ @role_name = role_name = 'California manager'
8
+ @role_name2 = role_name2 = 'Dummy, with comma'
9
+ @schema = Mondrian::OLAP::Schema.define do
10
+ cube 'Sales' do
11
+ table 'sales'
12
+ dimension 'Gender', :foreign_key => 'customer_id' do
13
+ hierarchy :has_all => true, :primary_key => 'id' do
14
+ table 'customers'
15
+ level 'Gender', :column => 'gender', :unique_members => true
16
+ end
17
+ end
18
+ dimension 'Customers', :foreign_key => 'customer_id' do
19
+ hierarchy :has_all => true, :all_member_name => 'All Customers', :primary_key => 'id' do
20
+ table 'customers'
21
+ level 'Country', :column => 'country', :unique_members => true
22
+ level 'State Province', :column => 'state_province', :unique_members => true
23
+ level 'City', :column => 'city', :unique_members => false
24
+ level 'Name', :column => 'fullname', :unique_members => true
25
+ end
26
+ end
27
+ dimension 'Time', :foreign_key => 'time_id' do
28
+ hierarchy :has_all => false, :primary_key => 'id' do
29
+ table 'time'
30
+ level 'Year', :column => 'the_year', :type => 'Numeric', :unique_members => true
31
+ level 'Quarter', :column => 'quarter', :unique_members => false
32
+ level 'Month', :column => 'month_of_year', :type => 'Numeric', :unique_members => false
33
+ end
34
+ end
35
+ measure 'Unit Sales', :column => 'unit_sales', :aggregator => 'sum'
36
+ measure 'Store Sales', :column => 'store_sales', :aggregator => 'sum'
37
+ end
38
+ role role_name do
39
+ schema_grant :access => 'none' do
40
+ cube_grant :cube => 'Sales', :access => 'all' do
41
+ dimension_grant :dimension => '[Measures]', :access => 'all'
42
+ hierarchy_grant :hierarchy => '[Customers]', :access => 'custom',
43
+ :top_level => '[Customers].[State Province]', :bottom_level => '[Customers].[City]' do
44
+ member_grant :member => '[Customers].[USA].[CA]', :access => 'all'
45
+ member_grant :member => '[Customers].[USA].[CA].[Los Angeles]', :access => 'none'
46
+ end
47
+ end
48
+ end
49
+ end
50
+ role role_name2
51
+
52
+ # to test that Role elements are generated before UserDefinedFunction
53
+ user_defined_function 'Factorial' do
54
+ ruby do
55
+ parameters :numeric
56
+ returns :numeric
57
+ def call(n)
58
+ n <= 1 ? 1 : n * call(n - 1)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ @olap = Mondrian::OLAP::Connection.create(CONNECTION_PARAMS.merge :schema => @schema)
64
+ end
65
+
66
+ it "should connect" do
67
+ @olap.should be_connected
68
+ end
69
+
70
+ it "should get available role names" do
71
+ @olap.available_role_names.should == [@role_name, @role_name2]
72
+ end
73
+
74
+ it "should not get role name if not set" do
75
+ @olap.role_name.should be_nil
76
+ @olap.role_names.should be_empty
77
+ end
78
+
79
+ it "should set and get role name" do
80
+ @olap.role_name = @role_name
81
+ @olap.role_name.should == @role_name
82
+ @olap.role_names.should == [@role_name]
83
+ end
84
+
85
+ it "should raise error when invalid role name is set" do
86
+ expect {
87
+ @olap.role_name = 'invalid'
88
+ }.to raise_error {|e|
89
+ e.should be_kind_of(Mondrian::OLAP::Error)
90
+ e.message.should == "org.olap4j.OlapException: Unknown role 'invalid'"
91
+ e.root_cause_message.should == "Unknown role 'invalid'"
92
+ }
93
+ end
94
+
95
+ it "should set and get several role names" do
96
+ @olap.role_names = [@role_name, @role_name2]
97
+ @olap.role_name.should == "[#{@role_name}, #{@role_name2}]"
98
+ @olap.role_names.should == [@role_name, @role_name2]
99
+ end
100
+
101
+ it "should not get non-visible member" do
102
+ @cube = @olap.cube('Sales')
103
+ @cube.member('[Customers].[USA].[CA].[Los Angeles]').should_not be_nil
104
+ @olap.role_name = @role_name
105
+ @cube.member('[Customers].[USA].[CA].[Los Angeles]').should be_nil
106
+ end
107
+
108
+ # TODO: investigate why role name is not returned when set in connection string
109
+ # it "should set role name from connection parameters" do
110
+ # @olap = Mondrian::OLAP::Connection.create(CONNECTION_PARAMS.merge :schema => @schema,
111
+ # :role => @role_name)
112
+ # @olap.role_name.should == @role_name
113
+ # end
114
+
115
+ it "should not get non-visible member when role name set in connection parameters" do
116
+ @olap = Mondrian::OLAP::Connection.create(CONNECTION_PARAMS.merge :schema => @schema,
117
+ :role => @role_name)
118
+ @cube = @olap.cube('Sales')
119
+ @cube.member('[Customers].[USA].[CA].[Los Angeles]').should be_nil
120
+ end
121
+
122
+ it "should not get non-visible member when several role names set in connection parameters" do
123
+ @olap = Mondrian::OLAP::Connection.create(CONNECTION_PARAMS.merge :schema => @schema,
124
+ :roles => [@role_name, @role_name2])
125
+ @cube = @olap.cube('Sales')
126
+ @cube.member('[Customers].[USA].[CA].[Los Angeles]').should be_nil
127
+ end
128
+
129
+ end
130
+ end