mondrian-olap 0.1.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 (41) hide show
  1. data/.rspec +2 -0
  2. data/Gemfile +15 -0
  3. data/LICENSE-Mondrian.html +259 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.rdoc +219 -0
  6. data/RUNNING_TESTS.rdoc +41 -0
  7. data/Rakefile +46 -0
  8. data/VERSION +1 -0
  9. data/lib/mondrian-olap.rb +1 -0
  10. data/lib/mondrian/jars/commons-collections-3.1.jar +0 -0
  11. data/lib/mondrian/jars/commons-dbcp-1.2.1.jar +0 -0
  12. data/lib/mondrian/jars/commons-logging-1.0.4.jar +0 -0
  13. data/lib/mondrian/jars/commons-math-1.0.jar +0 -0
  14. data/lib/mondrian/jars/commons-pool-1.2.jar +0 -0
  15. data/lib/mondrian/jars/commons-vfs-1.0.jar +0 -0
  16. data/lib/mondrian/jars/eigenbase-properties.jar +0 -0
  17. data/lib/mondrian/jars/eigenbase-resgen.jar +0 -0
  18. data/lib/mondrian/jars/eigenbase-xom.jar +0 -0
  19. data/lib/mondrian/jars/javacup.jar +0 -0
  20. data/lib/mondrian/jars/log4j-1.2.8.jar +0 -0
  21. data/lib/mondrian/jars/log4j.properties +18 -0
  22. data/lib/mondrian/jars/mondrian.jar +0 -0
  23. data/lib/mondrian/jars/olap4j.jar +0 -0
  24. data/lib/mondrian/olap.rb +14 -0
  25. data/lib/mondrian/olap/connection.rb +122 -0
  26. data/lib/mondrian/olap/cube.rb +236 -0
  27. data/lib/mondrian/olap/query.rb +313 -0
  28. data/lib/mondrian/olap/result.rb +155 -0
  29. data/lib/mondrian/olap/schema.rb +158 -0
  30. data/lib/mondrian/olap/schema_element.rb +123 -0
  31. data/mondrian-olap.gemspec +116 -0
  32. data/spec/connection_spec.rb +56 -0
  33. data/spec/cube_spec.rb +259 -0
  34. data/spec/fixtures/MondrianTest.xml +128 -0
  35. data/spec/fixtures/MondrianTestOracle.xml +128 -0
  36. data/spec/query_spec.rb +582 -0
  37. data/spec/rake_tasks.rb +185 -0
  38. data/spec/schema_definition_spec.rb +345 -0
  39. data/spec/spec_helper.rb +67 -0
  40. data/spec/support/matchers/be_like.rb +24 -0
  41. metadata +217 -0
@@ -0,0 +1,185 @@
1
+ namespace :db do
2
+ task :require_spec_helper do
3
+ require File.expand_path("../spec_helper", __FILE__)
4
+ end
5
+
6
+ desc "Create test database tables"
7
+ task :create_tables => :require_spec_helper do
8
+ puts "==> Creating tables for test data"
9
+ ActiveRecord::Schema.define do
10
+
11
+ create_table :time, :force => true do |t|
12
+ t.datetime :the_date
13
+ t.string :the_day, :limit => 30
14
+ t.string :the_month, :limit => 30
15
+ t.integer :the_year
16
+ t.integer :day_of_month
17
+ t.integer :week_of_year
18
+ t.integer :month_of_year
19
+ t.string :quarter, :limit => 30
20
+ end
21
+
22
+ create_table :products, :force => true do |t|
23
+ t.integer :product_class_id
24
+ t.string :brand_name, :limit => 60
25
+ t.string :product_name, :limit => 60
26
+ end
27
+
28
+ create_table :product_classes, :force => true do |t|
29
+ t.string :product_subcategory, :limit => 30
30
+ t.string :product_category, :limit => 30
31
+ t.string :product_department, :limit => 30
32
+ t.string :product_family, :limit => 30
33
+ end
34
+
35
+ create_table :customers, :force => true do |t|
36
+ t.string :country, :limit => 30
37
+ t.string :state_province, :limit => 30
38
+ t.string :city, :limit => 30
39
+ t.string :fname, :limit => 30
40
+ t.string :lname, :limit => 30
41
+ t.string :fullname, :limit => 60
42
+ t.string :gender, :limit => 30
43
+ end
44
+
45
+ create_table :sales, :force => true, :id => false do |t|
46
+ t.integer :product_id
47
+ t.integer :time_id
48
+ t.integer :customer_id
49
+ t.decimal :store_sales, :precision => 10, :scale => 4
50
+ t.decimal :store_cost, :precision => 10, :scale => 4
51
+ t.decimal :unit_sales, :precision => 10, :scale => 4
52
+ end
53
+ end
54
+ end
55
+
56
+ task :define_models => :require_spec_helper do
57
+ class TimeDimension < ActiveRecord::Base
58
+ set_table_name "time"
59
+ validates_presence_of :the_date
60
+ before_create do
61
+ self.the_day = the_date.strftime("%A")
62
+ self.the_month = the_date.strftime("%B")
63
+ self.the_year = the_date.strftime("%Y").to_i
64
+ self.day_of_month = the_date.strftime("%d").to_i
65
+ self.week_of_year = the_date.strftime("%W").to_i
66
+ self.month_of_year = the_date.strftime("%m").to_i
67
+ self.quarter = "Q#{(month_of_year-1)/3+1}"
68
+ end
69
+ end
70
+ class Product < ActiveRecord::Base
71
+ belongs_to :product_class
72
+ end
73
+ class ProductClass < ActiveRecord::Base
74
+ end
75
+ class Customer < ActiveRecord::Base
76
+ end
77
+ class Sales < ActiveRecord::Base
78
+ set_table_name "sales"
79
+ belongs_to :time_by_day
80
+ belongs_to :product
81
+ belongs_to :customer
82
+ end
83
+ end
84
+
85
+ desc "Create test data"
86
+ task :create_data => [:create_tables, :create_time_data, :create_product_data, :create_customer_data, :create_sales_data]
87
+
88
+ task :create_time_data => :define_models do
89
+ puts "==> Creating time dimension"
90
+ TimeDimension.delete_all
91
+ start_time = Time.local(2010,1,1)
92
+ (2*365).times do |i|
93
+ TimeDimension.create!(:the_date => start_time + i.day)
94
+ end
95
+ end
96
+
97
+ task :create_product_data => :define_models do
98
+ puts "==> Creating product data"
99
+ Product.delete_all
100
+ ProductClass.delete_all
101
+ families = ["Drink", "Food", "Non-Consumable"]
102
+ (1..100).each do |i|
103
+ product_class = ProductClass.create!(
104
+ :product_family => families[i % 3],
105
+ :product_department => "Department #{i}",
106
+ :product_category => "Category #{i}",
107
+ :product_subcategory => "Subcategory #{i}"
108
+ )
109
+ Product.create!(
110
+ :product_class_id => product_class.id,
111
+ :brand_name => "Brand #{i}",
112
+ :product_name => "Product #{i}"
113
+ )
114
+ end
115
+ end
116
+
117
+ task :create_customer_data => :define_models do
118
+ puts "==> Creating customer data"
119
+ Customer.delete_all
120
+ i = 0
121
+ [
122
+ ["Canada", "BC", "Burnaby"],["Canada", "BC", "Cliffside"],["Canada", "BC", "Haney"],["Canada", "BC", "Ladner"],
123
+ ["Canada", "BC", "Langford"],["Canada", "BC", "Langley"],["Canada", "BC", "Metchosin"],["Canada", "BC", "N. Vancouver"],
124
+ ["Canada", "BC", "Newton"],["Canada", "BC", "Oak Bay"],["Canada", "BC", "Port Hammond"],["Canada", "BC", "Richmond"],
125
+ ["Canada", "BC", "Royal Oak"],["Canada", "BC", "Shawnee"],["Canada", "BC", "Sooke"],["Canada", "BC", "Vancouver"],
126
+ ["Canada", "BC", "Victoria"],["Canada", "BC", "Westminster"],
127
+ ["Mexico", "DF", "San Andres"],["Mexico", "DF", "Santa Anita"],["Mexico", "DF", "Santa Fe"],["Mexico", "DF", "Tixapan"],
128
+ ["Mexico", "Guerrero", "Acapulco"],["Mexico", "Jalisco", "Guadalajara"],["Mexico", "Mexico", "Mexico City"],
129
+ ["Mexico", "Oaxaca", "Tlaxiaco"],["Mexico", "Sinaloa", "La Cruz"],["Mexico", "Veracruz", "Orizaba"],
130
+ ["Mexico", "Yucatan", "Merida"],["Mexico", "Zacatecas", "Camacho"],["Mexico", "Zacatecas", "Hidalgo"],
131
+ ["USA", "CA", "Altadena"],["USA", "CA", "Arcadia"],["USA", "CA", "Bellflower"],["USA", "CA", "Berkeley"],
132
+ ["USA", "CA", "Beverly Hills"],["USA", "CA", "Burbank"],["USA", "CA", "Burlingame"],["USA", "CA", "Chula Vista"],
133
+ ["USA", "CA", "Colma"],["USA", "CA", "Concord"],["USA", "CA", "Coronado"],["USA", "CA", "Daly City"],
134
+ ["USA", "CA", "Downey"],["USA", "CA", "El Cajon"],["USA", "CA", "Fremont"],["USA", "CA", "Glendale"],
135
+ ["USA", "CA", "Grossmont"],["USA", "CA", "Imperial Beach"],["USA", "CA", "La Jolla"],["USA", "CA", "La Mesa"],
136
+ ["USA", "CA", "Lakewood"],["USA", "CA", "Lemon Grove"],["USA", "CA", "Lincoln Acres"],["USA", "CA", "Long Beach"],
137
+ ["USA", "CA", "Los Angeles"],["USA", "CA", "Mill Valley"],["USA", "CA", "National City"],["USA", "CA", "Newport Beach"],
138
+ ["USA", "CA", "Novato"],["USA", "CA", "Oakland"],["USA", "CA", "Palo Alto"],["USA", "CA", "Pomona"],
139
+ ["USA", "CA", "Redwood City"],["USA", "CA", "Richmond"],["USA", "CA", "San Carlos"],["USA", "CA", "San Diego"],
140
+ ["USA", "CA", "San Francisco"],["USA", "CA", "San Gabriel"],["USA", "CA", "San Jose"],["USA", "CA", "Santa Cruz"],
141
+ ["USA", "CA", "Santa Monica"],["USA", "CA", "Spring Valley"],["USA", "CA", "Torrance"],["USA", "CA", "West Covina"],
142
+ ["USA", "CA", "Woodland Hills"],
143
+ ["USA", "OR", "Albany"],["USA", "OR", "Beaverton"],["USA", "OR", "Corvallis"],["USA", "OR", "Lake Oswego"],
144
+ ["USA", "OR", "Lebanon"],["USA", "OR", "Milwaukie"],["USA", "OR", "Oregon City"],["USA", "OR", "Portland"],
145
+ ["USA", "OR", "Salem"],["USA", "OR", "W. Linn"],["USA", "OR", "Woodburn"],
146
+ ["USA", "WA", "Anacortes"],["USA", "WA", "Ballard"],["USA", "WA", "Bellingham"],["USA", "WA", "Bremerton"],
147
+ ["USA", "WA", "Burien"],["USA", "WA", "Edmonds"],["USA", "WA", "Everett"],["USA", "WA", "Issaquah"],
148
+ ["USA", "WA", "Kirkland"],["USA", "WA", "Lynnwood"],["USA", "WA", "Marysville"],["USA", "WA", "Olympia"],
149
+ ["USA", "WA", "Port Orchard"],["USA", "WA", "Puyallup"],["USA", "WA", "Redmond"],["USA", "WA", "Renton"],
150
+ ["USA", "WA", "Seattle"],["USA", "WA", "Sedro Woolley"],["USA", "WA", "Spokane"],["USA", "WA", "Tacoma"],
151
+ ["USA", "WA", "Walla Walla"],["USA", "WA", "Yakima"]
152
+ ].each do |country, state, city|
153
+ i += 1
154
+ Customer.create!(
155
+ :country => country,
156
+ :state_province => state,
157
+ :city => city,
158
+ :fname => "First#{i}",
159
+ :lname => "Last#{i}",
160
+ :fullname => "First#{i} Last#{i}",
161
+ :gender => i % 2 == 0 ? "M" : "F"
162
+ )
163
+ end
164
+ end
165
+
166
+ task :create_sales_data => :define_models do
167
+ puts "==> Creating sales data"
168
+ Sales.delete_all
169
+ count = 100
170
+ products = Product.order("id").limit(count).all
171
+ times = TimeDimension.order("id").limit(count).all
172
+ customers = Customer.order("id").limit(count).all
173
+ count.times do |i|
174
+ Sales.create!(
175
+ :product_id => products[i].id,
176
+ :time_id => times[i].id,
177
+ :customer_id => customers[i].id,
178
+ :store_sales => BigDecimal("2#{i}.12"),
179
+ :store_cost => BigDecimal("1#{i}.1234"),
180
+ :unit_sales => i+1
181
+ )
182
+ end
183
+ end
184
+
185
+ end
@@ -0,0 +1,345 @@
1
+ require "spec_helper"
2
+
3
+ describe "Schema definition" do
4
+
5
+ describe "elements" do
6
+ before(:each) do
7
+ @schema = Mondrian::OLAP::Schema.new
8
+ end
9
+
10
+ describe "root element" do
11
+ it "should render to XML" do
12
+ @schema.to_xml.should be_like <<-XML
13
+ <?xml version="1.0"?>
14
+ <Schema/>
15
+ XML
16
+ end
17
+
18
+ it "should render to XML with attributes" do
19
+ @schema.define('FoodMart') do
20
+ description 'Demo "FoodMart" schema'
21
+ end
22
+ @schema.to_xml.should be_like <<-XML
23
+ <?xml version="1.0"?>
24
+ <Schema description="Demo &quot;FoodMart&quot; schema" name="FoodMart"/>
25
+ XML
26
+ end
27
+
28
+ it "should render to XML using class method" do
29
+ schema = Mondrian::OLAP::Schema.define('FoodMart')
30
+ schema.to_xml.should be_like <<-XML
31
+ <?xml version="1.0"?>
32
+ <Schema name="FoodMart"/>
33
+ XML
34
+ end
35
+ end
36
+
37
+ describe "Cube" do
38
+ it "should render to XML" do
39
+ @schema.define do
40
+ cube 'Sales' do
41
+ default_measure 'Unit Sales'
42
+ description 'Sales cube'
43
+ cache false
44
+ enabled true
45
+ end
46
+ end
47
+ @schema.to_xml.should be_like <<-XML
48
+ <?xml version="1.0"?>
49
+ <Schema name="default">
50
+ <Cube cache="false" defaultMeasure="Unit Sales" description="Sales cube" enabled="true" name="Sales"/>
51
+ </Schema>
52
+ XML
53
+ end
54
+
55
+ it "should render to XML using options hash" do
56
+ @schema.define do
57
+ cube 'Sales', :default_measure => 'Unit Sales',
58
+ :description => 'Sales cube', :cache => false, :enabled => true
59
+ end
60
+ @schema.to_xml.should be_like <<-XML
61
+ <?xml version="1.0"?>
62
+ <Schema name="default">
63
+ <Cube cache="false" defaultMeasure="Unit Sales" description="Sales cube" enabled="true" name="Sales"/>
64
+ </Schema>
65
+ XML
66
+ end
67
+ end
68
+
69
+ describe "Table" do
70
+ it "should render to XML" do
71
+ @schema.define do
72
+ cube 'Sales' do
73
+ table 'sales_fact', :alias => 'sales'
74
+ end
75
+ end
76
+ @schema.to_xml.should be_like <<-XML
77
+ <?xml version="1.0"?>
78
+ <Schema name="default">
79
+ <Cube name="Sales">
80
+ <Table alias="sales" name="sales_fact"/>
81
+ </Cube>
82
+ </Schema>
83
+ XML
84
+ end
85
+
86
+ it "should render table name in uppercase when using Oracle driver" do
87
+ @schema.define do
88
+ cube 'Sales' do
89
+ table 'sales_fact', :alias => 'sales'
90
+ end
91
+ end
92
+ @schema.to_xml(:driver => 'oracle').should be_like <<-XML
93
+ <?xml version="1.0"?>
94
+ <Schema name="default">
95
+ <Cube name="Sales">
96
+ <Table alias="SALES" name="SALES_FACT"/>
97
+ </Cube>
98
+ </Schema>
99
+ XML
100
+ end
101
+ end
102
+
103
+ describe "Dimension" do
104
+ it "should render to XML" do
105
+ @schema.define do
106
+ cube 'Sales' do
107
+ dimension 'Gender' do
108
+ foreign_key 'customer_id'
109
+ hierarchy do
110
+ has_all true
111
+ all_member_name 'All Genders'
112
+ primary_key 'customer_id'
113
+ table 'customer'
114
+ level 'Gender', :column => 'gender', :unique_members => true
115
+ end
116
+ end
117
+ end
118
+ end
119
+ @schema.to_xml.should be_like <<-XML
120
+ <?xml version="1.0"?>
121
+ <Schema name="default">
122
+ <Cube name="Sales">
123
+ <Dimension foreignKey="customer_id" name="Gender">
124
+ <Hierarchy allMemberName="All Genders" hasAll="true" primaryKey="customer_id">
125
+ <Table name="customer"/>
126
+ <Level column="gender" name="Gender" uniqueMembers="true"/>
127
+ </Hierarchy>
128
+ </Dimension>
129
+ </Cube>
130
+ </Schema>
131
+ XML
132
+ end
133
+
134
+ it "should render time dimension" do
135
+ @schema.define do
136
+ cube 'Sales' do
137
+ dimension 'Time' do
138
+ foreign_key 'time_id'
139
+ hierarchy do
140
+ has_all false
141
+ primary_key 'time_id'
142
+ table 'time_by_day'
143
+ level 'Year', :column => 'the_year', :type => 'Numeric', :unique_members => true
144
+ level 'Quarter', :column => 'quarter', :unique_members => false
145
+ level 'Month', :column => 'month_of_year', :type => 'Numeric', :unique_members => false
146
+ end
147
+ end
148
+ end
149
+ end
150
+ @schema.to_xml.should be_like <<-XML
151
+ <?xml version="1.0"?>
152
+ <Schema name="default">
153
+ <Cube name="Sales">
154
+ <Dimension foreignKey="time_id" name="Time">
155
+ <Hierarchy hasAll="false" primaryKey="time_id">
156
+ <Table name="time_by_day"/>
157
+ <Level column="the_year" name="Year" type="Numeric" uniqueMembers="true"/>
158
+ <Level column="quarter" name="Quarter" uniqueMembers="false"/>
159
+ <Level column="month_of_year" name="Month" type="Numeric" uniqueMembers="false"/>
160
+ </Hierarchy>
161
+ </Dimension>
162
+ </Cube>
163
+ </Schema>
164
+ XML
165
+ end
166
+
167
+ it "should render dimension hierarchy with join" do
168
+ @schema.define do
169
+ cube 'Sales' do
170
+ dimension 'Products', :foreign_key => 'product_id' do
171
+ hierarchy :has_all => true, :all_member_name => 'All Products',
172
+ :primary_key => 'product_id', :primary_key_table => 'product' do
173
+ join :left_key => 'product_class_id', :right_key => 'product_class_id' do
174
+ table 'product'
175
+ table 'product_class'
176
+ end
177
+ level 'Product Family', :table => 'product_class', :column => 'product_family', :unique_members => true
178
+ level 'Brand Name', :table => 'product', :column => 'brand_name', :unique_members => false
179
+ level 'Product Name', :table => 'product', :column => 'product_name', :unique_members => true
180
+ end
181
+ end
182
+ end
183
+ end
184
+ @schema.to_xml.should be_like <<-XML
185
+ <?xml version="1.0"?>
186
+ <Schema name="default">
187
+ <Cube name="Sales">
188
+ <Dimension foreignKey="product_id" name="Products">
189
+ <Hierarchy allMemberName="All Products" hasAll="true" primaryKey="product_id" primaryKeyTable="product">
190
+ <Join leftKey="product_class_id" rightKey="product_class_id">
191
+ <Table name="product"/>
192
+ <Table name="product_class"/>
193
+ </Join>
194
+ <Level column="product_family" name="Product Family" table="product_class" uniqueMembers="true"/>
195
+ <Level column="brand_name" name="Brand Name" table="product" uniqueMembers="false"/>
196
+ <Level column="product_name" name="Product Name" table="product" uniqueMembers="true"/>
197
+ </Hierarchy>
198
+ </Dimension>
199
+ </Cube>
200
+ </Schema>
201
+ XML
202
+ end
203
+
204
+ it "should render table and column names in uppercase when using Oracle driver" do
205
+ @schema.define do
206
+ cube 'Sales' do
207
+ dimension 'Products', :foreign_key => 'product_id' do
208
+ hierarchy :has_all => true, :all_member_name => 'All Products',
209
+ :primary_key => 'product_id', :primary_key_table => 'product' do
210
+ join :left_key => 'product_class_id', :right_key => 'product_class_id' do
211
+ table 'product'
212
+ table 'product_class'
213
+ end
214
+ level 'Product Family', :table => 'product_class', :column => 'product_family', :unique_members => true
215
+ level 'Brand Name', :table => 'product', :column => 'brand_name', :unique_members => false
216
+ level 'Product Name', :table => 'product', :column => 'product_name', :unique_members => true
217
+ end
218
+ end
219
+ end
220
+ end
221
+ @schema.to_xml(:driver => 'oracle').should be_like <<-XML
222
+ <?xml version="1.0"?>
223
+ <Schema name="default">
224
+ <Cube name="Sales">
225
+ <Dimension foreignKey="PRODUCT_ID" name="Products">
226
+ <Hierarchy allMemberName="All Products" hasAll="true" primaryKey="PRODUCT_ID" primaryKeyTable="PRODUCT">
227
+ <Join leftKey="PRODUCT_CLASS_ID" rightKey="PRODUCT_CLASS_ID">
228
+ <Table name="PRODUCT"/>
229
+ <Table name="PRODUCT_CLASS"/>
230
+ </Join>
231
+ <Level column="PRODUCT_FAMILY" name="Product Family" table="PRODUCT_CLASS" uniqueMembers="true"/>
232
+ <Level column="BRAND_NAME" name="Brand Name" table="PRODUCT" uniqueMembers="false"/>
233
+ <Level column="PRODUCT_NAME" name="Product Name" table="PRODUCT" uniqueMembers="true"/>
234
+ </Hierarchy>
235
+ </Dimension>
236
+ </Cube>
237
+ </Schema>
238
+ XML
239
+ end
240
+
241
+ end
242
+
243
+ describe "Measure" do
244
+ it "should render XML" do
245
+ @schema.define do
246
+ cube 'Sales' do
247
+ measure 'Unit Sales' do
248
+ column 'unit_sales'
249
+ aggregator 'sum'
250
+ end
251
+ end
252
+ end
253
+ @schema.to_xml.should be_like <<-XML
254
+ <?xml version="1.0"?>
255
+ <Schema name="default">
256
+ <Cube name="Sales">
257
+ <Measure aggregator="sum" column="unit_sales" name="Unit Sales"/>
258
+ </Cube>
259
+ </Schema>
260
+ XML
261
+ end
262
+
263
+ it "should render column name in uppercase when using Oracle driver" do
264
+ @schema.define do
265
+ cube 'Sales' do
266
+ measure 'Unit Sales' do
267
+ column 'unit_sales'
268
+ aggregator 'sum'
269
+ end
270
+ end
271
+ end
272
+ @schema.to_xml(:driver => 'oracle').should be_like <<-XML
273
+ <?xml version="1.0"?>
274
+ <Schema name="default">
275
+ <Cube name="Sales">
276
+ <Measure aggregator="sum" column="UNIT_SALES" name="Unit Sales"/>
277
+ </Cube>
278
+ </Schema>
279
+ XML
280
+ end
281
+ end
282
+
283
+ describe "Calculated Member" do
284
+ it "should render XML" do
285
+ @schema.define do
286
+ cube 'Sales' do
287
+ calculated_member 'Profit' do
288
+ dimension 'Measures'
289
+ formula '[Measures].[Store Sales] - [Measures].[Store Cost]'
290
+ end
291
+ end
292
+ end
293
+ @schema.to_xml.should be_like <<-XML
294
+ <?xml version="1.0"?>
295
+ <Schema name="default">
296
+ <Cube name="Sales">
297
+ <CalculatedMember dimension="Measures" formula="[Measures].[Store Sales] - [Measures].[Store Cost]" name="Profit"/>
298
+ </Cube>
299
+ </Schema>
300
+ XML
301
+ end
302
+ end
303
+ end
304
+
305
+ describe "connection with schema" do
306
+ before(:all) do
307
+ @schema = Mondrian::OLAP::Schema.define do
308
+ cube 'Sales' do
309
+ table 'sales'
310
+ dimension 'Gender', :foreign_key => 'customer_id' do
311
+ hierarchy :has_all => true, :primary_key => 'id' do
312
+ table 'customers'
313
+ level 'Gender', :column => 'gender', :unique_members => true
314
+ end
315
+ end
316
+ dimension 'Time', :foreign_key => 'time_id' do
317
+ hierarchy :has_all => false, :primary_key => 'id' do
318
+ table 'time'
319
+ level 'Year', :column => 'the_year', :type => 'Numeric', :unique_members => true
320
+ level 'Quarter', :column => 'quarter', :unique_members => false
321
+ level 'Month', :column => 'month_of_year', :type => 'Numeric', :unique_members => false
322
+ end
323
+ end
324
+ measure 'Unit Sales', :column => 'unit_sales', :aggregator => 'sum'
325
+ measure 'Store Sales', :column => 'store_sales', :aggregator => 'sum'
326
+ end
327
+ end
328
+ @olap = Mondrian::OLAP::Connection.create(CONNECTION_PARAMS.merge :schema => @schema)
329
+ end
330
+
331
+ it "should connect" do
332
+ @olap.should be_connected
333
+ end
334
+
335
+ it "should execute query" do
336
+ @olap.from('Sales').
337
+ columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]').
338
+ rows('descendants([Time].[2010].[Q1])').
339
+ where('[Gender].[F]').
340
+ execute.should be_a(Mondrian::OLAP::Result)
341
+ end
342
+
343
+ end
344
+
345
+ end