1 package body BSC_AW_ADAPTER_KPI AS
2 /*$Header: BSCAWAKB.pls 120.30 2006/05/20 02:10:19 vsurendr ship $*/
3
4 procedure create_kpi(p_kpi_list dbms_sql.varchar2_table) is
5 l_kpi kpi_tb;
6 Begin
7 for i in 1..p_kpi_list.count loop
8 l_kpi(i).kpi:=p_kpi_list(i);
9 end loop;
10 for i in 1..l_kpi.count loop
11 create_kpi(l_kpi(i));
12 end loop;
13 Exception when others then
14 log_n('Exception in create_kpi '||sqlerrm);
15 raise;
16 End;
17
18 procedure create_kpi(p_kpi in out nocopy kpi_r) is
19 --
20 Begin
21 --first we need to get the dimension sets of the kpi
22 --get_kpi_properties gets calendar etc
23 if g_debug then
24 log_n('=====================================================');
25 log('KPI Adapter. Process KPI ->'||p_kpi.kpi);
26 end if;
27 /*
28 if the kpi is already implemented as AW, we do
29 1. if recreate is specified, its all cleaned up and recretaed
30 2. else , return. do nothing
31 */
32 if check_kpi_create(p_kpi.kpi) then
33 bsc_aw_bsc_metadata.get_kpi_properties(p_kpi);--gets calendar
34 bsc_aw_bsc_metadata.get_kpi_dim_sets(p_kpi);
35 --for each dim set, get the bsc dim levels in it. for these levels, get the cc dim
36 for i in 1..p_kpi.dim_set.count loop
37 get_dim_set_properties(p_kpi.kpi,p_kpi.dim_set(i)); --forecast yes or no
38 get_dim_set_dims(p_kpi.kpi,p_kpi.dim_set(i));
39 identify_standalone_levels(p_kpi.kpi,p_kpi.dim_set(i)); --user specifies city and country with no parent child relation
40 create_missing_dim_levels(p_kpi.kpi,p_kpi.dim_set(i)); --if intermediate levels are not specified for the kpi
41 get_dim_set_std_dims(p_kpi.kpi,p_kpi.dim_set(i));--type and projection dim
42 get_dim_set_calendar(p_kpi,p_kpi.dim_set(i));
43 --we go to bsc olap metadata to get the dim properties
44 get_dim_set_dim_properties(p_kpi.kpi,p_kpi.dim_set(i)); --recursive, multi level, time or normal
45 set_dim_level_positions(p_kpi.kpi,p_kpi.dim_set(i));
46 set_dim_order(p_kpi.dim_set(i));
47 get_dim_set_measures(p_kpi.kpi,p_kpi.dim_set(i));
48 end loop;
49 --get the targets at higher level info (if there are targets at higher levels)
50 get_dim_set_targets(p_kpi);
51 --set_dim_agg_level will set the agg level for each dim
52 set_dim_agg_level(p_kpi);
53 set_calendar_agg_level(p_kpi);
54 --
55 for i in 1..p_kpi.dim_set.count loop
56 get_s_views(p_kpi.kpi,p_kpi.dim_set(i)); --gets both regular and z views
57 get_dim_set_data_source(p_kpi,p_kpi.dim_set(i));
58 if p_kpi.dim_set(i).targets_higher_levels='Y' then
59 get_dim_set_data_source(p_kpi,p_kpi.target_dim_set(i));
60 end if;
61 end loop;
62 /*set the DS levels. this has to be set before check_compressed_composite*/
63 for i in 1..p_kpi.dim_set.count loop
64 set_DS_dim_levels(p_kpi,p_kpi.dim_set(i));
65 if p_kpi.dim_set(i).targets_higher_levels='Y' then
66 set_DS_dim_levels(p_kpi,p_kpi.target_dim_set(i));
67 end if;
68 end loop;
69 /*see if we can set the sql_aggregated flag for non std agg to Y. this can enable compressed composites and partitions */
70 set_sql_aggregations(p_kpi,'set');
71 /*first set the partition for target, only then actual. actual can be partitioned only of target can also be partitioned
72 set_dimset_partition_info can change the agg_level of the dimensions if hash partitions are involved */
73 for i in 1..p_kpi.dim_set.count loop
74 check_compressed_composite(p_kpi.dim_set(i),p_kpi.target_dim_set(i));
75 set_dimset_partition_info(p_kpi.kpi,p_kpi.dim_set(i),p_kpi.target_dim_set(i));
76 end loop;
77 /*if we do not have partitions, we can unset the sql_aggregation flag */
78 set_sql_aggregations(p_kpi,'unset');
79 --make the sql stmt etc
80 for i in 1..p_kpi.dim_set.count loop
81 /*set the PT info in the dimset */
82 set_data_source_PT(p_kpi,p_kpi.dim_set(i));
83 set_dim_set_data_source(p_kpi,p_kpi.dim_set(i));
84 if p_kpi.dim_set(i).targets_higher_levels='Y' then
85 set_data_source_PT(p_kpi,p_kpi.target_dim_set(i));
86 set_dim_set_data_source(p_kpi,p_kpi.target_dim_set(i));
87 end if;
88 end loop;
89 --set properties like pre-calculated dimset etc
90 set_dim_set_properties(p_kpi);
91 --metadata read complete.
92 --create_aw_object_names gives the names to the aw objects like dim, cubes
93 create_aw_object_names(p_kpi);
94 make_agg_formula(p_kpi);
95 if g_debug then
96 dmp_kpi(p_kpi);
97 end if;
98 create_kpi_aw(p_kpi);--create the aw objects
99 --create the kpi metadata
100 bsc_aw_md_api.create_kpi(p_kpi);
101 end if;
102 Exception when others then
103 log_n('Exception in create_kpi '||sqlerrm);
104 raise;
105 End;
106
107 /*
108 given a kpi object filled with all reqd metadata, this creates the aw objects.
109 can be used later to recreate kpi from olap metadata. we fill kpi_r and send it
110 to this api
111 we do not create the metadata here since its already there in case of recreate
112 */
113 procedure create_kpi_aw(p_kpi in out nocopy kpi_r) is
114 Begin
115 create_kpi_objects(p_kpi);
116 create_kpi_program(p_kpi);
117 create_kpi_program_parallel(p_kpi); --creates program based on partition or program based on measure
118 create_kpi_view(p_kpi); --creates the S views based on olap table functions
119 Exception when others then
120 log_n('Exception in create_kpi '||sqlerrm);
121 raise;
122 End;
123
124 /*
125 see if recreate is specified. if yes, drop the kpi (if it exists)
126 if RECREATE is specified, aw objects are dropped
127 */
128 function check_kpi_create(p_kpi varchar2) return boolean is
129 Begin
130 --see if the kpi exists
131 if bsc_aw_md_api.is_kpi_present(p_kpi) then
132 if bsc_aw_utility.get_parameter_value(bsc_aw_utility.g_options,'RECREATE KPI')='Y' then
133 drop_kpi_objects(p_kpi); --drops aw objects and olap metadata
134 return true;
135 else
136 return false; --do not create the kpi. already present
137 end if;
138 else --new kpi
139 return true;
140 end if;
141 Exception when others then
142 log_n('Exception in check_kpi_create '||sqlerrm);
143 raise;
144 End;
145
146
147 /*
148 from bsc olap metadata, get the dim properties
149 we consider time and other dim separately. time is considered in calendars, not in dim
150
151 here we are getting level properties in 2 parts.
152 bsc_aw_bsc_metadata.get_dim_level_properties gets it from metadata
153 for rec dim, we also do bsc_aw_md_api.get_bsc_olap_object_relation to find the rec_parent_level.
154 this is ok since rec_parent_level is not a bsc metadata property. its specific to our implementation.
155 */
156 procedure get_dim_set_dim_properties(p_kpi varchar2,p_dim_set in out nocopy dim_set_r) is
157 Begin
158 for i in 1..p_dim_set.dim.count loop
159 get_dim_properties(p_kpi,p_dim_set.dim(i));
160 end loop;
161 --need to see if we need zero code on the dim
162 bsc_aw_bsc_metadata.check_dim_zero_code(p_kpi,p_dim_set);
163 Exception when others then
164 log_n('Exception in get_dim_set_dim_properties '||sqlerrm);
165 raise;
166 End;
167
168 procedure get_dim_properties(p_kpi varchar2,p_dim in out nocopy dim_r) is
169 --
170 l_olap_object_relation bsc_aw_md_wrapper.bsc_olap_object_relation_tb;
171 Begin
172 bsc_aw_md_api.get_dim_properties(p_dim); --recursive, multi level, time or normal, concat?, base value cube etc
173 bsc_aw_bsc_metadata.get_dim_level_properties(p_kpi,p_dim); --pk,fk,datatype for the levels and the filter
174 l_olap_object_relation.delete;
175 --'zero code level' 'recursive parent level'
176 bsc_aw_md_api.get_bsc_olap_object_relation(null,null,null,p_dim.dim_name,'dimension',l_olap_object_relation);
177 for i in 1..l_olap_object_relation.count loop
178 if l_olap_object_relation(i).object_type='dimension level' and l_olap_object_relation(i).relation_type='zero code level' then
179 for j in 1..p_dim.levels.count loop
180 if l_olap_object_relation(i).object=p_dim.levels(j).level_name then
181 p_dim.levels(j).zero_code_level:=l_olap_object_relation(i).relation_object;
182 exit;
183 end if;
184 end loop;
185 elsif l_olap_object_relation(i).object_type='dimension level' and l_olap_object_relation(i).relation_type='recursive parent level' then
186 for j in 1..p_dim.levels.count loop
187 if l_olap_object_relation(i).object=p_dim.levels(j).level_name then
188 p_dim.levels(j).rec_parent_level:=l_olap_object_relation(i).relation_object;
189 exit;
190 end if;
191 end loop;
192 end if;
193 end loop;
194 Exception when others then
195 log_n('Exception in get_dim_properties '||sqlerrm);
196 raise;
197 End;
198
199 /*set the level position by reading the olap metadata
200 required for set_dim_agg_level
201 */
202 procedure set_dim_level_positions(p_kpi varchar2,p_dim_set in out nocopy dim_set_r) is
203 Begin
204 for i in 1..p_dim_set.dim.count loop
205 set_dim_level_positions(p_dim_set.dim(i));
206 end loop;
207 --std dim
208 for i in 1..p_dim_set.std_dim.count loop
209 set_dim_level_positions(p_dim_set.std_dim(i));
210 end loop;
211 Exception when others then
212 log_n('Exception in set_dim_level_positions '||sqlerrm);
213 raise;
214 End;
215
216 procedure set_dim_level_positions(p_dim in out nocopy dim_r) is
217 l_olap_object bsc_aw_md_wrapper.bsc_olap_object_tb;
218 Begin
219 l_olap_object.delete;
220 bsc_aw_md_api.get_bsc_olap_object(null,'dimension level',p_dim.dim_name,'dimension',l_olap_object);
221 for i in 1..p_dim.levels.count loop
222 --standalone dim for each dim level do not have dimension levels with them.
223 p_dim.levels(i).position:=1;
224 for j in 1..l_olap_object.count loop
225 if p_dim.levels(i).level_name=l_olap_object(j).object then
226 p_dim.levels(i).position:=bsc_aw_utility.get_parameter_value(l_olap_object(j).property1,'position',',');
227 exit;
228 end if;
229 end loop;
230 end loop;
231 Exception when others then
232 log_n('Exception in set_dim_level_positions '||sqlerrm);
233 raise;
234 End;
235
236 /*
237 given a kpi and dim set, find out the calendar and the periodicity info
238 calendar is at kpi level, we store it at dimset level to keep consistent with other dim
239 NOTE!! for calendar,we cannot assume that periodicity(1) is the lowest level
240 simply because there can be multiple lowest levels. so we have a flag in periodicity_r called
241 lowest_level
242 */
243 procedure get_dim_set_calendar(p_kpi kpi_r,p_dim_set in out nocopy dim_set_r) is
244 l_pc cal_parent_child_tb;
245 Begin
246 p_dim_set.calendar.calendar:=p_kpi.calendar;
247 bsc_aw_bsc_metadata.get_dim_set_calendar(p_kpi.kpi,p_dim_set);
248 --give the aw dim names
249 p_dim_set.calendar.aw_dim:=bsc_aw_calendar.get_calendar_name(p_dim_set.calendar.calendar);
250 --set the relation name, periodicity aw name
251 bsc_aw_md_api.get_dim_set_calendar(p_kpi,p_dim_set);
252 --now, get the missing periodicity, and mark lowest level
253 get_missing_periodicity(p_kpi,p_dim_set);
254 /*of all hier relations in the calendar, grab only those that are relevant to the dimset */
255 get_relevant_cal_hier(p_dim_set.calendar.periodicity,p_dim_set.calendar.parent_child,l_pc);
256 if p_dim_set.calendar.periodicity.count>1 and l_pc.count=0 then
257 log('correct_relevant_cal_hier could not get the relevant cal hier');
258 raise bsc_aw_utility.g_exception;
259 end if;
260 p_dim_set.calendar.parent_child.delete;
261 for i in 1..l_pc.count loop
262 p_dim_set.calendar.parent_child(i):=l_pc(i);
263 end loop;
264 Exception when others then
265 log_n('Exception in get_dim_set_calendar '||sqlerrm);
266 raise;
267 End;
268
269 /*
270 given a dim set, finds out the levels in it and also finds from olap metadata
271 what the cc dim is. the data structure is then loaded
272 in get_dim_set_dims, we expect the dim levels come with the lowest levels first. this means we can assume
273 that the first level for any dim is the lowest level
274
275 get_dim_set_dims returns the missing levels. so if the kpi has city and country, the api will also return
276 state
277 */
278 procedure get_dim_set_dims(
279 p_kpi varchar2,
280 p_dim_set in out nocopy dim_set_r) is
281 --
282 l_dim_level dbms_sql.varchar2_table;
283 l_mo_dim_group dbms_sql.varchar2_table; --used to see if a level is stand alone or part of parent child
284 l_skip_level dbms_sql.varchar2_table;
285 l_dim varchar2(300);
286 Begin
287 bsc_aw_bsc_metadata.get_dim_set_dims(p_kpi,p_dim_set.dim_set,l_dim_level,l_mo_dim_group,l_skip_level);
288 for i in 1..l_dim_level.count loop
289 bsc_aw_md_api.get_dim_for_level(l_dim_level(i),l_dim);
290 if g_debug then
291 log('For level '||l_dim_level(i)||' got dim '||l_dim);
292 end if;
293 set_dim_and_level(p_dim_set,l_dim,l_dim_level(i),l_mo_dim_group(i),l_skip_level(i)); --level properties are set in get_dim_set_dim_properties
294 end loop;
295 Exception when others then
296 log_n('Exception in get_dim_set_dims '||sqlerrm);
297 raise;
298 End;
299
300 /*
301 given a cc dim and level, see if the cc dim exists. if not create it . if yes,
302 see if the level is already in. if not, add it.
303 */
304 procedure set_dim_and_level(
305 p_dim_set in out nocopy dim_set_r,
306 p_dim varchar2,
307 p_level varchar2,
308 p_mo_dim_group varchar2,
309 p_skip_level varchar2
310 ) is
311 Begin
312 for i in 1..p_dim_set.dim.count loop
313 if p_dim_set.dim(i).dim_name=p_dim then
314 for j in 1..p_dim_set.dim(i).levels.count loop
315 if p_dim_set.dim(i).levels(j).level_name=p_level then
316 return;
317 end if;
318 end loop;
319 --at this point, p_level was not in the levels list...so add it
320 p_dim_set.dim(i).levels(p_dim_set.dim(i).levels.count+1).level_name:=p_level;
321 p_dim_set.dim(i).levels(p_dim_set.dim(i).levels.count).property:='mo dim group='||p_mo_dim_group||',skip level='||
322 nvl(p_skip_level,'N');
323 return;
324 end if;
325 end loop;
326 --here, p_dim was not found in the dim set. create the dim and add the level
327 p_dim_set.dim(p_dim_set.dim.count+1).dim_name:=p_dim;
328 p_dim_set.dim(p_dim_set.dim.count).levels(p_dim_set.dim(p_dim_set.dim.count).levels.count+1).level_name:=p_level;
329 p_dim_set.dim(p_dim_set.dim.count).levels(p_dim_set.dim(p_dim_set.dim.count).levels.count).property:='mo dim group='||
330 p_mo_dim_group||',skip level='||nvl(p_skip_level,'N');
331 Exception when others then
332 log_n('Exception in set_dim_and_level '||sqlerrm);
333 raise;
334 End;
335
336 /*
337 in the composite, the order of dim is
338 dim with no agg, no zero code
339 dim with no agg, zero code
340 dim with agg
341 rec dim
342 time
343 also, in the load program, we follow the same order. this api just rearranges the dim in this order
344 please note that time dim is handled differently in calendar in the dim set
345 */
346 procedure set_dim_order(p_dim_set in out nocopy dim_set_r) is
350 Begin
347 l_order dbms_sql.number_table;
348 l_rank number;
349 l_dim dim_tb;
351 for i in 1..p_dim_set.dim.count loop
352 l_order(i):=null;
353 end loop;
354 l_rank:=0;
355 for i in 1..p_dim_set.dim.count loop
356 log_n('prop='||p_dim_set.dim(i).property||' rec='||p_dim_set.dim(i).recursive||' count='||p_dim_set.dim(i).levels.count||' zero='||
357 p_dim_set.dim(i).zero_code);
358 if p_dim_set.dim(i).property='normal' and p_dim_set.dim(i).recursive='N' and p_dim_set.dim(i).levels.count=1
359 and p_dim_set.dim(i).zero_code='N' then
360 l_rank:=l_rank+1;
361 l_order(i):=l_rank;
362 end if;
363 end loop;
364 for i in 1..p_dim_set.dim.count loop
365 if p_dim_set.dim(i).property='normal' and p_dim_set.dim(i).recursive='N' and p_dim_set.dim(i).levels.count=1
366 and p_dim_set.dim(i).zero_code='Y' and l_order(i) is null then
367 l_rank:=l_rank+1;
368 l_order(i):=l_rank;
369 end if;
370 end loop;
371 for i in 1..p_dim_set.dim.count loop
372 if p_dim_set.dim(i).property='normal' and p_dim_set.dim(i).recursive='N' and l_order(i) is null then
373 l_rank:=l_rank+1;
374 l_order(i):=l_rank;
375 end if;
376 end loop;
377 for i in 1..p_dim_set.dim.count loop
378 if p_dim_set.dim(i).property='normal' and p_dim_set.dim(i).recursive='Y' and l_order(i) is null then
379 l_rank:=l_rank+1;
380 l_order(i):=l_rank;
381 end if;
382 end loop;
383 --copy back in the correct order
384 l_dim:=p_dim_set.dim;
385 p_dim_set.dim.delete;
386 for i in 1..l_rank loop
387 for j in 1..l_dim.count loop
388 if l_order(j)=i then
389 p_dim_set.dim(p_dim_set.dim.count+1):=l_dim(j);
390 exit;
391 end if;
392 end loop;
393 end loop;
394 Exception when others then
395 log_n('Exception in set_dim_order '||sqlerrm);
396 raise;
397 End;
398
399 /*
400 get properties like
401 1. are there targets at higher levels
402 2. is there forecast
403 */
404 procedure get_dim_set_properties(p_kpi varchar2,p_dim_set in out nocopy dim_set_r) is
405 Begin
406 p_dim_set.dim_set_type:='actual';
407 Exception when others then
408 log_n('Exception in get_dim_set_properties '||sqlerrm);
409 raise;
410 End;
411
412 procedure get_dim_set_measures(p_kpi varchar2,p_dim_set in out nocopy dim_set_r) is
413 Begin
414 bsc_aw_bsc_metadata.get_dim_set_measures(p_kpi,p_dim_set.dim_set,p_dim_set.measure);
415 /*if there are BALANCE LAST VALUE measures add the .period and .year property, used in measure name dim or cubes in 9i */
416 /* NOTE the period cube and year cube name change in create_PT_comp_names for 9i*/
417 for i in 1..p_dim_set.measure.count loop
418 if p_dim_set.measure(i).measure_type=g_balance_last_value_prop then
419 bsc_aw_utility.merge_property(p_dim_set.measure(i).property,'period cube',null,p_dim_set.measure(i).measure||'.period');
420 bsc_aw_utility.merge_property(p_dim_set.measure(i).property,'year cube',null,p_dim_set.measure(i).measure||'.year');
421 end if;
422 end loop;
423 Exception when others then
424 log_n('Exception in get_dim_set_measures '||sqlerrm);
425 raise;
426 End;
427
428 /*
429 get the target dim and the dim levels
430 given the kpi and the dim set we see if there is targets at this dim set
431 for each dimset see if there are targets implemented
432 */
433 procedure get_dim_set_targets(p_kpi in out nocopy kpi_r) is
434 Begin
435 for i in 1..p_kpi.dim_set.count loop
436 p_kpi.dim_set(i).targets_higher_levels:=bsc_aw_bsc_metadata.is_target_at_higher_level(p_kpi.kpi,p_kpi.dim_set(i).dim_set);
437 if p_kpi.dim_set(i).targets_higher_levels='Y' then
438 p_kpi.target_dim_set(i):=p_kpi.dim_set(i);--copy all dim set properties excluding s_views and data source
439 --change the dimset name. append .target to it
440 p_kpi.target_dim_set(i).dim_set_name:=p_kpi.target_dim_set(i).dim_set_name||'.tgt';
441 p_kpi.target_dim_set(i).dim_set_type:='target';
442 p_kpi.target_dim_set(i).base_dim_set:=p_kpi.dim_set(i).dim_set_name;--for actuals, base_dim_set is null
443 bsc_aw_bsc_metadata.get_target_dim_levels(p_kpi.kpi,p_kpi.target_dim_set(i));
444 bsc_aw_bsc_metadata.get_target_dim_periodicity(p_kpi.kpi,p_kpi.target_dim_set(i));
445 else
446 p_kpi.target_dim_set(i).dim_set:=null;
447 end if;
448 end loop;
449 Exception when others then
450 log_n('Exception in get_dim_set_targets '||sqlerrm);
451 raise;
452 End;
453
454 --get both regular MV and ZMV
455 procedure get_s_views(p_kpi varchar2,p_dim_set in out nocopy dim_set_r) is
456 Begin
457 bsc_aw_bsc_metadata.get_s_views(p_kpi,p_dim_set);
458 Exception when others then
459 log_n('Exception in get_s_views '||sqlerrm);
460 raise;
461 End;
462
463 /*
464 This is an imp procedure!
465 this procedure will create the data sources for dim sets. finds out the base tables, finds out the level
466 of the base tables and create the sql statements as data source
467
468 at this point in time, we assume that all dim properties have been set. for example, dim levels
469 filters etc. we assign data_source.dim=dim_set.dim inside bsc_aw_bsc_metadata.get_dim_set_data_source
470 --
471 each data source is at a certain periodicity. they also contain
472 */
473 procedure get_dim_set_data_source(p_kpi kpi_r,p_dim_set in out nocopy dim_set_r) is
474 Begin
475 --get_dim_set_data_source fills data_source and inc_data_source
476 bsc_aw_bsc_metadata.get_dim_set_data_source(p_kpi.kpi,p_dim_set);
477 Exception when others then
478 log_n('Exception in get_dim_set_data_source '||sqlerrm);
479 raise;
480 End;
481
482 procedure set_dim_set_data_source(p_kpi kpi_r,p_dim_set in out nocopy dim_set_r) is
483 Begin
487 get_change_vector sets the change vector for initial, inc and target data sources
484 /*
485 get the change vector value. we look at bsc_olap_object_relation to see what change vectors are currently
486 used for base tables. then we allocate the next higher number
488
489 we have obsoleted the old approach to inc load as mentioned above . (date today is 18 may 2005)
490 we change the inc approach to not using the aw table. we will not have a bsc_b_aw table. we will have the change_vector column in the b table
491 it will be indexed. every time we load the b table or process it, we will load a unique value into this column. then we will also register
492 in olap metadata what the latest value is. this value is from a seq
493 in olap metadaat, for b table and dimset relation, we will have
494 current change vector
495 current change vector is the value that this b->dimset looked at.
496 current is what is in b table now.
497 we will create the aw programs to accept 2 more parameters . the sql will look as
498 select ...from b table where change_vector between min value and max value from a temp table
499 we will insert into the temp table the min value and max value . min value is what the dim set last loaded +1
500 max value is the value for change vector from the base table
501 if the kpi has less keys, we will replace the aw table with in - line sql again with where change_vector between min and max
502 after loading, we will do update set last change vector=current change vector
503 when b table is loaded, it will call an api that will update the current change vector for this b table.
504 we will not call bsc_aw_md_api.get_change_vector(p_kpi.kpi,p_dim_set) or correct_change_vector(p_kpi,p_dim_set) anymore
505
506 issue is : what if the b table already exists with data and we are creating the kpi. in this case, what will we set
507 current change vector to?
508 we will set it to 0. during load time, we check the b table for max(change_vector), set the current change vector
509 to that value and then continue. we want this at load time and not at optimizer time. after mo is run, someone can
510 load the b table.
511
512 at this time the following are true
513 -we have the base table names in each data source
514 -the levels in the base table have the level names. also pk and fk.
515 -the measure in data source has measure names and formula. no other info
516 -the measure record of the dim set does not have the formula info.
517 to construct the data source from the base table level info, this package must get the level relation info from
518 bsc olap metadata and construct the sql. it needs to go to olap metadata since the level info from the dim set
519 will not contain the in-between levels from the base table to the first level in the dim set
520 */
521 for i in 1..p_dim_set.data_source.count loop
522 create_data_source_sql(p_kpi.kpi,p_dim_set,p_dim_set.data_source(i));
523 end loop;
524 for i in 1..p_dim_set.inc_data_source.count loop
525 create_data_source_sql(p_kpi.kpi,p_dim_set,p_dim_set.inc_data_source(i));
526 end loop;
527 /*
528 the data source sql is mainly driven by the base table. we encountered perf issue 4549680 where we had 6 baes tables. each base table
529 feeds one measure. the load went sequentially loading from each base table. this added to the time. if there are multiple data source
530 and we load the dimset, we need to load all the cubes 1 shot. create new virtual data source with base tables together. this will be
531 invoked when the dimset is loaded
532 */
533 create_dimset_data_source_sql(p_kpi.kpi,p_dim_set,p_dim_set.data_source);
534 create_dimset_data_source_sql(p_kpi.kpi,p_dim_set,p_dim_set.inc_data_source);
535 Exception when others then
536 log_n('Exception in set_dim_set_data_source '||sqlerrm);
537 raise;
538 End;
539
540 /*
541 4642937 need to correct the levels of a data source. kpi can be a pre-calc kpi. this means there is B table data at upper levels also
542 if B table data comes at higher levels, we consider the dimset pre-calculated
543 data source has levels from the dimset. this means for targets, are already at higher level.
544 All B tables in a DS must have the same dim levels
545 status:correct,lower,higher,extra,skip
546 */
547 procedure set_DS_dim_levels(p_kpi kpi_r,p_dim_set in out nocopy dim_set_r) is
548 Begin
549 for i in 1..p_dim_set.data_source.count loop
550 set_DS_dim_levels(p_kpi.kpi,p_dim_set,p_dim_set.data_source(i));
551 end loop;
552 for i in 1..p_dim_set.inc_data_source.count loop
553 set_DS_dim_levels(p_kpi.kpi,p_dim_set,p_dim_set.inc_data_source(i));
554 end loop;
555 Exception when others then
556 log_n('Exception in set_DS_dim_levels '||sqlerrm);
557 raise;
558 End;
559
560 procedure set_DS_dim_levels(p_kpi varchar2,p_dim_set in out nocopy dim_set_r,p_data_source in out nocopy data_source_r) is
561 l_base_table base_table_r;
562 l_dim dim_r;
563 l_level level_r;
564 l_ds_dim_set dbms_sql.varchar2_table;
565 Begin
566 for i in 1..p_data_source.base_tables.count loop
567 set_DS_dim_levels(p_kpi,p_dim_set,p_data_source,p_data_source.base_tables(i));
568 end loop;
569 --correct the ds dim levels. since all B tables have the same dim levels in a DS, take just the first one
570 l_base_table:=p_data_source.base_tables(1);
571 for i in 1..l_base_table.levels.count loop
572 if l_base_table.level_status(i)='higher' then
573 l_dim:=get_kpi_level_dim_r(p_dim_set,l_base_table.levels(i).level_name);
574 l_level:=get_dim_level_r(l_dim,l_base_table.levels(i).level_name);
575 l_ds_dim_set(l_ds_dim_set.count+1):=l_dim.dim_name;
576 for j in 1..p_data_source.dim.count loop
577 if p_data_source.dim(j).dim_name=l_dim.dim_name then
578 p_data_source.dim(j).levels.delete;
579 p_data_source.dim(j).levels(p_data_source.dim(j).levels.count+1):=l_level;
580 exit;
581 end if;
582 end loop;
583 end if;
584 end loop;
585 --set lower and correct keys
589 p_data_source.dim(i).levels.delete;
586 for i in 1..p_data_source.dim.count loop
587 if bsc_aw_utility.in_array(l_ds_dim_set,p_data_source.dim(i).dim_name)=false then
588 l_level:=p_data_source.dim(i).levels(1);
590 p_data_source.dim(i).levels(p_data_source.dim(i).levels.count+1):=l_level;
591 end if;
592 end loop;
593 Exception when others then
594 log_n('Exception in set_DS_dim_levels '||sqlerrm);
595 raise;
596 End;
597
598 /*status:correct,lower,higher,extra,skip keys
599 we need from MO api as to what level B table feeds
600 */
601 procedure set_DS_dim_levels(p_kpi varchar2,p_dim_set dim_set_r,p_data_source data_source_r,p_base_table in out nocopy base_table_r) is
602 l_dim dim_r;
603 l_oo_dim varchar2(100);
604 l_ds_dim_set dbms_sql.varchar2_table;
605 Begin
606 for i in 1..p_base_table.levels.count loop
607 p_base_table.level_status(i):=null;
608 end loop;
609 --mark correct keys
610 for i in 1..p_base_table.levels.count loop
611 if p_base_table.feed_levels(i)='Y' then
612 l_dim:=get_kpi_level_dim_r(p_dim_set,p_base_table.levels(i).level_name);
613 if l_dim.dim_name is null then --lower or higher
614 bsc_aw_md_api.get_dim_for_level(p_base_table.levels(i).level_name,l_oo_dim);
615 if g_debug then
616 log('Level '||p_base_table.levels(i).level_name||' has no dim in this dimset '||p_dim_set.dim_set||', found dim '||
617 l_oo_dim||' from oo metadata');
618 end if;
619 l_dim:=get_dim_given_dim_name(l_oo_dim,p_dim_set);
620 end if;
621 l_ds_dim_set(l_ds_dim_set.count+1):=l_dim.dim_name;
622 if p_base_table.levels(i).level_name=l_dim.levels(1).level_name then
623 p_base_table.level_status(i):='correct';
624 else --higher or lower
625 p_base_table.level_status(i):='lower';
626 for j in 1..l_dim.levels.count loop
627 if p_base_table.levels(i).level_name=l_dim.levels(j).level_name then --higher
628 p_base_table.level_status(i):='higher';
629 exit;
630 end if;
631 end loop;
632 end if;
633 end if;
634 end loop;
635 --now mark the extra keys as extra or skip
636 for i in 1..p_base_table.levels.count loop
637 if p_base_table.feed_levels(i)='N' then
638 l_dim:=get_kpi_level_dim_r(p_dim_set,p_base_table.levels(i).level_name);
639 if l_dim.dim_name is null then
640 bsc_aw_md_api.get_dim_for_level(p_base_table.levels(i).level_name,l_oo_dim);
641 else
642 l_oo_dim:=l_dim.dim_name;
643 end if;
644 if l_oo_dim is null or bsc_aw_utility.in_array(l_ds_dim_set,l_oo_dim)=false then
645 p_base_table.level_status(i):='extra';
646 else
647 p_base_table.level_status(i):='skip';
648 end if;
649 end if;
650 end loop;
651 if g_debug then
652 log('set_DS_dim_levels dimset='||p_dim_set.dim_set||', base table='||p_base_table.base_table_name);
653 for i in 1..p_base_table.levels.count loop
654 log('Level '||p_base_table.levels(i).level_name||', Status '||p_base_table.level_status(i));
655 end loop;
656 end if;
657 Exception when others then
658 log_n('Exception in set_DS_dim_levels '||sqlerrm);
659 raise;
660 End;
661
662 /*
663 group all DS with the same dim levels and periodicity
664 note>>> we usually have 2 scenarios. B tables witl column merge or B tables with row merge. row merge is diff periodicities
665 if we have a scenario with row merge and same periodicity (i dont think this will ever happen), we can have an issue when we load
666 dimset vs we load B tables separately. dimset has union all and group by. so the data is added up.
667 this api will increase the number of p_data_source
668 */
669 procedure create_dimset_data_source_sql(
670 p_kpi varchar2,
671 p_dim_set dim_set_r,
672 p_data_source in out nocopy data_source_tb
673 ) is
674 --
675 l_distinct_levels dbms_sql.varchar2_table;
676 l_level_string dbms_sql.varchar2_table;
677 l_data_source data_source_tb;
678 l_new_data_source data_source_tb;
679 Begin
680 if p_data_source.count=0 then
681 return;
682 end if;
683 for i in 1..p_data_source.count loop
684 l_level_string(i):=null;
685 for j in 1..p_data_source(i).dim.count loop
686 l_level_string(i):=l_level_string(i)||p_data_source(i).dim(j).levels(1).level_name||'.';
687 end loop;
688 for j in 1..p_data_source(i).std_dim.count loop
689 l_level_string(i):=l_level_string(i)||p_data_source(i).std_dim(j).levels(1).level_name||'.';
690 end loop;
691 l_level_string(i):=l_level_string(i)||p_data_source(i).calendar.periodicity(1).periodicity;
692 --
693 bsc_aw_utility.merge_value(l_distinct_levels,l_level_string(i));
694 end loop;
695 if g_debug then
696 log('create_dimset_data_source_sql: Distinct level combinations');
697 for i in 1..l_distinct_levels.count loop
698 log(l_distinct_levels(i));
699 end loop;
700 end if;
701 for i in 1..l_distinct_levels.count loop
702 l_data_source.delete;
703 for j in 1..l_level_string.count loop
704 if l_level_string(j)=l_distinct_levels(i) then
705 l_data_source(l_data_source.count+1):=p_data_source(j);
706 end if;
707 end loop;
708 --l_data_source has the same dim levels and periodicity
709 --if we have 1 data source, we do not need to merge data source sql for performance
710 if l_data_source.count>1 then
711 l_new_data_source(l_new_data_source.count+1).ds_type:=l_data_source(1).ds_type||',dimset'; --initial dimset or inc dimset
712 create_dimset_data_source_sql(p_kpi,p_dim_set,l_data_source,l_new_data_source(l_new_data_source.count));
713 end if;
714 end loop;
715 --
716 for i in 1..l_new_data_source.count loop
720 log_n('Exception in create_dimset_data_source_sql '||sqlerrm);
717 p_data_source(p_data_source.count+1):=l_new_data_source(i);
718 end loop;
719 Exception when others then
721 raise;
722 End;
723
724 /*
725 this generates sql for pulling into dimset
726 each DS is a unit of data. filter is inside DS. this is fine. tested perf with prototype.
727 */
728 procedure create_dimset_data_source_sql(
729 p_kpi varchar2,
730 p_dim_set dim_set_r,
731 p_data_source data_source_tb,
732 p_new_data_source in out nocopy data_source_r
733 ) is
734 --
735 j integer;
736 l_measure_index bsc_aw_utility.number_table;
737 l_balance_loaded_column dbms_sql.varchar2_table;
738 Begin
739 p_new_data_source.dim:=p_data_source(1).dim;
740 p_new_data_source.std_dim:=p_data_source(1).std_dim;
741 p_new_data_source.calendar:=p_data_source(1).calendar;
742 p_new_data_source.data_source_PT:=p_data_source(1).data_source_PT;
743 /*here we make a copy of data_source_PT from the first DS of the dimset. to make a new DS with many DS in it, all the DS must share the
744 same PT characteristics */
745 --get the B tables
746 bsc_aw_utility.init_is_new_value(1);
747 for i in 1..p_data_source.count loop
748 for j in 1..p_data_source(i).base_tables.count loop
749 if bsc_aw_utility.is_new_value(p_data_source(i).base_tables(j).base_table_name,1) then
750 p_new_data_source.base_tables(p_new_data_source.base_tables.count+1):=p_data_source(i).base_tables(j);
751 end if;
752 end loop;
753 end loop;
754 --get the measures in all the datasource
755 bsc_aw_utility.init_is_new_value(1);
756 for i in 1..p_data_source.count loop
757 for j in 1..p_data_source(i).measure.count loop
758 if bsc_aw_utility.is_new_value(p_data_source(i).measure(j).measure,1) then
759 p_new_data_source.measure(p_new_data_source.measure.count+1):=
760 p_data_source(i).measure(j);
761 end if;
762 end loop;
763 end loop;
764 /*merge all the properties like dimension filter or balance last value */
765 for i in 1..p_data_source.count loop
766 for j in 1..p_data_source(i).property.count loop
767 bsc_aw_utility.merge_property(p_new_data_source.property,p_data_source(i).property(j).property_name,p_data_source(i).property(j).property_type,
768 p_data_source(i).property(j).property_value);
769 end loop;
770 end loop;
771 if g_debug then
772 log('New datasource dmp');
773 dmp_data_source(p_new_data_source);
774 end if;
775 p_new_data_source.data_source_stmt.delete;
776 p_new_data_source.data_source_stmt_type.delete;
777 --
778 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='sql declare c1 cursor for select';
779 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql select';
780 for i in 1..p_new_data_source.dim.count loop
781 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=p_new_data_source.dim(i).levels(1).fk||',';
782 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='dimension='||p_new_data_source.dim(i).dim_name;
783 end loop;
784 for i in 1..p_dim_set.std_dim.count loop
785 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=p_dim_set.std_dim(i).levels(1).fk||',';
786 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='dimension='||p_dim_set.std_dim(i).dim_name;
787 end loop;
788 --time
789 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='period,';
790 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='dimension=time';
791 if bsc_aw_utility.get_property(p_new_data_source.property,g_balance_last_value_prop).property_value='Y' then
792 /*period.temp and year.temp */
793 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=g_period_temp||',';
794 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='temp time='||g_period_temp;
795 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=g_year_temp||',';
796 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='temp time='||g_year_temp;
797 end if;
798 --
799 if p_dim_set.number_partitions>0 then
800 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=p_new_data_source.data_source_PT.partition_template.template_dim||',';
801 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='partition dim';
802 end if;
803 --measures
804 for i in 1..p_new_data_source.measure.count loop
805 --we need here the agg fn from the formula for the measure. its not the formula or the agg formula!
806 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=
807 substr(p_new_data_source.measure(i).formula,1,instr(p_new_data_source.measure(i).formula,'(')-1)||'('||p_new_data_source.measure(i).measure||') '||
808 p_new_data_source.measure(i).measure||',';
809 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='measure='||upper(p_new_data_source.measure(i).measure);
810 end loop;
811 /*balance loaded column */
812 for i in 1..p_new_data_source.measure.count loop
813 l_balance_loaded_column(i):=null;
814 if p_new_data_source.measure(i).measure_type=g_balance_last_value_prop then
815 l_balance_loaded_column(i):=bsc_aw_utility.get_property(p_new_data_source.measure(i).property,g_balance_loaded_column_prop).property_value;
816 if l_balance_loaded_column(i) is not null then /*balance loaded column is always summed up */
817 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='SUM('||l_balance_loaded_column(i)||') '||
818 l_balance_loaded_column(i)||',';
819 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='temp balance loaded column='||
823 end loop;
820 p_new_data_source.measure(i).measure;
821 end if;
822 end if;
824 --the markers for the fk
825 for i in 1..p_new_data_source.dim.count loop
826 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='1,';
827 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='limit cube='||p_new_data_source.dim(i).dim_name;
828 end loop;
829 --markers for std dim
830 for i in 1..p_dim_set.std_dim.count loop
831 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='1,';
832 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='limit cube='||p_dim_set.std_dim(i).dim_name;
833 end loop;
834 --marker for time
835 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='1';
836 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='limit cube=time';
837 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='from (';
838 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql from';
839 --
840 --
841 --now we have the sql from the data sources
842 /*
843 each data source has its measues. we need to place null for the other measures. each data source must only contain its measures
844 and also, the DS stmt have the filter in them
845 */
846 for i in 1..p_data_source.count loop
847 if i<>1 then
848 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='union all';
849 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql union all';
850 end if;
851 j:=1;
852 loop
853 if substr(p_data_source(i).data_source_stmt_type(j),1,8)='measure=' then
854 --first insert nulls
855 for k in 1..p_new_data_source.measure.count loop
856 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=
857 'null '||p_new_data_source.measure(k).measure||',';
858 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):=
859 'measure='||upper(p_new_data_source.measure(k).measure);
860 l_measure_index(upper(p_new_data_source.measure(k).measure)):=p_new_data_source.data_source_stmt.count;
861 end loop;
862 loop
863 p_new_data_source.data_source_stmt(l_measure_index(substr(p_data_source(i).data_source_stmt_type(j),9))):=
864 p_data_source(i).data_source_stmt(j);
865 j:=j+1;
866 if substr(p_data_source(i).data_source_stmt_type(j),1,8)<>'measure=' then
867 exit;
868 end if;
869 end loop;
870 l_measure_index.delete;
871 /*balance loaded column temp balance loaded column=*/
872 if bsc_aw_utility.get_property(p_new_data_source.property,g_balance_last_value_prop).property_value='Y' then
873 for k in 1..p_new_data_source.measure.count loop
874 if p_new_data_source.measure(k).measure_type=g_balance_last_value_prop and l_balance_loaded_column(k) is not null then
875 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=
876 '0 '||l_balance_loaded_column(k)||',';
877 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='temp balance loaded column='||
878 p_new_data_source.measure(k).measure;
879 l_measure_index(p_new_data_source.measure(k).measure):=p_new_data_source.data_source_stmt.count;
880 end if;
881 end loop;
882 loop
883 if substr(p_data_source(i).data_source_stmt_type(j),1,27)<>'temp balance loaded column=' then
884 exit;
885 end if;
886 p_new_data_source.data_source_stmt(l_measure_index(substr(p_data_source(i).data_source_stmt_type(j),28))):=
887 p_data_source(i).data_source_stmt(j);
888 j:=j+1;
889 end loop;
890 end if;
891 end if;
892 --
893 if p_data_source(i).data_source_stmt_type(j)='sql select' and p_data_source(i).data_source_stmt(j)='sql declare c1 cursor for select' then
894 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='select';
895 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):=p_data_source(i).data_source_stmt_type(j);
896 elsif substr(p_data_source(i).data_source_stmt_type(j),1,11)='limit cube=' then
897 null; --do not add this
898 else
899 if p_data_source(i).data_source_stmt_type(j)='sql from' and p_data_source(i).data_source_stmt_type(j-1)<>'sql from' then
900 --if the last stmt has a trailing , remove it . this must happen only for the first <sql from>
901 if substr(p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count),
902 length(p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count)))=',' then
903 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count):=substr(
904 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count),1,
905 length(p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count))-1);
906 end if;
907 end if;
908 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=p_data_source(i).data_source_stmt(j);
909 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):=p_data_source(i).data_source_stmt_type(j);
910 /*if the new data source has balance last value and the individual data source does not, we have to force adding period temp and year temp
911 p_data_source(i) will not have period_temp and year_temp*/
912 if p_data_source(i).data_source_stmt_type(j)='dimension=time' then
913 if bsc_aw_utility.get_property(p_new_data_source.property,g_balance_last_value_prop).property_value='Y'
917 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='temp time='||g_period_temp;
914 and bsc_aw_utility.get_property(p_data_source(i).property,g_balance_last_value_prop).property_value is null then
915 if p_data_source(i).data_source_stmt_type(j+1)<>'temp time='||g_period_temp then
916 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='period '||g_period_temp||',';
918 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='year '||g_year_temp||',';
919 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='temp time='||g_year_temp;
920 end if;
921 end if;
922 end if;
923 end if;
924 j:=j+1;
925 if j>p_data_source(i).data_source_stmt.count then
926 exit;
927 end if;
928 end loop;
929 end loop;
930 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=') BSC_B';
931 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql from';
932 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='group by';
933 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql group by';
934 for i in reverse 1..p_dim_set.std_dim.count loop
935 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=p_dim_set.std_dim(i).levels(1).fk||',';
936 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql group by stmt';
937 end loop;
938 for i in reverse 1..p_new_data_source.dim.count loop
939 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=p_new_data_source.dim(i).levels(1).fk||',';
940 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql group by stmt';
941 end loop;
942 --time
943 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):='period,';
944 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql group by stmt';
945 if bsc_aw_utility.get_property(p_new_data_source.property,g_balance_last_value_prop).property_value='Y' then
946 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=g_period_temp||',';
947 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql group by stmt';
948 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=g_year_temp||',';
949 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql group by stmt';
950 end if;
951 --
952 if p_dim_set.number_partitions>0 then
953 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count+1):=p_new_data_source.data_source_PT.partition_template.template_dim||',';
954 p_new_data_source.data_source_stmt_type(p_new_data_source.data_source_stmt.count):='sql group by stmt';
955 end if;
956 --remove the trailing ,
957 p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count):=
958 substr(p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count),1,
959 length(p_new_data_source.data_source_stmt(p_new_data_source.data_source_stmt.count))-1);
960 Exception when others then
961 log_n('Exception in create_dimset_data_source_sql '||sqlerrm);
962 raise;
963 End;
964
965 /*
966 given a data source, create the sql data source stmt
967 if the level of the base table is the same as that of the lowest level of the dim set, no need to
968 join to dim tables. else, have to join
969 if the base table has the same number of keys as the dim set, no agg needed. else agg needed
970 this generates the sql for driving from B table
971 */
972 procedure create_data_source_sql(
973 p_kpi varchar2,
974 p_dim_set dim_set_r,
975 p_data_source in out nocopy data_source_r
976 ) is
977 --
978 l_balance_loaded_column varchar2(40);
979 l_DS_dim_parent_child parent_child_tb;
980 Begin
981 p_data_source.data_source_stmt.delete;
982 p_data_source.data_source_stmt_type.delete;
983 /*set the properties */
984 if is_filter_in_data_source(p_data_source)='Y' then
985 bsc_aw_utility.merge_property(p_data_source.property,'dimension filter',null,'Y');
986 end if;
987 if is_balance_last_value_in_DS(p_data_source)='Y' then
988 bsc_aw_utility.merge_property(p_data_source.property,g_balance_last_value_prop,null,'Y');
989 end if;
990 --for now, we only have 1 base table per data source. not any more...we can have the prj table as the second b table in the DS
991 for i in 1..p_data_source.base_tables.count loop
992 if i=1 then
993 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='sql declare c1 cursor for select';
994 else
995 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='select';
996 end if;
997 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql select';
998 --for each base table, keys are the same
999 for j in 1..p_data_source.dim.count loop
1000 if instr(lower(p_data_source.dim(j).levels(1).data_type),'varchar')>0 then
1001 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='to_char('||p_data_source.dim(j).levels(1).fk||') '||
1002 p_data_source.dim(j).levels(1).fk||',';
1003 else
1004 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=p_data_source.dim(j).levels(1).fk||',';
1005 end if;
1006 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='dimension='||p_data_source.dim(j).dim_name;
1007 end loop;
1008 --std dim
1009 for j in 1..p_dim_set.std_dim.count loop
1010 if instr(lower(p_dim_set.std_dim(j).levels(1).data_type),'varchar')>0 then
1011 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='to_char('||p_dim_set.std_dim(j).levels(1).fk||') '||
1012 p_dim_set.std_dim(j).levels(1).fk||',';
1016 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='dimension='||p_dim_set.std_dim(j).dim_name;
1013 else
1014 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=p_dim_set.std_dim(j).levels(1).fk||',';
1015 end if;
1017 end loop;
1018 --time
1019 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='period||\''.\''||year period,';
1020 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='dimension=time';
1021 if bsc_aw_utility.get_property(p_data_source.property,g_balance_last_value_prop).property_value='Y' then
1022 /*select period and year separately to load period.temp and year.temp. used for BALANCE LAST VALUE
1023 Q: classified as temp or measure? keep temp for now*/
1024 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='period '||g_period_temp||',';
1025 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='temp time='||g_period_temp;
1026 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='year '||g_year_temp||',';
1027 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='temp time='||g_year_temp;
1028 end if;
1029 /*
1030 if we have partition, we want to select the partiton key here
1031 the partition key is made of the dim keys
1032 we set the partition_dim of the data source only if there are partitions in the dimset
1033 */
1034 --
1035 if p_dim_set.number_partitions>0 then
1036 /*we need to see in the future how to support range partitions etc. for now, we only support hash partitons(list)
1037 if the B table is list partitioned, we can simply select from the B table partition
1038 all B tables in a DS have the same partition type
1039 note>>>diff DS can have diff partitions. one B table may have list, another may have no partitions at all
1040 this is not ok. if a dimset has multiple DS, we cannot be sure of the partition value in the B table. each B table may have diff
1041 keys and the order used may be diff. so a row from B1 and a corresponding row from B2 may show diff partition list values. in this case,
1042 we cannot channel them to separate PT and then calculated measures(formula) will be wrong.
1043 */
1044 if p_dim_set.partition_type='list' then
1045 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=
1046 p_data_source.base_tables(1).table_partition.main_partition.partition_column||' '||p_data_source.data_source_PT.partition_template.template_dim||',';
1047 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='partition dim list';
1048 else /*hash partitions */
1049 /*now hpt_data drives what dimensions are in the hash list */
1050 /*Q:do we have master pt or cube pt? we will have master pt. cube pt holds physical info like axis name etc. the logical properties
1051 must be in master PT. for each DS, we see which dim from hpt_data match and use them. example one DS may be at week level, another at month
1052 level. hpt_data contains both week and month
1053 DS must have partition info set. DS cannot be feeding levels that have no partitions
1054 p_data_source.data_source_PT should be set if there are hash partitions. when there are multiple DS, the order of dim keys in the hash
1055 function is important*/
1056 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=get_DS_PT_hash_stmt(p_dim_set,p_data_source)||' '||
1057 p_data_source.data_source_PT.partition_template.template_dim||',';
1058 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='partition dim hash';
1059 end if;
1060 end if;
1061 --measures...measures are dependent on the data source
1062 --a data source always feeds the same measures, even if there are multiple base tables
1063 for j in 1..p_data_source.measure.count loop
1064 --please note that the formula is already resolved in create_base_table_sql and aliased to p_data_source.measure(j).measure
1065 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=p_data_source.measure(j).measure||',';
1066 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='measure='||upper(p_data_source.measure(j).measure);
1067 end loop;
1068 /*balance loaded column */
1069 for j in 1..p_data_source.measure.count loop
1070 if p_data_source.measure(j).measure_type=g_balance_last_value_prop then
1071 l_balance_loaded_column:=bsc_aw_utility.get_property(p_data_source.measure(j).property,g_balance_loaded_column_prop).property_value;
1072 if l_balance_loaded_column is not null then
1073 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=l_balance_loaded_column||',';
1074 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='temp balance loaded column='||p_data_source.measure(j).measure;
1075 end if;
1076 end if;
1077 end loop;
1078 --the markers for the fk
1079 for j in 1..p_data_source.dim.count loop
1080 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='1,';
1081 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='limit cube='||p_data_source.dim(j).dim_name;
1082 end loop;
1083 --markers for std dim
1084 for j in 1..p_dim_set.std_dim.count loop
1085 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='1,';
1086 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='limit cube='||p_dim_set.std_dim(j).dim_name;
1087 end loop;
1088 --marker for time
1089 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='1';
1090 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='limit cube=time';
1091 --we then create the sql for the base tables
1092 create_base_table_sql(p_dim_set,p_data_source,p_data_source.base_tables(i));
1093 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):='from ';
1094 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql from';
1098 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql from table';
1095 --base_table_sql is o the form (select...from base where ...)
1096 for j in 1..p_data_source.base_tables(i).base_table_sql.count loop
1097 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=p_data_source.base_tables(i).base_table_sql(j);
1099 end loop;
1100 /*if we have partition dim levels at higher level than the floor level of the DS, we need to join to levels or calendar to get
1101 the higher keys */
1102 for j in 1..p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count loop
1103 l_DS_dim_parent_child.delete;
1104 l_DS_dim_parent_child:=p_data_source.data_source_PT.dim_parent_child(
1105 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(j).dim_name);
1106 if l_DS_dim_parent_child.count>0 then
1107 bsc_aw_utility.init_is_new_value(1);
1108 for k in 1..l_DS_dim_parent_child.count loop
1109 if bsc_aw_utility.is_new_value(l_DS_dim_parent_child(k).child_level,1) then
1110 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=','||l_DS_dim_parent_child(k).child_level;
1111 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql from table';
1112 end if;
1113 end loop;
1114 end if;
1115 end loop;
1116 if p_data_source.data_source_PT.cal_parent_child.count>0 then
1117 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=',(select distinct year pt_year';
1118 bsc_aw_utility.init_is_new_value(1);
1119 for j in 1..p_data_source.data_source_PT.cal_parent_child.count loop
1120 if bsc_aw_utility.is_new_value(p_data_source.data_source_PT.cal_parent_child(j).child_dim_name,1) then /*child_dim_name is db_column_name */
1121 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count):=p_data_source.data_source_stmt(p_data_source.data_source_stmt.count)||','||
1122 p_data_source.data_source_PT.cal_parent_child(j).child_dim_name;
1123 end if;
1124 if bsc_aw_utility.is_new_value(p_data_source.data_source_PT.cal_parent_child(j).parent_dim_name,1) then /*parent_dim_name is db_column_name */
1125 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count):=p_data_source.data_source_stmt(p_data_source.data_source_stmt.count)||','||
1126 p_data_source.data_source_PT.cal_parent_child(j).parent_dim_name;
1127 end if;
1128 end loop;
1129 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count):=p_data_source.data_source_stmt(p_data_source.data_source_stmt.count)||
1130 ' from bsc_db_calendar) bsc_db_calendar';
1131 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql from table';
1132 end if;
1133 --
1134 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=' where 1=1 ';
1135 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql where';
1136 --add the filter
1137 --check for the filter at the lowest level
1138 --filter is (select..from bsc_sys_filters...)
1139 for j in 1..p_data_source.dim.count loop
1140 if p_data_source.dim(j).levels(1).filter.count > 0 then
1141 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=' and '||p_data_source.base_tables(i).base_table_name||'.'||
1142 p_data_source.dim(j).levels(1).fk||' in ';
1143 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql where stmt';
1144 for k in 1..p_data_source.dim(j).levels(1).filter.count loop
1145 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=p_data_source.dim(j).levels(1).filter(k);
1146 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql where stmt';
1147 end loop;
1148 end if;
1149 end loop;
1150 /*now add the join if there are higher level partitions */
1151 for j in 1..p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count loop
1152 l_DS_dim_parent_child.delete;
1153 l_DS_dim_parent_child:=p_data_source.data_source_PT.dim_parent_child(
1154 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(j).dim_name);
1155 if l_DS_dim_parent_child.count>0 then
1156 /*first the B table join */
1157 for k in 1..p_data_source.dim.count loop
1158 /*assumption: l_DS_dim_parent_child.count has the lowest level which the level of the DS */
1159 if p_data_source.dim(k).dim_name=p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(j).dim_name then
1160 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=' and '||p_data_source.base_tables(i).base_table_name||'.'||
1161 p_data_source.dim(k).levels(1).fk||'='||l_DS_dim_parent_child(l_DS_dim_parent_child.count).child_level||'.'||
1162 l_DS_dim_parent_child(l_DS_dim_parent_child.count).parent_pk;/*assume parent_pk is same like CODE across levels */
1163 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql where stmt';
1164 --
1165 exit;
1166 end if;
1167 end loop;
1168 /*now, the join between the levels */
1169 for k in 2..l_DS_dim_parent_child.count loop /*we start from 2 since we do not include the top most level for perf reasons */
1170 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=' and '||l_DS_dim_parent_child(k).child_level||'.'||
1171 l_DS_dim_parent_child(k).child_fk||'='||l_DS_dim_parent_child(k).parent_level||'.'||l_DS_dim_parent_child(k).parent_pk;
1172 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql where stmt';
1173 end loop;
1174 end if;
1175 end loop;
1176 /*now the calendar */
1177 if p_data_source.data_source_PT.cal_parent_child.count>0 then
1178 /*first the B table join */
1179 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=' and '||p_data_source.base_tables(i).base_table_name||'.year='||
1183 end if;
1180 'bsc_db_calendar.pt_year and '||p_data_source.base_tables(i).base_table_name||'.period=bsc_db_calendar.'||
1181 p_data_source.data_source_PT.cal_parent_child(1).child_dim_name;/*cal_parent_child(1).child_dim_name will all be the DS periodicity */
1182 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql where stmt';
1184 if p_data_source.base_tables.count>1 and i<>p_data_source.base_tables.count then
1185 p_data_source.data_source_stmt(p_data_source.data_source_stmt.count+1):=' union all ';
1186 p_data_source.data_source_stmt_type(p_data_source.data_source_stmt.count):='sql union all';
1187 end if;
1188 end loop;
1189 Exception when others then
1190 log_n('Exception in create_data_source_sql '||sqlerrm);
1191 raise;
1192 End;
1193
1194 /*
1195 this procedure creates the base table sql. the base table can be at a lower level than the first level of the dim set.
1196 in this case, it need to rollup the data before loading the kpi dim set
1197 base table can have larger number of keys. in this case also rollup.
1198 the base table can have the same number of keys at the same level. in this case no rollup. remove the agg function from
1199 the formula
1200 agg formula is like MIN(Gr_806Sim1/DECODE(Gr_806Sim2,0,NULL,Gr_806Sim2)) change it to
1201 (Gr_806Sim1/DECODE(Gr_806Sim2,0,NULL,Gr_806Sim2))
1202
1203 if the base table has more keys than the dim set, when we move data from the _AW table, we have to join with the base table.
1204 if the base table has more keys, then the aw table is used only as a fk table. the sql will be
1205 select
1206 base.k1,
1207 base.k2,
1208 ..
1209 formula(base.m1) m1,
1210 formula(base.m2) m1,
1211 ...
1212 from
1213 base,
1214 (select distinct k1,k2... from base_aw where bitand(...)) base_aw
1215 where base.k1=base_aw.k1 and ...
1216
1217 if the number of keys in the base and dimset are the same, we only need the base_aw table in the inc mode
1218 */
1219 procedure create_base_table_sql(
1220 p_dim_set dim_set_r,
1221 p_data_source data_source_r,
1222 p_base_table in out nocopy base_table_r
1223 ) is
1224 --
1225 l_dim varchar2(300);
1226 l_parent_child bsc_aw_adapter_dim.dim_parent_child_tb;
1227 l_pc_subset bsc_aw_adapter_dim.dim_parent_child_tb;
1228 l_from_sql dbms_sql.varchar2_table;
1229 l_where_sql dbms_sql.varchar2_table;
1230 l_group_sql dbms_sql.varchar2_table;
1231 l_base_cal_column varchar2(100); --lower periodicity column name from bsc_db_calendar
1232 l_dimset_cal_column varchar2(100);
1233 l_remove_agg_flag boolean;
1234 l_formula varchar(4000);
1235 l_flag boolean;
1236 --l_base_aw_join_flag is used only for inc load if the number of keys in the base > that in the dim set
1237 --keeps track of what keys to join between base and base_aw
1238 l_base_aw_join_flag dbms_sql.varchar2_table;
1239 l_alias varchar2(100);
1240 l_aw_table_fk_driver_only boolean;--if true the aw table is only a fk driver table
1241 l_balance_loaded_column varchar2(40);
1242 Begin
1243 p_base_table.base_table_sql.delete;
1244 l_aw_table_fk_driver_only:=false;
1245 if p_data_source.ds_type='inc' then
1246 if bsc_aw_utility.in_array(p_base_table.level_status,'extra') then
1247 l_aw_table_fk_driver_only:=true;
1248 end if;
1249 end if;
1250 l_from_sql.delete;
1251 l_where_sql.delete;
1252 p_base_table.base_table_sql(1):='(select ';
1253 if (p_data_source.ds_type='initial') or (p_data_source.ds_type='inc' and l_aw_table_fk_driver_only) then
1254 --in this case, bsc_aw_temp_cv is in the inner sql
1255 l_from_sql(1):=' from '||p_base_table.base_table_name;
1256 l_alias:=p_base_table.base_table_name;
1257 l_where_sql(1):=' where 1=1 ';
1258 else
1259 l_from_sql(1):=' from bsc_aw_temp_cv,'||p_base_table.base_table_name;
1260 l_alias:=p_base_table.base_table_name;
1261 l_where_sql(1):=' where 1=1 ';
1262 l_where_sql(l_where_sql.count+1):=' and bsc_aw_temp_cv.change_vector_base_table=\'''||upper(p_base_table.base_table_name)||'\'' and '||
1263 l_alias||'.change_vector between bsc_aw_temp_cv.change_vector_min_value and bsc_aw_temp_cv.change_vector_max_value ';
1264 end if;
1265 l_group_sql(1):='group by ';
1266 --for all the keys that are N, we need to further process
1267 for i in 1..p_base_table.levels.count loop
1268 l_base_aw_join_flag(i):='N';
1269 if p_base_table.level_status(i)='lower' then --the level is lower than the lowest level of dim set
1270 l_parent_child.delete;
1271 l_pc_subset.delete;
1272 bsc_aw_md_api.get_dim_for_level(p_base_table.levels(i).level_name,l_dim);
1273 bsc_aw_md_api.get_dim_parent_child(l_dim,l_parent_child);
1274 l_pc_subset:=bsc_aw_adapter_dim.get_hier_subset(l_parent_child,get_dim_given_dim_name(l_dim,p_data_source.dim).levels(1).level_name,
1275 p_base_table.levels(i).level_name);
1276 if l_pc_subset.count=0 then
1277 log('Could not rollup from B table to dimset '||p_base_table.base_table_name||', at level '||p_base_table.levels(i).level_name);
1278 raise bsc_aw_utility.g_exception;
1279 end if;
1280 l_base_aw_join_flag(i):='Y';
1281 --first entry is the data source level
1282 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=l_pc_subset(1).child_level||'.'||l_pc_subset(1).child_fk||',';
1283 l_group_sql(l_group_sql.count+1):=l_pc_subset(1).child_level||'.'||l_pc_subset(1).child_fk||',';
1284 l_where_sql(l_where_sql.count+1):=' and '||l_alias||'.'||p_base_table.levels(i).fk||'='||
1285 l_pc_subset(l_pc_subset.count).child_level||'.'||l_pc_subset(l_pc_subset.count).parent_pk;
1286 for j in 1..l_pc_subset.count loop
1287 l_from_sql(l_from_sql.count+1):=','||l_pc_subset(j).child_level;
1288 if j <> 1 then --we do not include the last level...for performance
1289 l_where_sql(l_where_sql.count+1):=' and '||l_pc_subset(j).child_level||'.'||l_pc_subset(j).child_fk||
1290 '='||l_pc_subset(j).parent_level||'.'||l_pc_subset(j).parent_pk;
1291 end if;
1292 end loop;
1296 l_group_sql(l_group_sql.count+1):=l_alias||'.'||p_base_table.levels(i).fk||',';
1293 elsif p_base_table.level_status(i)='correct' or p_base_table.level_status(i)='higher' then
1294 l_base_aw_join_flag(i):='Y';--base table key has to join with the _AW table key
1295 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=l_alias||'.'||p_base_table.levels(i).fk||',';
1297 else --the skip key
1298 --if the lowest key and a higher key exists in the base table, we dont have to group by the lowest key since the data
1299 --is already at the lowest key granularity
1300 null;
1301 end if;
1302 end loop;
1303 --now the std dim, type and projection
1304 for i in 1..p_data_source.std_dim.count loop
1305 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=l_alias||'.'||p_data_source.std_dim(i).levels(1).fk||',';
1306 l_group_sql(l_group_sql.count+1):=l_alias||'.'||p_data_source.std_dim(i).levels(1).fk||',';
1307 end loop;
1308 --now period and year
1309 --if the base table is at lower perioidicity than the dim set, also have to rollup on time
1310 --p_dim_set.calendar.periodicity(1) is the lowest level in time: NO this is not true. look at lowest_level flag
1311 --if p_base_table.periodicity.periodicity <> p_data_source.calendar.periodicity(1).periodicity then
1312 /*there is an interesting issue here. what if the measure is a balance measure and we have to rollup B table on time? so far this
1313 issue has not come up because balance is at day level */
1314 if p_base_table.periodicity.periodicity <> p_data_source.calendar.periodicity(1).periodicity then --then this is coming at a lower level
1315 l_base_cal_column:=bsc_aw_bsc_metadata.get_db_calendar_column(p_dim_set.calendar.calendar,p_base_table.periodicity.periodicity);
1316 --note>>>datasource has one periodicity. see get_dim_set_data_source in bsc_aw_bsc_metadata
1317 l_dimset_cal_column:=bsc_aw_bsc_metadata.get_db_calendar_column(p_dim_set.calendar.calendar,p_data_source.calendar.periodicity(1).periodicity);
1318 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):='bsc_db_calendar.'||l_dimset_cal_column||' period,'||
1319 'bsc_db_calendar.year year,';
1320 l_group_sql(l_group_sql.count+1):='bsc_db_calendar.'||l_dimset_cal_column||',bsc_db_calendar.year,';
1321 l_from_sql(l_from_sql.count+1):=',(select distinct '||l_base_cal_column||','||l_dimset_cal_column||',year from bsc_db_calendar where calendar_id='||
1322 p_data_source.calendar.calendar||') bsc_db_calendar';
1323 l_where_sql(l_where_sql.count+1):=' and bsc_db_calendar.'||l_base_cal_column||'='||l_alias||'.period and '||
1324 'bsc_db_calendar.year='||l_alias||'.year';
1325 else
1326 --base table at the same periodicity as the dim set
1327 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=l_alias||'.period,'||l_alias||'.year,';
1328 l_group_sql(l_group_sql.count+1):=l_alias||'.period,'||l_alias||'.year,';
1329 end if;
1330 --if base keys > dim set keys and inc load
1331 --in this case the aw table is only a key drive table. data comes from base table
1332 --please note that if the extra keys are keys with l_ok(i)='S', we do not have to do this.
1333 --skip keys are simply ignored. its as if they did not exist
1334 --do p_base_table.levels.count - p_data_source.dim.count if this is > count(l_ok='S') then we have to do this
1335 if p_data_source.ds_type='inc' and l_aw_table_fk_driver_only then
1336 --make the from clause
1337 l_from_sql(l_from_sql.count+1):=',(select distinct ';
1338 for i in 1..p_base_table.levels.count loop
1339 if l_base_aw_join_flag(i)='Y' then
1340 --we have _AW appended to the fk from the _AW table (in line sql) to avoid the issue of having to correctly
1341 --specify the table name in the select and group by part.
1342 l_from_sql(l_from_sql.count+1):=p_base_table.base_table_name||'.'||p_base_table.levels(i).fk||' '||p_base_table.levels(i).fk||'_AW,';
1343 end if;
1344 end loop;
1345 --we need the std dim
1346 for i in 1..p_data_source.std_dim.count loop
1347 l_from_sql(l_from_sql.count+1):=p_base_table.base_table_name||'.'||p_data_source.std_dim(i).levels(1).fk||' '||
1348 p_data_source.std_dim(i).levels(1).fk||'_AW,';
1349 end loop;
1350 --also we need period and year
1351 /*in caes of partitions, the filter on the partition is added in create_kpi_program_partition*/
1352 l_from_sql(l_from_sql.count+1):=p_base_table.base_table_name||'.period period_aw,'||
1353 p_base_table.base_table_name||'.year year_aw from bsc_aw_temp_cv,'||p_base_table.base_table_name;
1354 l_from_sql(l_from_sql.count+1):=' where 1=1 ';
1355 l_from_sql(l_from_sql.count+1):='and bsc_aw_temp_cv.change_vector_base_table=\'''||upper(p_base_table.base_table_name)||'\'' and '||
1356 p_base_table.base_table_name||'.change_vector between bsc_aw_temp_cv.change_vector_min_value and bsc_aw_temp_cv.change_vector_max_value) B_AW';
1357 --make the where clause
1358 for i in 1..p_base_table.levels.count loop
1359 if l_base_aw_join_flag(i)='Y' then
1360 --we have _AW appended to the fk from the _AW table (in line sql) to avoid the issue of having to correctly
1361 --specify the table name in the select and group by part.
1362 l_where_sql(l_where_sql.count+1):=' and '||l_alias||'.'||p_base_table.levels(i).fk||'='||
1363 'B_AW.'||p_base_table.levels(i).fk||'_AW';
1364 end if;
1365 end loop;
1366 --std dim
1367 for i in 1..p_data_source.std_dim.count loop
1368 l_where_sql(l_where_sql.count+1):=' and '||l_alias||'.'||p_data_source.std_dim(i).levels(1).fk||'='||
1369 'B_AW.'||p_data_source.std_dim(i).levels(1).fk||'_AW';
1370 end loop;
1371 --join period and year
1372 l_where_sql(l_where_sql.count+1):=' and '||l_alias||'.period=B_AW.period_AW';
1373 l_where_sql(l_where_sql.count+1):=' and '||l_alias||'.year=B_AW.year_AW';
1374 end if;
1375 --if we have list partitions, include the list partition column also
1376 /*we can select partition col only if dimset is partitioned. otherwise, group by batch from B table will make data loaded into dimset incorrect
1377 there is no group by at data source level
1381 if p_base_table.table_partition.main_partition.partition_type='LIST' then
1378 if dimset partition type is list, then we can be assured that B table is partitioned by list partitions, with the same number of partitions
1379 as the dimset. this is done in api load_master_PT*/
1380 if p_dim_set.number_partitions>0 and p_dim_set.partition_type='list' then
1382 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=l_alias||'.'||p_base_table.table_partition.main_partition.partition_column||',';
1383 l_group_sql(l_group_sql.count+1):=l_alias||'.'||p_base_table.table_partition.main_partition.partition_column||',';
1384 end if;
1385 end if;
1386 --now the measures
1387 l_remove_agg_flag:=false;
1388 if bsc_aw_utility.in_array(p_base_table.level_status,'lower')=false and bsc_aw_utility.in_array(p_base_table.level_status,'extra')=false
1389 and p_base_table.periodicity.periodicity=p_data_source.calendar.periodicity(1).periodicity then
1390 --there are no keys with rollup or there are no extra keys and the periodicity of base is same as dimset
1391 --this means we can remove the agg function
1392 l_remove_agg_flag:=true;
1393 --see if count is a part of the agg function. if yes, we have to force agg, make l_remove_agg_flag:=false
1394 --we saw if we can hardcode 1 in parse_out_agg_function. but AW threw error
1395 --ORA-34738: (NOUPDATE) A severe problem has been detected. Analytic workspace operations have been disabled.
1396 --ORA-06512: at "APPS.BSC_AW_UTILITY", line 466
1397 --ORA-06512: at "APPS.BSC_AW_LOAD", line 112. it was confusing 1 with true/false 1 so we are forced to have agg when count is involved
1398 --maybe we can use sql fetch c1 loop into...but for now, lets keep the agg when count is involved
1399 --database does not suffer too much in perf with a group by. note here that there is no joins involbed. its just group by on the
1400 --base table
1401 for i in 1..p_data_source.measure.count loop
1402 if lower(ltrim(rtrim(substr(p_data_source.measure(i).formula,1,instr(p_data_source.measure(i).formula,'(')-1))))='count' then
1403 l_remove_agg_flag:=false;
1404 exit;
1405 end if;
1406 end loop;
1407 end if;
1408 for i in 1..p_data_source.measure.count loop
1409 l_balance_loaded_column:=bsc_aw_utility.get_property(p_data_source.measure(i).property,g_balance_loaded_column_prop).property_value;
1410 if l_remove_agg_flag then
1411 --l_formula has no agg, we can have 3 types of agg in BSC
1412 --Apply aggregation method to the each element of the formula, e.g.: SUM(source_column1)/SUM(source_column2)
1413 --Apply aggregation method to the overall formula, e.g.: SUM(source_column1/source_column2)
1414 --Formulas between 2 calculated Measures e.g.: SUM(source_col1/source_col2)/AVG(source_col3+source_col4)
1415 bsc_aw_utility.parse_out_agg_function(p_data_source.measure(i).formula,l_formula);
1416 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=l_formula||' '||p_data_source.measure(i).measure||',';
1417 if p_data_source.measure(i).measure_type=g_balance_last_value_prop and l_balance_loaded_column is not null then
1418 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):='decode('||l_balance_loaded_column||',\''Y\'',1,0) '||
1419 l_balance_loaded_column||',';
1420 end if;
1421 else
1422 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=p_data_source.measure(i).formula||' '||
1423 p_data_source.measure(i).measure||',';
1424 if p_data_source.measure(i).measure_type=g_balance_last_value_prop and l_balance_loaded_column is not null then
1425 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):='SUM(decode('||l_balance_loaded_column||',\''Y\'',1,0)) '||
1426 l_balance_loaded_column||',';
1427 end if;
1428 end if;
1429 end loop;
1430 p_base_table.base_table_sql(p_base_table.base_table_sql.count):=substr(p_base_table.base_table_sql(p_base_table.base_table_sql.count),
1431 1,length(p_base_table.base_table_sql(p_base_table.base_table_sql.count))-1);
1432 for i in 1..l_from_sql.count loop
1433 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=l_from_sql(i);
1434 end loop;
1435 for i in 1..l_where_sql.count loop
1436 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=l_where_sql(i);
1437 end loop;
1438 --if l_remove_agg_flag=false, this means that there is either a rollup or an extra key
1439 if l_remove_agg_flag=false then
1440 --remove the trailing "," from groupby
1441 l_group_sql(l_group_sql.count):=substr(l_group_sql(l_group_sql.count),1,length(l_group_sql(l_group_sql.count))-1);
1442 for i in 1..l_group_sql.count loop
1443 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=l_group_sql(i);
1444 end loop;
1445 end if;
1446 p_base_table.base_table_sql(p_base_table.base_table_sql.count+1):=') '||p_base_table.base_table_name;
1447 Exception when others then
1448 log_n('Exception in create_base_table_sql '||sqlerrm);
1449 raise;
1450 End;
1451
1452 /*
1453 given a dim record, loop through the levels in it to see if the given level is a part of the dim or not
1454 used by trim_parent_child, which in turn is used by create_base_table_sql
1455 */
1456 function is_level_in_dim(p_dim dim_r,p_level varchar2) return boolean is
1457 Begin
1458 for i in 1..p_dim.levels.count loop
1459 if p_dim.levels(i).level_name=p_level then
1460 return true;
1461 end if;
1462 end loop;
1463 return false;
1464 Exception when others then
1465 log_n('Exception in is_level_in_dim '||sqlerrm);
1466 raise;
1467 End;
1468
1469 /*
1470 given a CC dim name, get the dim_r object
1471 */
1472 function get_dim_given_dim_name(p_dim varchar2,p_dim_set dim_set_r) return dim_r is
1473 Begin
1474 return get_dim_given_dim_name(p_dim,p_dim_set.dim);
1475 Exception when others then
1476 log_n('Exception in get_dim_given_dim_name '||sqlerrm);
1477 raise;
1478 End;
1479
1480 function get_dim_given_dim_name(p_dim varchar2,p_dim_t dim_tb) return dim_r is
1484 return p_dim_t(i);
1481 Begin
1482 for i in 1..p_dim_t.count loop
1483 if p_dim_t(i).dim_name=p_dim then
1485 end if;
1486 end loop;
1487 return null;
1488 Exception when others then
1489 log_n('Exception in get_dim_given_dim_name '||sqlerrm);
1490 raise;
1491 End;
1492
1493 function is_dim_in_dimset(p_dim_set dim_set_r,p_dim varchar2) return boolean is
1494 Begin
1495 for i in 1..p_dim_set.dim.count loop
1496 if p_dim_set.dim(i).dim_name=p_dim then
1497 return true;
1498 end if;
1499 end loop;
1500 return false;
1501 Exception when others then
1502 log_n('Exception in is_dim_in_dimset '||sqlerrm);
1503 raise;
1504 End;
1505
1506 procedure drop_kpi_objects(p_kpi varchar2) is
1507 Begin
1508 if g_debug then
1509 log_n('Drop KPI '||p_kpi);
1510 end if;
1511 drop_kpi_objects_aw(p_kpi);
1512 drop_kpi_objects_relational(p_kpi);
1513 --drop kpi metadata
1514 bsc_aw_md_api.drop_kpi(p_kpi);
1515 Exception when others then
1516 log_n('Exception in drop_kpi_objects '||sqlerrm);
1517 raise;
1518 End;
1519
1520 procedure drop_kpi_objects_aw(p_kpi varchar2) is
1521 --
1522 l_objects bsc_aw_utility.object_tb; --object_t is object_name and object_type
1523 l_flag dbms_sql.varchar2_table;
1524 Begin
1525 bsc_aw_md_api.get_kpi_olap_objects(p_kpi,l_objects,'all');
1526 for i in 1..l_objects.count loop
1527 l_flag(i):='N';
1528 end loop;
1529 --get_kpi_olap_objects will only populate l_objects when olap object type is not null
1530 for i in 1..l_objects.count loop
1531 if l_flag(i)='N' and l_objects(i).object_type <> 'partition template' and
1532 l_objects(i).object_type <> 'dimension' and l_objects(i).object_type <> 'composite' then
1533 bsc_aw_utility.delete_aw_object(l_objects(i).object_name);
1534 l_flag(i):='Y';
1535 end if;
1536 end loop;
1537 --partition template
1538 for i in 1..l_objects.count loop
1539 if l_flag(i)='N' and l_objects(i).object_type = 'partition template' then
1540 bsc_aw_utility.delete_aw_object(l_objects(i).object_name);
1541 l_flag(i):='Y';
1542 end if;
1543 end loop;
1544 --composite
1545 for i in 1..l_objects.count loop
1546 if l_flag(i)='N' and l_objects(i).object_type = 'composite' then
1547 bsc_aw_utility.delete_aw_object(l_objects(i).object_name);
1548 l_flag(i):='Y';
1549 end if;
1550 end loop;
1551 --dimensions
1552 for i in 1..l_objects.count loop
1553 if l_flag(i)='N' and l_objects(i).object_type = 'dimension' then
1554 bsc_aw_utility.delete_aw_object(l_objects(i).object_name);
1555 l_flag(i):='Y';
1556 end if;
1557 end loop;
1558 --all the other objects
1559 for i in 1..l_objects.count loop
1560 if l_flag(i)='N' then
1561 bsc_aw_utility.delete_aw_object(l_objects(i).object_name);
1562 l_flag(i):='Y';
1563 end if;
1564 end loop;
1565 /*
1566 we do not want to drop olap table function types and views since the drop is permanent, if there is failure
1567 we cannot rollback
1568 This is no more true. we drop these objects. (In drop_kpi_objects_relational). we drop them because we have
1569 to clean up old objects. if midway the drop fails, the system is in unusuable state anyway
1570 */
1571 ---
1572 Exception when others then
1573 log_n('Exception in drop_kpi_objects_aw '||sqlerrm);
1574 raise;
1575 End;
1576
1577 /*
1578 we will hold the type and view name in bsc olap objects. olap_object column will be null. so
1579 drop_kpi_objects_relational action is final. due to database commit, if there is a failure in between, we cannot guarantee
1580 the system. drop has to be rerun till successful
1581 */
1582 procedure drop_kpi_objects_relational(p_kpi varchar2) is
1583 l_flag dbms_sql.varchar2_table;
1584 l_olap_object bsc_aw_md_wrapper.bsc_olap_object_tb;
1585 Begin
1586 bsc_aw_md_api.get_bsc_olap_object(null,null,p_kpi,'kpi',l_olap_object);
1587 for i in 1..l_olap_object.count loop
1588 l_flag(i):='N';
1589 end loop;
1590 --
1591 for i in 1..l_olap_object.count loop
1592 if l_flag(i)='N' and l_olap_object(i).object_type='relational view' then
1593 bsc_aw_utility.execute_stmt_ne('drop view '||l_olap_object(i).object);
1594 l_flag(i):='Y';
1595 end if;
1596 end loop;
1597 --
1598 for i in 1..l_olap_object.count loop
1599 if l_flag(i)='N' and l_olap_object(i).object_type='relational type' then
1600 bsc_aw_utility.execute_stmt_ne('drop type '||l_olap_object(i).object||'_tab'); --assume naming convention
1601 bsc_aw_utility.execute_stmt_ne('drop type '||l_olap_object(i).object);
1602 l_flag(i):='Y';
1603 end if;
1604 end loop;
1605 --
1606 Exception when others then
1607 log_n('Exception in drop_kpi_objects_relational '||sqlerrm);
1608 raise;
1609 End;
1610
1611 /*
1612 set the partition info.
1613 note>>> we need to set this before the call to set_dim_set_data_source
1614 by default, there are no partitions.
1615 --
1616 if there are non std agg, we have difficulty with hahs partitions. consider the case where we have bugnew=bugopen/bugclosed
1617 here, the data looked as
1618 ------------------------------------DATACUBE.1.4014------------------------------------
1619 ----------------------------------HASH_PARTITION_DIM-----------------------------------
1620 MEASURENAME.1.
1621 4014 0 1 2 3 4 5 6 7
1622 -------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
1623 BUGOPEN 200.00 20.00 NA NA NA NA NA NA
1624 BUGCLOSED 100.00 10.00 NA NA NA NA NA NA
1628 the soln is not to materialize the formulas. we can define a formula as bugnew=total(bugopen)/total(bugclosed) and this formula is in the
1625 BUGNEW 2.00 2.00 NA NA NA NA NA NA
1626 the formula was correctly calculated for each partition. however, when we sum the measure, we get a value 4. this is incorrect
1627 since the real value is 220/110 = 2 and not 4.
1629 view.also note the impact for avg measure. for now, we will disable partitions when we have non std agg
1630 if 10.1.04 and greater and we have 2 times the cpu count as partitions reqd, try partition out.
1631 */
1632 procedure set_dimset_partition_info(p_kpi varchar2,p_actual_dim_set in out nocopy dim_set_r,p_target_dim_set in out nocopy dim_set_r) is
1633 Begin
1634 if g_debug then
1635 log('set_dimset_partition_info dimset='||p_actual_dim_set.dim_set_name||', with target='||p_target_dim_set.dim_set_name);
1636 end if;
1637 p_actual_dim_set.number_partitions:=0;
1638 p_target_dim_set.number_partitions:=0;
1639 load_master_PT(p_actual_dim_set,p_target_dim_set);
1640 Exception when others then
1641 log_n('Exception in set_dimset_partition_info '||sqlerrm);
1642 raise;
1643 End;
1644
1645 /*
1646 create_aw_object_names gives names to cubes, programs etc
1647 */
1648 procedure create_aw_object_names(p_kpi in out nocopy kpi_r) is
1649 --
1650 l_dim_index bsc_aw_utility.number_table;--used to populate limit cubes into data source.dim
1651 l_measure_index bsc_aw_utility.number_table;--used to populate cubes into data source.measure
1652 Begin
1653 for i in 1..p_kpi.dim_set.count loop
1654 --
1655 p_kpi.dim_set(i).aggmap_operator.measure_dim:='measuredim.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi;
1656 p_kpi.dim_set(i).aggmap_operator.opvar:='opvar.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi;
1657 p_kpi.dim_set(i).aggmap_operator.argvar:='argvar.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi;
1658 --
1659 p_kpi.dim_set(i).agg_map.agg_map:='aggmap.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi;
1660 p_kpi.dim_set(i).agg_map.aggmap_operator:=p_kpi.dim_set(i).aggmap_operator;
1661 --
1662 p_kpi.dim_set(i).agg_map_notime.agg_map:='aggmap.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi||'.notime';
1663 p_kpi.dim_set(i).agg_map_notime.aggmap_operator:=p_kpi.dim_set(i).aggmap_operator;
1664 --
1665 p_kpi.dim_set(i).initial_load_program.program_name:='load.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi||'.initial';
1666 p_kpi.dim_set(i).inc_load_program.program_name:='load.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi||'.inc';
1667 --
1668 p_kpi.dim_set(i).initial_load_program_parallel.program_name:='load.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi||'.initial.parallel';
1669 p_kpi.dim_set(i).inc_load_program_parallel.program_name:='load.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi||'.inc.parallel';
1670 --
1671 p_kpi.dim_set(i).aggregate_marker_program:='aggmark.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi||'.program';
1672 --for 10g, targets will need a separate program so it can run in parallel
1673 for j in 1..p_kpi.dim_set(i).dim.count loop
1674 l_dim_index(p_kpi.dim_set(i).dim(j).dim_name):=j;
1675 p_kpi.dim_set(i).dim(j).limit_cube:='kpi.'||p_kpi.kpi||'.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.dim_set(i).dim(j).dim_name||'.LB';
1676 p_kpi.dim_set(i).dim(j).reset_cube:='kpi.'||p_kpi.kpi||'.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.dim_set(i).dim(j).dim_name||'.RB';
1677 if nvl(bsc_aw_utility.get_parameter_value('NO LIMIT CUBE COMPOSITE'),'N')='N' then
1678 p_kpi.dim_set(i).dim(j).limit_cube_composite:='c.'||p_kpi.dim_set(i).dim(j).limit_cube;
1679 end if;
1680 p_kpi.dim_set(i).dim(j).aggregate_marker:='aggmark.'||p_kpi.kpi||'.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.dim_set(i).dim(j).dim_name;
1681 p_kpi.dim_set(i).dim(j).agg_map.agg_map:='aggmap.'||p_kpi.dim_set(i).dim(j).dim_name||'.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi;
1682 p_kpi.dim_set(i).dim(j).agg_map.aggmap_operator:=p_kpi.dim_set(i).aggmap_operator;
1683 end loop;
1684 --std dim
1685 for j in 1..p_kpi.dim_set(i).std_dim.count loop
1686 l_dim_index(p_kpi.dim_set(i).std_dim(j).dim_name):=j;
1687 p_kpi.dim_set(i).std_dim(j).limit_cube:='kpi.'||p_kpi.kpi||'.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.dim_set(i).std_dim(j).dim_name||'.LB';
1688 if nvl(bsc_aw_utility.get_parameter_value('NO LIMIT CUBE COMPOSITE'),'N')='N' then
1689 p_kpi.dim_set(i).std_dim(j).limit_cube_composite:='c.'||p_kpi.dim_set(i).std_dim(j).limit_cube;
1690 end if;
1691 end loop;
1692 --time limit cube
1693 p_kpi.dim_set(i).calendar.limit_cube:='kpi.'||p_kpi.kpi||'.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.dim_set(i).calendar.aw_dim||'.LB';
1694 if nvl(bsc_aw_utility.get_parameter_value('NO LIMIT CUBE COMPOSITE'),'N')='N' then
1695 p_kpi.dim_set(i).calendar.limit_cube_composite:='c.'||p_kpi.dim_set(i).calendar.limit_cube;
1696 end if;
1697 p_kpi.dim_set(i).calendar.aggregate_marker:='aggmark.'||p_kpi.kpi||'.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.dim_set(i).calendar.aw_dim;
1698 /*also add aggmap for calendar. used to aggregate non bal measures uptime if bal measure also present in dimset */
1699 p_kpi.dim_set(i).calendar.agg_map.agg_map:='aggmap.'||p_kpi.dim_set(i).calendar.aw_dim||'.'||p_kpi.dim_set(i).dim_set||'.'||p_kpi.kpi;
1700 p_kpi.dim_set(i).calendar.agg_map.aggmap_operator:=p_kpi.dim_set(i).aggmap_operator;
1701 --measures
1702 --first, load the partition, composite and cube info
1703 --names partitions, composites, cubes and measure cubes
1704 create_PT_comp_names(p_kpi.kpi,p_kpi.dim_set(i));
1705 --
1706 for j in 1..p_kpi.dim_set(i).measure.count loop
1707 l_measure_index(p_kpi.dim_set(i).measure(j).measure):=j;
1708 end loop;
1709 --give cube names to data source measures
1710 for j in 1..p_kpi.dim_set(i).data_source.count loop
1711 for k in 1..p_kpi.dim_set(i).data_source(j).measure.count loop
1712 p_kpi.dim_set(i).data_source(j).measure(k).cube:=p_kpi.dim_set(i).measure(l_measure_index(p_kpi.dim_set(i).data_source(j).measure(k).measure)).cube;
1713 p_kpi.dim_set(i).data_source(j).measure(k).property:=
1717 for k in 1..p_kpi.dim_set(i).data_source(j).dim.count loop
1714 p_kpi.dim_set(i).measure(l_measure_index(p_kpi.dim_set(i).data_source(j).measure(k).measure)).property;
1715 end loop;
1716 --set the dim limit cubes
1718 p_kpi.dim_set(i).data_source(j).dim(k).limit_cube:=
1719 p_kpi.dim_set(i).dim(l_dim_index(p_kpi.dim_set(i).data_source(j).dim(k).dim_name)).limit_cube;
1720 end loop;
1721 for k in 1..p_kpi.dim_set(i).data_source(j).std_dim.count loop
1722 p_kpi.dim_set(i).data_source(j).std_dim(k).limit_cube:=
1723 p_kpi.dim_set(i).std_dim(l_dim_index(p_kpi.dim_set(i).data_source(j).std_dim(k).dim_name)).limit_cube;
1724 end loop;
1725 p_kpi.dim_set(i).data_source(j).calendar.limit_cube:=p_kpi.dim_set(i).calendar.limit_cube;
1726 end loop;
1727 for j in 1..p_kpi.dim_set(i).inc_data_source.count loop
1728 for k in 1..p_kpi.dim_set(i).inc_data_source(j).measure.count loop
1729 p_kpi.dim_set(i).inc_data_source(j).measure(k).cube:=p_kpi.dim_set(i).measure(
1730 l_measure_index(p_kpi.dim_set(i).inc_data_source(j).measure(k).measure)).cube;
1731 p_kpi.dim_set(i).inc_data_source(j).measure(k).property:=p_kpi.dim_set(i).measure(
1732 l_measure_index(p_kpi.dim_set(i).inc_data_source(j).measure(k).measure)).property;
1733 end loop;
1734 for k in 1..p_kpi.dim_set(i).inc_data_source(j).dim.count loop
1735 p_kpi.dim_set(i).inc_data_source(j).dim(k).limit_cube:=
1736 p_kpi.dim_set(i).dim(l_dim_index(p_kpi.dim_set(i).inc_data_source(j).dim(k).dim_name)).limit_cube;
1737 end loop;
1738 for k in 1..p_kpi.dim_set(i).inc_data_source(j).std_dim.count loop
1739 p_kpi.dim_set(i).inc_data_source(j).std_dim(k).limit_cube:=
1740 p_kpi.dim_set(i).std_dim(l_dim_index(p_kpi.dim_set(i).inc_data_source(j).std_dim(k).dim_name)).limit_cube;
1741 end loop;
1742 p_kpi.dim_set(i).inc_data_source(j).calendar.limit_cube:=p_kpi.dim_set(i).calendar.limit_cube;
1743 end loop;
1744 --targets only have cubes, limit cubes and load programs
1745 if p_kpi.dim_set(i).targets_higher_levels='Y' then
1746 p_kpi.target_dim_set(i).agg_map.agg_map:=null;
1747 --
1748 p_kpi.target_dim_set(i).initial_load_program.program_name:=p_kpi.dim_set(i).initial_load_program.program_name||'.tgt';
1749 p_kpi.target_dim_set(i).inc_load_program.program_name:=p_kpi.dim_set(i).inc_load_program.program_name||'.tgt';
1750 p_kpi.target_dim_set(i).initial_load_program_parallel.program_name:=p_kpi.dim_set(i).initial_load_program_parallel.program_name||'.tgt';
1751 p_kpi.target_dim_set(i).inc_load_program_parallel.program_name:=p_kpi.dim_set(i).inc_load_program_parallel.program_name||'.tgt';
1752 --for 10g, targets will need a separate program so it can run in parallel
1753 for j in 1..p_kpi.target_dim_set(i).dim.count loop
1754 p_kpi.target_dim_set(i).dim(j).limit_cube:=p_kpi.dim_set(i).dim(j).limit_cube||'.tgt';
1755 if nvl(bsc_aw_utility.get_parameter_value('NO LIMIT CUBE COMPOSITE'),'N')='N' then
1756 p_kpi.target_dim_set(i).dim(j).limit_cube_composite:='c.'||p_kpi.target_dim_set(i).dim(j).limit_cube;
1757 end if;
1758 end loop;
1759 --std dim
1760 for j in 1..p_kpi.target_dim_set(i).std_dim.count loop
1761 p_kpi.target_dim_set(i).std_dim(j).limit_cube:=p_kpi.dim_set(i).std_dim(j).limit_cube||'.tgt';
1762 if nvl(bsc_aw_utility.get_parameter_value('NO LIMIT CUBE COMPOSITE'),'N')='N' then
1763 p_kpi.target_dim_set(i).std_dim(j).limit_cube_composite:='c.'||p_kpi.target_dim_set(i).std_dim(j).limit_cube;
1764 end if;
1765 end loop;
1766 --time limit cube
1767 p_kpi.target_dim_set(i).calendar.limit_cube:=p_kpi.dim_set(i).calendar.limit_cube||'.tgt';
1768 if nvl(bsc_aw_utility.get_parameter_value('NO LIMIT CUBE COMPOSITE'),'N')='N' then
1769 p_kpi.target_dim_set(i).calendar.limit_cube_composite:='c.'||p_kpi.target_dim_set(i).calendar.limit_cube;
1770 end if;
1771 --
1772 create_PT_comp_names(p_kpi.kpi,p_kpi.target_dim_set(i));
1773 --give cube names to data source measures
1774 for j in 1..p_kpi.target_dim_set(i).data_source.count loop
1775 for k in 1..p_kpi.target_dim_set(i).data_source(j).measure.count loop
1776 p_kpi.target_dim_set(i).data_source(j).measure(k).cube:=p_kpi.target_dim_set(i).measure(l_measure_index(p_kpi.target_dim_set(i).data_source(j).measure(k).measure)).cube;
1777 p_kpi.target_dim_set(i).data_source(j).measure(k).property:=
1778 p_kpi.target_dim_set(i).measure(l_measure_index(p_kpi.target_dim_set(i).data_source(j).measure(k).measure)).property;
1779 end loop;
1780 --set the dim limit cubes
1781 for k in 1..p_kpi.target_dim_set(i).data_source(j).dim.count loop
1782 p_kpi.target_dim_set(i).data_source(j).dim(k).limit_cube:=
1783 p_kpi.target_dim_set(i).dim(l_dim_index(p_kpi.target_dim_set(i).data_source(j).dim(k).dim_name)).limit_cube;
1784 end loop;
1785 for k in 1..p_kpi.target_dim_set(i).data_source(j).std_dim.count loop
1786 p_kpi.target_dim_set(i).data_source(j).std_dim(k).limit_cube:=
1787 p_kpi.target_dim_set(i).std_dim(l_dim_index(p_kpi.target_dim_set(i).data_source(j).std_dim(k).dim_name)).limit_cube;
1788 end loop;
1789 p_kpi.target_dim_set(i).data_source(j).calendar.limit_cube:=p_kpi.target_dim_set(i).calendar.limit_cube;
1790 end loop;
1791 for j in 1..p_kpi.target_dim_set(i).inc_data_source.count loop
1792 for k in 1..p_kpi.target_dim_set(i).inc_data_source(j).measure.count loop
1793 p_kpi.target_dim_set(i).inc_data_source(j).measure(k).cube:=p_kpi.target_dim_set(i).measure(
1794 l_measure_index(p_kpi.target_dim_set(i).inc_data_source(j).measure(k).measure)).cube;
1795 p_kpi.target_dim_set(i).inc_data_source(j).measure(k).property:=p_kpi.target_dim_set(i).measure(
1796 l_measure_index(p_kpi.target_dim_set(i).inc_data_source(j).measure(k).measure)).property;
1797 end loop;
1798 for k in 1..p_kpi.target_dim_set(i).inc_data_source(j).dim.count loop
1799 p_kpi.target_dim_set(i).inc_data_source(j).dim(k).limit_cube:=
1803 p_kpi.target_dim_set(i).inc_data_source(j).std_dim(k).limit_cube:=
1800 p_kpi.target_dim_set(i).dim(l_dim_index(p_kpi.target_dim_set(i).inc_data_source(j).dim(k).dim_name)).limit_cube;
1801 end loop;
1802 for k in 1..p_kpi.target_dim_set(i).inc_data_source(j).std_dim.count loop
1804 p_kpi.target_dim_set(i).std_dim(l_dim_index(p_kpi.target_dim_set(i).inc_data_source(j).std_dim(k).dim_name)).limit_cube;
1805 end loop;
1806 p_kpi.target_dim_set(i).inc_data_source(j).calendar.limit_cube:=p_kpi.target_dim_set(i).calendar.limit_cube;
1807 end loop;
1808 end if;
1809 end loop;
1810 Exception when others then
1811 log_n('Exception in create_aw_object_names '||sqlerrm);
1812 raise;
1813 End;
1814
1815 /*
1816 this procedure names the partitions , composites.
1817 p_dimset cane be actual or target for target, dim_set_name contains .tgt at the end
1818 with the display cube concept, create_PT_comp_names must be called only after compressed composite parameters and partition parameters
1819 are set
1820 */
1821 procedure create_PT_comp_names(p_kpi varchar2,p_dimset in out nocopy dim_set_r) is
1822 l_kpi varchar2(100); --just used to name objects
1823 l_composite_name varchar2(200);
1824 l_countvar_flag boolean;
1825 composite_index bsc_aw_utility.number_table;
1826 Begin
1827 l_kpi:=p_kpi;
1828 if p_dimset.dim_set_type='target' then
1829 l_kpi:=l_kpi||'.tgt';
1830 end if;
1831 --measurename_dim cannot be null
1832 /*
1833 measurename muct be shared by the tgt and actual. otherwise, data is not copied correctly.
1834 so also partition dim
1835 note>>> for measurename, we use p_kpi, not l_kpi
1836 */
1837 p_dimset.measurename_dim:='measurename.'||p_dimset.dim_set||'.'||p_kpi;
1838 l_composite_name:='comp.'||p_dimset.dim_set||'.'||l_kpi;
1839 --
1840 l_countvar_flag:=check_countvar_cube_needed(p_dimset);
1841 if bsc_aw_utility.get_db_version >=10 and nvl(bsc_aw_utility.get_parameter_value('NO DATACUBE'),'N')='N' then
1842 --
1843 p_dimset.cube_design:='datacube';
1844 if p_dimset.number_partitions>0 then
1845 --dimset can have multiple partition templates to support PT for countvar cubes when we have to use compressed composites
1846 /*copy the info from master partition template. master_partition_template(1) is for datacubes */
1847 p_dimset.partition_template(1):=p_dimset.master_partition_template(1);
1848 p_dimset.partition_template(1).template_name:='PT.'||p_dimset.dim_set||'.'||l_kpi;
1849 for i in 1..p_dimset.number_partitions loop --partitions are named P0, P1 etc. name starts with "0"
1850 p_dimset.composite(p_dimset.composite.count+1).composite_name:=l_composite_name||'.'||(i-1);
1851 if p_dimset.compressed='N' then
1852 p_dimset.composite(p_dimset.composite.count).composite_type:='non compressed';
1853 else
1854 p_dimset.composite(p_dimset.composite.count).composite_type:='compressed';
1855 end if;
1856 composite_index('cube'||i):=p_dimset.composite.count;
1857 --we cannot have compressed composites when we have targets at higher levels since we cannot copy data into higher levels
1858 --from targets to the actuals
1859 --
1860 p_dimset.partition_template(1).template_partitions(i).partition_name:='P.'||(i-1);
1861 p_dimset.partition_template(1).template_partitions(i).partition_dim_value:=to_char(i-1);
1862 p_dimset.partition_template(1).template_partitions(i).partition_axis.delete;
1863 p_dimset.partition_template(1).template_partitions(i).partition_axis(1).axis_name:=p_dimset.partition_template(1).template_dim;
1864 p_dimset.partition_template(1).template_partitions(i).partition_axis(1).axis_type:='dimension';
1865 p_dimset.partition_template(1).template_partitions(i).partition_axis(
1866 p_dimset.partition_template(1).template_partitions(i).partition_axis.count+1).axis_name:=p_dimset.measurename_dim;
1867 p_dimset.partition_template(1).template_partitions(i).partition_axis(
1868 p_dimset.partition_template(1).template_partitions(i).partition_axis.count).axis_type:='dimension';
1869 p_dimset.partition_template(1).template_partitions(i).partition_axis(
1870 p_dimset.partition_template(1).template_partitions(i).partition_axis.count+1).axis_name:=
1871 p_dimset.composite(composite_index('cube'||i)).composite_name;
1872 p_dimset.partition_template(1).template_partitions(i).partition_axis(
1873 p_dimset.partition_template(1).template_partitions(i).partition_axis.count).axis_type:='composite';
1874 end loop;
1875 --if there is countvar and compressed composite, we create separate PT for countvar cube . this is not supported now
1876 --by AW. but in case in the future we have it...
1877 if l_countvar_flag and p_dimset.compressed='Y' then
1878 p_dimset.partition_template(2):=p_dimset.master_partition_template(1);
1879 p_dimset.partition_template(2).template_name:='PT.'||p_dimset.dim_set||'.'||l_kpi||'.countvar';
1880 for i in 1..p_dimset.number_partitions loop --partitions are named P0, P1 etc. name starts with "0"
1881 p_dimset.composite(p_dimset.composite.count+1).composite_name:=l_composite_name||'.'||(i-1)||'.countvar';
1882 if p_dimset.compressed='N' then
1883 p_dimset.composite(p_dimset.composite.count).composite_type:='non compressed';
1884 else
1885 p_dimset.composite(p_dimset.composite.count).composite_type:='compressed';
1886 end if;
1887 composite_index('countvar'||i):=p_dimset.composite.count;
1888 p_dimset.partition_template(2).template_partitions(i).partition_name:='P.'||(i-1);
1889 p_dimset.partition_template(2).template_partitions(i).partition_dim_value:=to_char(i-1);
1890 p_dimset.partition_template(2).template_partitions(i).partition_axis.delete;
1891 p_dimset.partition_template(2).template_partitions(i).partition_axis(1).axis_name:=p_dimset.partition_template(2).template_dim;
1892 p_dimset.partition_template(2).template_partitions(i).partition_axis(1).axis_type:='dimension';
1896 p_dimset.partition_template(2).template_partitions(i).partition_axis.count).axis_type:='dimension';
1893 p_dimset.partition_template(2).template_partitions(i).partition_axis(
1894 p_dimset.partition_template(2).template_partitions(i).partition_axis.count+1).axis_name:=p_dimset.measurename_dim;
1895 p_dimset.partition_template(2).template_partitions(i).partition_axis(
1897 p_dimset.partition_template(2).template_partitions(i).partition_axis(
1898 p_dimset.partition_template(2).template_partitions(i).partition_axis.count+1).axis_name:=
1899 p_dimset.composite(composite_index('countvar'||i)).composite_name;
1900 p_dimset.partition_template(2).template_partitions(i).partition_axis(
1901 p_dimset.partition_template(2).template_partitions(i).partition_axis.count).axis_type:='composite';
1902 end loop;
1903 end if;
1904 else --this is 10g, but there are no partitions
1905 --10g will have datacube.
1906 p_dimset.composite(1).composite_name:=l_composite_name;
1907 if p_dimset.compressed='N' then
1908 p_dimset.composite(1).composite_type:='non compressed';
1909 else
1910 p_dimset.composite(1).composite_type:='compressed';
1911 end if;
1912 composite_index('cube'):=1;
1913 if l_countvar_flag and p_dimset.compressed='Y' then
1914 p_dimset.composite(2).composite_name:=l_composite_name||'.countvar';
1915 if p_dimset.compressed='N' then
1916 p_dimset.composite(2).composite_type:='non compressed';
1917 else
1918 p_dimset.composite(2).composite_type:='compressed';
1919 end if;
1920 composite_index('countvar'):=2;
1921 end if;
1922 end if;
1923 --cubes
1924 /*
1925 we need algo to decide the datatype. for now, we go with number
1926 */
1927 p_dimset.cube_set(1).cube_set_name:='cube set.'||p_dimset.dim_set_name||'.1';
1928 p_dimset.cube_set(1).cube_set_type:='datacube';
1929 p_dimset.cube_set(1).cube.cube_name:='datacube.'||p_dimset.dim_set||'.'||l_kpi;
1930 p_dimset.cube_set(1).cube.cube_datatype:='number';
1931 p_dimset.cube_set(1).fcst_cube.cube_name:=p_dimset.cube_set(1).cube.cube_name||'.fcst';
1932 p_dimset.cube_set(1).fcst_cube.cube_datatype:='number';
1933 if l_countvar_flag then
1934 if bsc_aw_utility.get_property(p_dimset.property,'aggcount').property_value='Y' then
1935 null;
1936 else
1937 p_dimset.cube_set(1).countvar_cube.cube_name:=p_dimset.cube_set(1).cube.cube_name||'.countvar'; --countvar not used in targets
1938 p_dimset.cube_set(1).countvar_cube.cube_datatype:='integer';
1939 end if;
1940 end if;
1941 p_dimset.cube_set(1).measurename_dim:=p_dimset.measurename_dim;
1942 for i in 1..p_dimset.measure.count loop
1943 p_dimset.measure(i).cube:=p_dimset.cube_set(1).cube.cube_name;
1944 p_dimset.measure(i).fcst_cube:=p_dimset.cube_set(1).fcst_cube.cube_name;
1945 --if there is one measure with avg, we need countvar for all cubes
1946 if p_dimset.cube_set(1).countvar_cube.cube_name is not null then
1947 p_dimset.measure(i).countvar_cube:=p_dimset.cube_set(1).countvar_cube.cube_name;
1948 end if;
1949 p_dimset.measure(i).aw_formula.formula_name:=p_dimset.measure(i).measure||'.'||p_dimset.dim_set||'.'||l_kpi;
1950 p_dimset.measure(i).aw_formula.formula_expression:=p_dimset.measure(i).cube||'('||p_dimset.measurename_dim||' '''||
1951 p_dimset.measure(i).measure||''')';
1952 end loop;
1953 /*if we have partitions and this is compressed composite, we have a problem when we need to aggregate data on the fly. compressed
1954 composites cannot be limited in dim status and aggregated. this means we will copy the data into a display cube and then aggregate the display
1955 cube. the view runs off the display cube. for now, we have no composites for the display cube. it must have all the dim of the cube including
1956 partition dim. this name must also be added to measuredim for aggregation
1957 display cube axis is set in create_cube. we need to make sure that display cube axis has the same dim in the same order as that of the cube*/
1958 if is_display_cube_required(p_dimset,p_dimset.cube_set(1).cube.cube_name) then
1959 p_dimset.cube_set(1).display_cube.cube_name:=p_dimset.cube_set(1).cube.cube_name||'.disp';
1960 p_dimset.cube_set(1).display_cube.cube_type:=p_dimset.cube_set(1).cube.cube_type;
1961 p_dimset.cube_set(1).display_cube.cube_datatype:=p_dimset.cube_set(1).cube.cube_datatype;
1962 /*display cube will have its composite */
1963 p_dimset.composite(p_dimset.composite.count+1).composite_name:='c.'||p_dimset.cube_set(1).display_cube.cube_name;
1964 p_dimset.composite(p_dimset.composite.count).composite_type:='non compressed';
1965 composite_index('display'):=p_dimset.composite.count;
1966 /*no partition dim for display cube. in the reader,we copy from main cube to display cube. display=main cube
1967 since there is no node duplication across partitions, when data is copied into the display cube, there is no overwriting
1968 so display cube does not need partition dim. this means we can implement avg measure also with display cubes */
1969 p_dimset.cube_set(1).display_cube.cube_axis(1).axis_name:=p_dimset.measurename_dim;
1970 p_dimset.cube_set(1).display_cube.cube_axis(1).axis_type:='dimension';
1971 p_dimset.cube_set(1).display_cube.cube_axis(2).axis_name:=p_dimset.composite(composite_index('display')).composite_name;
1972 p_dimset.cube_set(1).display_cube.cube_axis(2).axis_type:='composite';
1973 end if;
1974 /*set the display cube properties for the measures */
1975 for i in 1..p_dimset.measure.count loop
1976 p_dimset.measure(i).display_cube:=p_dimset.cube_set(1).display_cube.cube_name;
1977 if p_dimset.measure(i).display_cube is not null then /*partitions with CC or avg agg or non-sql-agg formula */
1978 p_dimset.measure(i).aw_formula.formula_expression:=p_dimset.measure(i).display_cube||'('||p_dimset.measurename_dim||' '''||
1979 p_dimset.measure(i).measure||''')';
1980 end if;
1981 end loop;
1982 /* */
1986 p_dimset.cube_set(1).cube.cube_axis(1).axis_type:='partition template';
1983 if p_dimset.number_partitions>0 then
1984 --here countvar cube and regular cube share the partition since the partition is non compressed
1985 p_dimset.cube_set(1).cube.cube_axis(1).axis_name:=p_dimset.partition_template(1).template_name;
1987 if p_dimset.cube_set(1).countvar_cube.cube_name is not null then
1988 if p_dimset.compressed='Y' then
1989 p_dimset.cube_set(1).countvar_cube.cube_axis(1).axis_name:=p_dimset.partition_template(2).template_name;
1990 else
1991 p_dimset.cube_set(1).countvar_cube.cube_axis(1).axis_name:=p_dimset.partition_template(1).template_name;
1992 end if;
1993 p_dimset.cube_set(1).countvar_cube.cube_axis(1).axis_type:='partition template';
1994 end if;
1995 --we dont populate the fcst cubes for now
1996 else --10g but with no partitions
1997 --here countvar cube and regular cube share the partition since the partition is non compressed
1998 p_dimset.cube_set(1).cube.cube_axis(1).axis_name:=p_dimset.measurename_dim;
1999 p_dimset.cube_set(1).cube.cube_axis(1).axis_type:='dimension';
2000 p_dimset.cube_set(1).cube.cube_axis(2).axis_name:=p_dimset.composite(composite_index('cube')).composite_name;
2001 p_dimset.cube_set(1).cube.cube_axis(2).axis_type:='composite';
2002 if p_dimset.cube_set(1).countvar_cube.cube_name is not null then
2003 p_dimset.cube_set(1).countvar_cube.cube_axis(1).axis_name:=p_dimset.measurename_dim;
2004 p_dimset.cube_set(1).countvar_cube.cube_axis(1).axis_type:='dimension';
2005 if p_dimset.compressed='Y' then
2006 p_dimset.cube_set(1).countvar_cube.cube_axis(2).axis_name:=p_dimset.composite(composite_index('countvar')).composite_name;
2007 else
2008 p_dimset.cube_set(1).countvar_cube.cube_axis(2).axis_name:=p_dimset.composite(composite_index('cube')).composite_name;
2009 end if;
2010 p_dimset.cube_set(1).countvar_cube.cube_axis(2).axis_type:='composite';
2011 end if;
2012 --we dont populate the fcst cubes for now
2013 end if;
2014 else --9i no compressed composite in 9i
2015 --no partitions 1 composite , multiple cubes at measure level
2016 p_dimset.composite(1).composite_name:=l_composite_name;
2017 p_dimset.composite(1).composite_type:='non compressed';
2018 composite_index('cube'):=1;
2019 p_dimset.cube_design:='single composite';
2020 p_dimset.compressed:='N';
2021 for i in 1..p_dimset.measure.count loop
2022 p_dimset.cube_set(i).cube_set_name:='cube set.'||p_dimset.dim_set_name||'.'||i;
2023 p_dimset.cube_set(i).cube_set_type:='measurecube';
2024 p_dimset.cube_set(i).cube.cube_name:=p_dimset.measure(i).measure||'.'||p_dimset.dim_set||'.'||l_kpi;
2025 p_dimset.cube_set(i).cube.cube_datatype:=p_dimset.measure(i).data_type;
2026 p_dimset.cube_set(i).fcst_cube.cube_name:=p_dimset.cube_set(i).cube.cube_name||'.fcst';
2027 p_dimset.cube_set(i).fcst_cube.cube_datatype:=p_dimset.measure(i).data_type;
2028 if l_countvar_flag then
2029 p_dimset.cube_set(i).countvar_cube.cube_name:=p_dimset.cube_set(i).cube.cube_name||'.countvar';
2030 p_dimset.cube_set(i).countvar_cube.cube_datatype:='integer';
2031 end if;
2032 --
2033 p_dimset.cube_set(i).measurename_dim:=p_dimset.measurename_dim;
2034 --
2035 p_dimset.cube_set(i).cube.cube_axis(1).axis_name:=p_dimset.composite(composite_index('cube')).composite_name;
2036 p_dimset.cube_set(i).cube.cube_axis(1).axis_type:='composite';
2037 if p_dimset.cube_set(i).countvar_cube.cube_name is not null then
2038 p_dimset.cube_set(i).countvar_cube.cube_axis(1).axis_name:=p_dimset.composite(composite_index('cube')).composite_name;
2039 p_dimset.cube_set(i).countvar_cube.cube_axis(1).axis_type:='composite';
2040 end if;
2041 --dont populate the fcst cube for now
2042 --
2043 p_dimset.measure(i).cube:=p_dimset.cube_set(i).cube.cube_name;
2044 if p_dimset.cube_set(i).countvar_cube.cube_name is not null then
2045 p_dimset.measure(i).countvar_cube:=p_dimset.cube_set(i).countvar_cube.cube_name;
2046 end if;
2047 p_dimset.measure(i).fcst_cube:=p_dimset.cube_set(i).fcst_cube.cube_name;
2048 --
2049 end loop;
2050 /*if there are period cubes and year cubes then create the extra cubes for these objects*/
2051 for i in 1..p_dimset.measure.count loop
2052 for j in 1..p_dimset.measure(i).property.count loop
2053 if p_dimset.measure(i).property(j).property_name='period cube' or p_dimset.measure(i).property(j).property_name='year cube' then
2054 p_dimset.cube_set(p_dimset.cube_set.count+1).cube_set_name:='cube set.'||p_dimset.dim_set_name||'.'||
2055 p_dimset.measure(i).property(j).property_name||'.'||i||'.'||j;
2056 p_dimset.cube_set(p_dimset.cube_set.count).cube_set_type:='measurecube';
2057 p_dimset.cube_set(p_dimset.cube_set.count).cube.cube_name:=p_dimset.measure(i).property(j).property_value||'.'||
2058 p_dimset.dim_set||'.'||l_kpi;
2059 /*set the property name to reflect the correct cube name*/
2060 p_dimset.measure(i).property(j).property_value:=p_dimset.cube_set(p_dimset.cube_set.count).cube.cube_name;
2061 p_dimset.cube_set(p_dimset.cube_set.count).cube.cube_datatype:=p_dimset.measure(i).data_type; /*should be number */
2062 p_dimset.cube_set(p_dimset.cube_set.count).measurename_dim:=p_dimset.measurename_dim;
2063 p_dimset.cube_set(p_dimset.cube_set.count).cube.cube_axis(1).axis_name:=p_dimset.composite(composite_index('cube')).composite_name;
2064 p_dimset.cube_set(p_dimset.cube_set.count).cube.cube_axis(1).axis_type:='composite';
2065 /*no fcst cubes or countvar cubes */
2066 end if;
2067 end loop;
2068 end loop;
2069 end if;
2070 Exception when others then
2071 log_n('Exception in create_PT_comp_names '||sqlerrm);
2072 raise;
2073 End;
2074
2075 /*
2076 */
2077 procedure create_kpi_objects(p_kpi in out nocopy kpi_r) is
2078 Begin
2079 for i in 1..p_kpi.dim_set.count loop
2083 end if;
2080 create_kpi_objects(p_kpi,p_kpi.dim_set(i));
2081 if p_kpi.dim_set(i).targets_higher_levels='Y' then
2082 create_kpi_objects(p_kpi,p_kpi.target_dim_set(i));
2084 end loop;
2085 Exception when others then
2086 log_n('Exception in create_kpi_objects '||sqlerrm);
2087 raise;
2088 End;
2089
2090 /*
2091 composite name : comp_dimset_kpi
2092 in the composite, the order of dim is
2093 dim with no agg, no zero code
2094 dim with no agg, zero code
2095 dim with agg
2096 rec dim
2097 time
2098 */
2099 procedure create_kpi_objects(
2100 p_kpi kpi_r,
2101 p_dim_set in out nocopy dim_set_r) is
2102 l_comp varchar2(300);
2103 Begin
2104 create_measure_dim(p_kpi,p_dim_set);
2105 create_composite(p_kpi,p_dim_set);
2106 create_partition_template(p_kpi,p_dim_set);
2107 create_cube(p_kpi,p_dim_set);
2108 create_measure_formula(p_kpi,p_dim_set);
2109 create_aggmap_operators(p_kpi,p_dim_set);
2110 create_agg_map(p_kpi,p_dim_set);
2111 Exception when others then
2112 log_n('Exception in create_kpi_objects '||sqlerrm);
2113 raise;
2114 End;
2115
2116 procedure create_measure_dim(
2117 p_kpi kpi_r,
2118 p_dim_set in out nocopy dim_set_r) is
2119 l_pt_comp_type varchar2(100);
2120 l_pt_comp varchar2(100);
2121 l_partition_template partition_template_r;
2122 l_stmt varchar2(2000);
2123 Begin
2124 if g_debug then
2125 log_n('create_measure_dim, dimset='||p_dim_set.dim_set_name);
2126 end if;
2127 --if this is targets, we share the measuredim with the actuals. so no need to create it
2128 --actuals are created before targets. see procedure create_kpi_objects(p_kpi in out nocopy kpi_r) is
2129 if p_dim_set.dim_set_type <> 'target' then
2130 l_stmt:='dfn '||p_dim_set.measurename_dim||' dimension TEXT';
2131 bsc_aw_dbms_aw.execute(l_stmt);
2132 for i in 1..p_dim_set.measure.count loop
2133 l_stmt:='mnt '||p_dim_set.measurename_dim||' add '''||p_dim_set.measure(i).measure||'''';
2134 bsc_aw_dbms_aw.execute(l_stmt);
2135 if p_dim_set.measure(i).measure_type=g_balance_last_value_prop then
2136 for j in 1..p_dim_set.measure(i).property.count loop
2137 if p_dim_set.measure(i).property(j).property_name='period cube' or p_dim_set.measure(i).property(j).property_name='year cube' then
2138 l_stmt:='mnt '||p_dim_set.measurename_dim||' add '''||p_dim_set.measure(i).property(j).property_value||'''';
2139 bsc_aw_dbms_aw.execute(l_stmt);
2140 end if;
2141 end loop;
2142 end if;
2143 end loop;
2144 end if;
2145 --
2146 if p_dim_set.aggmap_operator.measure_dim is not null then
2147 l_stmt:='dfn '||p_dim_set.aggmap_operator.measure_dim||' dimension TEXT';
2148 bsc_aw_dbms_aw.execute(l_stmt);
2149 for i in 1..p_dim_set.cube_set.count loop
2150 l_stmt:='mnt '||p_dim_set.aggmap_operator.measure_dim||' add '''||p_dim_set.cube_set(i).cube.cube_name||'''';
2151 bsc_aw_dbms_aw.execute(l_stmt);
2152 if p_dim_set.cube_set(i).display_cube.cube_name is not null then
2153 l_stmt:='mnt '||p_dim_set.aggmap_operator.measure_dim||' add '''||p_dim_set.cube_set(i).display_cube.cube_name||'''';
2154 bsc_aw_dbms_aw.execute(l_stmt);
2155 end if;
2156 /*if the main cube is partitioned, we also add the cube partitions. with this, we can now say
2157 aggregate datacube.4.4014 (partition P.0) using aggmap.4.4014.notime for nonCC composites. earlier we were limiting the
2158 hash partition dim to ensure that only the specified partition got aggregated. but, all partitions ended up getting
2159 aggregated. if we specify datacube.4.4014 (partition P.0) , then only P.0 gets aggregated. but we need an entry for
2160 datacube.4.4014 (partition P.0) in opvar */
2161 l_pt_comp:=get_cube_pt_comp(p_dim_set.cube_set(i).cube.cube_name,p_dim_set,l_pt_comp_type);
2162 if l_pt_comp_type='partition template' then
2163 l_partition_template:=get_partition_template_r(l_pt_comp,p_dim_set);
2164 for j in 1..l_partition_template.template_partitions.count loop
2165 l_stmt:='mnt '||p_dim_set.aggmap_operator.measure_dim||' add '''||p_dim_set.cube_set(i).cube.cube_name||' (PARTITION '||
2166 l_partition_template.template_partitions(j).partition_name||')''';
2167 bsc_aw_dbms_aw.execute(l_stmt);
2168 end loop;
2169 end if;
2170 end loop;
2171 end if;
2172 Exception when others then
2173 log_n('Exception in create_measure_dim '||sqlerrm);
2174 raise;
2175 End;
2176
2177 function get_comp_dimensions(p_dim_set in out nocopy dim_set_r) return dbms_sql.varchar2_table is
2178 --
2179 l_comp_dimensions dbms_sql.varchar2_table;
2180 Begin
2181 --first we have the dim on which are going to aggregate. confirmed with AW team. best to have the dim on which we are aggregating
2182 --ahead in the index. we will have time first
2183 l_comp_dimensions(l_comp_dimensions.count+1):=p_dim_set.calendar.aw_dim;
2184 --dim on which we aggregate
2185 for i in 1..p_dim_set.dim.count loop
2186 --if p_dim_set.dim(i).levels.count>1 or p_dim_set.dim(i).zero_code='Y' or p_dim_set.dim(i).recursive='Y' then
2187 if is_dim_aggregated(p_dim_set.dim(i)) then
2188 p_dim_set.dim(i).agg_map.created:='Y'; --from now, we will check this flag to see if we need to aggregate on this dim
2189 l_comp_dimensions(l_comp_dimensions.count+1):=p_dim_set.dim(i).dim_name;
2190 end if;
2191 end loop;
2192 --dim on which there is no agg
2193 for i in 1..p_dim_set.dim.count loop
2194 if p_dim_set.dim(i).agg_map.created is null or p_dim_set.dim(i).agg_map.created <> 'Y' then
2195 l_comp_dimensions(l_comp_dimensions.count+1):=p_dim_set.dim(i).dim_name;
2196 end if;
2197 end loop;
2198 --last have the std dim
2199 for i in 1..p_dim_set.std_dim.count loop
2200 l_comp_dimensions(l_comp_dimensions.count+1):=p_dim_set.std_dim(i).dim_name;
2201 end loop;
2202 return l_comp_dimensions;
2206 End;
2203 Exception when others then
2204 log_n('Exception in get_comp_dimensions '||sqlerrm);
2205 raise;
2207
2208 /*
2209 composite name : comp_dimset_kpi
2210 in the composite, the order of dim is
2211 dim with no agg, no zero code
2212 dim with no agg, zero code
2213 dim with agg
2214 rec dim
2215 time
2216 please note that the procedure set_dim_order has already set the dim in the correct order
2217 */
2218 procedure create_composite(
2219 p_kpi kpi_r,
2220 p_dim_set in out nocopy dim_set_r) is
2221 l_comp_created dbms_sql.varchar2_table;
2222 l_comp_dimensions dbms_sql.varchar2_table;
2223 Begin
2224 l_comp_dimensions:=get_comp_dimensions(p_dim_set);
2225 --first create the composites
2226 for i in 1..p_dim_set.composite.count loop
2227 if bsc_aw_utility.in_array(l_comp_created,p_dim_set.composite(i).composite_name)=false then
2228 p_dim_set.composite(i).composite_dimensions:=l_comp_dimensions;
2229 g_stmt:='dfn '||p_dim_set.composite(i).composite_name||' composite <';
2230 for j in 1..p_dim_set.composite(i).composite_dimensions.count loop
2231 g_stmt:=g_stmt||p_dim_set.composite(i).composite_dimensions(j)||' ';
2232 end loop;
2233 g_stmt:=g_stmt||'>';
2234 if p_dim_set.composite(i).composite_type='compressed' then
2235 g_stmt:=g_stmt||' compressed';
2236 end if;
2237 bsc_aw_dbms_aw.execute(g_stmt);
2238 l_comp_created(l_comp_created.count+1):=p_dim_set.composite(i).composite_name;
2239 end if;
2240 end loop;
2241 Exception when others then
2242 log_n('Exception in create_composite '||sqlerrm);
2243 raise;
2244 End;
2245
2246 /*
2247 now, we only create list partitions, these list partitions are essentially hash partitions
2248 */
2249 procedure create_partition_template(
2250 p_kpi kpi_r,
2251 p_dim_set in out nocopy dim_set_r) is
2252 Begin
2253 --create the partitions
2254 for i in 1..p_dim_set.partition_template.count loop
2255 create_partition_template(p_kpi,p_dim_set,p_dim_set.partition_template(i));
2256 end loop;
2257 Exception when others then
2258 log_n('Exception in create_partition '||sqlerrm);
2259 raise;
2260 End;
2261
2262 procedure create_partition_template(
2263 p_kpi kpi_r,
2264 p_dim_set in out nocopy dim_set_r,
2265 p_partition_template in out nocopy partition_template_r
2266 ) is
2267 --
2268 l_comp_dimensions dbms_sql.varchar2_table;
2269 Begin
2270 if p_partition_template.template_name is not null then
2271 l_comp_dimensions:=get_comp_dimensions(p_dim_set);
2272 p_partition_template.template_dimensions(1):=p_partition_template.template_dim;
2273 p_partition_template.template_dimensions(p_partition_template.template_dimensions.count+1):=p_dim_set.measurename_dim;
2274 for i in 1..l_comp_dimensions.count loop
2275 p_partition_template.template_dimensions(p_partition_template.template_dimensions.count+1):=l_comp_dimensions(i);
2276 end loop;
2277 g_stmt:='dfn '||p_partition_template.template_name||' PARTITION TEMPLATE <';
2278 for i in 1..p_partition_template.template_dimensions.count loop
2279 g_stmt:=g_stmt||' '||p_partition_template.template_dimensions(i);
2280 end loop;
2281 g_stmt:=g_stmt||'> -'||bsc_aw_utility.g_newline;
2282 g_stmt:=g_stmt||'partition by '||p_partition_template.template_type||' ('||p_partition_template.template_dim||') -'||bsc_aw_utility.g_newline;
2283 g_stmt:=g_stmt||'( -'||bsc_aw_utility.g_newline;
2284 for i in 1..p_partition_template.template_partitions.count loop
2285 g_stmt:=g_stmt||'PARTITION '||p_partition_template.template_partitions(i).partition_name||' VALUES ('||
2286 p_partition_template.template_partitions(i).partition_dim_value||') <';
2287 for j in 1..p_partition_template.template_partitions(i).partition_axis.count loop
2288 g_stmt:=g_stmt||' '||p_partition_template.template_partitions(i).partition_axis(j).axis_name;
2289 if p_partition_template.template_partitions(i).partition_axis(j).axis_type='composite' then --mention the composite dim also
2290 l_comp_dimensions:=get_composite_r(p_partition_template.template_partitions(i).partition_axis(j).axis_name,p_dim_set).composite_dimensions;
2291 g_stmt:=g_stmt||'<';
2292 for k in 1..l_comp_dimensions.count loop
2293 g_stmt:=g_stmt||' '||l_comp_dimensions(k);
2294 end loop;
2295 g_stmt:=g_stmt||'>';
2296 end if;
2297 end loop;
2298 g_stmt:=g_stmt||'> -'||bsc_aw_utility.g_newline;
2299 end loop;
2300 g_stmt:=g_stmt||')';
2301 bsc_aw_dbms_aw.execute(g_stmt);
2302 end if;
2303 Exception when others then
2304 log_n('Exception in create_partition_template '||sqlerrm);
2305 raise;
2306 End;
2307
2308 procedure create_cube(
2309 p_kpi kpi_r,
2310 p_dim_set in out nocopy dim_set_r) is
2311 --
2312 l_lc_axis varchar2(400);
2313 Begin
2314 for i in 1..p_dim_set.cube_set.count loop
2315 create_cube(p_kpi,p_dim_set,p_dim_set.cube_set(i).cube);
2316 if p_dim_set.cube_set(i).countvar_cube.cube_name is not null then
2317 create_cube(p_kpi,p_dim_set,p_dim_set.cube_set(i).countvar_cube);
2318 end if;
2319 if p_dim_set.cube_set(i).display_cube.cube_name is not null then
2320 --create_cube(p_kpi,p_dim_set,p_dim_set.cube_set(i).display_cube,make_display_cube_axis(p_dim_set,p_dim_set.cube_set(i).cube));
2321 create_cube(p_kpi,p_dim_set,p_dim_set.cube_set(i).display_cube);
2322 end if;
2323 --we do not create the fcst cube now
2324 end loop;
2325 --create the limit cubes
2326 for i in 1..p_dim_set.dim.count loop
2327 --create the composite
2328 if p_dim_set.dim(i).limit_cube_composite is not null then
2329 g_stmt:='dfn '||p_dim_set.dim(i).limit_cube_composite||' composite <'||p_dim_set.dim(i).dim_name||'>';
2330 bsc_aw_dbms_aw.execute(g_stmt);
2334 end if;
2331 l_lc_axis:=p_dim_set.dim(i).limit_cube_composite||'<'||p_dim_set.dim(i).dim_name||'>';
2332 else
2333 l_lc_axis:=p_dim_set.dim(i).dim_name;
2335 g_stmt:='dfn '||p_dim_set.dim(i).limit_cube||' variable boolean <'||l_lc_axis||'>';
2336 bsc_aw_dbms_aw.execute(g_stmt);
2337 if p_dim_set.dim(i).reset_cube is not null then
2338 g_stmt:='dfn '||p_dim_set.dim(i).reset_cube||' variable boolean <'||l_lc_axis||'>';
2339 bsc_aw_dbms_aw.execute(g_stmt);
2340 end if;
2341 if p_dim_set.dim(i).aggregate_marker is not null then
2342 g_stmt:='dfn '||p_dim_set.dim(i).aggregate_marker||' boolean';
2343 bsc_aw_dbms_aw.execute(g_stmt);
2344 g_stmt:=p_dim_set.dim(i).aggregate_marker||'=false';
2345 bsc_aw_dbms_aw.execute(g_stmt);
2346 end if;
2347 end loop;
2348 --std dim
2349 for i in 1..p_dim_set.std_dim.count loop
2350 if p_dim_set.std_dim(i).limit_cube_composite is not null then
2351 g_stmt:='dfn '||p_dim_set.std_dim(i).limit_cube_composite||' composite <'||p_dim_set.std_dim(i).dim_name||'>';
2352 bsc_aw_dbms_aw.execute(g_stmt);
2353 l_lc_axis:=p_dim_set.std_dim(i).limit_cube_composite||'<'||p_dim_set.std_dim(i).dim_name||'>';
2354 else
2355 l_lc_axis:=p_dim_set.std_dim(i).dim_name;
2356 end if;
2357 g_stmt:='dfn '||p_dim_set.std_dim(i).limit_cube||' variable boolean <'||l_lc_axis||'>';
2358 bsc_aw_dbms_aw.execute(g_stmt);
2359 end loop;
2360 --limit cube for time dim
2361 if p_dim_set.calendar.limit_cube_composite is not null then
2362 g_stmt:='dfn '||p_dim_set.calendar.limit_cube_composite||' composite <'||p_dim_set.calendar.aw_dim||'>';
2363 bsc_aw_dbms_aw.execute(g_stmt);
2364 l_lc_axis:=p_dim_set.calendar.limit_cube_composite||'<'||p_dim_set.calendar.aw_dim||'>';
2365 else
2366 l_lc_axis:=p_dim_set.calendar.aw_dim;
2367 end if;
2368 g_stmt:='dfn '||p_dim_set.calendar.limit_cube||' variable boolean <'||l_lc_axis||'>';
2369 bsc_aw_dbms_aw.execute(g_stmt);
2370 if p_dim_set.calendar.aggregate_marker is not null then
2371 g_stmt:='dfn '||p_dim_set.calendar.aggregate_marker||' boolean';
2372 bsc_aw_dbms_aw.execute(g_stmt);
2373 end if;
2374 Exception when others then
2375 log_n('Exception in create_cube '||sqlerrm);
2376 raise;
2377 End;
2378
2379 procedure create_cube(
2380 p_kpi kpi_r,
2381 p_dim_set dim_set_r,
2382 p_cube cube_r) is
2383 Begin
2384 create_cube(p_kpi,p_dim_set,p_cube,p_cube.cube_axis);
2385 Exception when others then
2386 log_n('Exception in create_cube '||sqlerrm);
2387 raise;
2388 End;
2389
2390 procedure create_cube(p_kpi kpi_r,p_dim_set dim_set_r,p_cube cube_r,p_cube_axis axis_tb) is
2391 l_stmt varchar2(4000);
2392 l_dimensions dbms_sql.varchar2_table;
2393 Begin
2394 l_stmt:='dfn '||p_cube.cube_name||' '||p_cube.cube_datatype||'<';
2395 for i in 1..p_cube_axis.count loop
2396 l_stmt:=l_stmt||' '||p_cube_axis(i).axis_name;
2397 l_dimensions.delete;
2398 if p_cube_axis(i).axis_type='partition template' then
2399 l_dimensions:=get_partition_template_r(p_cube_axis(i).axis_name,p_dim_set).template_dimensions;
2400 elsif p_cube_axis(i).axis_type='composite' then
2401 l_dimensions:=get_composite_r(p_cube_axis(i).axis_name,p_dim_set).composite_dimensions;
2402 else --dimension
2403 null; --no action reqd
2404 end if;
2405 if l_dimensions.count>0 then
2406 l_stmt:=l_stmt||' <';
2407 for j in 1..l_dimensions.count loop
2408 l_stmt:=l_stmt||' '||l_dimensions(j);
2409 end loop;
2410 l_stmt:=l_stmt||' >';
2411 end if;
2412 end loop;
2413 l_stmt:=l_stmt||' >';
2414 if bsc_aw_utility.get_property(p_dim_set.property,'aggcount').property_value='Y' then
2415 l_stmt:=l_stmt||' WITH AGGCOUNT';
2416 end if;
2417 bsc_aw_dbms_aw.execute(l_stmt);
2418 Exception when others then
2419 log_n('Exception in create_cube '||sqlerrm);
2420 raise;
2421 End;
2422
2423 procedure create_measure_formula(
2424 p_kpi kpi_r,
2425 p_dim_set in out nocopy dim_set_r) is
2426 Begin
2427 for i in 1..p_dim_set.measure.count loop
2428 if p_dim_set.measure(i).aw_formula.formula_name is not null then
2429 g_stmt:='dfn '||p_dim_set.measure(i).aw_formula.formula_name||' formula '||p_dim_set.measure(i).aw_formula.formula_expression;
2430 bsc_aw_dbms_aw.execute(g_stmt);
2431 end if;
2432 end loop;
2433 Exception when others then
2434 log_n('Exception in create_measure_formula '||sqlerrm);
2435 raise;
2436 End;
2437
2438 /*
2439 aggregation is performed if
2440 1. dim.levels.count>1
2441 2. zero code=Y
2442 3. recursive=Y
2443 */
2444 procedure create_agg_map(
2445 p_kpi kpi_r,
2446 p_dim_set in out nocopy dim_set_r) is
2447 --
2448 l_flag boolean;
2449 Begin
2450 if p_dim_set.agg_map.agg_map is not null then
2451 p_dim_set.agg_map.property:='normal';
2452 p_dim_set.agg_map_notime.property:='notime';
2453 create_agg_map(p_dim_set,p_dim_set.agg_map);
2454 create_agg_map(p_dim_set,p_dim_set.agg_map_notime);
2455 ----agg maps for individual dims
2456 --we create agg map for each individual dim for use in on-line agg. we create it with opvar, argvar and measure dim
2457 --if the dimset has 4 cubes and we want to agg only 1, we will limit p_agg_map.measure_dim to just that cube
2458 for i in 1..p_dim_set.dim.count loop
2459 if p_dim_set.dim(i).agg_map.created='Y' then --create_composite has already set this flag
2460 g_commands.delete;
2461 bsc_aw_utility.add_g_commands(g_commands,'dfn '||p_dim_set.dim(i).agg_map.agg_map||' aggmap ');
2462 bsc_aw_utility.add_g_commands(g_commands,'relation '||p_dim_set.dim(i).relation_name||' OPERATOR '||
2463 p_dim_set.dim(i).agg_map.aggmap_operator.opvar||' ARGS '||p_dim_set.dim(i).agg_map.aggmap_operator.argvar);
2467 is set. for us, all dim are in composite. so no need to have this */
2464 bsc_aw_utility.add_g_commands(g_commands,'MEASUREDIM '||p_dim_set.dim(i).agg_map.aggmap_operator.measure_dim);
2465 bsc_aw_utility.exec_aggmap_commands(p_dim_set.dim(i).agg_map.agg_map,g_commands);
2466 /*had aggindex=no. from olap doc, if aggindex=no, then dim outside the composite are aggregated on the fly when natrigger property
2468 end if;
2469 end loop;
2470 /*create aggmap of calendar */
2471 g_commands.delete;
2472 bsc_aw_utility.add_g_commands(g_commands,'dfn '||p_dim_set.calendar.agg_map.agg_map||' aggmap ');
2473 bsc_aw_utility.add_g_commands(g_commands,'relation '||p_dim_set.calendar.relation_name||' OPERATOR '||
2474 p_dim_set.calendar.agg_map.aggmap_operator.opvar||' ARGS '||p_dim_set.calendar.agg_map.aggmap_operator.argvar);
2475 bsc_aw_utility.add_g_commands(g_commands,'MEASUREDIM '||p_dim_set.calendar.agg_map.aggmap_operator.measure_dim);
2476 bsc_aw_utility.exec_aggmap_commands(p_dim_set.calendar.agg_map.agg_map,g_commands);
2477 end if;
2478 Exception when others then
2479 log_n('Exception in create_agg_map '||sqlerrm);
2480 raise;
2481 End;
2482
2483 /*
2484 the operators for agg maps need not be specific to each aggmap. say aggmap, aggmap_notime
2485 and dim agg maps.
2486 aggmap and aggmap_notime have diff measures. the operator dim will contain all measures
2487 so before firing an aggmap, we must limit the measuredim
2488 tested to make sure that we can have measurename and measuredim that holds the cube name in opvar.
2489 */
2490 procedure create_aggmap_operators(p_kpi kpi_r,p_dim_set dim_set_r) is
2491 l_cube_set cube_set_r;
2492 l_pt_comp_type varchar2(100);
2493 l_pt_comp varchar2(100);
2494 l_partition_template partition_template_r;
2495 Begin
2496 --measure_dim created in create_measure_dim
2497 --opvar makes sense only for std agg. for formulas, it makes no sense. but we just have it here
2498 if p_dim_set.aggmap_operator.opvar is not null then
2499 g_stmt:='dfn '||p_dim_set.aggmap_operator.opvar||' TEXT<'||p_dim_set.measurename_dim||' '||p_dim_set.aggmap_operator.measure_dim||'>';
2500 bsc_aw_dbms_aw.execute(g_stmt);
2501 for i in 1..p_dim_set.measure.count loop
2502 l_cube_set:=get_cube_set_r(p_dim_set.measure(i).cube,p_dim_set);
2503 g_stmt:=p_dim_set.aggmap_operator.opvar||'('||p_dim_set.measurename_dim||' '''||p_dim_set.measure(i).measure||''' '||
2504 p_dim_set.aggmap_operator.measure_dim||' '''||l_cube_set.cube.cube_name||
2505 ''')='''||replace(p_dim_set.measure(i).agg_formula.agg_formula,'''','\''')||'''';
2506 bsc_aw_dbms_aw.execute(g_stmt);
2507 /*we need to add the aggregation function for the partitions */
2508 l_pt_comp:=get_cube_pt_comp(l_cube_set.cube.cube_name,p_dim_set,l_pt_comp_type);
2509 if l_pt_comp_type='partition template' then
2510 l_partition_template:=get_partition_template_r(l_pt_comp,p_dim_set);
2511 for j in 1..l_partition_template.template_partitions.count loop
2512 g_stmt:=p_dim_set.aggmap_operator.opvar||'('||p_dim_set.measurename_dim||' '''||p_dim_set.measure(i).measure||''' '||
2513 p_dim_set.aggmap_operator.measure_dim||' '''||l_cube_set.cube.cube_name||' (PARTITION '||
2514 l_partition_template.template_partitions(j).partition_name||')'')='''||replace(p_dim_set.measure(i).agg_formula.agg_formula,'''','\''')||'''';
2515 bsc_aw_dbms_aw.execute(g_stmt);
2516 end loop;
2517 end if;
2518 if l_cube_set.display_cube.cube_name is not null then
2519 g_stmt:=p_dim_set.aggmap_operator.opvar||'('||p_dim_set.measurename_dim||' '''||p_dim_set.measure(i).measure||''' '||
2520 p_dim_set.aggmap_operator.measure_dim||' '''||l_cube_set.display_cube.cube_name||
2521 ''')='''||replace(p_dim_set.measure(i).agg_formula.agg_formula,'''','\''')||'''';
2522 bsc_aw_dbms_aw.execute(g_stmt);
2523 end if;
2524 end loop;
2525 end if;
2526 if p_dim_set.aggmap_operator.argvar is not null then
2527 g_stmt:='dfn '||p_dim_set.aggmap_operator.argvar||' TEXT<'||p_dim_set.measurename_dim||' '||p_dim_set.aggmap_operator.measure_dim||'>';
2528 bsc_aw_dbms_aw.execute(g_stmt);
2529 for i in 1..p_dim_set.measure.count loop
2530 l_cube_set:=get_cube_set_r(p_dim_set.measure(i).cube,p_dim_set);
2531 g_stmt:=p_dim_set.aggmap_operator.argvar||'('||p_dim_set.measurename_dim||' '''||p_dim_set.measure(i).measure||''' '||
2532 p_dim_set.aggmap_operator.measure_dim||' '''||l_cube_set.cube.cube_name||''')=NA';
2533 bsc_aw_dbms_aw.execute(g_stmt);
2534 if l_cube_set.display_cube.cube_name is not null then
2535 g_stmt:=p_dim_set.aggmap_operator.argvar||'('||p_dim_set.measurename_dim||' '''||p_dim_set.measure(i).measure||''' '||
2536 p_dim_set.aggmap_operator.measure_dim||' '''||l_cube_set.display_cube.cube_name||''')=NA';
2537 bsc_aw_dbms_aw.execute(g_stmt);
2538 end if;
2539 end loop;
2540 end if;
2541 Exception when others then
2542 log_n('Exception in create_aggmap_operators '||sqlerrm);
2543 raise;
2544 End;
2545
2546 /*
2547 if the aggmap is regular one, time is added
2548 if notime, no time relation is added
2549 */
2550 procedure create_agg_map(p_dim_set dim_set_r,p_agg_map in out nocopy agg_map_r) is
2551 --
2552 l_flag boolean;
2553 agg_formula varchar2(2000);
2554 Begin
2555 --create the agg map
2556 g_commands.delete;
2557 l_flag:=false;
2558 bsc_aw_utility.add_g_commands(g_commands,'dfn '||p_agg_map.agg_map||' aggmap ');
2559 if p_dim_set.compressed='Y' then /* 5236161*/
2560 for i in 1..p_dim_set.measure.count loop
2561 if bsc_aw_utility.is_std_aggregation_function(p_dim_set.measure(i).agg_formula.agg_formula)='Y' then
2562 agg_formula:=p_dim_set.measure(i).agg_formula.agg_formula;
2563 if agg_formula is not null then
2564 exit;
2565 end if;
2566 end if;
2567 end loop;
2568 if agg_formula is null then
2569 log('Could not get an agg formula with std aggregation for CC');
2573 --if regular aggmap, add time relation also
2570 raise bsc_aw_utility.g_exception;
2571 end if;
2572 end if;
2574 if p_agg_map.property='normal' then
2575 if is_calendar_aggregated(p_dim_set.calendar) then
2576 l_flag:=true;
2577 if p_dim_set.compressed='Y' then
2578 --cannot have opvar, argvar or measuredim. so we have restricted implementation. all measures must have the same agg
2579 --formula. if the agg formula is diff, create_PT_comp_names would have set compressed to N
2580 bsc_aw_utility.add_g_commands(g_commands,'relation '||p_dim_set.calendar.relation_name||' OPERATOR '||
2581 agg_formula);
2582 else
2583 bsc_aw_utility.add_g_commands(g_commands,'relation '||p_dim_set.calendar.relation_name||' OPERATOR '||
2584 p_agg_map.aggmap_operator.opvar||' ARGS '||p_agg_map.aggmap_operator.argvar);
2585 end if;
2586 end if;
2587 end if;
2588 for i in 1..p_dim_set.dim.count loop
2589 if p_dim_set.dim(i).agg_map.created='Y' then --create_composite has already set this flag
2590 l_flag:=true;
2591 if p_dim_set.compressed='Y' then
2592 bsc_aw_utility.add_g_commands(g_commands,'relation '||p_dim_set.dim(i).relation_name||' OPERATOR '||
2593 agg_formula);
2594 else
2595 bsc_aw_utility.add_g_commands(g_commands,'relation '||p_dim_set.dim(i).relation_name||' OPERATOR '||
2596 p_agg_map.aggmap_operator.opvar||' ARGS '||p_agg_map.aggmap_operator.argvar);
2597 end if;
2598 end if;
2599 end loop;
2600 if p_dim_set.compressed='Y' then
2601 null;
2602 else
2603 bsc_aw_utility.add_g_commands(g_commands,'MEASUREDIM '||p_agg_map.aggmap_operator.measure_dim);
2604 end if;
2605 if l_flag then
2606 p_agg_map.created:='Y';
2607 bsc_aw_utility.exec_aggmap_commands(p_agg_map.agg_map,g_commands);
2608 else
2609 p_agg_map.created:='N';
2610 end if;
2611 Exception when others then
2612 log_n('Exception in create_agg_map '||sqlerrm);
2613 raise;
2614 End;
2615
2616 procedure create_kpi_program(p_kpi in out nocopy kpi_r) is
2617 Begin
2618 for i in 1..p_kpi.dim_set.count loop
2619 create_kpi_program(p_kpi,p_kpi.dim_set(i),'initial');
2620 create_kpi_program(p_kpi,p_kpi.dim_set(i),'inc');
2621 create_aggregate_marker_pgm(p_kpi,p_kpi.dim_set(i));
2622 end loop;
2623 --if targets are implemented, create load programs for targets also
2624 for i in 1..p_kpi.target_dim_set.count loop
2625 if p_kpi.target_dim_set(i).dim_set is not null then
2626 create_kpi_program(p_kpi,p_kpi.target_dim_set(i),'initial');
2627 create_kpi_program(p_kpi,p_kpi.target_dim_set(i),'inc');
2628 end if;
2629 end loop;
2630 Exception when others then
2631 log_n('Exception in create_kpi_program 1 '||sqlerrm);
2632 raise;
2633 End;
2634
2635 /*
2636 only creates load program. no aggregation or forecast
2637 the program has a if findchars check for each data source each data source has base tables
2638 RSG will load base tables, not KPI. so we need to load only those data sources which have the
2639 base tables RSG has specified. also, the load may be for the kpi. so we do the check at each
2640 datasource witl ALL and the base table names
2641 arg(1) will be ALL or BSC_B_1,BSC_B_2, etc. we have a comma at the end and check with the comma to prevent
2642 BSC_B_1 being oked for BSC_B_10
2643 */
2644 procedure create_kpi_program(
2645 p_kpi kpi_r,
2646 p_dim_set in out nocopy dim_set_r,
2647 p_mode varchar2) is
2648 --
2649 l_pgm varchar2(300);
2650 l_stmt varchar2(4000);
2651 Begin
2652 g_commands.delete;
2653 if p_mode='initial' then
2654 set_program_property(p_dim_set.initial_load_program,p_dim_set.data_source);
2655 l_pgm:=p_dim_set.initial_load_program.program_name;
2656 bsc_aw_utility.add_g_commands(g_commands,'dfn '||l_pgm||' program');
2657 for i in 1..p_dim_set.data_source.count loop
2658 create_kpi_program(p_kpi,p_dim_set,p_dim_set.data_source(i));
2659 end loop;
2660 else
2661 set_program_property(p_dim_set.inc_load_program,p_dim_set.inc_data_source);
2662 l_pgm:=p_dim_set.inc_load_program.program_name;
2663 bsc_aw_utility.add_g_commands(g_commands,'dfn '||l_pgm||' program');
2664 for i in 1..p_dim_set.inc_data_source.count loop
2665 create_kpi_program(p_kpi,p_dim_set,p_dim_set.inc_data_source(i));
2666 end loop;
2667 end if;
2668 bsc_aw_utility.exec_program_commands(l_pgm,g_commands);
2669 Exception when others then
2670 log_n('Exception in create_kpi_program 2 '||sqlerrm);
2671 raise;
2672 End;
2673
2674 /*
2675 given a data source construct the program statements.
2676 this procesure creates the program that will load all measures at the same time. this is done for 9i and 10g.
2677 in 10g, we will also have a program that will load measures in diff sessions for parallelism
2678 this is created so that in case parallelism is disabled, we can launch this process to load all measures at the same
2679 time
2680 for 10g with partitions, we have programs that load on partition basis
2681 we now AND the base tables in a data source. these base tables are ordered according to name
2682 */
2683 procedure create_kpi_program(
2684 p_kpi kpi_r,
2685 p_dim_set dim_set_r,
2686 p_data_source data_source_r) is
2687 l_stmt varchar(4000);
2688 --
2689 l_cube_set cube_set_r;
2690 l_filter varchar2(2000);
2691 l_ordered_b_tables dbms_sql.varchar2_table;
2692 l_balance_loaded_column varchar2(40);
2693 Begin
2694 for i in 1..p_data_source.base_tables.count loop
2695 bsc_aw_utility.merge_value(l_ordered_b_tables,p_data_source.base_tables(i).base_table_name);
2696 end loop;
2697 l_ordered_b_tables:=bsc_aw_utility.order_array(l_ordered_b_tables);
2698 bsc_aw_utility.add_g_commands(g_commands,'if arg(1) EQ \'''||bsc_aw_utility.make_string_from_list(l_ordered_b_tables)||'\'' --');
2702 bsc_aw_utility.add_g_commands(g_commands,l_filter||' --');
2699 --see if there are any additional filter properties defined..used when partitions are involved
2700 l_filter:=bsc_aw_utility.get_property(p_data_source.property,'datasource filter').property_value;
2701 if l_filter is not null then
2703 end if;
2704 bsc_aw_utility.trim_g_commands(g_commands,3,null);
2705 bsc_aw_utility.add_g_commands(g_commands,'then do');
2706 /*temp variables period.temp and year.temp hold the period and year values. they are present in all cube loading programs. they are used when we
2707 have BALANCE LAST VALUE type measure */
2708 create_temp_variables(p_dim_set,p_data_source);
2709 bsc_aw_utility.add_g_commands(g_commands,'allstat');
2710 --if compressed composite, clear the aggregates. if < 10.2
2711 if p_dim_set.compressed='Y' and bsc_aw_utility.get_db_version<10.2 then
2712 bsc_aw_utility.init_is_new_value(1);
2713 for i in 1..p_data_source.measure.count loop
2714 if bsc_aw_utility.is_new_value(p_data_source.measure(i).cube,1) then
2715 bsc_aw_utility.add_g_commands(g_commands,'clear all aggregates from '||p_data_source.measure(i).cube);
2716 /*here we clear all aggregates from the cubes without looking at which measures are involved. if we load only 1
2717 B, we aggregate all measures. this is ok, since cost is not in the arthmetic, but in composite build
2718 */
2719 end if;
2720 end loop;
2721 end if;
2722 for i in 1..p_data_source.data_source_stmt.count loop
2723 bsc_aw_utility.add_g_commands(g_commands,p_data_source.data_source_stmt(i)||' --');
2724 end loop;
2725 bsc_aw_utility.trim_g_commands(g_commands,3,null);
2726 create_dim_match_header(p_data_source);
2727 /*
2728 if the dimset has partitions, data source stmt will have the partition key
2729 if the data source partition dim is not null, it means partitions are implemented in the dimset
2730 */
2731 if p_dim_set.number_partitions>0 and p_data_source.data_source_PT.partition_template.template_dim is not null then
2732 bsc_aw_utility.add_g_commands(g_commands,':match '||p_data_source.data_source_PT.partition_template.template_dim||' --');
2733 end if;
2734 --now the cubes
2735 --every dim has CC dim. we have this so that we can do zero code on any of them.
2736 for i in 1..p_data_source.measure.count loop
2737 l_stmt:=':'||p_data_source.measure(i).cube||'(';
2738 l_cube_set:=get_cube_set_r(p_data_source.measure(i).cube,p_dim_set);
2739 if l_cube_set.cube_set_type='datacube' then --specify the measure name
2740 l_stmt:=l_stmt||l_cube_set.measurename_dim||' \'''||p_data_source.measure(i).measure||'\'' ';
2741 end if;
2742 --time will always be concat
2743 --we dont need to have std dim since they do not have concat dim
2744 --dim. we also need to filter out dim which are standalone and not concat
2745 --note: std dim are automatically filtered since they are not concat
2746 for j in 1..p_data_source.dim.count loop
2747 if p_data_source.dim(j).concat='Y' then
2748 l_stmt:=l_stmt||p_data_source.dim(j).dim_name||' '||p_data_source.dim(j).levels(1).level_name||' ';
2749 end if;
2750 end loop;
2751 --time
2752 l_stmt:=l_stmt||p_data_source.calendar.aw_dim||' '||p_data_source.calendar.periodicity(1).aw_dim||' ';
2753 l_stmt:=l_stmt||') --';
2754 bsc_aw_utility.add_g_commands(g_commands,l_stmt);
2755 end loop;
2756 for i in 1..p_data_source.measure.count loop
2757 if p_data_source.measure(i).measure_type=g_balance_last_value_prop then
2758 /*if this is a BALANCE LAST VALUE column, also grab the loaded Y/N column */
2759 l_balance_loaded_column:=bsc_aw_utility.get_property(p_data_source.measure(i).property,g_balance_loaded_column_prop).property_value;
2760 if l_balance_loaded_column is not null then
2761 bsc_aw_utility.add_g_commands(g_commands,':'||l_balance_loaded_column||' --');
2762 end if;
2763 end if;
2764 end loop;
2765 --markers...limit cubes
2766 create_limit_cube_tail(p_data_source);
2767 /*have a then stmt. if there are balance measures, we need the then */
2768 bsc_aw_utility.add_g_commands(g_commands,'then --');
2769 bsc_aw_utility.add_g_commands(g_commands,'temp_number=NA --');
2770 --if there is balance, add the balance aggregation statements
2771 create_balance_aggregation(p_dim_set,p_data_source,p_data_source.measure);
2772 --
2773 bsc_aw_utility.trim_g_commands(g_commands,3,null);
2774 bsc_aw_utility.add_g_commands(g_commands,'sql close c1');
2775 bsc_aw_utility.add_g_commands(g_commands,'sql cleanup');
2776 bsc_aw_utility.add_g_commands(g_commands,'doend');
2777 Exception when others then
2778 log_n('Exception in create_kpi_program 3 ,dimset='||p_dim_set.dim_set_name||' '||sqlerrm);
2779 raise;
2780 End;
2781
2782 procedure create_balance_aggregation(p_dim_set dim_set_r, p_data_source data_source_r,p_measures measure_tb) is
2783 l_upper_periodicity dbms_sql.varchar2_table;
2784 l_cube_copy_stmt dbms_sql.varchar2_table;
2785 l_limit_cube_copy_stmt dbms_sql.varchar2_table;
2786 l_stmt varchar2(8000);
2787 l_cube_set cube_set_r;
2788 --
2789 l_balance_loaded_column varchar2(40);
2790 l_year_cube varchar2(80);
2791 l_period_cube varchar2(80);
2792 l_year_cube_stmt varchar2(2000);
2793 l_period_cube_stmt varchar2(2000);
2794 Begin
2795 for i in 1..p_data_source.calendar.parent_child.count loop
2796 if p_data_source.calendar.parent_child(i).parent_dim_name is not null
2797 and p_data_source.calendar.parent_child(i).parent_dim_name<>p_data_source.calendar.periodicity(1).aw_dim then
2798 bsc_aw_utility.merge_value(l_upper_periodicity,p_data_source.calendar.parent_child(i).parent_dim_name);
2799 end if;
2800 if p_data_source.calendar.parent_child(i).child_dim_name is not null
2801 and p_data_source.calendar.parent_child(i).child_dim_name<>p_data_source.calendar.periodicity(1).aw_dim then
2802 bsc_aw_utility.merge_value(l_upper_periodicity,p_data_source.calendar.parent_child(i).child_dim_name);
2803 end if;
2804 end loop;
2808 log(l_upper_periodicity(i));
2805 if g_debug then
2806 log('In create_balance_aggregation dimset '||p_dim_set.dim_set_name||', upper periodicities:-');
2807 for i in 1..l_upper_periodicity.count loop
2809 end loop;
2810 end if;
2811 for i in 1..p_measures.count loop
2812 if g_debug then
2813 log(p_measures(i).measure||' '||p_measures(i).measure_type);
2814 end if;
2815 if p_measures(i).measure_type=g_balance_end_period_prop or p_measures(i).measure_type=g_balance_last_value_prop then
2816 l_cube_set:=get_cube_set_r(p_measures(i).cube,p_dim_set);
2817 for j in 1..l_upper_periodicity.count loop
2818 l_cube_copy_stmt(j):=p_measures(i).cube||'(';
2819 if l_cube_set.cube_set_type='datacube' then --specify the measure name
2820 l_cube_copy_stmt(j):=l_cube_copy_stmt(j)||l_cube_set.measurename_dim||' \'''||p_measures(i).measure||'\'' ';
2821 end if;
2822 for k in 1..p_data_source.dim.count loop
2823 if p_data_source.dim(k).concat='Y' then
2824 l_cube_copy_stmt(j):=l_cube_copy_stmt(j)||p_data_source.dim(k).dim_name||' '||p_data_source.dim(k).levels(1).level_name||' ';
2825 end if;
2826 end loop;
2827 --time
2828 l_cube_copy_stmt(j):=l_cube_copy_stmt(j)||p_data_source.calendar.aw_dim||' '||p_data_source.calendar.denorm_relation_name||'('||
2829 p_data_source.calendar.aw_dim||' '||p_data_source.calendar.periodicity(1).aw_dim||' '||
2830 p_data_source.calendar.end_period_level_name_dim||' \'''||l_upper_periodicity(j)||'\''))=';
2831 l_cube_copy_stmt(j):=l_cube_copy_stmt(j)||p_measures(i).cube||'(';
2832 if l_cube_set.cube_set_type='datacube' then --specify the measure name
2833 l_cube_copy_stmt(j):=l_cube_copy_stmt(j)||l_cube_set.measurename_dim||' \'''||p_measures(i).measure||'\'' ';
2834 end if;
2835 for k in 1..p_data_source.dim.count loop
2836 if p_data_source.dim(k).concat='Y' then
2837 l_cube_copy_stmt(j):=l_cube_copy_stmt(j)||p_data_source.dim(k).dim_name||' '||p_data_source.dim(k).levels(1).level_name||' ';
2838 end if;
2839 end loop;
2840 --time
2841 l_cube_copy_stmt(j):=l_cube_copy_stmt(j)||p_data_source.calendar.aw_dim||' '||p_data_source.calendar.periodicity(1).aw_dim||') --';
2842 /*limit cube stmt */
2843 l_limit_cube_copy_stmt(j):=p_data_source.calendar.limit_cube||'('||p_data_source.calendar.aw_dim||' '||
2844 p_data_source.calendar.denorm_relation_name||'('||p_data_source.calendar.aw_dim||' '||p_data_source.calendar.periodicity(1).aw_dim||' '||
2845 p_data_source.calendar.end_period_level_name_dim||' \'''||l_upper_periodicity(j)||'\''))=TRUE --';
2846 end loop;
2847 end if;
2848 if p_measures(i).measure_type=g_balance_end_period_prop then --default end period balance
2849 /*must have rollup to all upper periodicities */
2850 for j in 1..l_upper_periodicity.count loop
2851 l_stmt:='if '||p_data_source.calendar.aw_dim||'('||p_data_source.calendar.aw_dim||' '||p_data_source.calendar.periodicity(1).aw_dim||') '||
2852 'EQ '||p_data_source.calendar.end_period_relation_name||'('||p_data_source.calendar.aw_dim||' '||
2853 p_data_source.calendar.denorm_relation_name||'('||p_data_source.calendar.aw_dim||' '||p_data_source.calendar.periodicity(1).aw_dim||' '||
2854 p_data_source.calendar.end_period_level_name_dim||' \'''||l_upper_periodicity(j)||'\'') '||
2855 p_data_source.calendar.end_period_level_name_dim||' \'''||p_data_source.calendar.periodicity(1).aw_dim||'\'') --';
2856 bsc_aw_utility.add_g_commands(g_commands,l_stmt);
2857 bsc_aw_utility.add_g_commands(g_commands,'then do --');
2858 bsc_aw_utility.add_g_commands(g_commands,l_cube_copy_stmt(j));
2859 /*set the limit cube of time also to true. this means we are simulating the time agg to come from the B table. this is important
2860 later for aggregation and target copy */
2861 bsc_aw_utility.add_g_commands(g_commands,l_limit_cube_copy_stmt(j));
2862 bsc_aw_utility.add_g_commands(g_commands,'doend --');
2863 end loop;
2864 elsif p_measures(i).measure_type=g_balance_last_value_prop then --last value balance
2865 l_balance_loaded_column:=bsc_aw_utility.get_property(p_measures(i).property,g_balance_loaded_column_prop).property_value;
2866 l_year_cube:=bsc_aw_utility.get_property(p_measures(i).property,'year cube').property_value;
2867 l_period_cube:=bsc_aw_utility.get_property(p_measures(i).property,'period cube').property_value;
2868 /*l_year_cube and l_period_cube cannot be null */
2869 if l_balance_loaded_column is not null then
2870 bsc_aw_utility.add_g_commands(g_commands,'if '||l_balance_loaded_column||' GT 0 --');
2871 bsc_aw_utility.add_g_commands(g_commands,'then do --');
2872 end if;
2873 for j in 1..l_upper_periodicity.count loop
2874 if l_cube_set.cube_set_type='datacube' then
2875 l_year_cube_stmt:=p_measures(i).cube||'('||l_cube_set.measurename_dim||' \'''||l_year_cube||'\'' ';
2876 l_period_cube_stmt:=p_measures(i).cube||'('||l_cube_set.measurename_dim||' \'''||l_period_cube||'\'' ';
2877 else
2878 l_year_cube_stmt:=l_year_cube||'(';
2879 l_period_cube_stmt:=l_period_cube||'(';
2880 end if;
2881 l_stmt:=null;
2882 for k in 1..p_data_source.dim.count loop
2883 if p_data_source.dim(k).concat='Y' then
2884 l_stmt:=l_stmt||p_data_source.dim(k).dim_name||' '||p_data_source.dim(k).levels(1).level_name||' ';
2885 end if;
2886 end loop;
2887 --time
2888 l_stmt:=l_stmt||p_data_source.calendar.aw_dim||' '||p_data_source.calendar.denorm_relation_name||'('||
2889 p_data_source.calendar.aw_dim||' '||p_data_source.calendar.periodicity(1).aw_dim||' '||
2890 p_data_source.calendar.end_period_level_name_dim||' \'''||l_upper_periodicity(j)||'\''))';
2891 l_year_cube_stmt:=l_year_cube_stmt||l_stmt;
2892 l_period_cube_stmt:=l_period_cube_stmt||l_stmt;
2893 bsc_aw_utility.add_g_commands(g_commands,'if '||l_year_cube_stmt||' EQ NA OR --');
2897 bsc_aw_utility.add_g_commands(g_commands,'then do --');
2894 bsc_aw_utility.add_g_commands(g_commands,g_year_temp||' GT '||l_year_cube_stmt||' OR --');
2895 bsc_aw_utility.add_g_commands(g_commands,'('||g_year_temp||' EQ '||l_year_cube_stmt||' AND --');
2896 bsc_aw_utility.add_g_commands(g_commands,g_period_temp||' GT '||l_period_cube_stmt||') --');
2898 bsc_aw_utility.add_g_commands(g_commands,l_cube_copy_stmt(j));
2899 bsc_aw_utility.add_g_commands(g_commands,l_limit_cube_copy_stmt(j));
2900 /*we must set the upper year and period values also */
2901 bsc_aw_utility.add_g_commands(g_commands,l_year_cube_stmt||'='||g_year_temp||' --');
2902 bsc_aw_utility.add_g_commands(g_commands,l_period_cube_stmt||'='||g_period_temp||' --');
2903 bsc_aw_utility.add_g_commands(g_commands,'doend --');
2904 end loop;
2905 if l_balance_loaded_column is not null then
2906 bsc_aw_utility.add_g_commands(g_commands,'doend --');
2907 end if;
2908 end if;
2909 end loop;
2910 Exception when others then
2911 log_n('Exception in create_balance_aggregation,dimset='||p_dim_set.dim_set_name||' '||sqlerrm);
2912 raise;
2913 End;
2914
2915 /*
2916 this procedure will create the :match header. we have this procesure in place because the following will need it.
2917 creation of generic load program for all measures
2918 creation of load program per measure (10g)
2919 creation of limit cube program (10g)
2920 we have this so we can avoid repeating the code
2921 */
2922 procedure create_dim_match_header(p_data_source data_source_r) is
2923 Begin
2924 bsc_aw_utility.add_g_commands(g_commands,'sql open c1');
2925 --even after arun changed the filter to be like (select code from dim_view), import does not work. this means
2926 --if there is filter, we have to have fetch loop...
2927 if bsc_aw_utility.get_property(p_data_source.property,'dimension filter').property_value='Y'
2928 or bsc_aw_utility.get_property(p_data_source.property,g_balance_last_value_prop).property_value='Y' then
2929 bsc_aw_utility.add_g_commands(g_commands,'sql fetch c1 loop into --');
2930 else
2931 bsc_aw_utility.add_g_commands(g_commands,'sql import c1 into --');
2932 end if;
2933 for i in 1..p_data_source.dim.count loop
2934 bsc_aw_utility.add_g_commands(g_commands,':match '||p_data_source.dim(i).levels(1).level_name||' --');
2935 end loop;
2936 --std dim
2937 for i in 1..p_data_source.std_dim.count loop
2938 bsc_aw_utility.add_g_commands(g_commands,':match '||p_data_source.std_dim(i).levels(1).level_name||' --');
2939 end loop;
2940 --time dim. data source will only have 1 periodicity, the periodicity of the base table
2941 bsc_aw_utility.add_g_commands(g_commands,':match '||p_data_source.calendar.periodicity(1).aw_dim||' --');
2942 if bsc_aw_utility.get_property(p_data_source.property,g_balance_last_value_prop).property_value='Y' then
2943 /*we need to place period and year values into the temp variables */
2944 bsc_aw_utility.add_g_commands(g_commands,':'||g_period_temp||' --');
2945 bsc_aw_utility.add_g_commands(g_commands,':'||g_year_temp||' --');
2946 end if;
2947 Exception when others then
2948 log_n('Exception in create_dim_match_header '||sqlerrm);
2949 raise;
2950 End;
2951
2952 /*
2953 creates the trailing :limit cube stmt. here in place to avoid duplicating code
2954 needed by generic program for all measures and the program for individual measures and limit cubes
2955 */
2956 procedure create_limit_cube_tail(p_data_source data_source_r) is
2957 Begin
2958 for i in 1..p_data_source.dim.count loop
2959 if p_data_source.dim(i).concat='Y' then
2960 bsc_aw_utility.add_g_commands(g_commands,':'||p_data_source.dim(i).limit_cube||'('||
2961 p_data_source.dim(i).dim_name||' '||p_data_source.dim(i).levels(1).level_name||') --');
2962 else
2963 bsc_aw_utility.add_g_commands(g_commands,':'||p_data_source.dim(i).limit_cube||' --');
2964 end if;
2965 end loop;
2966 --limit cubes for std dim...std dim are not concat
2967 for i in 1..p_data_source.std_dim.count loop
2968 bsc_aw_utility.add_g_commands(g_commands,':'||p_data_source.std_dim(i).limit_cube||' --');
2969 end loop;
2970 --we dont need to have std dim since they do not have concat dim
2971 --time dim
2972 bsc_aw_utility.add_g_commands(g_commands,':'||p_data_source.calendar.limit_cube||'('||
2973 p_data_source.calendar.aw_dim||' '||p_data_source.calendar.periodicity(1).aw_dim||') --');
2974 Exception when others then
2975 log_n('Exception in create_limit_cube_tail '||sqlerrm);
2976 raise;
2977 End;
2978
2979 /*
2980 this procedure creates the program that can load in parallel the dim limit cubes and the measures
2981 the program will look as
2982 --data source 1
2983 if findchars(MEASURE1) GT 0
2984 then do
2985 select dim1,dim2,measure1 from B1 where ...
2986 sql import into :match dim1 :match dim2 :cube1(..)
2987 doend
2988 if findchars(MEASURE2) GT 0
2989 then do
2990 select dim1,dim2,measure2 from B1 where ...
2991 sql import into :match dim1 :match dim2 :cube1(..)
2992 doend
2993 if findchars(LIMIT CUBE) GT 0
2994 then do
2995 select dim1,dim2,1,1,1.. from B1 where ...
2996 sql import into :match dim1 :match dim2 :limitcube1,limitcube2...(..)
2997 doend
2998 --data source 2
2999 if findchars(MEASURE1) GT 0
3000 then do
3001 select dim1,dim2,measure1 from B2 where ...
3002 sql import into :match dim1 :match dim2 :cube1(..)
3003 doend
3004 if findchars(LIMIT CUBE) GT 0
3005 then do
3006 select dim1,dim2,1,1,1.. from B2 where ...
3007 sql import into :match dim1 :match dim2 :limitcube1,limitcube2...(..)
3008 doend
3009 */
3010 procedure create_kpi_program_parallel(p_kpi in out nocopy kpi_r) is
3011 Begin
3012 for i in 1..p_kpi.dim_set.count loop
3013 if p_kpi.dim_set(i).number_partitions>0 then
3014 create_kpi_program_LB_resync(p_kpi,p_kpi.dim_set(i));
3018 create_kpi_program_cube(p_kpi,p_kpi.dim_set(i),'initial');
3015 create_kpi_program_partition(p_kpi,p_kpi.dim_set(i),'initial');
3016 create_kpi_program_partition(p_kpi,p_kpi.dim_set(i),'inc');
3017 else
3019 create_kpi_program_cube(p_kpi,p_kpi.dim_set(i),'inc');
3020 end if;
3021 end loop;
3022 --if targets are implemented, create load programs for targets also
3023 for i in 1..p_kpi.target_dim_set.count loop
3024 if p_kpi.target_dim_set(i).dim_set is not null then
3025 if p_kpi.target_dim_set(i).number_partitions>0 then
3026 create_kpi_program_LB_resync(p_kpi,p_kpi.target_dim_set(i));
3027 create_kpi_program_partition(p_kpi,p_kpi.target_dim_set(i),'initial');
3028 create_kpi_program_partition(p_kpi,p_kpi.target_dim_set(i),'inc');
3029 else
3030 create_kpi_program_cube(p_kpi,p_kpi.target_dim_set(i),'initial');
3031 create_kpi_program_cube(p_kpi,p_kpi.target_dim_set(i),'inc');
3032 end if;
3033 end if;
3034 end loop;
3035 Exception when others then
3036 log_n('Exception in create_kpi_program_parallel '||sqlerrm);
3037 raise;
3038 End;
3039
3040 /*
3041 this procedure creates the program that can load in parallel the dim limit cubes and the measures
3042 */
3043 procedure create_kpi_program_cube(
3044 p_kpi kpi_r,
3045 p_dim_set in out nocopy dim_set_r,
3046 p_mode varchar2) is
3047 --
3048 l_data_source data_source_tb;
3049 l_pgm varchar2(300);
3050 l_cube_measures measure_tb;
3051 l_cube_considered dbms_sql.varchar2_table;
3052 Begin
3053 g_commands.delete;
3054 if p_mode='initial' then
3055 set_program_property(p_dim_set.initial_load_program_parallel,p_dim_set.data_source);
3056 l_pgm:=p_dim_set.initial_load_program_parallel.program_name;
3057 l_data_source:=p_dim_set.data_source;
3058 else
3059 set_program_property(p_dim_set.inc_load_program_parallel,p_dim_set.inc_data_source);
3060 l_pgm:=p_dim_set.inc_load_program_parallel.program_name;
3061 l_data_source:=p_dim_set.inc_data_source;
3062 end if;
3063 bsc_aw_utility.add_g_commands(g_commands,'dfn '||l_pgm||' program');
3064 for i in 1..l_data_source.count loop
3065 l_cube_considered.delete;
3066 for j in 1..l_data_source(i).measure.count loop
3067 if bsc_aw_utility.in_array(l_cube_considered,l_data_source(i).measure(j).cube)=false then
3068 l_cube_considered(l_cube_considered.count+1):=l_data_source(i).measure(j).cube;
3069 end if;
3070 end loop;
3071 for j in 1..l_cube_considered.count loop
3072 l_cube_measures.delete;
3073 for k in 1..l_data_source(i).measure.count loop
3074 if l_data_source(i).measure(k).cube=l_cube_considered(j) then
3075 l_cube_measures(l_cube_measures.count+1):=l_data_source(i).measure(k);
3076 end if;
3077 end loop;
3078 create_kpi_program_cube(p_kpi,p_dim_set,get_cube_set_r(l_cube_considered(j),p_dim_set),l_cube_measures,l_data_source(i));
3079 end loop;
3080 --limit cubes
3081 create_kpi_program_limit_cube(p_kpi,p_dim_set,l_data_source(i));
3082 end loop;
3083 bsc_aw_utility.exec_program_commands(l_pgm,g_commands);
3084 Exception when others then
3085 log_n('Exception in create_kpi_program_cube 2 '||sqlerrm);
3086 raise;
3087 End;
3088
3089 /*
3090 this procedure adds to the program that loads measures in parallel. input is a measure and a data source. if the datasource
3091 has the measure, then create the program stmt
3092 */
3093 procedure create_kpi_program_cube(
3094 p_kpi kpi_r,
3095 p_dim_set dim_set_r,
3096 p_cube_set cube_set_r,
3097 p_measures measure_tb,
3098 p_data_source data_source_r) is
3099 --
3100 l_measure_index number;
3101 l_stmt varchar(4000);
3102 l_measures dbms_sql.varchar2_table;
3103 l_ordered_b_tables dbms_sql.varchar2_table;
3104 l_balance_loaded_column varchar2(40);
3105 Begin
3106 for i in 1..p_measures.count loop
3107 l_measures(i):=p_measures(i).measure;
3108 end loop;
3109 for i in 1..p_data_source.base_tables.count loop
3110 bsc_aw_utility.merge_value(l_ordered_b_tables,p_data_source.base_tables(i).base_table_name);
3111 end loop;
3112 l_ordered_b_tables:=bsc_aw_utility.order_array(l_ordered_b_tables);
3113 bsc_aw_utility.add_g_commands(g_commands,'if arg(1) EQ \'''||bsc_aw_utility.make_string_from_list(l_ordered_b_tables)||'\'' --');
3114 bsc_aw_utility.add_g_commands(g_commands,' AND arg(2) EQ \'''||upper(p_cube_set.cube.cube_name)||',\'' ');
3115 bsc_aw_utility.add_g_commands(g_commands,'then do');
3116 /*temp variables period.temp and year.temp hold the period and year values. they are present in all cube loading programs. they are used when we
3117 have BALANCE LAST VALUE type measure */
3118 create_temp_variables(p_dim_set,p_data_source);
3119 --if compressed composite, clear the aggregates. if < 10.2
3120 if p_dim_set.compressed='Y' and bsc_aw_utility.get_db_version<10.2 then
3121 bsc_aw_utility.add_g_commands(g_commands,'clear all aggregates from '||p_cube_set.cube.cube_name);
3122 end if;
3123 --we do not have limit cubes. only the sql, dim and the measure we are looking at
3124 for i in 1..p_data_source.data_source_stmt.count loop
3125 if substr(p_data_source.data_source_stmt_type(i),1,3)='sql' or substr(p_data_source.data_source_stmt_type(i),1,10)='dimension=' or
3126 substr(p_data_source.data_source_stmt_type(i),1,10)='temp time=' then
3127 if p_data_source.data_source_stmt_type(i)='sql from' then
3128 if substr(bsc_aw_utility.get_g_commands(g_commands,null),-4)=', --' then
3129 bsc_aw_utility.trim_g_commands(g_commands,4,' --'); --remove the trailing ,
3130 end if;
3131 end if;
3132 bsc_aw_utility.add_g_commands(g_commands,p_data_source.data_source_stmt(i)||' --');
3133 elsif substr(p_data_source.data_source_stmt_type(i),1,8)='measure=' then
3134 if bsc_aw_utility.in_array(l_measures,substr(p_data_source.data_source_stmt_type(i),9,length(p_data_source.data_source_stmt_type(i)))) then
3138 if bsc_aw_utility.in_array(l_measures,substr(p_data_source.data_source_stmt_type(i),28,length(p_data_source.data_source_stmt_type(i)))) then
3135 bsc_aw_utility.add_g_commands(g_commands,p_data_source.data_source_stmt(i)||' --');
3136 end if;
3137 elsif substr(p_data_source.data_source_stmt_type(i),1,27)='temp balance loaded column=' then /*temp balance loaded column=measure name */
3139 bsc_aw_utility.add_g_commands(g_commands,p_data_source.data_source_stmt(i)||' --');
3140 end if;
3141 end if;
3142 end loop;
3143 bsc_aw_utility.trim_g_commands(g_commands,3,null);
3144 create_dim_match_header(p_data_source);
3145 --now the cube for the measures
3146 for i in 1..p_measures.count loop
3147 l_stmt:=':'||p_cube_set.cube.cube_name||'('; --time will always be concat
3148 if p_cube_set.cube_set_type='datacube' then
3149 l_stmt:=l_stmt||p_cube_set.measurename_dim||' \'''||p_measures(i).measure||'\'' ';
3150 end if;
3151 for j in 1..p_data_source.dim.count loop
3152 if p_data_source.dim(j).concat='Y' then
3153 l_stmt:=l_stmt||p_data_source.dim(j).dim_name||' '||p_data_source.dim(j).levels(1).level_name||' ';
3154 end if;
3155 end loop;
3156 --time
3157 l_stmt:=l_stmt||p_data_source.calendar.aw_dim||' '||p_data_source.calendar.periodicity(1).aw_dim||' ';
3158 l_stmt:=l_stmt||') --';
3159 bsc_aw_utility.add_g_commands(g_commands,l_stmt);
3160 end loop;
3161 for i in 1..p_measures.count loop
3162 if p_measures(i).measure_type=g_balance_last_value_prop then
3163 /*if this is a BALANCE LAST VALUE column, also grab the loaded Y/N column */
3164 l_balance_loaded_column:=bsc_aw_utility.get_property(p_measures(i).property,g_balance_loaded_column_prop).property_value;
3165 if l_balance_loaded_column is not null then
3166 bsc_aw_utility.add_g_commands(g_commands,':'||l_balance_loaded_column||' --');
3167 end if;
3168 end if;
3169 end loop;
3170 /*have a then stmt. if there are balance measures, we need the then */
3171 bsc_aw_utility.add_g_commands(g_commands,'then --');
3172 bsc_aw_utility.add_g_commands(g_commands,'temp_number=NA --');
3173 --if there is balance, add the balance aggregation statements
3174 create_balance_aggregation(p_dim_set,p_data_source,p_measures);
3175 --
3176 bsc_aw_utility.trim_g_commands(g_commands,3,null);
3177 bsc_aw_utility.add_g_commands(g_commands,'sql close c1');
3178 bsc_aw_utility.add_g_commands(g_commands,'sql cleanup');
3179 bsc_aw_utility.add_g_commands(g_commands,'doend');
3180 Exception when others then
3181 log_n('Exception in create_kpi_program_cube 3 '||sqlerrm);
3182 raise;
3183 End;
3184
3185 /*
3186 this program is reqd when we have partitions. the dim LB is the same across partition loads. we need to acquire lock with
3187 resync at the end on the LB. resync discards private data changes. so before getting the lock, we save the state to session
3188 variables, get the lock, then merge the status from session variables into LB and then save it back. so the program has a
3189 pre and post part
3190 */
3191 procedure create_kpi_program_LB_resync(
3192 p_kpi kpi_r,
3193 p_dim_set in out nocopy dim_set_r
3194 ) is
3195 --
3196 l_kpi varchar2(200);
3197 l_name varchar2(200);
3198 Begin
3199 l_kpi:=p_kpi.kpi;
3200 if p_dim_set.dim_set_type='target' then
3201 l_kpi:=l_kpi||'.tgt';
3202 end if;
3203 p_dim_set.LB_resync_program:='LB.resync.'||p_dim_set.dim_set||'.'||l_kpi;
3204 g_commands.delete;
3205 bsc_aw_utility.add_g_commands(g_commands,'dfn '||p_dim_set.LB_resync_program||' program');
3206 --all LB of the dimset
3207 bsc_aw_utility.add_g_commands(g_commands,'if arg(1) EQ \''PRE\'' ');
3208 bsc_aw_utility.add_g_commands(g_commands,'then do');
3209 for i in 1..p_dim_set.dim.count loop
3210 l_name:=p_dim_set.dim(i).limit_cube||'.S';
3211 bsc_aw_utility.add_g_commands(g_commands,'if exists(\'''||l_name||'\'') eq false');
3212 bsc_aw_utility.add_g_commands(g_commands,'then do');
3213 bsc_aw_utility.add_g_commands(g_commands,'dfn '||l_name||' boolean <'||p_dim_set.dim(i).dim_name||'> session');
3214 bsc_aw_utility.add_g_commands(g_commands,'doend');
3215 end loop;
3216 for i in 1..p_dim_set.std_dim.count loop
3217 l_name:=p_dim_set.std_dim(i).limit_cube||'.S';
3218 bsc_aw_utility.add_g_commands(g_commands,'if exists(\'''||l_name||'\'') eq false');
3219 bsc_aw_utility.add_g_commands(g_commands,'then do');
3220 bsc_aw_utility.add_g_commands(g_commands,'dfn '||l_name||' boolean <'||p_dim_set.std_dim(i).dim_name||'> session');
3221 bsc_aw_utility.add_g_commands(g_commands,'doend');
3222 end loop;
3223 l_name:=p_dim_set.calendar.limit_cube||'.S';
3224 bsc_aw_utility.add_g_commands(g_commands,'if exists(\'''||l_name||'\'') eq false');
3225 bsc_aw_utility.add_g_commands(g_commands,'then do');
3226 bsc_aw_utility.add_g_commands(g_commands,'dfn '||l_name||' boolean <'||p_dim_set.calendar.aw_dim||'> session');
3227 bsc_aw_utility.add_g_commands(g_commands,'doend');
3228 --
3229 for i in 1..p_dim_set.dim.count loop
3230 bsc_aw_utility.add_g_commands(g_commands,'push '||p_dim_set.dim(i).dim_name);
3231 bsc_aw_utility.add_g_commands(g_commands,'limit '||p_dim_set.dim(i).dim_name||' to '||p_dim_set.dim(i).limit_cube);
3232 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.dim(i).limit_cube||'.S=true');
3233 bsc_aw_utility.add_g_commands(g_commands,'pop '||p_dim_set.dim(i).dim_name);
3234 end loop;
3235 for i in 1..p_dim_set.std_dim.count loop
3236 bsc_aw_utility.add_g_commands(g_commands,'push '||p_dim_set.std_dim(i).dim_name);
3237 bsc_aw_utility.add_g_commands(g_commands,'limit '||p_dim_set.std_dim(i).dim_name||' to '||p_dim_set.std_dim(i).limit_cube);
3238 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.std_dim(i).limit_cube||'.S=true');
3239 bsc_aw_utility.add_g_commands(g_commands,'pop '||p_dim_set.std_dim(i).dim_name);
3240 end loop;
3241 bsc_aw_utility.add_g_commands(g_commands,'push '||p_dim_set.calendar.aw_dim);
3245 --
3242 bsc_aw_utility.add_g_commands(g_commands,'limit '||p_dim_set.calendar.aw_dim||' to '||p_dim_set.calendar.limit_cube);
3243 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.calendar.limit_cube||'.S=true');
3244 bsc_aw_utility.add_g_commands(g_commands,'pop '||p_dim_set.calendar.aw_dim);
3246 bsc_aw_utility.add_g_commands(g_commands,'doend');
3247 --
3248 bsc_aw_utility.add_g_commands(g_commands,'if arg(1) EQ \''POST\'' ');
3249 bsc_aw_utility.add_g_commands(g_commands,'then do');
3250 for i in 1..p_dim_set.dim.count loop
3251 bsc_aw_utility.add_g_commands(g_commands,'push '||p_dim_set.dim(i).dim_name);
3252 bsc_aw_utility.add_g_commands(g_commands,'limit '||p_dim_set.dim(i).dim_name||' to '||p_dim_set.dim(i).limit_cube||'.S');
3253 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.dim(i).limit_cube||'=true');
3254 bsc_aw_utility.add_g_commands(g_commands,'pop '||p_dim_set.dim(i).dim_name);
3255 end loop;
3256 for i in 1..p_dim_set.std_dim.count loop
3257 bsc_aw_utility.add_g_commands(g_commands,'push '||p_dim_set.std_dim(i).dim_name);
3258 bsc_aw_utility.add_g_commands(g_commands,'limit '||p_dim_set.std_dim(i).dim_name||' to '||p_dim_set.std_dim(i).limit_cube||'.S');
3259 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.std_dim(i).limit_cube||'=true');
3260 bsc_aw_utility.add_g_commands(g_commands,'pop '||p_dim_set.std_dim(i).dim_name);
3261 end loop;
3262 bsc_aw_utility.add_g_commands(g_commands,'push '||p_dim_set.calendar.aw_dim);
3263 bsc_aw_utility.add_g_commands(g_commands,'limit '||p_dim_set.calendar.aw_dim||' to '||p_dim_set.calendar.limit_cube||'.S');
3264 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.calendar.limit_cube||'=true');
3265 bsc_aw_utility.add_g_commands(g_commands,'pop '||p_dim_set.calendar.aw_dim);
3266 bsc_aw_utility.add_g_commands(g_commands,'doend');
3267 --
3268 bsc_aw_utility.exec_program_commands(p_dim_set.LB_resync_program,g_commands);
3269 Exception when others then
3270 log_n('Exception in create_kpi_program_LB_resync '||sqlerrm);
3271 raise;
3272 End;
3273
3274 procedure create_kpi_program_partition(
3275 p_kpi kpi_r,
3276 p_dim_set in out nocopy dim_set_r,
3277 p_mode varchar2) is
3278 --
3279 l_pgm varchar2(300);
3280 l_data_source data_source_tb;
3281 l_partition_template partition_template_r;
3282 l_pt_name varchar2(200);
3283 Begin
3284 g_commands.delete;
3285 if p_mode='initial' then
3286 set_program_property(p_dim_set.initial_load_program_parallel,p_dim_set.data_source);
3287 l_pgm:=p_dim_set.initial_load_program_parallel.program_name;
3288 l_data_source:=p_dim_set.data_source;
3289 else
3290 set_program_property(p_dim_set.inc_load_program_parallel,p_dim_set.inc_data_source);
3291 l_pgm:=p_dim_set.inc_load_program_parallel.program_name;
3292 l_data_source:=p_dim_set.inc_data_source;
3293 end if;
3294 bsc_aw_utility.add_g_commands(g_commands,'dfn '||l_pgm||' program');
3295 --
3296 for i in 1..l_data_source.count loop
3297 l_pt_name:=get_cube_axis(l_data_source(i).measure(1).cube,p_dim_set,'partition template');
3298 --note>>> all measures of a data source share a PT. a cube can have at most 1 PT
3299 l_partition_template:=get_partition_template_r(l_pt_name,p_dim_set);
3300 for j in 1..l_partition_template.template_partitions.count loop
3301 create_kpi_program_partition(p_kpi,l_partition_template.template_partitions(j),p_dim_set,l_data_source(i),j);
3302 end loop;
3303 end loop;
3304 bsc_aw_utility.exec_program_commands(l_pgm,g_commands);
3305 Exception when others then
3306 log_n('Exception in create_kpi_program_partition '||sqlerrm);
3307 raise;
3308 End;
3309
3310 /*
3311 we loop through the data source and fix the where clause to add the 'where partition_dim=partition_dim_value'
3312 */
3313 procedure create_kpi_program_partition(
3314 p_kpi kpi_r,
3315 template_partition partition_r,
3316 p_dim_set in out nocopy dim_set_r,
3317 p_data_source data_source_r,
3318 partition_index number --1,2,3,4 etc
3319 ) is
3320 --
3321 l_data_source data_source_r;
3322 i integer;
3323 l_partition_stmt varchar2(4000);
3324 l_partition_type varchar2(40);
3325 l_cubes dbms_sql.varchar2_table;
3326 l_property_value varchar2(4000);
3327 Begin
3328 l_data_source:=p_data_source;
3329 i:=1;
3330 loop
3331 if l_data_source.data_source_stmt_type(i)='partition dim list' then
3332 l_partition_type:='list';
3333 elsif l_data_source.data_source_stmt_type(i)='partition dim hash' then
3334 /*l_partition_stmt will look like
3335 dbms_utility.get_hash_value(RELEASE_CODE||'-'||COMPO_CODE||'-'||CITY_CODE||'-'||PER_CODE||'-'||TYPE||'-'||PROJECTION||'-'||
3336 period||'.'||year,0,4) hash_partition_dim,
3337 so we need to substr this to remove the hash_partition_dim, look for the last )
3338 */
3339 l_partition_stmt:=l_data_source.data_source_stmt(i);
3340 l_partition_stmt:=substr(l_partition_stmt,1,instr(l_partition_stmt,')',-1));
3341 l_partition_type:='hash';
3342 end if;
3343 if l_partition_type='hash' and l_data_source.data_source_stmt_type(i)='sql where' and l_data_source.data_source_stmt(i)=' where 1=1 ' then
3344 --we add partition filter to the DS stmt
3345 l_data_source.data_source_stmt(i):=l_data_source.data_source_stmt(i)||'and '||template_partition.partition_dim_value||'='||
3346 l_partition_stmt;
3347 end if;
3348 if l_partition_type='list' and l_data_source.data_source_stmt_type(i)='sql from table' and l_data_source.data_source_stmt(i)=' where 1=1 ' then
3349 --we add partition filter to the B table stmt
3350 if l_data_source.base_tables(1).table_partition.main_partition.partition_column_data_type='NUMBER' then
3351 l_data_source.data_source_stmt(i):=l_data_source.data_source_stmt(i)||'and '||
3352 l_data_source.base_tables(1).table_partition.main_partition.partitions(partition_index).partition_value||'='||
3353 l_data_source.base_tables(1).table_partition.main_partition.partition_column;
3354 else
3358 end if;
3355 l_data_source.data_source_stmt(i):=l_data_source.data_source_stmt(i)||'and '||
3356 '\'''||l_data_source.base_tables(1).table_partition.main_partition.partitions(partition_index).partition_value||'\''='||
3357 l_data_source.base_tables(1).table_partition.main_partition.partition_column;
3359 end if;
3360 i:=i+1;
3361 if i>l_data_source.data_source_stmt.count then
3362 exit;
3363 end if;
3364 end loop;
3365 --
3366 for i in 1..l_data_source.measure.count loop
3367 if bsc_aw_utility.in_array(l_cubes,l_data_source.measure(i).cube)=false then
3368 l_cubes(l_cubes.count+1):=l_data_source.measure(i).cube;
3369 end if;
3370 end loop;
3371 l_property_value:='AND (';
3372 for i in 1..l_cubes.count loop
3373 l_property_value:=l_property_value||'arg(2) EQ \'''||l_cubes(i)||',\'' OR ';
3374 end loop;
3375 l_property_value:=substr(l_property_value,1,length(l_property_value)-3);
3376 l_property_value:=l_property_value||') AND arg(3) EQ \''partition='||template_partition.partition_name||',\'' ';
3377 bsc_aw_utility.merge_property(l_data_source.property,'datasource filter',null,l_property_value);
3378 bsc_aw_utility.merge_property(l_data_source.property,'partition',null,template_partition.partition_name);
3379 --
3380 create_kpi_program(p_kpi,p_dim_set,l_data_source);
3381 Exception when others then
3382 log_n('Exception in create_kpi_program_partition '||sqlerrm);
3383 raise;
3384 End;
3385
3386 /*
3387 used to create the program where measures and limit cubes run in parallel
3388 */
3389 procedure create_kpi_program_limit_cube(
3390 p_kpi kpi_r,
3391 p_dim_set dim_set_r,
3392 p_data_source data_source_r) is
3393 l_ordered_b_tables dbms_sql.varchar2_table;
3394 Begin
3395 for i in 1..p_data_source.base_tables.count loop
3396 bsc_aw_utility.merge_value(l_ordered_b_tables,p_data_source.base_tables(i).base_table_name);
3397 end loop;
3398 l_ordered_b_tables:=bsc_aw_utility.order_array(l_ordered_b_tables);
3399 bsc_aw_utility.add_g_commands(g_commands,'if arg(1) EQ \'''||bsc_aw_utility.make_string_from_list(l_ordered_b_tables)||'\'' --');
3400 bsc_aw_utility.add_g_commands(g_commands,' AND arg(2) EQ \''LIMIT CUBE\'' ');
3401 bsc_aw_utility.add_g_commands(g_commands,'then do');
3402 create_temp_variables(p_dim_set,p_data_source);
3403 for i in 1..p_data_source.data_source_stmt.count loop
3404 if p_data_source.data_source_stmt_type(i)='sql from' then
3405 if substr(bsc_aw_utility.get_g_commands(g_commands,null),-4)=', --' then
3406 bsc_aw_utility.trim_g_commands(g_commands,4,' --'); --remove the trailing ,
3407 end if;
3408 end if;
3409 if substr(p_data_source.data_source_stmt_type(i),1,3)='sql' or
3410 substr(p_data_source.data_source_stmt_type(i),1,10)='dimension=' or
3411 substr(p_data_source.data_source_stmt_type(i),1,10)='temp time=' or
3412 substr(p_data_source.data_source_stmt_type(i),1,11)='limit cube=' then
3413 bsc_aw_utility.add_g_commands(g_commands,p_data_source.data_source_stmt(i)||' --');
3414 end if;
3415 end loop;
3416 bsc_aw_utility.trim_g_commands(g_commands,3,null);
3417 create_dim_match_header(p_data_source);
3418 create_limit_cube_tail(p_data_source);
3419 bsc_aw_utility.trim_g_commands(g_commands,3,null);
3420 bsc_aw_utility.add_g_commands(g_commands,'sql close c1');
3421 bsc_aw_utility.add_g_commands(g_commands,'sql cleanup');
3422 bsc_aw_utility.add_g_commands(g_commands,'doend');
3423 Exception when others then
3424 log_n('Exception in create_kpi_program_limit_cube '||sqlerrm);
3425 raise;
3426 End;
3427
3428 /*
3429 used in create_kpi_program to see if we need to use sql fetch c1 loop into or import
3430 import is faster but filter has hardcoded numbers that import does not allow.
3431 */
3432 function is_filter_in_data_source(
3433 p_data_source data_source_r
3434 )return varchar2 is
3435 Begin
3436 for i in 1..p_data_source.dim.count loop
3437 if p_data_source.dim(i).levels(1).filter.count > 0 then
3438 return 'Y';
3439 end if;
3440 end loop;
3441 return 'N';
3442 Exception when others then
3443 log_n('Exception in is_filter_in_data_source '||sqlerrm);
3444 raise;
3445 End;
3446
3447 function is_balance_last_value_in_DS(p_data_source data_source_r) return varchar2 is
3448 Begin
3449 for i in 1..p_data_source.measure.count loop
3450 if p_data_source.measure(i).measure_type=g_balance_last_value_prop then
3451 return 'Y';
3452 end if;
3453 end loop;
3454 return 'N';
3455 Exception when others then
3456 log_n('Exception in is_balance_last_value_in_DS '||sqlerrm);
3457 raise;
3458 End;
3459
3460 /*
3461 creates the S views. we dont create the SB views since they are never queried directly
3462 we do have SB cubes though
3463
3464 create kpi view and create type must be autonomous transactions. otherwise, they result in
3465 implicit commit
3466 */
3467 procedure create_kpi_view(p_kpi in out nocopy kpi_r) is
3468 PRAGMA AUTONOMOUS_TRANSACTION;
3469 Begin
3470 for i in 1..p_kpi.dim_set.count loop
3471 create_kpi_view(p_kpi,p_kpi.dim_set(i));
3472 end loop;
3473 Exception when others then
3474 log_n('Exception in create_kpi_view '||sqlerrm);
3475 raise;
3476 End;
3477
3478 procedure create_kpi_view(p_kpi kpi_r,p_dim_set in out nocopy dim_set_r) is
3479 PRAGMA AUTONOMOUS_TRANSACTION;
3480 Begin
3481 create_db_type(p_kpi,p_dim_set);
3482 --std S MV
3483 for i in 1..p_dim_set.s_view.count loop
3484 create_kpi_view(p_kpi,p_dim_set,p_dim_set.s_view(i),'mv');
3485 end loop;
3486 --
3487 --Zero code MV
3488 for i in 1..p_dim_set.z_s_view.count loop
3489 create_kpi_view(p_kpi,p_dim_set,p_dim_set.z_s_view(i),'zmv');
3490 end loop;
3491 Exception when others then
3495
3492 log_n('Exception in create_kpi_view '||sqlerrm);
3493 raise;
3494 End;
3496 /*s view dim have 1 level
3497 */
3498 procedure create_kpi_view(p_kpi kpi_r,p_dim_set dim_set_r,p_s_view s_view_r,p_type varchar2) is
3499 PRAGMA AUTONOMOUS_TRANSACTION;
3500 --
3501 l_dimensions dbms_sql.varchar2_table;
3502 l_outer_measures dbms_sql.varchar2_table;
3503 l_outer_measure_agg_types dbms_sql.varchar2_table;
3504 l_outer_measure_aggregations dbms_sql.varchar2_table;/*holds the agg formula */
3505 l_inner_measures dbms_sql.varchar2_table;
3506 l_inner_select_columns dbms_sql.varchar2_table;
3507 l_inner_select_column_types dbms_sql.varchar2_table;/*fk or measure */
3508 l_name varchar2(30);
3509 l_inner_stmt varchar2(32000);
3510 l_sql_agg_stmt varchar2(32000);
3511 sql_aggregation boolean;
3512 Begin
3513 sql_aggregation:=false;
3514 l_inner_stmt:=' from table (
3515 olap_table('''||bsc_aw_management.get_aw_workspace_name||' duration session'','''||p_s_view.type_table_name||''','''',
3516 ''';
3517 for i in 1..p_s_view.dim.count loop
3518 if p_s_view.dim(i).levels(1).level_type='normal' then
3519 if p_s_view.dim(i).base_value_cube is not null then
3520 --use get_hash to make sure we are within 30 chars
3521 l_name:='D_'||bsc_aw_utility.get_hash_value(p_s_view.dim(i).dim_name||'.'||p_s_view.dim(i).levels(1).level_name||'.'||i,
3522 100,1073741824);
3523 l_inner_stmt:=l_inner_stmt||' dimension '||l_name||' from '||p_s_view.dim(i).dim_name||bsc_aw_utility.g_newline;
3524 l_dimensions(l_dimensions.count+1):=l_name;
3525 l_inner_stmt:=l_inner_stmt||' with attribute '||p_s_view.dim(i).levels(1).fk||' from '||p_s_view.dim(i).base_value_cube||
3526 bsc_aw_utility.g_newline;
3527 l_inner_measures(l_inner_measures.count+1):=p_s_view.dim(i).levels(1).fk;
3528 l_inner_select_columns(l_inner_select_columns.count+1):=p_s_view.dim(i).levels(1).fk;
3529 l_inner_select_column_types(l_inner_select_column_types.count+1):='fk';
3530 else
3531 --if a rec dim, we must be referncing the parent level
3532 if p_s_view.dim(i).levels(1).rec_parent_level is not null then
3533 l_inner_stmt:=l_inner_stmt||' dimension '||p_s_view.dim(i).levels(1).fk||' from '||p_s_view.dim(i).levels(1).rec_parent_level||'
3534 ';
3535 /*elsif p_type='zmv' and p_s_view.dim(i).levels(1).zero_code_level is not null then
3536 l_inner_stmt:=l_inner_stmt||' dimension '||p_s_view.dim(i).levels(1).fk||' from '||p_s_view.dim(i).levels(1).zero_code_level||'
3537 ';
3538 cannot have this...the zero code mv must be based on regular levels. if we base it on zero code level
3539 how can we limit dim to any other value? zero code mv has 0 and other values.
3540 so we need to limit zero code levelto 0, limit dim to zero code level, then limit level to 0
3541 so when we query from the mv, we will see the level value as 0 and also see the measure value for "all"
3542 */
3543 else
3544 l_inner_stmt:=l_inner_stmt||' dimension '||p_s_view.dim(i).levels(1).fk||' from '||p_s_view.dim(i).levels(1).level_name||'
3545 ';
3546 end if;
3547 l_inner_measures(l_inner_measures.count+1):=p_s_view.dim(i).levels(1).fk;
3548 l_inner_select_columns(l_inner_select_columns.count+1):=p_s_view.dim(i).levels(1).fk;
3549 l_inner_select_column_types(l_inner_select_column_types.count+1):='fk';
3550 end if;
3551 end if;
3552 end loop;
3553 --std dim
3554 for i in 1..p_dim_set.std_dim.count loop
3555 l_inner_stmt:=l_inner_stmt||' dimension '||p_dim_set.std_dim(i).levels(1).fk||' from '||p_dim_set.std_dim(i).levels(1).level_name||'
3556 ';
3557 l_dimensions(l_dimensions.count+1):=p_dim_set.std_dim(i).levels(1).fk;
3558 l_inner_select_columns(l_inner_select_columns.count+1):=p_dim_set.std_dim(i).levels(1).fk;
3559 l_inner_select_column_types(l_inner_select_column_types.count+1):='fk';
3560 --assume std dim are non concat?
3561 end loop;
3562 --time
3563 --all s views have period and year and periodicity
3564 l_inner_stmt:=l_inner_stmt||' measure period from period_cal_'||p_kpi.calendar||'
3565 measure year from year_cal_'||p_kpi.calendar||'
3566 measure periodicity_id from periodicity_cal_'||p_kpi.calendar||'
3567 ';
3568 l_inner_measures(l_inner_measures.count+1):='period';
3569 l_inner_measures(l_inner_measures.count+1):='year';
3570 l_inner_measures(l_inner_measures.count+1):='periodicity_id';
3571 l_inner_select_columns(l_inner_select_columns.count+1):='period';
3572 l_inner_select_column_types(l_inner_select_column_types.count+1):='fk';
3573 l_inner_select_columns(l_inner_select_columns.count+1):='year';
3574 l_inner_select_column_types(l_inner_select_column_types.count+1):='fk';
3575 l_inner_select_columns(l_inner_select_columns.count+1):='periodicity_id';
3576 l_inner_select_column_types(l_inner_select_column_types.count+1):='fk';
3577 for i in 1..p_dim_set.measure.count loop
3578 l_outer_measures(l_outer_measures.count+1):=p_dim_set.measure(i).measure;
3579 l_outer_measure_aggregations(l_outer_measure_aggregations.count+1):=p_dim_set.measure(i).agg_formula.sql_agg_formula;
3580 if p_dim_set.measure(i).sql_aggregated='N' then
3581 l_outer_measure_agg_types(l_outer_measure_agg_types.count+1):='std';
3582 l_inner_stmt:=l_inner_stmt||' measure '||p_dim_set.measure(i).measure||' from ';
3583 if p_dim_set.measure(i).aw_formula.formula_name is not null then
3584 l_inner_stmt:=l_inner_stmt||p_dim_set.measure(i).aw_formula.formula_name;
3585 else
3586 l_inner_stmt:=l_inner_stmt||p_dim_set.measure(i).cube;
3587 end if;
3588 l_inner_stmt:=l_inner_stmt||'
3589 ';
3590 l_inner_measures(l_inner_measures.count+1):=p_dim_set.measure(i).measure;
3591 l_inner_select_columns(l_inner_select_columns.count+1):=p_dim_set.measure(i).measure;
3592 l_inner_select_column_types(l_inner_select_column_types.count+1):='measure';
3593 else
3594 sql_aggregation:=true;
3598 l_inner_stmt:=l_inner_stmt||'''))';
3595 l_outer_measure_agg_types(l_outer_measure_agg_types.count+1):='non std';
3596 end if;
3597 end loop;
3599 if bsc_aw_utility.get_db_version>10.1 and l_dimensions.count>0 and l_inner_measures.count>0 then
3600 l_inner_stmt:=l_inner_stmt||bsc_aw_utility.g_newline;
3601 l_inner_stmt:=l_inner_stmt||'model'||bsc_aw_utility.g_newline;
3602 l_inner_stmt:=l_inner_stmt||'UNIQUE SINGLE REFERENCE'||bsc_aw_utility.g_newline;
3603 l_inner_stmt:=l_inner_stmt||'dimension by('||bsc_aw_utility.g_newline;
3604 for i in 1..l_dimensions.count loop
3605 if i=1 then
3606 l_inner_stmt:=l_inner_stmt||l_dimensions(i)||bsc_aw_utility.g_newline;
3607 else
3608 l_inner_stmt:=l_inner_stmt||','||l_dimensions(i)||bsc_aw_utility.g_newline;
3609 end if;
3610 end loop;
3611 l_inner_stmt:=l_inner_stmt||')'||bsc_aw_utility.g_newline;
3612 l_inner_stmt:=l_inner_stmt||'measures('||bsc_aw_utility.g_newline;
3613 for i in 1..l_inner_measures.count loop
3614 if i=1 then
3615 l_inner_stmt:=l_inner_stmt||l_inner_measures(i)||bsc_aw_utility.g_newline;
3616 else
3617 l_inner_stmt:=l_inner_stmt||','||l_inner_measures(i)||bsc_aw_utility.g_newline;
3618 end if;
3619 end loop;
3620 l_inner_stmt:=l_inner_stmt||')'||bsc_aw_utility.g_newline;
3621 l_inner_stmt:=l_inner_stmt||'rules update sequential order()';
3622 end if;
3623 /*if there is sql agg for non std measures (when there are non std agg and partitions), we need to create the stmt as (AVGBUG is the formula)
3624 create or replace view testv as
3625 select PER_CODE,COUNTRY_CODE,TYPE,PROJECTION,period,year,periodicity_id,BUGLOG,BUGLOG/BUGOPEN AVGBUG
3626 from(
3627 select PER_CODE,COUNTRY_CODE,TYPE,PROJECTION,period,year,periodicity_id,sum(BUGLOG) BUGLOG,sum(BUGOPEN) BUGOPEN
3628 from
3629 (select PER_CODE,COUNTRY_CODE,TYPE,PROJECTION,period,year,periodicity_id,BUGLOG,BUGOPEN
3630 from table ( olap_table( ...
3631 ...
3632 rules update sequential order())
3633 group by PER_CODE,COUNTRY_CODE,TYPE,PROJECTION,period,year,periodicity_id)
3634 */
3635 g_stmt:='create or replace view '||p_s_view.s_view||' as select ';
3636 if sql_aggregation then
3637 for i in 1..l_inner_select_columns.count loop
3638 if l_inner_select_column_types(i)='fk' then
3639 g_stmt:=g_stmt||l_inner_select_columns(i)||',';
3640 end if;
3641 end loop;
3642 /*now the measures */
3643 for i in 1..l_outer_measures.count loop
3644 if l_outer_measure_agg_types(i)='std' then
3645 g_stmt:=g_stmt||l_outer_measures(i)||',';
3646 else/*non std */
3647 g_stmt:=g_stmt||'('||l_outer_measure_aggregations(i)||') '||l_outer_measures(i)||',';
3648 end if;
3649 end loop;
3650 /*now the second part */
3651 g_stmt:=substr(g_stmt,1,length(g_stmt)-1);
3652 g_stmt:=g_stmt||bsc_aw_utility.g_newline;
3653 g_stmt:=g_stmt||'from (select ';
3654 for i in 1..l_inner_select_columns.count loop
3655 if l_inner_select_column_types(i)='fk' then
3656 g_stmt:=g_stmt||l_inner_select_columns(i)||',';
3657 end if;
3658 end loop;
3659 for i in 1..l_outer_measures.count loop
3660 if l_outer_measure_agg_types(i)='std' then
3661 g_stmt:=g_stmt||l_outer_measure_aggregations(i)||'('||l_outer_measures(i)||') '||l_outer_measures(i)||',';
3662 end if;
3663 end loop;
3664 g_stmt:=substr(g_stmt,1,length(g_stmt)-1);
3665 g_stmt:=g_stmt||bsc_aw_utility.g_newline;
3666 g_stmt:=g_stmt||'from (select ';
3667 end if;
3668 for i in 1..l_inner_select_columns.count loop
3669 g_stmt:=g_stmt||l_inner_select_columns(i)||',';
3670 end loop;
3671 g_stmt:=substr(g_stmt,1,length(g_stmt)-1);
3672 g_stmt:=g_stmt||l_inner_stmt;
3673 if sql_aggregation then
3674 g_stmt:=g_stmt||')'||bsc_aw_utility.g_newline;
3675 g_stmt:=g_stmt||'group by ';
3676 for i in 1..l_inner_select_columns.count loop
3677 if l_inner_select_column_types(i)='fk' then
3678 g_stmt:=g_stmt||l_inner_select_columns(i)||',';
3679 end if;
3680 end loop;
3681 g_stmt:=substr(g_stmt,1,length(g_stmt)-1);
3682 g_stmt:=g_stmt||')';
3683 end if;
3684 bsc_aw_utility.execute_ddl(g_stmt);
3685 Exception when others then
3686 log_n('Exception in create_kpi_view '||sqlerrm);
3687 raise;
3688 End;
3689
3690 /*
3691 this procedure creates the database type and table of type so that we can build the olap table
3692 function on top of this
3693 we have to create a type for each s view since the column names have to match if we are going to go
3694 with the model of having 2 views , the second view doing to_number(), then we only need one type
3695 per dim set. for now, we create a type per s view
3696
3697 we can create one type object for all the views in a dims set,. this would mean that all upper levels
3698 of a dim also share the same data type. can we assume this?
3699 if City is varchar2 and State is number, then we have a problem. in our implementation, all dim are TEXT. so
3700 we can assume this.
3701 this will not work because if we have one type with col names FK_1, FK_2 etc, then the views created will also
3702 have these column names. this will not do. so each s view must have its own type
3703 */
3704 procedure create_db_type(p_kpi kpi_r,p_dim_set in out nocopy dim_set_r) is
3705 PRAGMA AUTONOMOUS_TRANSACTION;
3706 Begin
3707 for i in 1..p_dim_set.s_view.count loop
3708 create_db_type(p_kpi.kpi,p_dim_set,p_dim_set.s_view(i));
3709 end loop;
3710 for i in 1..p_dim_set.z_s_view.count loop
3711 create_db_type(p_kpi.kpi,p_dim_set,p_dim_set.z_s_view(i));
3712 end loop;
3713 Exception when others then
3714 log_n('Exception in create_db_type '||sqlerrm);
3715 raise;
3716 End;
3717
3718 procedure create_db_type(p_kpi varchar2,p_dim_set dim_set_r,p_s_view in out nocopy s_view_r) is
3719 PRAGMA AUTONOMOUS_TRANSACTION;
3723 p_s_view.type_name:='type_'||p_kpi||'_'||p_dim_set.dim_set||'_'||p_s_view.id;
3720 --
3721 l_name varchar2(30);
3722 Begin
3724 p_s_view.type_table_name:=p_s_view.type_name||'_tab';
3725 g_stmt:='drop type '||p_s_view.type_table_name;
3726 bsc_aw_utility.execute_ddl_ne(g_stmt);
3727 g_stmt:='drop type '||p_s_view.type_name;
3728 bsc_aw_utility.execute_ddl_ne(g_stmt);
3729 g_stmt:='create or replace type '||p_s_view.type_name||' as object (';
3730 for i in 1..p_s_view.dim.count loop
3731 if p_s_view.dim(i).levels(1).level_type='normal' then
3732 if p_s_view.dim(i).base_value_cube is not null then
3733 l_name:='D_'||bsc_aw_utility.get_hash_value(p_s_view.dim(i).dim_name||'.'||p_s_view.dim(i).levels(1).level_name||'.'||i,
3734 100,1073741824);
3735 g_stmt:=g_stmt||l_name||' varchar2(800),';
3736 end if;
3737 g_stmt:=g_stmt||p_s_view.dim(i).levels(1).fk||' '||p_s_view.dim(i).levels(1).data_type||',';
3738 end if;
3739 end loop;
3740 --std dim
3741 for j in 1..p_dim_set.std_dim.count loop
3742 g_stmt:=g_stmt||p_dim_set.std_dim(j).levels(1).fk||' '||p_dim_set.std_dim(j).levels(1).data_type||',';
3743 end loop;
3744 --time
3745 g_stmt:=g_stmt||'period number,year number,periodicity_id number,';
3746 for j in 1..p_dim_set.measure.count loop
3747 g_stmt:=g_stmt||p_dim_set.measure(j).measure||' '||p_dim_set.measure(j).data_type||',';
3748 end loop;
3749 g_stmt:=substr(g_stmt,1,length(g_stmt)-1)||')';
3750 bsc_aw_utility.execute_ddl(g_stmt);
3751 --create the table of type
3752 g_stmt:='create or replace type '||p_s_view.type_table_name||' as table of '||p_s_view.type_name;
3753 bsc_aw_utility.execute_ddl(g_stmt);
3754 Exception when others then
3755 log_n('Exception in create_db_type '||sqlerrm);
3756 raise;
3757 End;
3758
3759 /*
3760 dmp the kpi record and all its properties
3761 */
3762 procedure dmp_kpi(p_kpi kpi_r) is
3763 Begin
3764 log_n('KPI Dmp');
3765 log('---------------------------------');
3766 log('KPI '||p_kpi.kpi);
3767 log('Dim Sets');
3768 for i in 1..p_kpi.dim_set.count loop
3769 log(p_kpi.dim_set(i).dim_set);
3770 end loop;
3771 log('Calendar');
3772 log(p_kpi.calendar);
3773 log('KPI Dim Set Parameters =');
3774 for i in 1..p_kpi.dim_set.count loop
3775 dmp_dimset(p_kpi.dim_set(i));
3776 end loop;
3777 log('================================================');
3778 log('================================================');
3779 log('KPI Target Dim Set Parameters =');
3780 for i in 1..p_kpi.target_dim_set.count loop
3781 dmp_dimset(p_kpi.target_dim_set(i));
3782 end loop;
3783 Exception when others then
3784 log_n('Exception in dmp_kpi '||sqlerrm);
3785 raise;
3786 End;
3787
3788 procedure dmp_dimset(p_dim_set dim_set_r) is
3789 Begin
3790 if p_dim_set.dim_set is null then
3791 return;
3792 end if;
3793 log('----------------------------------------');
3794 log('Dmp Dim Set ='||p_dim_set.dim_set||', Dim Set Name ='||p_dim_set.dim_set_name);
3795 log('Dim Set Type='||p_dim_set.dim_set_type);
3796 log('Dim Set Aggmap Operators shared across Agg Maps');
3797 dmp_agg_map_operator(p_dim_set.aggmap_operator);
3798 dmp_agg_map(p_dim_set.agg_map);
3799 dmp_agg_map(p_dim_set.agg_map_notime);
3800 log('Initial Load Program='||p_dim_set.initial_load_program.program_name||', Inc Load Program='||p_dim_set.inc_load_program.program_name);
3801 dmp_calendar(p_dim_set.calendar);
3802 log('Dimensions =('||p_dim_set.dim.count||')');
3803 for i in 1..p_dim_set.dim.count loop
3804 dmp_dim(p_dim_set.dim(i));
3805 end loop;
3806 log('Std Dimensions =('||p_dim_set.std_dim.count||')');
3807 for i in 1..p_dim_set.std_dim.count loop
3808 dmp_dim(p_dim_set.std_dim(i));
3809 end loop;
3810 log('Targets at higher level? '||p_dim_set.targets_higher_levels);
3811 log('Measures =');
3812 for i in 1..p_dim_set.measure.count loop
3813 dmp_measure(p_dim_set.measure(i));
3814 end loop;
3815 log('Dimset Properties');
3816 log('Measurename Dim='||p_dim_set.measurename_dim);
3817 log('Partition Dim='||p_dim_set.partition_dim);
3818 log('Cube design='||p_dim_set.cube_design);
3819 log('Number partitions='||p_dim_set.number_partitions);
3820 log('Compressed='||p_dim_set.compressed);
3821 log('Partition Template');
3822 for i in 1..p_dim_set.partition_template.count loop
3823 dmp_partition_template(p_dim_set.partition_template(i));
3824 end loop;
3825 for i in 1..p_dim_set.composite.count loop
3826 dmp_composite(p_dim_set.composite(i));
3827 end loop;
3828 for i in 1..p_dim_set.cube_set.count loop
3829 dmp_cube_set(p_dim_set.cube_set(i));
3830 end loop;
3831 --
3832 log('Initial Data Source=');
3833 dmp_data_source(p_dim_set.data_source);
3834 log('Inc Data Source=');
3835 dmp_data_source(p_dim_set.inc_data_source);
3836 --
3837 log('S Views=');
3838 for i in 1..p_dim_set.s_view.count loop
3839 log('S View '||p_dim_set.s_view(i).s_view||', ID='||p_dim_set.s_view(i).id);
3840 log('S view levels ');
3841 for j in 1..p_dim_set.s_view(i).dim.count loop
3842 log('Dim '||p_dim_set.s_view(i).dim(j).dim_name);
3843 log('Levels');
3844 for k in 1..p_dim_set.s_view(i).dim(j).levels.count loop
3845 log(p_dim_set.s_view(i).dim(j).levels(k).level_name);
3846 end loop;
3847 end loop;
3848 end loop;
3849 --
3850 log('Z S Views=');
3851 for i in 1..p_dim_set.z_s_view.count loop
3852 log('S View '||p_dim_set.z_s_view(i).s_view||', ID='||p_dim_set.z_s_view(i).id);
3853 log('S view levels ');
3854 for j in 1..p_dim_set.z_s_view(i).dim.count loop
3855 log('Dim '||p_dim_set.z_s_view(i).dim(j).dim_name);
3856 log('Levels');
3857 for k in 1..p_dim_set.z_s_view(i).dim(j).levels.count loop
3861 end loop;
3858 log(p_dim_set.z_s_view(i).dim(j).levels(k).level_name);
3859 end loop;
3860 end loop;
3862 log('--------------------');
3863 Exception when others then
3864 log_n('Exception in dmp_dimset '||sqlerrm);
3865 raise;
3866 End;
3867
3868 procedure dmp_measure(p_measure measure_r) is
3869 Begin
3870 log(p_measure.measure||' type='||p_measure.measure_type||' data type='||p_measure.data_type);
3871 log('formula='||p_measure.formula||' agg formula='||p_measure.agg_formula.agg_formula||', std agg='||
3872 p_measure.agg_formula.std_aggregation);
3873 log('forecast='||p_measure.forecast||', forecast method='||p_measure.forecast_method);
3874 log('cube='||p_measure.cube||', countvar cube='||p_measure.countvar_cube||', fcst cube='||p_measure.fcst_cube);
3875 if p_measure.agg_formula.std_aggregation='N' then
3876 log('Agg formula cubes');
3877 for i in 1..p_measure.agg_formula.cubes.count loop
3878 log(p_measure.agg_formula.cubes(i));
3879 end loop;
3880 end if;
3881 Exception when others then
3882 log_n('Exception in dmp_measure '||sqlerrm);
3883 raise;
3884 End;
3885
3886 procedure dmp_agg_map(p_agg_map agg_map_r) is
3887 Begin
3888 log('Agg Map ='||p_agg_map.agg_map);
3889 log(' Property='||p_agg_map.property);
3890 dmp_agg_map_operator(p_agg_map.aggmap_operator);
3891 Exception when others then
3892 log_n('Exception in dmp_agg_map '||sqlerrm);
3893 raise;
3894 End;
3895
3896 procedure dmp_agg_map_operator(p_agg_map_operator aggmap_operator_r) is
3897 Begin
3898 log('Agg Map.Measure_dim='||p_agg_map_operator.measure_dim);
3899 log('Agg Map.Opvar='||p_agg_map_operator.opvar);
3900 log('Agg Map.Argvar='||p_agg_map_operator.argvar);
3901 Exception when others then
3902 log_n('Exception in dmp_agg_map_operator '||sqlerrm);
3903 raise;
3904 End;
3905
3906 procedure dmp_dim(p_dim dim_r) is
3907 Begin
3908 log('Dim '||p_dim.dim_name||' prop='||p_dim.property||' rec='||
3909 p_dim.recursive||' multi-level='||p_dim.multi_level||' zero code='||
3910 p_dim.zero_code||', concat='||p_dim.concat);
3911 log('limit cube='||p_dim.limit_cube||', limit cube composite='||p_dim.limit_cube_composite||
3912 ',reset cube='||p_dim.reset_cube||',aggregate marker='||p_dim.aggregate_marker||',agg map='||
3913 p_dim.agg_map.agg_map||', agg level='||p_dim.agg_level);
3914 log('Dim Levels =');
3915 for i in 1..p_dim.levels.count loop
3916 log(p_dim.levels(i).level_name||' type='||p_dim.levels(i).level_type||' pk='||
3917 p_dim.levels(i).pk||' fk='||p_dim.levels(i).fk||' data type='||
3918 p_dim.levels(i).data_type||' zero code='||p_dim.levels(i).zero_code||', zero code level='||p_dim.levels(i).zero_code_level||
3919 ', position='||p_dim.levels(i).position||',property='||p_dim.levels(i).property);
3920 log('filter=');
3921 for j in 1..p_dim.levels(i).filter.count loop
3922 log(p_dim.levels(i).filter(j));
3923 end loop;
3924 end loop;
3925 log('Dim Level Relations =');
3926 for i in 1..p_dim.parent_child.count loop
3927 log('Parent='||p_dim.parent_child(i).parent_level||', pk='||p_dim.parent_child(i).parent_pk||','||
3928 'Child='||p_dim.parent_child(i).child_level||',fk='||p_dim.parent_child(i).child_fk);
3929 end loop;
3930 Exception when others then
3931 log_n('Exception in dmp_dim '||sqlerrm);
3932 raise;
3933 End;
3934
3935 procedure dmp_data_source(p_data_source data_source_tb) is
3936 Begin
3937 for i in 1..p_data_source.count loop
3938 log('Data Source -> '||i);
3939 dmp_data_source(p_data_source(i));
3940 end loop;
3941 Exception when others then
3942 log_n('Exception in dmp_data_source '||sqlerrm);
3943 raise;
3944 End;
3945
3946 procedure dmp_data_source(p_data_source data_source_r) is
3947 Begin
3948 log('DS type='||p_data_source.ds_type);
3949 log('partition_dim='||p_data_source.data_source_PT.partition_template.template_dim);
3950 log('DS properties');
3951 for i in 1..p_data_source.property.count loop
3952 log(p_data_source.property(i).property_name||' '||p_data_source.property(i).property_type||' '||
3953 p_data_source.property(i).property_value);
3954 end loop;
3955 log('Data Source Dimensions=');
3956 for i in 1..p_data_source.dim.count loop
3957 dmp_dim(p_data_source.dim(i));
3958 end loop;
3959 log('Data Source Std dimensions=');
3960 for i in 1..p_data_source.std_dim.count loop
3961 dmp_dim(p_data_source.std_dim(i));
3962 end loop;
3963 dmp_calendar(p_data_source.calendar);
3964 log('Data Source Measures=');
3965 for i in 1..p_data_source.measure.count loop
3966 log(p_data_source.measure(i).measure||' cube='||p_data_source.measure(i).cube);
3967 end loop;
3968 log('Base Tables=');
3969 for i in 1..p_data_source.base_tables.count loop
3970 log(p_data_source.base_tables(i).base_table_name);
3971 log('Base Table periodicity >'||p_data_source.base_tables(i).periodicity.periodicity);
3972 log('Current period>'||p_data_source.base_tables(i).current_period);
3973 log('Base Table Levels');
3974 for j in 1..p_data_source.base_tables(i).levels.count loop
3975 log(p_data_source.base_tables(i).levels(j).level_name||', feed='||p_data_source.base_tables(i).feed_levels(j));
3976 end loop;
3977 dmp_table_partition(p_data_source.base_tables(i).table_partition);
3978 end loop;
3979 log('Data Source Stmt =');
3980 for i in 1..p_data_source.data_source_stmt.count loop
3981 log(p_data_source.data_source_stmt(i));
3982 end loop;
3983 Exception when others then
3984 log_n('Exception in dmp_data_source '||sqlerrm);
3985 raise;
3986 End;
3987
3988 procedure dmp_table_partition(p_partition bsc_aw_utility.object_partition_r) is
3989 Begin
3990 log('Table partitions');
3991 log('Main partition:-');
3992 dmp_partition_set(p_partition.main_partition);
3996 log_n('Exception in dmp_table_partition '||sqlerrm);
3993 log('Sub partition:-');
3994 dmp_partition_set(p_partition.sub_partition);
3995 Exception when others then
3997 raise;
3998 End;
3999
4000 procedure dmp_partition_set(p_partition_set bsc_aw_utility.partition_set_r) is
4001 Begin
4002 log('Partition set '||p_partition_set.set_name);
4003 if p_partition_set.set_name is not null then
4004 log('Partition type '||p_partition_set.partition_type);
4005 log('Partition Column '||p_partition_set.partition_column);
4006 log('Partition Column Data Type '||p_partition_set.partition_column_data_type);
4007 for i in 1..p_partition_set.partitions.count loop
4008 log('Partition Name '||p_partition_set.partitions(i).partition_name);
4009 log('Partition Value '||p_partition_set.partitions(i).partition_value);
4010 log('Partition Position '||p_partition_set.partitions(i).partition_position);
4011 end loop;
4012 end if;
4013 Exception when others then
4014 log_n('Exception in dmp_partition_set '||sqlerrm);
4015 raise;
4016 End;
4017
4018 procedure dmp_calendar(p_calendar calendar_r) is
4019 Begin
4020 log('Calendar '||p_calendar.calendar||' dim='||p_calendar.aw_dim||' relation='||
4021 p_calendar.relation_name||', denorm relation='||p_calendar.denorm_relation_name);
4022 log('Limit cube='||p_calendar.limit_cube||', Limit cube composite='||p_calendar.limit_cube_composite||
4023 ', aggregate marker='||p_calendar.aggregate_marker);
4024 log('Periodicities');
4025 for i in 1..p_calendar.periodicity.count loop
4026 log('Periodicity='||p_calendar.periodicity(i).periodicity||' dim='||p_calendar.periodicity(i).aw_dim||
4027 ', property='||p_calendar.periodicity(i).property||', lowest level='||p_calendar.periodicity(i).lowest_level||', missing level='||
4028 p_calendar.periodicity(i).missing_level);
4029 end loop;
4030 log('Periodicitie Relations');
4031 for i in 1..p_calendar.parent_child.count loop
4032 log('Parent='||p_calendar.parent_child(i).parent_dim_name||', Parent periodicity='||
4033 p_calendar.parent_child(i).parent||',Child='||p_calendar.parent_child(i).child_dim_name||',Child periodicity='||
4034 p_calendar.parent_child(i).child);
4035 end loop;
4036 Exception when others then
4037 log_n('Exception in dmp_calendar '||sqlerrm);
4038 raise;
4039 End;
4040
4041 procedure dmp_partition_template(p_partition_template partition_template_r) is
4042 Begin
4043 log('Partition Template:-');
4044 log('Template name='||p_partition_template.template_name);
4045 log('Template type='||p_partition_template.template_type);
4046 log('Template use='||p_partition_template.template_use);
4047 log('Template dim='||p_partition_template.template_dim);
4048 log('hpt data');
4049 dmp_hpt_data(p_partition_template.hpt_data);
4050 log('Template dimensions');
4051 for i in 1..p_partition_template.template_dimensions.count loop
4052 log(p_partition_template.template_dimensions(i));
4053 end loop;
4054 log('Partitions:-');
4055 for i in 1..p_partition_template.template_partitions.count loop
4056 dmp_partition(p_partition_template.template_partitions(i));
4057 end loop;
4058 Exception when others then
4059 log_n('Exception in dmp_partition_template '||sqlerrm);
4060 raise;
4061 End;
4062
4063 procedure dmp_partition(p_partition partition_r) is
4064 Begin
4065 log('Partition name='||p_partition.partition_name);
4066 log('Partition Dim Value='||p_partition.partition_dim_value);
4067 for i in 1..p_partition.partition_axis.count loop
4068 dmp_axis(p_partition.partition_axis(i));
4069 end loop;
4070 Exception when others then
4071 log_n('Exception in dmp_partition '||sqlerrm);
4072 raise;
4073 End;
4074
4075 procedure dmp_axis(p_axis axis_r) is
4076 Begin
4077 log('Axis name='||p_axis.axis_name||', Axis type='||p_axis.axis_type);
4078 Exception when others then
4079 log_n('Exception in dmp_axis '||sqlerrm);
4080 raise;
4081 End;
4082
4083 procedure dmp_composite(p_composite composite_r) is
4084 Begin
4085 log('Composite name='||p_composite.composite_name);
4086 log('Composite type='||p_composite.composite_type);
4087 log('Composite dimensions');
4088 for i in 1..p_composite.composite_dimensions.count loop
4089 log(p_composite.composite_dimensions(i));
4090 end loop;
4091 Exception when others then
4092 log_n('Exception in dmp_composite '||sqlerrm);
4093 raise;
4094 End;
4095
4096 procedure dmp_cube_set(p_cube_set cube_set_r) is
4097 Begin
4098 log('Cube set name='||p_cube_set.cube_set_name||', Cube set type='||p_cube_set.cube_set_type);
4099 log('Measurename Dim='||p_cube_set.measurename_dim);
4100 log('Cube:-');
4101 dmp_cube(p_cube_set.cube);
4102 log('Fcst Cube:-');
4103 dmp_cube(p_cube_set.fcst_cube);
4104 log('Countvar Cube:-');
4105 dmp_cube(p_cube_set.countvar_cube);
4106 Exception when others then
4107 log_n('Exception in dmp_cube_set '||sqlerrm);
4108 raise;
4109 End;
4110
4111 procedure dmp_cube(p_cube cube_r) is
4112 Begin
4113 log('Cube name='||p_cube.cube_name);
4114 log('Cube type='||p_cube.cube_type);
4115 log('Cube datatype='||p_cube.cube_datatype);
4116 for i in 1..p_cube.cube_axis.count loop
4117 dmp_axis(p_cube.cube_axis(i));
4118 end loop;
4119 Exception when others then
4120 log_n('Exception in dmp_cube '||sqlerrm);
4121 raise;
4122 End;
4123
4124 /*
4125 every kpi has the type and projection dim attached to it. this api adds these std dimensions
4126 to the kpi dimset
4127 */
4128 procedure get_dim_set_std_dims(
4129 p_kpi varchar2,
4130 p_dim_set in out nocopy dim_set_r) is
4131 --
4132 Begin
4133 p_dim_set.std_dim(1):=null;
4134 p_dim_set.std_dim(2):=null;
4135 get_dim_set_std_dim_type(p_kpi,p_dim_set.std_dim(1));
4139 raise;
4136 get_dim_set_std_dim_projection(p_kpi,p_dim_set.std_dim(2));
4137 Exception when others then
4138 log_n('Exception in get_dim_set_std_dims '||sqlerrm);
4140 End;
4141
4142 --adds TYPE dim to the dim of the dimset
4143 procedure get_dim_set_std_dim_type(
4144 p_kpi varchar2,
4145 p_dim in out nocopy dim_r) is
4146 --
4147 l_dim varchar2(300);
4148 Begin
4149 bsc_aw_md_api.get_dim_for_level('TYPE',l_dim);
4150 p_dim.dim_name:=l_dim;
4151 p_dim.zero_code:='N';
4152 p_dim.relation_name:=null;
4153 p_dim.property:='normal';
4154 p_dim.recursive:='N';
4155 p_dim.multi_level:='N';
4156 p_dim.zero_code:='N';
4157 p_dim.agg_level:=0;
4158 p_dim.levels(1).level_name:='TYPE';
4159 p_dim.levels(1).level_type:='normal';
4160 p_dim.levels(1).pk:='TYPE';
4161 p_dim.levels(1).fk:='TYPE';
4162 p_dim.levels(1).data_type:='varchar2(100)';
4163 p_dim.levels(1).zero_code:='N';
4164 p_dim.levels(1).position:=1;
4165 Exception when others then
4166 log_n('Exception in get_dim_set_std_dim_type '||sqlerrm);
4167 raise;
4168 End;
4169
4170 --adds TYPE dim to the dim of the dimset
4171 procedure get_dim_set_std_dim_projection(
4172 p_kpi varchar2,
4173 p_dim in out nocopy dim_r) is
4174 --
4175 l_dim varchar2(300);
4176 Begin
4177 bsc_aw_md_api.get_dim_for_level('PROJECTION',l_dim);
4178 p_dim.dim_name:=l_dim;
4179 p_dim.zero_code:='N';
4180 p_dim.relation_name:=null;
4181 p_dim.property:='normal';
4182 p_dim.recursive:='N';
4183 p_dim.multi_level:='N';
4184 p_dim.zero_code:='N';
4185 p_dim.agg_level:=0;
4186 p_dim.levels(1).level_name:='PROJECTION';
4187 p_dim.levels(1).level_type:='normal';
4188 p_dim.levels(1).pk:='PROJECTION';
4189 p_dim.levels(1).fk:='PROJECTION';
4190 p_dim.levels(1).data_type:='varchar2(100)';
4191 p_dim.levels(1).zero_code:='N';
4192 p_dim.levels(1).position:=1;
4193 Exception when others then
4194 log_n('Exception in get_dim_set_std_dim_projection '||sqlerrm);
4195 raise;
4196 End;
4197
4198 /*
4199 this procedure takes in an agg formula based on measures and then substitutes the cube names. once the cube names are in, we
4200 can simply execute the formula
4201
4202 note: this changes the agg formula. it substitutes the cube names in the place of measure names
4203
4204 the formula is ALL CAPS
4205 */
4206 procedure make_agg_formula(
4207 p_kpi in out nocopy kpi_r
4208 ) is
4209 Begin
4210 for i in 1..p_kpi.dim_set.count loop
4211 make_agg_formula(p_kpi.dim_set(i));
4212 --no need for targets since they have no agg
4213 end loop;
4214 Exception when others then
4215 log_n('Exception in make_agg_formula '||sqlerrm);
4216 raise;
4217 End;
4218
4219 procedure make_agg_formula(
4220 p_dim_set in out nocopy dim_set_r
4221 ) is
4222 Begin
4223 for i in 1..p_dim_set.measure.count loop
4224 if p_dim_set.measure(i).agg_formula.std_aggregation='N' then
4225 make_agg_formula(p_dim_set.measure(i),p_dim_set.measure,p_dim_set);
4226 end if;
4227 end loop;
4228 Exception when others then
4229 log_n('Exception in make_agg_formula '||sqlerrm);
4230 raise;
4231 End;
4232
4233 procedure make_agg_formula(
4234 p_measure in out nocopy measure_r,
4235 p_all_measures measure_tb,
4236 p_dim_set dim_set_r
4237 ) is
4238 --
4239 l_agg_formula varchar2(1000);
4240 l_start_array dbms_sql.number_table; --contains the start address of a measure in a formula
4241 l_cube varchar2(200);
4242 l_cube_set cube_set_r;
4243 Begin
4244 l_agg_formula:=p_measure.agg_formula.agg_formula;
4245 if g_debug then
4246 log_n('In make_agg_formula, old agg formula='||l_agg_formula);
4247 end if;
4248 --search for each measure and substitute it
4249 for i in 1..p_all_measures.count loop
4250 l_start_array.delete;
4251 if bsc_aw_utility.is_string_present(l_agg_formula,p_all_measures(i).measure,l_start_array) then
4252 if l_start_array.count>0 then
4253 l_cube_set:=get_cube_set_r(p_all_measures(i).cube,p_dim_set);
4254 if l_cube_set.cube_set_type='datacube' then
4255 l_cube:=p_all_measures(i).cube||'('||l_cube_set.measurename_dim||' '''||p_all_measures(i).measure||''')';
4256 else
4257 l_cube:=p_all_measures(i).cube;
4258 end if;
4259 --we leave the agg_formula.cubes as the original name of the cube
4260 bsc_aw_utility.merge_value(p_measure.agg_formula.cubes,p_all_measures(i).cube);
4261 bsc_aw_utility.merge_value(p_measure.agg_formula.measures,p_all_measures(i).measure);
4262 bsc_aw_utility.replace_string(l_agg_formula,p_all_measures(i).measure,l_cube,l_start_array);
4263 end if;
4264 end if;
4265 end loop;
4266 if g_debug then
4267 log('New agg formula='||l_agg_formula);
4268 log('--');
4269 end if;
4270 --now change the record to reflect the agg formula with the cube
4271 p_measure.agg_formula.agg_formula:=l_agg_formula;
4272 /*agg_formula.sql_agg_formula retains the original agg formula from metadata */
4273 Exception when others then
4274 log_n('Exception in make_agg_formula '||sqlerrm);
4275 raise;
4276 End;
4277
4278 /*
4279 this procedure decides what the agg level should be for each dim in the dim sets
4280 the first choise is adv sum profile. it gets complicated if targets at higher levels are involved.
4281 say adv sum profile is to state. if targets come to country level, then we have to aggregate to
4282 country. its too complicated to handle this on-line.
4283
4284 since we set the agg level at the creation time, when adv sum profile changes, we have to drop the
4285 cubes, recreate them and reload them,
4286 this is better for aw. sotherwise, when adv sum profile is dropped from 3 to 2, how do we reclaim space
4290 l_flag dbms_sql.varchar2_table;--to track if we do change the agg level in a target dim set
4287 from the cubes? it gets complicated
4288 */
4289 procedure set_dim_agg_level(p_kpi in out nocopy kpi_r) is
4291 Begin
4292 --
4293 for i in 1..p_kpi.dim_set.count loop
4294 init_agg_level(p_kpi.dim_set(i));
4295 end loop;
4296 for i in 1..p_kpi.target_dim_set.count loop
4297 init_agg_level(p_kpi.target_dim_set(i));
4298 end loop;
4299 --
4300 for i in 1..p_kpi.target_dim_set.count loop
4301 l_flag(i):='N';
4302 --for each dim, see if the first level > adv sum profile
4303 for j in 1..p_kpi.target_dim_set(i).dim.count loop
4304 if p_kpi.target_dim_set(i).dim(j).recursive='N' then
4305 if p_kpi.target_dim_set(i).dim(j).levels(1).position > p_kpi.target_dim_set(i).dim(j).agg_level then
4306 l_flag(i):='Y';
4307 p_kpi.target_dim_set(i).dim(j).agg_level:=p_kpi.target_dim_set(i).dim(j).levels(1).position;
4308 end if;
4309 end if;
4310 end loop;
4311 end loop;
4312 --also set the agg level for the corresponding actual dimset
4313 for i in 1..p_kpi.target_dim_set.count loop
4314 if l_flag(i)='Y' then
4315 --get the corresponding actual dimset
4316 for j in 1..p_kpi.dim_set.count loop
4317 if p_kpi.target_dim_set(i).base_dim_set=p_kpi.dim_set(j).dim_set_name then
4318 for k in 1..p_kpi.target_dim_set(i).dim.count loop
4319 for m in 1..p_kpi.dim_set(j).dim.count loop
4320 if p_kpi.target_dim_set(i).dim(k).dim_name=p_kpi.dim_set(j).dim(m).dim_name then
4321 if p_kpi.dim_set(j).dim(m).agg_level < p_kpi.target_dim_set(i).dim(k).agg_level then
4322 p_kpi.dim_set(j).dim(m).agg_level:=p_kpi.target_dim_set(i).dim(k).agg_level;
4323 end if;
4324 exit;
4325 end if;
4326 end loop;
4327 end loop;
4328 exit;
4329 end if;
4330 end loop;
4331 end if;
4332 end loop;
4333 for i in 1..p_kpi.dim_set.count loop
4334 set_dim_agg_level(p_kpi.dim_set(i));
4335 end loop;
4336 for i in 1..p_kpi.target_dim_set.count loop
4337 set_dim_agg_level(p_kpi.target_dim_set(i));
4338 end loop;
4339 Exception when others then
4340 log_n('Exception in set_dim_agg_level '||sqlerrm);
4341 raise;
4342 End;
4343
4344 /*level positions are read from bsc_olap_object. level positions are set when the dim metadata is created. so the lowest level for a kpi
4345 need not have level position of 1 */
4346 procedure set_dim_agg_level(p_dim_set in out nocopy dim_set_r) is
4347 Begin
4348 for i in 1..p_dim_set.dim.count loop
4349 set_dim_agg_level(p_dim_set.dim(i));
4350 end loop;
4351 Exception when others then
4352 log_n('Exception in set_dim_agg_level '||sqlerrm);
4353 raise;
4354 End;
4355
4356 procedure set_dim_agg_level(p_dim in out nocopy dim_r) is
4357 Begin
4358 for i in 1..p_dim.levels.count loop
4359 p_dim.levels(i).aggregated:='Y';
4360 p_dim.levels(i).zero_aggregated:=nvl(p_dim.levels(i).zero_code,'N');
4361 if p_dim.levels(i).position>p_dim.agg_level then
4362 p_dim.levels(i).aggregated:='N';
4363 p_dim.levels(i).zero_aggregated:='N';
4364 end if;
4365 end loop;
4366 Exception when others then
4367 log_n('Exception in set_dim_agg_level '||sqlerrm);
4368 raise;
4369 End;
4370
4371 /*set the aggregated flag for each periodicity */
4372 procedure set_calendar_agg_level(p_kpi in out nocopy kpi_r) is
4373 Begin
4374 for i in 1..p_kpi.dim_set.count loop
4375 set_calendar_agg_level(p_kpi.dim_set(i),p_kpi.target_dim_set(i));
4376 end loop;
4377 for i in 1..p_kpi.target_dim_set.count loop
4378 set_calendar_agg_level(p_kpi.target_dim_set(i));
4379 end loop;
4380 Exception when others then
4381 log_n('Exception in set_calendar_agg_level '||sqlerrm);
4382 raise;
4383 End;
4384
4385 /*by default, we will not aggregate on time, unless explicitly specified */
4386 procedure set_calendar_agg_level(p_dim_set in out nocopy dim_set_r) is
4387 aggregated boolean;
4388 Begin
4389 if bsc_aw_utility.get_parameter_value('AGGREGATE TIME')='Y' then
4390 aggregated:=true;
4391 else
4392 aggregated:=false;
4393 end if;
4394 for i in 1..p_dim_set.calendar.periodicity.count loop
4395 if p_dim_set.calendar.periodicity(i).lowest_level='Y' then
4396 p_dim_set.calendar.periodicity(i).aggregated:='Y';
4397 else
4398 if aggregated then
4399 p_dim_set.calendar.periodicity(i).aggregated:='Y';
4400 else
4401 p_dim_set.calendar.periodicity(i).aggregated:='N';
4402 end if;
4403 end if;
4404 end loop;
4405 Exception when others then
4406 log_n('Exception in set_calendar_agg_level '||sqlerrm);
4407 raise;
4408 End;
4409
4410 /*if there are targets, we need to make sure that the level at the target is aggregated. if target is at month, we cannot just agg to
4411 day level */
4412 procedure set_calendar_agg_level(p_dim_set in out nocopy dim_set_r,p_target_dim_set dim_set_r) is
4413 l_pc bsc_aw_utility.parent_child_tb;
4414 l_child_levels dbms_sql.varchar2_table;
4415 Begin
4416 set_calendar_agg_level(p_dim_set);
4417 if p_dim_set.targets_higher_levels='Y' then
4418 for i in 1..p_dim_set.calendar.parent_child.count loop
4419 if p_dim_set.calendar.parent_child(i).parent_dim_name is not null and p_dim_set.calendar.parent_child(i).child_dim_name is not null then
4420 l_pc(l_pc.count+1).parent:=p_dim_set.calendar.parent_child(i).parent_dim_name;
4421 l_pc(l_pc.count).child:=p_dim_set.calendar.parent_child(i).child_dim_name;
4422 end if;
4423 end loop;
4424 for i in 1..p_target_dim_set.calendar.periodicity.count loop
4425 if p_target_dim_set.calendar.periodicity(i).lowest_level='Y' then
4429 p_dim_set.calendar.periodicity(j).aggregated:='Y';
4426 /*set the actual per corresponding to targets as aggregated */
4427 for j in 1..p_dim_set.calendar.periodicity.count loop
4428 if p_dim_set.calendar.periodicity(j).aw_dim=p_target_dim_set.calendar.periodicity(i).aw_dim then
4430 if g_debug then
4431 log('Due to targets('||p_dim_set.dim_set_name||'), setting '||p_dim_set.calendar.periodicity(j).aw_dim||' aggregated flag to ''Y''');
4432 end if;
4433 --
4434 exit;
4435 end if;
4436 end loop;
4437 l_child_levels.delete;
4438 bsc_aw_utility.get_all_children(l_pc,p_target_dim_set.calendar.periodicity(i).aw_dim,l_child_levels);
4439 if l_child_levels.count>0 then
4440 for j in 1..p_dim_set.calendar.periodicity.count loop
4441 if bsc_aw_utility.in_array(l_child_levels,p_dim_set.calendar.periodicity(j).aw_dim) then
4442 p_dim_set.calendar.periodicity(j).aggregated:='Y';
4443 if g_debug then
4444 log('Due to targets('||p_dim_set.dim_set_name||'), setting '||p_dim_set.calendar.periodicity(j).aw_dim||' aggregated flag to ''Y''');
4445 end if;
4446 end if;
4447 end loop;
4448 end if;
4449 end if;
4450 end loop;
4451 end if;
4452 Exception when others then
4453 log_n('Exception in set_calendar_agg_level '||sqlerrm);
4454 raise;
4455 End;
4456
4457 procedure init_agg_level(p_dim_set in out nocopy dim_set_r) is
4458 --
4459 l_adv_sum_profile number;
4460 Begin
4461 l_adv_sum_profile:=bsc_aw_utility.get_adv_sum_profile;
4462 --init the agg level to adv sum profile first
4463 for i in 1..p_dim_set.dim.count loop
4464 if p_dim_set.dim(i).recursive='Y' then
4465 p_dim_set.dim(i).agg_level:=1000000; --hard coded. agg all levels for rec dim
4466 else
4467 p_dim_set.dim(i).agg_level:=l_adv_sum_profile;
4468 end if;
4469 end loop;
4470 for i in 1..p_dim_set.std_dim.count loop
4471 p_dim_set.std_dim(i).agg_level:=l_adv_sum_profile;
4472 end loop;
4473 Exception when others then
4474 log_n('Exception in init_agg_level '||sqlerrm);
4475 raise;
4476 End;
4477
4478 /*
4479 open: we have an issue where user can have missing levels for a kpi. they can have city and country. right now, in BSC, this is
4480 treated as independent dimensions.
4481 in aw, we will find out the missing levels. we will optimize to get the shortest path between the levels.
4482 then we will make sure that the agg level for this dim is set to the max of the levels specified for the kpi. so wven if
4483 agg level is 2, we will make it 3 since country is an independent level for the kpi
4484 in the s views, we will have both the city and country keys. we query the s view levels. so the MO api is going to come back with
4485 city and country. so we will end up with city and country levels and fk. also the read api must handle multiple level values being
4486 specified for the same dim.
4487
4488 when this procedure is called, targets are not yet in the picture. so we do not have to think about propagating
4489 the missing levels to targets
4490
4491 NOTE!!! get_dim_set_dims will return the missing levels. so we really do not need an api to create the missing levels.
4492 now, the issue will be this. say city and country are the levels. get_dim_set_dims returns city,state and country.
4493 if the adv sum profile is 2, then we only aggregate to state. when country is specified, we have to agg on the fly. in bsc, when
4494 city and country are specified, both are level 1.
4495
4496 Other issue : what about zero code? when city and country are specified, there is zero code for both. get_zero_code_levels will
4497 say there is zero code for both city and country.
4498 we now have zero code in dim at all levels.
4499 */
4500 procedure create_missing_dim_levels(p_kpi varchar2,p_dim_set in out nocopy dim_set_r) is
4501 Begin
4502 null;
4503 Exception when others then
4504 log_n('Exception in create_missing_dim_levels '||sqlerrm);
4505 raise;
4506 End;
4507
4508 /*
4509 user can specify city and country with no relation between each other. they become independent levels. so the cube must have
4510 city and country as the dim, not geog.
4511 we do this:
4512 lets say in a dim we see levels with diff MO dim groups. this means they are independent. say
4513 geog :
4514 city mo : 1
4515 state mo : 1
4516 country mo : 2
4517 region mo : 2
4518
4519 we group all levels associated with the lowest level into the geog dim.
4520 all others become independent levels.
4521
4522 This is not possible. this is because if we dim with the concat dim, then we cannot dim by any otger level
4523 we get this error
4524 ORA-33376: (DUPCLCHK03) BSC_AW!BSC_D_STATE_AW and BSC_AW!BSC_CCDIM_400_401_402 cannot both appear in a dimension list because they
4525 this means if there are more than 1 MO dim groups, we have to have all levels as snow flake.
4526 also we need to skip missing levels.
4527
4528 note>>> how will we ever support multiple references to the same dim in BSC?
4529 do we create diff copies of the dim?
4530 */
4531 procedure identify_standalone_levels(
4532 p_kpi varchar2,
4533 p_dim_set in out nocopy dim_set_r) is
4534 --
4535 l_distict_mo_dim_groups dbms_sql.varchar2_table;
4536 l_levels level_tb;
4537 l_levels_for_new_dim level_tb;
4538 l_dim_to_split dim_tb;
4539 l_dim_copy dim_tb;
4540 l_flag bsc_aw_utility.boolean_table;
4541 l_skip_flag varchar2(40);
4542 Begin
4543 --for each dim, get a list of distinct mo
4544 for i in 1..p_dim_set.dim.count loop
4545 l_flag(i):=false;
4546 l_distict_mo_dim_groups.delete;
4547 get_dim_mo_dim_groups(p_dim_set.dim(i),l_distict_mo_dim_groups);
4548 if l_distict_mo_dim_groups.count>1 then
4549 --we have to remove this dim from the dimset
4550 l_dim_to_split(l_dim_to_split.count+1):=p_dim_set.dim(i);
4551 l_flag(i):=true;
4552 if g_debug then
4553 log_n('identify_standalone_levels: Remove Dim '||p_dim_set.dim(i).dim_name||', replace with levels');
4554 end if;
4555 end if;
4556 end loop;
4557 if l_dim_to_split.count>0 then
4558 --remove the split dim from the dimset
4559 l_dim_copy:=p_dim_set.dim;
4560 p_dim_set.dim.delete;
4561 for i in 1..l_dim_copy.count loop
4562 if l_flag(i)=false then
4563 p_dim_set.dim(p_dim_set.dim.count+1):=l_dim_copy(i);
4564 end if;
4565 end loop;
4566 --now split the dim
4567 l_levels_for_new_dim.delete;
4568 for i in 1..l_dim_to_split.count loop
4569 for j in 1..l_dim_to_split(i).levels.count loop
4570 l_skip_flag:=bsc_aw_utility.get_parameter_value(l_dim_to_split(i).levels(j).property,'skip level',',');
4571 --ignore the levels to skip
4572 if l_skip_flag='N' then
4573 l_levels_for_new_dim(l_levels_for_new_dim.count+1):=l_dim_to_split(i).levels(j);
4574 end if;
4575 end loop;
4576 end loop;
4577 end if;
4578 if g_debug then
4579 if l_levels_for_new_dim.count>0 then
4580 log_n('identify_standalone_levels : Create new dim for these levels');
4581 for i in 1..l_levels_for_new_dim.count loop
4582 log(l_levels_for_new_dim(i).level_name);
4583 end loop;
4584 end if;
4585 end if;
4586 --create the new dim
4587 --dim with name=level name are seeded in bsc olap metadata. this is the snowflake implementation.
4588 --this metadata is created when the dim is created
4589 if l_levels_for_new_dim.count>0 then
4590 for i in 1..l_levels_for_new_dim.count loop
4591 p_dim_set.dim(p_dim_set.dim.count+1).dim_name:=l_levels_for_new_dim(i).level_name;
4592 p_dim_set.dim(p_dim_set.dim.count).levels(p_dim_set.dim(p_dim_set.dim.count).levels.count+1):=l_levels_for_new_dim(i);
4593 end loop;
4594 end if;
4595 --
4596 Exception when others then
4597 log_n('Exception in identify_standalone_levels '||sqlerrm);
4598 raise;
4599 End;
4600
4601 --level mo dim group is held in level.property
4602 procedure get_dim_mo_dim_groups(
4603 p_dim dim_r,
4604 p_distict_mo_dim_groups out nocopy dbms_sql.varchar2_table) is
4605 --
4606 l_mo_dim_group varchar2(200);
4607 Begin
4608 for i in 1..p_dim.levels.count loop
4609 l_mo_dim_group:=bsc_aw_utility.get_parameter_value(p_dim.levels(i).property,'mo dim group',',');
4610 if bsc_aw_utility.in_array(p_distict_mo_dim_groups,l_mo_dim_group)=false then
4611 p_distict_mo_dim_groups(p_distict_mo_dim_groups.count+1):=l_mo_dim_group;
4612 end if;
4613 end loop;
4614 Exception when others then
4615 log_n('Exception in get_dim_mo_dim_groups '||sqlerrm);
4616 raise;
4617 End;
4618
4619 /*
4620 used to dmp cube data into a table.
4621 dmps all cubes of the dimset
4622 p_table_name is dropped and recreated
4623 p_dimset will be 0 or 1 etc
4624 */
4625 procedure create_dmp_program(
4626 p_kpi varchar2,
4627 p_dimset varchar2,
4628 p_dim_levels dbms_sql.varchar2_table,
4629 p_name varchar2,
4630 p_table_name varchar2) is
4631 --
4632 l_oo_object bsc_aw_md_wrapper.bsc_olap_object_tb;
4633 l_oo_relation bsc_aw_md_wrapper.bsc_olap_object_relation_tb;
4634 l_dimset varchar2(100);
4635 l_dim_level_dims dbms_sql.varchar2_table;
4636 l_measures dbms_sql.varchar2_table;
4637 l_cubes dbms_sql.varchar2_table;
4638 l_cube_formula dbms_sql.varchar2_table;
4639 l_cube_composites dbms_sql.varchar2_table;
4640 l_stmt varchar2(8000);
4641 l_calendar_id number;
4642 l_dim_levels dbms_sql.varchar2_table;
4643 l_axis_type varchar2(100);
4644 Begin
4645 l_dim_levels:=p_dim_levels;
4646 bsc_aw_md_api.get_kpi_dimset(p_kpi,l_oo_object);
4647 for i in 1..l_oo_object.count loop
4648 if bsc_aw_utility.get_parameter_value(l_oo_object(i).property1,'dim set',',')=p_dimset then
4649 if bsc_aw_utility.get_parameter_value(l_oo_object(i).property1,'dim set type',',')='actual' then
4650 l_dimset:=l_oo_object(i).object;
4651 exit;
4652 end if;
4653 end if;
4654 end loop;
4655 if l_dimset is not null then
4656 bsc_aw_md_api.get_bsc_olap_object_relation(null,null,null,p_kpi,'kpi',l_oo_relation);
4657 for i in 1..l_dim_levels.count loop
4658 l_dim_level_dims(i):=null;
4659 for j in 1..l_oo_relation.count loop
4660 if l_oo_relation(j).relation_object=l_dim_levels(i) and l_oo_relation(j).relation_type='dim set dim level' and
4661 instr(l_oo_relation(j).object,'+'||l_dimset)>0 and instr(l_oo_relation(j).object,'+'||l_dimset||'.')=0 then
4662 log(l_oo_relation(j).object);
4663 l_dim_level_dims(i):=substr(l_oo_relation(j).object,1,instr(l_oo_relation(j).object,'+')-1);
4664 exit;
4665 end if;
4666 end loop;
4667 --is this rec dim, then get the parent level
4668 l_oo_object.delete;
4669 bsc_aw_md_api.get_bsc_olap_object(l_dim_level_dims(i),'dimension',l_dim_level_dims(i),'dimension',l_oo_object);
4670 if bsc_aw_utility.get_parameter_value(l_oo_object(1).property1,'recursive',',')='Y' then
4671 l_oo_object.delete;
4672 bsc_aw_md_api.get_bsc_olap_object(null,'recursive level',l_dim_level_dims(i),'dimension',l_oo_object);
4673 l_dim_levels(i):=l_oo_object(1).object;--store the parent rec level
4674 end if;
4675 end loop;
4676 --calendar
4677 for i in 1..l_oo_relation.count loop
4678 if l_oo_relation(i).object=l_dimset and l_oo_relation(i).relation_type='dim set calendar' then
4679 l_calendar_id:=to_number(bsc_aw_utility.get_parameter_value(l_oo_relation(i).property1,'calendar',','));
4680 exit;
4681 end if;
4682 end loop;
4683 --get the measures and cubes
4684 for i in 1..l_oo_relation.count loop
4685 if l_oo_relation(i).object=l_dimset and l_oo_relation(i).relation_type='dim set measure' then
4686 l_measures(l_measures.count+1):=l_oo_relation(i).relation_object;
4687 l_cubes(l_cubes.count+1):=bsc_aw_utility.get_parameter_value(l_oo_relation(i).property1,'cube',',');
4688 l_cube_formula(l_cube_formula.count+1):=bsc_aw_utility.get_parameter_value(l_oo_relation(i).property1,'aw formula',',');
4689 for j in 1..l_oo_relation.count loop
4690 if l_oo_relation(j).object=l_cubes(l_cubes.count) and l_oo_relation(j).relation_type='cube axis' then
4691 l_axis_type:=bsc_aw_utility.get_parameter_value(l_oo_relation(j).property1,'axis type',',');
4692 if l_axis_type='partition template' or l_axis_type='composite' then
4693 l_cube_composites(l_cubes.count):=l_oo_relation(j).relation_object;
4694 exit;
4695 end if;
4696 end if;
4697 end loop;
4698 end if;
4699 end loop;
4700 --create the table first
4701 bsc_aw_utility.execute_ddl_ne('drop table '||p_table_name);
4702 l_stmt:='create table '||p_table_name||'(
4703 ';
4704 for i in 1..l_dim_levels.count loop
4705 l_stmt:=l_stmt||l_dim_levels(i)||' varchar2(300),
4706 ';
4707 end loop;
4708 for i in 1..l_measures.count loop
4709 l_stmt:=l_stmt||l_measures(i)||' number,
4710 ';
4711 end loop;
4712 l_stmt:=l_stmt||'period number,year number,periodicity_id number)';
4713 bsc_aw_utility.execute_ddl(l_stmt);
4714 --create the program
4715 g_commands.delete;
4716 bsc_aw_utility.add_g_commands(g_commands,'dfn '||p_name||' program');
4717 bsc_aw_utility.add_g_commands(g_commands,'sql prepare c1 from --');
4718 bsc_aw_utility.add_g_commands(g_commands,'insert into '||p_table_name||' values ( --');
4719 for i in 1..l_dim_levels.count loop
4720 if l_dim_level_dims(i) <> l_dim_levels(i) then
4721 bsc_aw_utility.add_g_commands(g_commands,':key('||l_dim_level_dims(i)||' '||l_dim_levels(i)||'), --');
4722 else
4723 bsc_aw_utility.add_g_commands(g_commands,':'||l_dim_levels(i)||', --');
4724 end if;
4725 end loop;
4726 for i in 1..l_measures.count loop
4727 if l_cube_formula(i) is not null then
4728 bsc_aw_utility.add_g_commands(g_commands,':'||l_cube_formula(i)||', --');
4729 else
4730 bsc_aw_utility.add_g_commands(g_commands,':'||l_cubes(i)||', --');
4731 end if;
4732 end loop;
4733 bsc_aw_utility.add_g_commands(g_commands,':period_cal_'||l_calendar_id||',:year_cal_'||l_calendar_id||',:periodicity_cal_'||l_calendar_id||')');
4734 bsc_aw_utility.add_g_commands(g_commands,'for '||l_cube_composites(1));
4735 bsc_aw_utility.add_g_commands(g_commands,'do');
4736 bsc_aw_utility.add_g_commands(g_commands,'sql execute c1');
4737 bsc_aw_utility.add_g_commands(g_commands,'if sqlcode ne 0');
4738 bsc_aw_utility.add_g_commands(g_commands,'then break');
4739 bsc_aw_utility.add_g_commands(g_commands,'doend');
4740 bsc_aw_utility.exec_program_commands(p_name,g_commands);
4741 --limit the dimensions
4742 for i in 1..l_dim_levels.count loop
4743 if l_dim_level_dims(i) <> l_dim_levels(i) then
4744 bsc_aw_dbms_aw.execute('limit '||l_dim_level_dims(i)||' to '||l_dim_levels(i));
4745 end if;
4746 end loop;
4747 end if;
4748 Exception when others then
4749 log_n('Exception in create_dmp_program '||sqlerrm);
4750 raise;
4751 End;
4752
4753 procedure get_missing_periodicity(p_kpi kpi_r,p_dim_set in out nocopy dim_set_r) is
4754 --
4755 l_periodicity_dim dbms_sql.varchar2_table;
4756 l_lowest_level dbms_sql.varchar2_table;
4757 l_initial_count number;
4758 l_flag boolean;
4759 Begin
4760 l_initial_count:=p_dim_set.calendar.periodicity.count;
4761 for i in 1..p_dim_set.calendar.periodicity.count loop
4762 l_periodicity_dim(l_periodicity_dim.count+1):=p_dim_set.calendar.periodicity(i).aw_dim;
4763 end loop;
4764 --
4765 bsc_aw_calendar.get_missing_periodicity(p_dim_set.calendar.aw_dim,l_periodicity_dim,l_lowest_level);
4766 --
4767 for i in 1..l_periodicity_dim.count loop
4768 l_flag:=false;
4769 for j in 1..p_dim_set.calendar.periodicity.count loop
4773 l_flag:=true;
4770 if p_dim_set.calendar.periodicity(j).aw_dim=l_periodicity_dim(i) then
4771 p_dim_set.calendar.periodicity(j).lowest_level:=l_lowest_level(i);
4772 p_dim_set.calendar.periodicity(j).missing_level:='N';
4774 exit;
4775 end if;
4776 end loop;
4777 if l_flag=false then
4778 p_dim_set.calendar.periodicity(p_dim_set.calendar.periodicity.count+1).aw_dim:=l_periodicity_dim(i);
4779 p_dim_set.calendar.periodicity(p_dim_set.calendar.periodicity.count).lowest_level:=l_lowest_level(i);
4780 p_dim_set.calendar.periodicity(p_dim_set.calendar.periodicity.count).missing_level:='Y';
4781 end if;
4782 end loop;
4783 if l_initial_count < p_dim_set.calendar.periodicity.count then --we need to add periodicity id to the new dim..this is re-read cal info
4784 bsc_aw_md_api.get_dim_set_calendar(p_kpi,p_dim_set);
4785 end if;
4786 Exception when others then
4787 log_n('Exception in get_missing_periodicity '||sqlerrm);
4788 raise;
4789 End;
4790
4791 function get_periodicity_r(p_periodicity periodicity_tb,p_periodicity_dim varchar2) return periodicity_r is
4792 Begin
4793 for i in 1..p_periodicity.count loop
4794 if p_periodicity(i).aw_dim=p_periodicity_dim then
4795 return p_periodicity(i);
4796 end if;
4797 end loop;
4798 return null;
4799 Exception when others then
4800 log_n('Exception in get_periodicity_r '||sqlerrm);
4801 raise;
4802 End;
4803
4804 function get_periodicity_r(p_periodicity periodicity_tb,p_periodicity_id number) return periodicity_r is
4805 Begin
4806 for i in 1..p_periodicity.count loop
4807 if p_periodicity(i).periodicity=p_periodicity_id then
4808 return p_periodicity(i);
4809 end if;
4810 end loop;
4811 return null;
4812 Exception when others then
4813 log_n('Exception in get_periodicity_r '||sqlerrm);
4814 raise;
4815 End;
4816
4817 /*
4818 we have to handle re-agg of cubes when dim hier change. we do inc aggregations. this means we do limit dim to limit.cube
4819 this has an issue. if dim A needs re-agg, then we cannot limit dim B to limit cube. if we do, we re-agg only a portion
4820 of the data in the cube. if A has re-agg, we have to limit the limit cube to the composite of the cubes.
4821 we limit it to the composite of the cube for efficiency. we want to re-agg only those data that has to be re-aggregated. so we
4822 do not want to limit B to all values.
4823 this program must be called before calling the load of the dimset. the reason is that we want to do this
4824 only to those values of dim that have undergone hier change. if we load data, limit cubes capture inc data also
4825 */
4826 procedure create_aggregate_marker_pgm(
4827 p_kpi kpi_r,
4828 p_dim_set dim_set_r
4829 )is
4830 --
4831 l_composite_name dbms_sql.varchar2_table;
4832 l_flag boolean;
4833 l_cube cube_tb;
4834 Begin
4835 --note>>> we dont do this for std dim since they are single level dim
4836 for i in 1..p_dim_set.measure.count loop
4837 l_cube(i):=get_cube_set_r(p_dim_set.measure(i).cube,p_dim_set).cube;
4838 for j in 1..l_cube(i).cube_axis.count loop
4839 if l_cube(i).cube_axis(j).axis_type='partition template' or l_cube(i).cube_axis(j).axis_type='composite' then
4840 if bsc_aw_utility.in_array(l_composite_name,l_cube(i).cube_axis(j).axis_name)=false then
4841 l_composite_name(l_composite_name.count+1):=l_cube(i).cube_axis(j).axis_name;
4842 end if;
4843 end if;
4844 end loop;
4845 end loop;
4846 --there must be 1 entry only for l_composite_name, either a PT or composite
4847 l_flag:=false;
4848 g_commands.delete;
4849 bsc_aw_utility.add_g_commands(g_commands,'dfn '||p_dim_set.aggregate_marker_program||' program');
4850 l_flag:=true;
4851 for i in 1..p_dim_set.dim.count loop
4852 if p_dim_set.dim(i).aggregate_marker is not null then --there is a aggregate marker
4853 bsc_aw_utility.add_g_commands(g_commands,'allstat');
4854 bsc_aw_utility.add_g_commands(g_commands,'if '||p_dim_set.dim(i).aggregate_marker||' EQ true');
4855 bsc_aw_utility.add_g_commands(g_commands,'then do');
4856 bsc_aw_utility.add_g_commands(g_commands,'limit '||p_dim_set.dim(i).dim_name||' to '||p_dim_set.dim(i).limit_cube);
4857 bsc_aw_utility.add_g_commands(g_commands,'limit '||p_dim_set.dim(i).dim_name||' add ancestors using '||p_dim_set.dim(i).relation_name);
4858 for j in 1..p_dim_set.dim.count loop
4859 if i<>j then
4860 for k in 1..l_composite_name.count loop
4861 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.dim(j).limit_cube||'=true across '||l_composite_name(k));
4862 end loop;
4863 end if;
4864 end loop;
4865 for j in 1..p_dim_set.std_dim.count loop
4866 for k in 1..l_composite_name.count loop
4867 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.std_dim(j).limit_cube||'=true across '||l_composite_name(k));
4868 end loop;
4869 end loop;
4870 for j in 1..l_composite_name.count loop
4871 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.calendar.limit_cube||'=true across '||l_composite_name(j));
4872 end loop;
4873 bsc_aw_utility.add_g_commands(g_commands,'doend');
4874 end if;
4875 end loop;
4876 --for the reset cubes. loop across each dim and if each dim has a situation where a parent now no longer has any child nodes,
4877 --set the value of the cube to na
4878 for i in 1..p_dim_set.dim.count loop
4879 if p_dim_set.dim(i).reset_cube is not null and p_dim_set.dim(i).aggregate_marker is not null then --there is a aggregate marker and reset cube
4880 bsc_aw_utility.add_g_commands(g_commands,'if '||p_dim_set.dim(i).aggregate_marker||' EQ true');
4881 bsc_aw_utility.add_g_commands(g_commands,'then do');
4882 bsc_aw_utility.add_g_commands(g_commands,'allstat');
4883 bsc_aw_utility.add_g_commands(g_commands,'limit '||p_dim_set.dim(i).dim_name||' to '||p_dim_set.dim(i).reset_cube);
4887 for j in 1..p_dim_set.measure.count loop
4884 bsc_aw_utility.add_g_commands(g_commands,'if statlen('||p_dim_set.dim(i).dim_name||') GT 0');
4885 bsc_aw_utility.add_g_commands(g_commands,'then do');
4886 bsc_aw_utility.init_is_new_value(1);
4888 for k in 1..l_cube(j).cube_axis.count loop
4889 if l_cube(j).cube_axis(k).axis_type='partition template' or l_cube(j).cube_axis(k).axis_type='composite' then
4890 if bsc_aw_utility.is_new_value(p_dim_set.measure(j).cube,1) then
4891 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.measure(j).cube||'=NA across '||l_cube(j).cube_axis(k).axis_name);
4892 end if;
4893 end if;
4894 end loop;
4895 end loop;
4896 bsc_aw_utility.add_g_commands(g_commands,'doend');
4897 bsc_aw_utility.add_g_commands(g_commands,'doend');
4898 end if;
4899 end loop;
4900 --reset values
4901 bsc_aw_utility.add_g_commands(g_commands,'allstat');
4902 for i in 1..p_dim_set.dim.count loop
4903 if p_dim_set.dim(i).aggregate_marker is not null then
4904 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.dim(i).aggregate_marker||'=false');
4905 end if;
4906 if p_dim_set.dim(i).reset_cube is not null then
4907 if p_dim_set.dim(i).limit_cube_composite is not null then
4908 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.dim(i).reset_cube||'=false across '||p_dim_set.dim(i).limit_cube_composite);
4909 else
4910 bsc_aw_utility.add_g_commands(g_commands,p_dim_set.dim(i).reset_cube||'=false');
4911 end if;
4912 end if;
4913 end loop;
4914 if l_flag then
4915 bsc_aw_utility.exec_program_commands(p_dim_set.aggregate_marker_program,g_commands);
4916 end if;
4917 Exception when others then
4918 log_n('Exception in create_aggregate_marker_pgm '||sqlerrm);
4919 raise;
4920 End;
4921
4922 /*this procedure will load the master partition template pattern. then the dimset PT can make copies from this.
4923 this is the main procedure that will set the partition aspects of the dimset*/
4924 procedure load_master_PT(p_actual_dim_set in out nocopy dim_set_r,p_target_dim_set in out nocopy dim_set_r) is
4925 Begin
4926 if g_debug then
4927 log('load_master_PT '||p_actual_dim_set.dim_set_name);
4928 end if;
4929 if check_partition_possible(p_actual_dim_set,p_target_dim_set) then
4930 set_pt_type_count(p_actual_dim_set);
4931 if p_actual_dim_set.targets_higher_levels='Y' then
4932 set_pt_type_count(p_target_dim_set);
4933 end if;
4934 if p_actual_dim_set.number_partitions>0 then
4935 set_master_PT(p_actual_dim_set);
4936 /*this sets the hash dim to partition on if pt type=hash for example. may also turn off partitions if partitions cannot be implemented
4937 for the type specified */
4938 if p_actual_dim_set.number_partitions>0 then
4939 if p_actual_dim_set.targets_higher_levels='Y' then
4940 if p_target_dim_set.number_partitions>0 then
4941 set_master_PT(p_target_dim_set);
4942 end if;
4943 end if;
4944 else
4945 p_target_dim_set.number_partitions:=0;
4946 end if;
4947 end if;
4948 else
4949 p_actual_dim_set.number_partitions:=0;
4950 p_target_dim_set.number_partitions:=0;
4951 end if;
4952 if g_debug then
4953 if p_actual_dim_set.number_partitions>0 then
4954 log('Finally, Master Partition Template for Actuals');
4955 dmp_partition_template(p_actual_dim_set.master_partition_template(1));
4956 if p_actual_dim_set.targets_higher_levels='Y' then
4957 log('Finally, Master Partition Template for Targets');
4958 dmp_partition_template(p_target_dim_set.master_partition_template(1));
4959 end if;
4960 else
4961 log('Finally, No partitions');
4962 end if;
4963 end if;
4964 Exception when others then
4965 log_n('Exception in load_master_PT '||sqlerrm);
4966 raise;
4967 End;
4968
4969 /*right now, partitions are checked at dimset level. this means all cubes of a dimset have partitions or none have */
4970 function check_partition_possible(p_actual_dim_set in out nocopy dim_set_r,p_target_dim_set in out nocopy dim_set_r) return boolean is
4971 l_partition_count number;
4972 display_cube_flag boolean;
4973 actual_periodicity periodicity_tb;
4974 target_periodicity periodicity_tb;
4975 flag boolean;
4976 Begin
4977 if g_debug then
4978 log('check_partition_possible dimset '||p_actual_dim_set.dim_set_name||', with target '||p_target_dim_set.dim_set_name);
4979 end if;
4980 if bsc_aw_utility.get_db_version<10.2 then
4981 if g_debug then
4982 log('DB < 10.2. No partitions');
4983 end if;
4984 return false;
4985 end if;
4986 --
4987 if p_actual_dim_set.dim.count=0 then
4988 if g_debug then
4989 log('Only std dim and time, No other dimensions. No partitions');
4990 end if;
4991 return false;
4992 end if;
4993 --
4994 if nvl(bsc_aw_utility.get_parameter_value('NO PARTITION'),'N')='Y' then
4995 if g_debug then
4996 log('No partition specified.');
4997 end if;
4998 return false;
4999 end if;
5000 /*we have an issue with compressed composite and partitions in 10.104. clear all from aggregates does not work when we have cc
5001 and pt. 10.2, it should be resolved. if cc is specified, gets priority over pt specification
5002 we have partitions only when db is 10.2 and greater
5003 */
5004 --
5005 l_partition_count:=get_partition_count;
5006 if l_partition_count is null or l_partition_count<2 then
5007 if g_debug then
5008 log('Max possible partition count<2. No partitions');
5009 end if;
5010 return false;
5011 end if;
5012 /* */
5013 display_cube_flag:=is_display_cube_possible(p_actual_dim_set);
5014 if display_cube_flag=false then
5018 end if;
5015 if check_countvar_cube_needed(p_actual_dim_set) then
5016 if g_debug then
5017 log('Countvar cube needed. Partitions not possible');
5019 return false;
5020 end if;
5021 /*if sql aggregations are enabled, we can go for partitions. the view has the formula in it */
5022 for i in 1..p_actual_dim_set.measure.count loop
5023 if p_actual_dim_set.measure(i).sql_aggregated='N' then
5024 if p_actual_dim_set.measure(i).agg_formula.std_aggregation='N' then
5025 if g_debug then
5026 log('Non std agg in dimset '||p_actual_dim_set.dim_set||', partitions not possible');
5027 end if;
5028 return false;
5029 end if;
5030 /*for now, if thereis AVERAGE or COUNT aggregation, we disable partitions */
5031 if bsc_aw_utility.is_PT_aggregation_function(p_actual_dim_set.measure(i).agg_formula.agg_formula)='N' then
5032 if g_debug then
5033 log('Non partitionable aggregation function '||p_actual_dim_set.measure(i).agg_formula.agg_formula);
5034 end if;
5035 return false;
5036 end if;
5037 end if;
5038 end loop;
5039 else
5040 if g_debug then
5041 log('Display cube is possible. This means we can have partitions when there is AVERAGE or Non Std Aggregations');
5042 end if;
5043 end if;
5044 /*if there are targets at higher levels, we disable partitions
5045 targets can be partitioned if actuals are partitioned or not. however, actuals cannot be partitioned if there are targets.
5046 for targets we can introduce year based partitions. question is : is it really worth it. year based partitions (still list) will help
5047 parallelize initial aggregations. on an inc basis, there is no help. if a dbi style kpi is brought into bsc, it will not have targets at higher
5048 levels mostly. even without partitions, aw aggregations are fast. so not worth it to introduce year based aggregations
5049 --
5050 with hash partitions on time and agg on time on the fly, we can partition targets at higher levels as long as targets and actuals are at the
5051 same periodicity level. if actuals are at day and targets at month, no partitions. if at the same periodicity level, we enable only hash
5052 partitions on time. must make sure we have only hash and only on time. targets do not have rollups. so the system must not select list partitions
5053 for it. we can partition when there are targets as long as actuals and targets have the same number of partitions and a given period is guaranteed
5054 to be in P.x of actuals and P.x of targets
5055 */
5056 if p_actual_dim_set.targets_higher_levels='Y' then
5057 if nvl(bsc_aw_utility.get_parameter_value('NO TARGET PARTITION'),'N')='Y' then
5058 if g_debug then
5059 log('Targets at higher level and NO TARGET PARTITION specified. No partitions');
5060 end if;
5061 return false;
5062 end if;
5063 if g_debug then
5064 log('Targets at higher level. Partitions are possible only if targets and actuals have the same periodicity');
5065 end if;
5066 actual_periodicity:=get_dim_set_lowest_periodicity(p_actual_dim_set);
5067 target_periodicity:=get_dim_set_lowest_periodicity(p_target_dim_set);
5068 for i in 1..target_periodicity.count loop
5069 flag:=false;
5070 for j in 1..actual_periodicity.count loop
5071 if actual_periodicity(j).aw_dim=target_periodicity(i).aw_dim then
5072 flag:=true;
5073 exit;
5074 end if;
5075 end loop;
5076 if flag=false then
5077 if g_debug then
5078 log('Targets and Actuals do not have the same periodicity. Partitions not possible');
5079 end if;
5080 return false;
5081 end if;
5082 end loop;
5083 if g_debug then
5084 log('Partitions are possible. Only HASH partitions on Time Dimension');
5085 end if;
5086 bsc_aw_utility.merge_property(p_actual_dim_set.property,'hash partition',null,'Y');
5087 bsc_aw_utility.merge_property(p_actual_dim_set.property,'hash partition only time',null,'Y');
5088 /* */
5089 bsc_aw_utility.merge_property(p_target_dim_set.property,'hash partition',null,'Y');
5090 bsc_aw_utility.merge_property(p_target_dim_set.property,'hash partition only time',null,'Y');
5091 end if;
5092 /*partition possible*/
5093 return true;
5094 Exception when others then
5095 log_n('Exception in check_partition_possible '||sqlerrm);
5096 raise;
5097 End;
5098
5099 /*check to see if list partition is possible or we need hash partition the number of partitions are set here*/
5100 procedure set_pt_type_count(p_dim_set in out nocopy dim_set_r) is
5101 l_bt_pt_type varchar2(40);
5102 l_bt_pt_count number;
5103 l_bt_levels dbms_sql.varchar2_table;
5104 l_reason varchar2(8000);
5105 l_partition_count number;
5106 Begin
5107 if bsc_aw_utility.get_property(p_dim_set.property,'hash partition').property_value='Y' then
5108 p_dim_set.partition_type:='hash';
5109 else
5110 p_dim_set.partition_type:='list';--default
5111 end if;
5112 l_bt_levels.delete;
5113 for i in 1..p_dim_set.data_source(1).base_tables(1).levels.count loop
5114 l_bt_levels(l_bt_levels.count+1):=p_dim_set.data_source(1).base_tables(1).levels(i).level_name;
5115 end loop;
5116 /*list partitions are possible if this dimset has no aggregation in it and the dimset has the same number of keys at the same level
5117 as the B tables. also the periodicity must match */
5118 if p_dim_set.partition_type='list' then
5119 for i in 1..p_dim_set.dim.count loop
5120 if p_dim_set.dim(i).levels.count>1 then /*there is rollup */
5121 p_dim_set.partition_type:='hash';
5122 l_reason:='Dim '||p_dim_set.dim(i).dim_name||' has rollup. List partitions not possible';
5123 exit;
5124 end if;
5125 end loop;
5126 if p_dim_set.partition_type='list' then /*see if there is time rollup */
5127 for i in 1..p_dim_set.calendar.periodicity.count loop
5131 end if;
5128 if p_dim_set.calendar.periodicity(i).lowest_level<>'Y' then
5129 p_dim_set.partition_type:='hash';
5130 l_reason:='Dimset calendar has rollup. List partitions not possible';
5132 end loop;
5133 end if;
5134 if p_dim_set.partition_type='list' then
5135 if p_dim_set.dim.count<>l_bt_levels.count then
5136 p_dim_set.partition_type:='hash';
5137 l_reason:='Dimset has diff number of dimension keys than B table. Only hash partition possible';
5138 end if;
5139 end if;
5140 if p_dim_set.partition_type='list' then
5141 for i in 1..p_dim_set.dim.count loop
5142 if bsc_aw_utility.in_array(l_bt_levels,p_dim_set.dim(i).levels(1).level_name)=false then
5143 p_dim_set.partition_type:='hash';
5144 l_reason:='Dimset has diff dim levels than B table. Only hash partition possible';
5145 exit;
5146 end if;
5147 end loop;
5148 end if;
5149 end if;
5150 if p_dim_set.partition_type='list' then
5151 for i in 1..p_dim_set.data_source.count loop
5152 for j in 1..p_dim_set.data_source(i).base_tables.count loop
5153 if p_dim_set.data_source(i).base_tables(j).levels.count<>l_bt_levels.count then
5154 l_reason:='B table '||p_dim_set.data_source(i).base_tables(j).base_table_name||' has '||p_dim_set.data_source(i).base_tables(j).levels.count||
5155 ' number of levels while the first B table has '||l_bt_levels.count||' levels. List partitions not possible';
5156 p_dim_set.partition_type:='hash';
5157 exit;
5158 end if;
5159 /*check that each levels match */
5160 for k in 1..p_dim_set.data_source(i).base_tables(j).levels.count loop
5161 if bsc_aw_utility.in_array(l_bt_levels,p_dim_set.data_source(i).base_tables(j).levels(k).level_name)=false then
5162 l_reason:='B table '||p_dim_set.data_source(i).base_tables(j).base_table_name||' has level '||
5163 p_dim_set.data_source(i).base_tables(j).levels(k).level_name||' that is not in the first B table. List partitions not possible';
5164 p_dim_set.partition_type:='hash';
5165 exit;
5166 end if;
5167 end loop;
5168 end loop;
5169 /*check that there is no periodicity rollup reqd from any B table */
5170 if p_dim_set.data_source(i).calendar.periodicity(1).periodicity<>p_dim_set.data_source(i).base_tables(1).periodicity.periodicity then
5171 p_dim_set.partition_type:='hash';
5172 l_reason:='B table '||p_dim_set.data_source(i).base_tables(1).base_table_name||' needs rollup in periodicity. List partitions not possible';
5173 end if;
5174 if p_dim_set.partition_type='hash' then /*list partitions not possible */
5175 exit;
5176 end if;
5177 end loop;
5178 end if;
5179 /*if we can go for list partitions, now make sure that all B tables have the same list partitions */
5180 if p_dim_set.partition_type='list' then
5181 l_bt_pt_type:=nvl(p_dim_set.data_source(1).base_tables(1).table_partition.main_partition.partition_type,'none');
5182 l_bt_pt_count:=p_dim_set.data_source(1).base_tables(1).table_partition.main_partition.partitions.count;
5183 if l_bt_pt_type='LIST' and l_bt_pt_count>0 then
5184 for i in 1..p_dim_set.data_source.count loop
5185 for j in 1..p_dim_set.data_source(i).base_tables.count loop
5186 if nvl(p_dim_set.data_source(i).base_tables(j).table_partition.main_partition.partition_type,'none')<>l_bt_pt_type
5187 or p_dim_set.data_source(i).base_tables(j).table_partition.main_partition.partitions.count<>l_bt_pt_count then
5188 l_reason:='B table '||p_dim_set.data_source(i).base_tables(j).base_table_name||' has diff partition parameters.'||
5189 'List partitions on dimset not possible';
5190 p_dim_set.partition_type:='hash';
5191 exit;
5192 end if;
5193 end loop;
5194 if p_dim_set.partition_type='hash' then /*list partitions not possible */
5195 exit;
5196 end if;
5197 end loop;
5198 else
5199 l_reason:='B table does not have LIST partitions. So we can only attempt hash partitions';
5200 p_dim_set.partition_type:='hash';
5201 end if;
5202 end if;
5203 --
5204 if p_dim_set.partition_type='hash' then
5205 if g_debug then
5206 log('We can only try hash partitions for dimset '||p_dim_set.dim_set_name||'. Reason: '||l_reason);
5207 end if;
5208 end if;
5209 --
5210 l_reason:=null;
5211 l_partition_count:=get_partition_count;
5212 if p_dim_set.partition_type='list' then
5213 if l_bt_pt_count>l_partition_count then
5214 l_partition_count:=0;
5215 l_reason:='B tables have number of partitions='||l_bt_pt_count||' while max allowed partitions are '||l_partition_count||
5216 '. Cannot have partitions';
5217 elsif l_bt_pt_count<l_partition_count then
5218 l_partition_count:=l_bt_pt_count;
5219 l_reason:='B tables have number of partitions='||l_bt_pt_count||' while max allowed partitions are '||l_partition_count||
5220 '. Reducing number of partition to '||l_bt_pt_count;
5221 end if;
5222 end if;
5223 if l_partition_count is null then
5224 l_partition_count:=0;
5225 end if;
5226 p_dim_set.number_partitions:=l_partition_count;
5227 if g_debug then
5228 log('Finally, Dimset '||p_dim_set.dim_set||', partition type='||p_dim_set.partition_type||', number partitions='||
5229 p_dim_set.number_partitions||' and any reason(null if nothing)='||l_reason);
5230 end if;
5231 Exception when others then
5232 log_n('Exception in set_pt_type_count '||sqlerrm);
5233 raise;
5234 End;
5235
5236 /*here, we set the master PT template for list or hash or range partitions
5237 master PT only contains the logical metadata. will not contain axis info. this is loaded in create_pt_comp_names*/
5238 procedure set_master_PT(p_dim_set in out nocopy dim_set_r) is
5239 Begin
5243 p_dim_set.master_partition_template(1).template_use:='datacube';/*this pt is meant for cubes */
5240 p_dim_set.partition_dim:='hash_partition_dim';
5241 p_dim_set.master_partition_template(1).template_name:='master PT';
5242 p_dim_set.master_partition_template(1).template_type:='list'; /*hash and list are AW list partitions */
5244 p_dim_set.master_partition_template(1).template_dim:=p_dim_set.partition_dim;
5245 if p_dim_set.partition_type='hash' then
5246 if set_PT_hash_dimensions(p_dim_set,p_dim_set.master_partition_template(1)) then
5247 set_PT_dim_aggregated(p_dim_set,p_dim_set.master_partition_template(1));/*sets the aggregated flag */
5248 set_PT_calendar_aggregated(p_dim_set,p_dim_set.master_partition_template(1));/*sets the aggregated flag */
5249 else
5250 p_dim_set.number_partitions:=0;
5251 p_dim_set.partition_dim:=null;
5252 reset_PT_template(p_dim_set.master_partition_template(1));
5253 if g_debug then
5254 log('No Hash Partitions possible for '||p_dim_set.dim_set_name);
5255 end if;
5256 end if;
5257 end if;
5258 Exception when others then
5259 log_n('Exception in set_master_PT '||sqlerrm);
5260 raise;
5261 End;
5262
5263 /*this api must set the hash partition dim. what dim this sets has implication on what levels will get aggregated.
5264 if this sets partition at lowest calendar level (day) there is no aggrgation in time except at runtime
5265 if this is set at state, there is aggregation upto state. we will change the agg level per dim to reflect this
5266 have to account for targets. there are no partitions when there are targets. but still, must make sure that we do not include dim that have
5267 targets coming at diff levels
5268 if balance measures are involved and we partition on time, they are still aggregated to top levels in time since this is done in the
5269 load program itself. aggregation online is for non bal measures only
5270 if we have multiple lowest levels in a dim like
5271 city>-state>-country
5272 county>-state>-country, if we decide to partition on city, we must also partition on county because otherwise, data coming at county level
5273 has no partition to go to
5274 if the return flag=false, it means this api could not find dim suitable to hash partition on
5275 */
5276 function set_PT_hash_dimensions(p_dim_set dim_set_r,p_partition_template in out nocopy partition_template_r) return boolean is
5277 partition_time boolean;
5278 partition_dim boolean;
5279 Begin
5280 p_partition_template.hpt_data.hpt_dimensions.delete;
5281 p_partition_template.hpt_data.hpt_calendar.dim_name:=null;
5282 /*for now, we hash on time only. must handle kpi that only have year level.for now, if there is year only kpi, no hash partitions possible */
5283 /*if we have yearly kpi or balance last value measure, we cannot hash on time. if we just have balance measure (based on period end), we
5284 can hash on time. upper time nodes will not be duplicated across partitions in this case */
5285 if p_dim_set.calendar.periodicity.count=1 then
5286 if p_dim_set.calendar.periodicity(1).periodicity_type='1' then
5287 if g_debug then
5288 log('HASH Partitions not possible on time as the KPI is YEARLY kpi');
5289 end if;
5290 return false;
5291 end if;
5292 end if;
5293 /*check for balance last value */
5294 for i in 1..p_dim_set.measure.count loop
5295 if p_dim_set.measure(i).measure_type=g_balance_last_value_prop then
5296 if g_debug then
5297 log('HASH Partitions not possible on time as the KPI has measure of type '||g_balance_last_value_prop);
5298 end if;
5299 return false;
5300 end if;
5301 end loop;
5302 partition_dim:=false; /*for now, no dim involved in hash partitions */
5303 partition_time:=true;
5304 if bsc_aw_utility.get_property(p_dim_set.property,'hash partition only time').property_value='Y' then
5305 partition_dim:=false;/*this will be the case for targets at higher levels */
5306 end if;
5307 if partition_time then
5308 p_partition_template.hpt_data.hpt_calendar.dim_name:=p_dim_set.calendar.aw_dim;
5309 p_partition_template.hpt_data.hpt_calendar.dim_type:='time';
5310 p_partition_template.hpt_data.hpt_calendar.level_names.delete;
5311 p_partition_template.hpt_data.hpt_calendar.level_keys.delete;
5312 for i in 1..p_dim_set.calendar.periodicity.count loop
5313 if p_dim_set.calendar.periodicity(i).lowest_level='Y' then
5314 p_partition_template.hpt_data.hpt_calendar.level_names(
5315 p_partition_template.hpt_data.hpt_calendar.level_names.count+1):=
5316 p_dim_set.calendar.periodicity(i).aw_dim;
5317 p_partition_template.hpt_data.hpt_calendar.level_keys(
5318 p_partition_template.hpt_data.hpt_calendar.level_keys.count+1):='period';
5319 end if;
5320 end loop;
5321 end if;
5322 /*if we needed to partition on time, we can do so here. but for now, there are partitions only on time */
5323 if partition_dim then
5324 null;
5325 end if;
5326 if g_debug then
5327 log('set_PT_hash_dimensions for template '||p_partition_template.template_name);
5328 dmp_hpt_data(p_partition_template.hpt_data);
5329 end if;
5330 return true;
5331 Exception when others then
5332 log_n('Exception in set_PT_hash_dimensions '||sqlerrm);
5333 raise;
5334 End;
5335
5336 /*sets the aggregated flag */
5337 procedure set_PT_dim_aggregated(p_dim_set in out nocopy dim_set_r,p_partition_template partition_template_r) is
5338 Begin
5339 for i in 1..p_dim_set.dim.count loop
5340 for j in 1..p_partition_template.hpt_data.hpt_dimensions.count loop
5341 if p_dim_set.dim(i).dim_name=p_partition_template.hpt_data.hpt_dimensions(j).dim_name then
5342 set_PT_dim_aggregated(p_dim_set.dim(i),p_dim_set,p_partition_template.hpt_data.hpt_dimensions(j).level_names);
5343 --
5344 exit;
5345 end if;
5346 end loop;
5347 end loop;
5348 Exception when others then
5349 log_n('Exception in set_PT_dim_aggregated '||sqlerrm);
5350 raise;
5351 End;
5352
5356 l_child_levels dbms_sql.varchar2_table;
5353 procedure set_PT_dim_aggregated(p_dim in out nocopy dim_r,p_dim_set dim_set_r,p_levels dbms_sql.varchar2_table) is
5354 l_parent_child bsc_aw_adapter_dim.dim_parent_child_tb;
5355 l_pc bsc_aw_utility.parent_child_tb;
5357 zero_aggregated dbms_sql.varchar2_table;
5358 aggregated dbms_sql.varchar2_table;
5359 Begin
5360 bsc_aw_md_api.get_dim_parent_child(p_dim.dim_name,l_parent_child);
5361 for i in 1..l_parent_child.count loop
5362 if l_parent_child(i).parent_level is not null and l_parent_child(i).child_level is not null then
5363 l_pc(l_pc.count+1).parent:=l_parent_child(i).parent_level;
5364 l_pc(l_pc.count).child:=l_parent_child(i).child_level;
5365 end if;
5366 end loop;
5367 /*if there is partition at country say, we can rollup to country but not perform zero code */
5368 for i in 1..p_dim.levels.count loop
5369 if bsc_aw_utility.in_array(p_levels,p_dim.levels(i).level_name) then
5370 /*p_dim.levels(i).aggregated is left unchanged*/
5371 p_dim.levels(i).zero_aggregated:='N';/*there cannot be zero code aggregation at this level */
5372 aggregated(i):=p_dim.levels(i).aggregated;
5373 zero_aggregated(i):=p_dim.levels(i).zero_aggregated;
5374 if g_debug then
5375 log('Dimension '||p_dim.dim_name||', Partition Level '||p_dim.levels(i).level_name||' aggregated='''||p_dim.levels(i).aggregated||
5376 ''', zero_aggregated='''||p_dim.levels(i).zero_aggregated||'''');
5377 end if;
5378 else
5379 aggregated(i):=p_dim.levels(i).aggregated;
5380 zero_aggregated(i):=p_dim.levels(i).zero_aggregated;/*capture the prev setting for zero_aggregated */
5381 p_dim.levels(i).aggregated:='N';
5382 p_dim.levels(i).zero_aggregated:='N';
5383 end if;
5384 end loop;
5385 if l_pc.count>0 then
5386 for i in 1..p_levels.count loop
5387 l_child_levels.delete;
5388 bsc_aw_utility.get_all_children(l_pc,p_levels(i),l_child_levels);
5389 if l_child_levels.count>0 then
5390 for j in 1..p_dim.levels.count loop
5391 if bsc_aw_utility.in_array(l_child_levels,p_dim.levels(j).level_name) then
5392 p_dim.levels(j).aggregated:=aggregated(j);
5393 p_dim.levels(j).zero_aggregated:=zero_aggregated(j);
5394 if g_debug then
5395 log('Dimension '||p_dim.dim_name||', Child Level '||p_dim.levels(j).level_name||' aggregated='''||p_dim.levels(j).aggregated||
5396 ''', zero_aggregated='''||p_dim.levels(j).zero_aggregated||'''');
5397 end if;
5398 end if;
5399 end loop;
5400 end if;
5401 end loop;
5402 end if;
5403 Exception when others then
5404 log_n('Exception in set_PT_dim_aggregated '||sqlerrm);
5405 raise;
5406 End;
5407
5408 /*sets the aggregated flag */
5409 procedure set_PT_calendar_aggregated(p_dim_set in out nocopy dim_set_r,p_partition_template partition_template_r) is
5410 Begin
5411 if p_partition_template.hpt_data.hpt_calendar.dim_name is not null then /*There is partitioning on Calendar */
5412 set_PT_calendar_aggregated(p_dim_set.calendar,p_dim_set,p_partition_template.hpt_data.hpt_calendar.level_names);
5413 end if;
5414 Exception when others then
5415 log_n('Exception in set_PT_calendar_aggregated '||sqlerrm);
5416 raise;
5417 End;
5418
5419 procedure set_PT_calendar_aggregated(p_calendar in out nocopy calendar_r,p_dim_set dim_set_r,p_levels dbms_sql.varchar2_table) is
5420 l_pc bsc_aw_utility.parent_child_tb;
5421 l_child_levels dbms_sql.varchar2_table;
5422 aggregated dbms_sql.varchar2_table;
5423 Begin
5424 for i in 1..p_calendar.parent_child.count loop
5425 if p_calendar.parent_child(i).parent_dim_name is not null and p_calendar.parent_child(i).child_dim_name is not null then
5426 l_pc(l_pc.count+1).parent:=p_calendar.parent_child(i).parent_dim_name;
5427 l_pc(l_pc.count).child:=p_calendar.parent_child(i).child_dim_name;
5428 end if;
5429 end loop;
5430 for i in 1..p_calendar.periodicity.count loop
5431 if bsc_aw_utility.in_array(p_levels,p_calendar.periodicity(i).aw_dim) then
5432 /*p_calendar.periodicity(i).aggregated is left unchanged */
5433 aggregated(i):=p_calendar.periodicity(i).aggregated;/*could be Y or N */
5434 else
5435 aggregated(i):=p_calendar.periodicity(i).aggregated;
5436 p_calendar.periodicity(i).aggregated:='N';/*init all to N. then from the PT levels, drill down and mark as Y */
5437 end if;
5438 end loop;
5439 if l_pc.count>0 then
5440 for i in 1..p_levels.count loop
5441 l_child_levels.delete;
5442 bsc_aw_utility.get_all_children(l_pc,p_levels(i),l_child_levels);
5443 if l_child_levels.count>0 then
5444 for j in 1..p_calendar.periodicity.count loop
5445 if bsc_aw_utility.in_array(l_child_levels,p_calendar.periodicity(j).aw_dim) then
5446 p_calendar.periodicity(j).aggregated:=aggregated(j);
5447 if g_debug then
5448 log('Calendar '||p_calendar.aw_dim||', Child Periodicity '||p_calendar.periodicity(j).aw_dim||' aggregated='''||
5449 p_calendar.periodicity(j).aggregated||'''');
5450 end if;
5451 end if;
5452 end loop;
5453 end if;
5454 end loop;
5455 end if;
5456 Exception when others then
5457 log_n('Exception in set_PT_calendar_aggregated '||sqlerrm);
5458 raise;
5459 End;
5460
5461 function get_partition_count return number is
5462 l_cpu_count number;
5463 l_partition_count number;
5464 Begin
5465 l_cpu_count:=bsc_aw_utility.get_cpu_count;
5466 l_partition_count:=to_number(bsc_aw_utility.get_parameter_value('NUMBER PARTITION'));--most of the time null
5467 if l_partition_count is null or l_partition_count=0 then
5468 l_partition_count:=bsc_aw_utility.get_min(bsc_aw_utility.get_closest_2_power_number(l_cpu_count),bsc_aw_utility.g_max_partitions);
5469 else
5470 if l_partition_count>l_cpu_count then
5474 if l_partition_count>bsc_aw_utility.g_max_partitions then
5471 l_partition_count:=l_cpu_count; /*max partitions possible is cpu count */
5472 end if;
5473 end if;
5475 l_partition_count:=bsc_aw_utility.g_max_partitions;
5476 end if;
5477 return l_partition_count;
5478 Exception when others then
5479 log_n('Exception in get_partition_count '||sqlerrm);
5480 raise;
5481 End;
5482
5483 function get_cube_set_r(p_cube_name varchar2,p_dimset dim_set_r) return cube_set_r is
5484 Begin
5485 for i in 1..p_dimset.cube_set.count loop
5486 if p_dimset.cube_set(i).cube.cube_name=p_cube_name then
5487 return p_dimset.cube_set(i);
5488 end if;
5489 end loop;
5490 /*check countvar cube */
5491 for i in 1..p_dimset.cube_set.count loop
5492 if p_dimset.cube_set(i).countvar_cube.cube_name=p_cube_name then
5493 return p_dimset.cube_set(i);
5494 end if;
5495 end loop;
5496 /*check display cube */
5497 for i in 1..p_dimset.cube_set.count loop
5498 if p_dimset.cube_set(i).display_cube.cube_name=p_cube_name then
5499 return p_dimset.cube_set(i);
5500 end if;
5501 end loop;
5502 /* */
5503 return null;
5504 Exception when others then
5505 log_n('Exception in get_cube_set_r '||sqlerrm);
5506 raise;
5507 End;
5508
5509 function get_composite_r(p_composite_name varchar2,p_dimset dim_set_r) return composite_r is
5510 Begin
5511 for i in 1..p_dimset.composite.count loop
5512 if p_dimset.composite(i).composite_name=p_composite_name then
5513 return p_dimset.composite(i);
5514 end if;
5515 end loop;
5516 return null;
5517 Exception when others then
5518 log_n('Exception in get_composite_r '||sqlerrm);
5519 raise;
5520 End;
5521
5522 function get_partition_template_r(p_partition_template varchar2,p_dimset dim_set_r) return partition_template_r is
5523 Begin
5524 for i in 1..p_dimset.partition_template.count loop
5525 if p_dimset.partition_template(i).template_name=p_partition_template then
5526 return p_dimset.partition_template(i);
5527 end if;
5528 end loop;
5529 return null;
5530 Exception when others then
5531 log_n('Exception in get_partition_template_r '||sqlerrm);
5532 raise;
5533 End;
5534
5535 /*
5536 right now, we support p_axis_type of partition template or composite
5537 */
5538 function get_cube_axis(p_cube_name varchar2,p_dimset dim_set_r,p_axis_type varchar2) return varchar2 is
5539 cube_set cube_set_r;
5540 l_cube cube_r;
5541 Begin
5542 cube_set:=get_cube_set_r(p_cube_name,p_dimset);
5543 if cube_set.cube.cube_name=p_cube_name then
5544 l_cube:=cube_set.cube;
5545 elsif cube_set.countvar_cube.cube_name=p_cube_name then
5546 l_cube:=cube_set.countvar_cube;
5547 elsif cube_set.display_cube.cube_name=p_cube_name then
5548 l_cube:=cube_set.display_cube;
5549 end if;
5550 if l_cube.cube_name is not null then
5551 for i in 1..l_cube.cube_axis.count loop
5552 if l_cube.cube_axis(i).axis_type=p_axis_type then
5553 return l_cube.cube_axis(i).axis_name;
5554 end if;
5555 end loop;
5556 end if;
5557 return null;
5558 Exception when others then
5559 log_n('Exception in get_cube_axis '||sqlerrm);
5560 raise;
5561 End;
5562
5563 /*
5564 let us assume a cube has 1 PT or 1 composite. this function returns either PT or if not found, composite name
5565 */
5566 function get_cube_pt_comp(p_cube_name varchar2,p_dimset dim_set_r,p_type out nocopy varchar2) return varchar2 is
5567 l_pt_name varchar2(200);
5568 Begin
5569 p_type:=null;
5570 l_pt_name:=get_cube_axis(p_cube_name,p_dimset,'partition template');
5571 if l_pt_name is null then
5572 l_pt_name:=get_cube_axis(p_cube_name,p_dimset,'composite');
5573 if l_pt_name is not null then
5574 p_type:='composite';
5575 end if;
5576 else
5577 p_type:='partition template';
5578 end if;
5579 return l_pt_name;
5580 Exception when others then
5581 log_n('Exception in get_cube_pt_comp '||sqlerrm);
5582 raise;
5583 End;
5584
5585 procedure get_measures_for_cube(
5586 p_cube varchar2,
5587 p_dim_set dim_set_r,
5588 p_measures out nocopy measure_tb) is
5589 Begin
5590 for i in 1..p_dim_set.measure.count loop
5591 if p_dim_set.measure(i).cube=p_cube then
5592 p_measures(p_measures.count+1):=p_dim_set.measure(i);
5593 end if;
5594 end loop;
5595 Exception when others then
5596 log_n('Exception in get_measures_for_cube '||sqlerrm);
5597 raise;
5598 End;
5599
5600 function get_cube_set_for_measure(p_measure varchar2,p_dim_set dim_set_r) return cube_set_r is
5601 Begin
5602 for i in 1..p_dim_set.measure.count loop
5603 if p_dim_set.measure(i).measure=p_measure then
5604 return get_cube_set_r(p_dim_set.measure(i).cube,p_dim_set);
5605 end if;
5606 end loop;
5607 return null;
5608 Exception when others then
5609 log_n('Exception in get_measures_for_cube '||sqlerrm);
5610 raise;
5611 End;
5612
5613 /*
5614 this is to register the B table combinations used in the load program. when we load the B tables, we see which one of these combinations
5615 to use
5616 */
5617 procedure set_program_property(p_load_program in out nocopy load_program_r,p_data_source data_source_tb) is
5618 l_ordered_bt dbms_sql.varchar2_table;
5619 Begin
5620 p_load_program.ds_base_tables:=null;
5621 for i in 1..p_data_source.count loop
5622 l_ordered_bt.delete;
5623 for j in 1..p_data_source(i).base_tables.count loop
5624 l_ordered_bt(l_ordered_bt.count+1):=upper(p_data_source(i).base_tables(j).base_table_name);
5625 end loop;
5626 l_ordered_bt:=bsc_aw_utility.order_array(l_ordered_bt);
5630 log('Program name '||p_load_program.program_name||', DS Tables '||p_load_program.ds_base_tables);
5627 p_load_program.ds_base_tables:=p_load_program.ds_base_tables||bsc_aw_utility.make_string_from_list(l_ordered_bt,'^')||'+';
5628 end loop;
5629 if g_debug then
5631 end if;
5632 Exception when others then
5633 log_n('Exception in set_program_property '||sqlerrm);
5634 raise;
5635 End;
5636
5637 /*
5638 if we know the level name, this api will loop over the dim set dim and their levels and return the
5639 dim structure
5640 */
5641 function get_kpi_level_dim_r(
5642 p_dim_set dim_set_r,
5643 p_level varchar2) return dim_r is
5644 Begin
5645 for i in 1..p_dim_set.dim.count loop
5646 for j in 1..p_dim_set.dim(i).levels.count loop
5647 if p_dim_set.dim(i).levels(j).level_name=p_level then
5648 return p_dim_set.dim(i);
5649 end if;
5650 end loop;
5651 end loop;
5652 return null;
5653 Exception when others then
5654 log_n('Exception in get_kpi_level_dim_r '||sqlerrm);
5655 raise;
5656 End;
5657
5658 function get_dim_level_r(
5659 p_dim dim_r,
5660 p_level varchar2) return level_r is
5661 Begin
5662 for i in 1..p_dim.levels.count loop
5663 if p_dim.levels(i).level_name=p_level then
5664 return p_dim.levels(i);
5665 end if;
5666 end loop;
5667 return null;
5668 Exception when others then
5669 log_n('Exception in get_dim_level_r '||sqlerrm);
5670 raise;
5671 End;
5672
5673 procedure check_compressed_composite(p_actual_dim_set in out nocopy dim_set_r,p_target_dim_set in out nocopy dim_set_r) is
5674 l_reason varchar2(4000);
5675 l_countvar_flag boolean;
5676 l_agg_formula varchar2(4000);
5677 l_cal_aggregated boolean;
5678 Begin
5679 p_actual_dim_set.compressed:='N';--default
5680 p_target_dim_set.compressed:='N';--default
5681 l_countvar_flag:=check_countvar_cube_needed(p_actual_dim_set);
5682 if nvl(bsc_aw_utility.get_parameter_value('NO COMPRESSED COMPOSITE'),'N')='Y' then
5683 if g_debug then
5684 log('Non compressed composite specified');
5685 end if;
5686 return;
5687 end if;
5688 if bsc_aw_utility.get_db_version>=10.2 or nvl(bsc_aw_utility.get_parameter_value('COMPRESSED COMPOSITE'),'N')='Y' then
5689 /*if we have average in aggregation, we need countvar. countvar cannot share the same composite as main cube. if we have
5690 diff composite, we cannot aggregate. aw throws error
5691 ORA-36168: COUNTVAR variable BSC_AW!DATACUBE.1.4014.COUNTVAR must have the same dimensionality as AGGMAP object
5692 BSC_AW!DATACUBE.1.4014. so we have to disable compressed composite
5693 */
5694 p_actual_dim_set.compressed:='Y'; --default
5695 if p_actual_dim_set.targets_higher_levels='Y' then
5696 p_actual_dim_set.compressed:='N';
5697 l_reason:='Target at higher level';
5698 end if;
5699 /*if l_countvar_flag then
5700 bsc_aw_utility.merge_property(p_actual_dim_set.property,'aggcount',null,'Y');
5701 end if;*/
5702 /*even with aggcount set in the cube, aw still complains that we need countvar cube when we have aggregate cube using aggmap. so for now,
5703 no CC for avg */
5704 if l_countvar_flag then
5705 p_actual_dim_set.compressed:='N';
5706 l_reason:='countvar cube needed';
5707 end if;
5708 if p_actual_dim_set.compressed='Y' then --check to make sure all measures have the same agg formula
5709 --we cannot use opvar and argvar and measuredim in the aggmap with cc
5710 --now we have this restricted implementation. future,can create cubes by grouping according to agg formula
5711 l_agg_formula:=null;
5712 for i in 1..p_actual_dim_set.measure.count loop
5713 if p_actual_dim_set.measure(i).sql_aggregated='N' then
5714 l_agg_formula:=p_actual_dim_set.measure(i).agg_formula.agg_formula;
5715 exit;
5716 end if;
5717 end loop;
5718 if l_agg_formula is not null then
5719 if bsc_aw_utility.is_CC_aggregation_function(l_agg_formula)='N' then
5720 p_actual_dim_set.compressed:='N';
5721 l_reason:='Agg Formula '||l_agg_formula||' cannot have compressed composite';
5722 end if;
5723 end if;
5724 if p_actual_dim_set.compressed='Y' then
5725 for i in 1..p_actual_dim_set.measure.count loop
5726 if p_actual_dim_set.measure(i).sql_aggregated='N' then
5727 if p_actual_dim_set.measure(i).agg_formula.agg_formula<>l_agg_formula then
5728 p_actual_dim_set.compressed:='N';
5729 l_reason:='agg formula not the same across measures';
5730 exit;
5731 end if;
5732 end if;
5733 end loop;
5734 end if;
5735 end if;
5736 /*we have to consider ORA-37133: Cannot write into an aggregated VARIABLE dimensioned by a COMPRESSED COMPOSITE.
5737 this means we cannot have balance measures or formula measures or projection measures in compressed composite
5738 */
5739 if p_actual_dim_set.compressed='Y' then
5740 l_cal_aggregated:=is_calendar_aggregated(p_actual_dim_set.calendar);
5741 for i in 1..p_actual_dim_set.measure.count loop
5742 if p_actual_dim_set.measure(i).agg_formula.std_aggregation='N' and p_actual_dim_set.measure(i).sql_aggregated='N' then
5743 p_actual_dim_set.compressed:='N';
5744 l_reason:='non std agg (formula)';
5745 exit;
5746 elsif p_actual_dim_set.measure(i).measure_type=g_balance_end_period_prop or p_actual_dim_set.measure(i).measure_type=g_balance_last_value_prop then
5747 p_actual_dim_set.compressed:='N';
5748 l_reason:='balance measure';
5749 exit;
5750 elsif p_actual_dim_set.measure(i).forecast='Y' and l_cal_aggregated then
5751 /*its very important that set_calendar_agg_level be done before this is executed. if we do not have agg on calendar at load time,
5755 l_reason:='Measure has projection';
5752 we do not have to correct forecast. for CC, forecast correction done online is on the display cube. projection is on by default in BSC
5753 so we want to have CC even when there are forecasts */
5754 p_actual_dim_set.compressed:='N';
5756 exit;
5757 end if;
5758 end loop;
5759 end if;
5760 /*if we have B table loading at higher periodicity or dim level, cannot have compressed composite */
5761 if p_actual_dim_set.compressed='Y' then
5762 if is_higher_level_preloaded(p_actual_dim_set) then
5763 p_actual_dim_set.compressed:='N';
5764 l_reason:='Higher levels preloaded from Base Tables';
5765 end if;
5766 end if;
5767 if p_actual_dim_set.compressed='Y' then
5768 if is_higher_period_preloaded(p_actual_dim_set) then
5769 p_actual_dim_set.compressed:='N';
5770 l_reason:='Higher periodicity preloaded from Base Tables';
5771 end if;
5772 end if;
5773 /* */
5774 if p_actual_dim_set.compressed='N' then
5775 if g_debug then
5776 log('Could not implement compressed composite. dimset='||p_actual_dim_set.dim_set||', Reason '||l_reason);
5777 end if;
5778 end if;
5779 else
5780 p_actual_dim_set.compressed:='N'; --default, no compressed composite
5781 end if;
5782 if p_actual_dim_set.targets_higher_levels='Y' and p_actual_dim_set.compressed='Y' then /*not possible scenario for now */
5783 p_target_dim_set.compressed:='Y';
5784 end if;
5785 Exception when others then
5786 log_n('Exception in check_compressed_composite '||sqlerrm);
5787 raise;
5788 End;
5789
5790 function check_countvar_cube_needed(p_dimset dim_set_r) return boolean is
5791 l_countvar_flag boolean;
5792 Begin
5793 l_countvar_flag:=false;
5794 if p_dimset.dim_set_type<>'target' then --if target, no countvar cube
5795 for i in 1..p_dimset.measure.count loop --create countvar only if needed
5796 if p_dimset.measure(i).agg_formula.avg_aggregation='Y' then
5797 l_countvar_flag:=true;
5798 exit;
5799 end if;
5800 end loop;
5801 end if;
5802 return l_countvar_flag;
5803 Exception when others then
5804 log_n('Exception in check_countvar_cube_needed '||sqlerrm);
5805 raise;
5806 End;
5807
5808 /*set dimset properties like pre-calc etc. only actuals?
5809 */
5810 procedure set_dim_set_properties(p_kpi in out nocopy kpi_r) is
5811 Begin
5812 for i in 1..p_kpi.dim_set.count loop
5813 set_dim_set_properties(p_kpi.dim_set(i));
5814 end loop;
5815 Exception when others then
5816 log_n('Exception in set_dim_set_properties '||sqlerrm);
5817 raise;
5818 End;
5819
5820 procedure set_dim_set_properties(p_dim_set in out nocopy dim_set_r) is
5821 Begin
5822 --pre-calc
5823 if is_dimset_precalculated(p_dim_set) then
5824 p_dim_set.pre_calculated:='Y';
5825 else
5826 p_dim_set.pre_calculated:='N';
5827 end if;
5828 Exception when others then
5829 log_n('Exception in set_dim_set_properties '||sqlerrm);
5830 raise;
5831 End;
5832
5833 /*for now, see if there is any DS feeding at higher level and if so, its pre-calculated. ideally, pre-calc means all higher levels are
5834 provided by DS. Q is : what if we have a case where some higher levels are from DS and the remaining higher levels have to be done by AW?
5835 this can be quite complicated. user provides city and country. AW aggregates to state and then from country to region?
5836 we do not consider this case. if DS provides any higher level or periodicity, its pre-calc */
5837 function is_dimset_precalculated(p_dim_set dim_set_r) return boolean is
5838 Begin
5839 return is_higher_level_preloaded(p_dim_set);
5840 /*later, also check is_higher_period_preloaded */
5841 Exception when others then
5842 log_n('Exception in is_dimset_precalculated '||sqlerrm);
5843 raise;
5844 End;
5845
5846 /* this looks at the cal hier and looks at the periodicities in the dimset and trims the parent child relation to have only the relevant
5847 parent child relations*/
5848 procedure get_relevant_cal_hier(p_periodicity periodicity_tb,p_pc cal_parent_child_tb,p_relevant_pc out nocopy cal_parent_child_tb) is
5849 l_periodicity dbms_sql.varchar2_table;
5850 Begin
5851 for i in 1..p_periodicity.count loop
5852 l_periodicity(l_periodicity.count+1):=p_periodicity(i).aw_dim;
5853 end loop;
5854 for i in 1..p_pc.count loop
5855 if (p_pc(i).parent_dim_name is null or bsc_aw_utility.in_array(l_periodicity,p_pc(i).parent_dim_name))
5856 and (p_pc(i).child_dim_name is null or bsc_aw_utility.in_array(l_periodicity,p_pc(i).child_dim_name)) then
5857 p_relevant_pc(p_relevant_pc.count+1):=p_pc(i);
5858 end if;
5859 end loop;
5860 Exception when others then
5861 log_n('Exception in get_relevant_cal_hier '||sqlerrm);
5862 raise;
5863 End;
5864
5865 /*given a hier and a start value, it finds the upper hier */
5866 procedure get_upper_cal_hier(p_pc cal_parent_child_tb,p_child varchar2,p_upper_hier out nocopy cal_parent_child_tb) is
5867 l_pc bsc_aw_utility.parent_child_tb;
5868 l_trim_pc bsc_aw_utility.parent_child_tb;
5869 Begin
5870 for i in 1..p_pc.count loop
5871 l_pc(l_pc.count+1).parent:=p_pc(i).parent_dim_name;
5872 l_pc(l_pc.count).child:=p_pc(i).child_dim_name;
5873 end loop;
5874 bsc_aw_utility.get_upper_trim_hier(l_pc,p_child,l_trim_pc);
5875 --
5876 for i in 1..l_trim_pc.count loop
5877 for j in 1..p_pc.count loop
5878 if nvl(p_pc(j).parent_dim_name,'^^^')=nvl(l_trim_pc(i).parent,'^^^')
5879 and nvl(p_pc(j).child_dim_name,'^^^')=nvl(l_trim_pc(i).child,'^^^') then
5880 p_upper_hier(p_upper_hier.count+1):=p_pc(j);
5881 exit;
5882 end if;
5883 end loop;
5884 end loop;
5885 Exception when others then
5886 log_n('Exception in get_upper_cal_hier '||sqlerrm);
5890 /*temp variables period.temp and year.temp hold the period and year values. they are present in all cube loading programs. they are used when we
5887 raise;
5888 End;
5889
5891 have BALANCE LAST VALUE type measure */
5892 procedure create_temp_variables(p_dim_set dim_set_r,p_data_source data_source_r) is
5893 l_balance_loaded_column varchar2(40);
5894 Begin
5895 if bsc_aw_utility.get_property(p_data_source.property,g_balance_last_value_prop).property_value='Y' then
5896 bsc_aw_utility.add_g_commands(g_commands,'if exists(\'''||g_period_temp||'\'') eq false');
5897 bsc_aw_utility.add_g_commands(g_commands,'then do');
5898 bsc_aw_utility.add_g_commands(g_commands,'dfn '||g_period_temp||' NUMBER session');
5899 bsc_aw_utility.add_g_commands(g_commands,'doend');
5900 bsc_aw_utility.add_g_commands(g_commands,'if exists(\'''||g_year_temp||'\'') eq false');
5901 bsc_aw_utility.add_g_commands(g_commands,'then do');
5902 bsc_aw_utility.add_g_commands(g_commands,'dfn '||g_year_temp||' NUMBER session');
5903 bsc_aw_utility.add_g_commands(g_commands,'doend');
5904 /*columns to hold balance loaded are also temp . balance loaded column will hold number. see create_base_table_sql decodes this
5905 to number*/
5906 for i in 1..p_data_source.measure.count loop
5907 if p_data_source.measure(i).measure_type=g_balance_last_value_prop then
5908 l_balance_loaded_column:=bsc_aw_utility.get_property(p_data_source.measure(i).property,g_balance_loaded_column_prop).property_value;
5909 if l_balance_loaded_column is not null then
5910 bsc_aw_utility.add_g_commands(g_commands,'if exists(\'''||l_balance_loaded_column||'\'') eq false');
5911 bsc_aw_utility.add_g_commands(g_commands,'then do');
5912 bsc_aw_utility.add_g_commands(g_commands,'dfn '||l_balance_loaded_column||' NUMBER session');
5913 bsc_aw_utility.add_g_commands(g_commands,'doend');
5914 end if;
5915 end if;
5916 end loop;
5917 end if;
5918 Exception when others then
5919 log_n('Exception in create_temp_variables '||sqlerrm);
5920 raise;
5921 End;
5922
5923 procedure upgrade(p_new_version number,p_old_version number) is
5924 Begin
5925 null;
5926 Exception when others then
5927 log_n('Exception in upgrade '||sqlerrm);
5928 raise;
5929 End;
5930
5931 function is_higher_level_preloaded(p_dim_set dim_set_r) return boolean is
5932 Begin
5933 for i in 1..p_dim_set.dim.count loop
5934 for j in 1..p_dim_set.data_source.count loop
5935 for k in 1..p_dim_set.data_source(j).dim.count loop
5936 if p_dim_set.dim(i).dim_name=p_dim_set.data_source(j).dim(k).dim_name then
5937 if p_dim_set.dim(i).levels(1).level_name <> p_dim_set.data_source(j).dim(k).levels(1).level_name then
5938 if g_debug then
5939 log('Dimset dim '||p_dim_set.dim(i).dim_name||' has Lowest Level='||p_dim_set.dim(i).levels(1).level_name||', while DS has '||
5940 p_dim_set.data_source(j).dim(k).levels(1).level_name||'. Higher Level preloaded');
5941 end if;
5942 return true;
5943 end if;
5944 exit;
5945 end if;
5946 end loop;
5947 end loop;
5948 end loop;
5949 return false;
5950 Exception when others then
5951 log_n('Exception in is_higher_level_preloaded '||sqlerrm);
5952 raise;
5953 End;
5954
5955 function is_higher_period_preloaded(p_dim_set dim_set_r) return boolean is
5956 Begin
5957 for i in 1..p_dim_set.data_source.count loop
5958 for j in 1..p_dim_set.calendar.periodicity.count loop
5959 if p_dim_set.calendar.periodicity(j).periodicity=p_dim_set.data_source(i).calendar.periodicity(1).periodicity then
5960 if p_dim_set.calendar.periodicity(j).lowest_level<>'Y' then
5961 if g_debug then
5962 log('Datasource has periodicity '||p_dim_set.data_source(i).calendar.periodicity(1).periodicity||' and this is not the lowest '||
5963 'periodicity in dimset ');
5964 end if;
5965 return true;
5966 end if;
5967 exit;
5968 end if;
5969 end loop;
5970 end loop;
5971 return false;
5972 Exception when others then
5973 log_n('Exception in is_higher_period_preloaded '||sqlerrm);
5974 raise;
5975 End;
5976
5977 procedure dmp_hpt_data(p_hpt_data hpt_data_r) is
5978 Begin
5979 log('hpt dimensions');
5980 for i in 1..p_hpt_data.hpt_dimensions.count loop
5981 log(p_hpt_data.hpt_dimensions(i).dim_name||' '||p_hpt_data.hpt_dimensions(i).dim_type);
5982 for j in 1..p_hpt_data.hpt_dimensions(i).level_names.count loop
5983 log(' '||p_hpt_data.hpt_dimensions(i).level_names(j)||' ('||p_hpt_data.hpt_dimensions(i).level_keys(j)||')');
5984 end loop;
5985 end loop;
5986 log('hpt calendar');
5987 log(p_hpt_data.hpt_calendar.dim_name||' '||p_hpt_data.hpt_calendar.dim_type);
5988 for i in 1..p_hpt_data.hpt_calendar.level_names.count loop
5989 log(' '||p_hpt_data.hpt_calendar.level_names(i)||' ('||p_hpt_data.hpt_calendar.level_keys(i)||')');
5990 end loop;
5991 Exception when others then
5992 log_n('Exception in dmp_hpt_data '||sqlerrm);
5993 raise;
5994 End;
5995
5996 /*PT belong to dimsets. cubes point to the PT they want to use. DS has measures that its loading. from this, we find the cubes and find
5997 the PT. from PT we can get all info like partition dim, hpt_data etc. we assume that all the cubes a DS is loading has a similar PT
5998 so each DS deals with one PT*/
5999 function get_DS_partition_template(p_dim_set dim_set_r,p_data_source data_source_r) return partition_template_r is
6000 l_cube_set cube_set_r;
6001 l_axis axis_tb;
6002 l_pt partition_template_r;
6003 Begin
6004 l_cube_set:=get_cube_set_for_measure(p_data_source.measure(1).measure,p_dim_set);
6005 l_axis:=l_cube_set.cube.cube_axis;
6006 for i in 1..l_axis.count loop
6007 if l_axis(i).axis_type='partition template' then
6008 l_pt.template_name:=l_axis(i).axis_name;
6012 if l_pt.template_name is not null then
6009 exit;
6010 end if;
6011 end loop;
6013 l_pt:=get_partition_template_r(l_pt.template_name,p_dim_set);
6014 end if;
6015 return l_pt;
6016 Exception when others then
6017 log_n('Exception in get_DS_partition_template '||sqlerrm);
6018 raise;
6019 End;
6020
6021 /*PT belong to dimsets. cubes point to the PT they want to use. DS has measures that its loading. from this, we find the cubes and find
6022 the PT. from PT we can get all info like partition dim, hpt_data etc. we assume that all the cubes a DS is loading has similar PT
6023 so each DS deals with one PT
6024 because cube axis info is set in create_pt_comp_names, which comes after set_data_source_sql, for now, lets go with the assumption
6025 that a dimset has cubes all of which share the PT characteristics*/
6026 procedure set_data_source_PT(p_kpi kpi_r,p_dim_set in out nocopy dim_set_r) is
6027 Begin
6028 if p_dim_set.number_partitions>0 then
6029 for i in 1..p_dim_set.data_source.count loop
6030 set_data_source_PT(p_dim_set,p_dim_set.data_source(i));
6031 end loop;
6032 for i in 1..p_dim_set.inc_data_source.count loop
6033 set_data_source_PT(p_dim_set,p_dim_set.inc_data_source(i));
6034 end loop;
6035 end if;
6036 Exception when others then
6037 log_n('Exception in set_data_source_PT '||sqlerrm);
6038 raise;
6039 End;
6040
6041 procedure set_data_source_PT(p_dim_set dim_set_r,p_data_source in out nocopy data_source_r) is
6042 Begin
6043 p_data_source.data_source_PT.partition_template:=p_dim_set.master_partition_template(1);/*master_partition_template(1) is for datacubes */
6044 if p_data_source.data_source_PT.partition_template.template_name is not null then
6045 if p_dim_set.partition_type='hash' then
6046 /*we need info on hpt dimensions, rollups reqd if partition is at state level and DS is at city level */
6047 set_DS_hpt_rollup_data(p_dim_set,p_data_source);
6048 end if;
6049 end if;
6050 Exception when others then
6051 log_n('Exception in set_data_source_PT '||sqlerrm);
6052 raise;
6053 End;
6054
6055 /*given a DS and a dimset, this goes through the hpt data of the PT in the dimset, then assigns corrected hpt data to data source data_source_PT
6056 it also loads data_source_pt.dim_parent_child and data_source_pt.cal_parent_child if rollups are reqd */
6057 procedure set_DS_hpt_rollup_data(p_dim_set dim_set_r,p_data_source in out nocopy data_source_r) is
6058 l_hpt_data hpt_data_r;
6059 Begin
6060 l_hpt_data:=p_data_source.data_source_PT.partition_template.hpt_data;
6061 /*reset DS.partition.hpt_data info. we do so because we need to set only those levels that the DS is responsible for */
6062 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.delete;
6063 set_DS_hpt_rollup_data(p_data_source.dim,l_hpt_data,p_data_source);
6064 set_DS_hpt_rollup_data(p_data_source.std_dim,l_hpt_data,p_data_source);
6065 set_DS_hpt_rollup_data(p_dim_set.calendar,p_data_source.calendar,l_hpt_data,p_data_source);
6066 /*we have to pass dimset cal because DS cal does not have all periodicities */
6067 if g_debug then
6068 log('Datasource Partition Template dmp for '||p_dim_set.dim_set_name||' '||p_data_source.ds_type);
6069 dmp_partition_template(p_data_source.data_source_PT.partition_template);
6070 end if;
6071 Exception when others then
6072 log_n('Exception in set_DS_hpt_rollup_data '||sqlerrm);
6073 raise;
6074 End;
6075
6076 /*p_dim can be normal or std dim */
6077 procedure set_DS_hpt_rollup_data(p_DS_dim dim_tb,p_hpt_data hpt_data_r,p_data_source in out nocopy data_source_r) is
6078 l_dim_parent_child parent_child_tb;/*for initialization */
6079 l_index number;
6080 l_parent_child bsc_aw_adapter_dim.dim_parent_child_tb;
6081 l_pc_subset bsc_aw_adapter_dim.dim_parent_child_tb;
6082 l_child_levels dbms_sql.varchar2_table;
6083 Begin
6084 for i in 1..p_DS_dim.count loop
6085 for j in 1..p_hpt_data.hpt_dimensions.count loop /*hpt_dimension does not include time */
6086 if p_DS_dim(i).dim_name=p_hpt_data.hpt_dimensions(j).dim_name then
6087 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(
6088 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count+1).dim_name:=p_hpt_data.hpt_dimensions(j).dim_name;
6089 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(
6093 l_index:=bsc_aw_utility.get_array_index(p_hpt_data.hpt_dimensions(j).level_names,p_DS_dim(i).levels(1).level_name);
6090 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count).dim_type:=p_hpt_data.hpt_dimensions(j).dim_type;
6091 l_dim_parent_child.delete;
6092 p_data_source.data_source_PT.dim_parent_child(p_hpt_data.hpt_dimensions(j).dim_name):=l_dim_parent_child;/*empty parent child info */
6094 if l_index is not null then
6095 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(
6096 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count).level_names(
6097 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(
6098 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count).level_names.count+1):=
6099 p_hpt_data.hpt_dimensions(j).level_names(l_index);
6100 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(
6101 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count).level_keys(
6102 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(
6103 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count).level_keys.count+1):=
6104 p_hpt_data.hpt_dimensions(j).level_keys(l_index);
6105 /*level keys is initially set to dim(i).levels(j).fk */
6106 else
6107 /*there is rollup reqd . for std dim, this part should not be executed*/
6108 /*we will have to find the rollup info for each level that is partitioned and merge the parent child relations. example, we can have hier
6109 like comp>-prod>-prod fam, comp>-prod>-manager. we can have partition at prod fam and manager. then we find the rollup from comp->prodfam
6110 and comp->manager and then merge the 2 pc together */
6111 l_parent_child.delete;
6112 l_pc_subset.delete;
6113 l_child_levels.delete;
6114 bsc_aw_md_api.get_dim_parent_child(p_DS_dim(i).dim_name,l_parent_child);
6115 l_child_levels(l_child_levels.count+1):=p_DS_dim(i).levels(1).level_name;
6116 l_pc_subset:=bsc_aw_adapter_dim.get_hier_subset(l_parent_child,p_hpt_data.hpt_dimensions(j).level_names,l_child_levels);
6117 if l_pc_subset.count=0 then
6118 log('Could not rollup from '||p_DS_dim(i).levels(1).level_name||' to higher levels like '||p_hpt_data.hpt_dimensions(j).level_names(1));
6119 log('This means we cannot rollup from the dim level of the DS to the dim level at which the partition is defined. This is not allowed');
6120 raise bsc_aw_utility.g_exception;
6121 end if;
6122 l_dim_parent_child.delete;
6123 for k in 1..l_pc_subset.count loop
6124 l_dim_parent_child(l_dim_parent_child.count+1).parent_level:=l_pc_subset(k).parent_level;
6125 l_dim_parent_child(l_dim_parent_child.count).child_level:=l_pc_subset(k).child_level;
6126 l_dim_parent_child(l_dim_parent_child.count).parent_pk:=l_pc_subset(k).parent_pk;
6127 l_dim_parent_child(l_dim_parent_child.count).child_fk:=l_pc_subset(k).child_fk;
6128 end loop;
6129 p_data_source.data_source_PT.dim_parent_child(p_hpt_data.hpt_dimensions(j).dim_name):=l_dim_parent_child;
6130 /*from l_pc_subset, we need to find levels that match p_hpt_data.hpt_dimensions(j).level_names. these levels are then loaded
6131 into hpt_dimensions */
6132 for k in 1..p_hpt_data.hpt_dimensions(j).level_names.count loop
6133 for m in 1..l_pc_subset.count loop
6134 if p_hpt_data.hpt_dimensions(j).level_names(k)=l_pc_subset(m).parent_level then
6135 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(
6136 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count).level_names(
6140 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(
6137 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(
6138 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count).level_names.count+1):=
6139 l_pc_subset(m).child_level;
6141 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count).level_keys(
6142 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(
6143 p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count).level_keys.count+1):=
6144 l_pc_subset(m).child_level||'.'||l_pc_subset(m).child_fk;
6145 /*we modify the level key to pick the child.fk example bsc_d_city.state_code when partition is at state
6146 its initially set to dim(i).levels(j).fk . we use this column to hash on
6147 if PT is at DS dim level,level_key will be simply city_code etc. if there is rollup, then it will be bsc_d_city.state_code etc */
6148 --
6149 exit;
6150 end if;
6151 end loop;
6152 end loop;
6153 end if;
6154 --
6155 exit;
6156 end if;
6157 end loop;
6158 end loop;
6159 Exception when others then
6160 log_n('Exception in set_DS_hpt_rollup_data '||sqlerrm);
6161 raise;
6162 End;
6163
6164 /*we can have multiple levels at which partitons are defined. example month and week
6165 each DS can be at one periodicity only*/
6166 procedure set_DS_hpt_rollup_data(p_calendar calendar_r,p_DS_calendar calendar_r,p_hpt_data hpt_data_r,p_data_source in out nocopy data_source_r) is
6167 l_index number;
6168 l_calendar bsc_aw_calendar.calendar_r;
6169 l_ds_periodicity bsc_aw_calendar.periodicity_r;
6170 l_upper_periodicities bsc_aw_calendar.periodicity_tb;
6171 Begin
6172 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.dim_name:=null;
6173 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_names.delete;
6174 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_keys.delete;
6175 if p_hpt_data.hpt_calendar.dim_name is not null and p_hpt_data.hpt_calendar.dim_name=p_DS_calendar.aw_dim then
6176 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.dim_name:=p_hpt_data.hpt_calendar.dim_name;
6177 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.dim_type:=p_hpt_data.hpt_calendar.dim_type;
6178 l_index:=bsc_aw_utility.get_array_index(p_hpt_data.hpt_calendar.level_names,p_DS_calendar.periodicity(1).aw_dim);
6179 if l_index is not null then
6180 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_names(
6181 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_names.count+1):=
6182 p_hpt_data.hpt_calendar.level_names(l_index);
6183 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_keys(
6184 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_keys.count+1):=
6185 p_hpt_data.hpt_calendar.level_keys(l_index);
6186 else /*rollup required */
6187 /*find out the upper periodicities that DS periodicity touches */
6188 /*upgrade(to level 3) must reimplement all calendars so db_column_name is populated in bsc olap metadata */
6189 bsc_aw_calendar.get_calendar(p_DS_calendar.aw_dim,l_calendar);
6190 l_ds_periodicity:=bsc_aw_calendar.get_periodicity_r(p_DS_calendar.periodicity(1).periodicity,l_calendar.periodicity);
6191 bsc_aw_calendar.get_all_upper_periodicities(l_ds_periodicity,l_calendar,l_upper_periodicities);
6192 for j in 1..p_hpt_data.hpt_calendar.level_names.count loop
6193 for k in 1..l_upper_periodicities.count loop
6194 if p_hpt_data.hpt_calendar.level_names(j)=l_upper_periodicities(k).dim_name then
6195 p_data_source.data_source_PT.cal_parent_child(p_data_source.data_source_PT.cal_parent_child.count+1).parent:=
6196 l_upper_periodicities(k).periodicity_id;
6197 p_data_source.data_source_PT.cal_parent_child(p_data_source.data_source_PT.cal_parent_child.count).parent_dim_name:=
6198 l_upper_periodicities(k).db_column_name;
6199 p_data_source.data_source_PT.cal_parent_child(p_data_source.data_source_PT.cal_parent_child.count).child:=
6200 l_ds_periodicity.periodicity_id;
6201 p_data_source.data_source_PT.cal_parent_child(p_data_source.data_source_PT.cal_parent_child.count).child_dim_name:=
6202 l_ds_periodicity.db_column_name;
6203 --
6204 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_names(
6205 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_names.count+1):=l_upper_periodicities(k).dim_name;
6206 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_keys(
6207 p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_keys.count+1):='bsc_db_calendar.'||
6208 l_upper_periodicities(k).db_column_name;
6209 --
6210 exit;
6211 end if;
6212 end loop;
6213 end loop;
6214 end if;
6215 end if;
6216 Exception when others then
6217 log_n('Exception in set_DS_hpt_rollup_data '||sqlerrm);
6218 raise;
6219 End;
6220
6221 function get_DS_PT_hash_stmt(p_dim_set dim_set_r,p_data_source data_source_r)return varchar2 is
6222 pt_stmt varchar2(4000);
6223 Begin
6224 pt_stmt:='dbms_utility.get_hash_value(\''H\''';
6225 for i in 1..p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions.count loop /*loop through dim (Not time)*/
6226 for j in 1..p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(i).level_names.count loop
6227 pt_stmt:=pt_stmt||'||\''-\''||'||p_data_source.data_source_PT.partition_template.hpt_data.hpt_dimensions(i).level_keys(j);
6228 end loop;
6229 end loop;
6230 if p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.dim_name is not null then
6234 pt_ is appended to the columns selected from calendar to prevent clash with columns selected from the DS*/
6231 for i in 1..p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_names.count loop
6232 pt_stmt:=pt_stmt||'||\''-\''||'||p_data_source.data_source_PT.partition_template.hpt_data.hpt_calendar.level_keys(i)||'||\''.\''||year';
6233 /*append year also as part of the calendar key
6235 end loop;
6236 end if;
6237 pt_stmt:=pt_stmt||',0,'||p_dim_set.number_partitions||') ';
6238 return pt_stmt;
6239 Exception when others then
6240 log_n('Exception in get_DS_PT_hash_stmt '||sqlerrm);
6241 raise;
6242 End;
6243
6244 function is_dim_aggregated(p_dim dim_r) return boolean is
6245 Begin
6246 /*if p_dim_set.dim(i).levels.count>1 or p_dim_set.dim(i).zero_code='Y' or p_dim_set.dim(i).recursive='Y' then */
6247 if p_dim.recursive='Y' then
6248 return true;
6249 else
6250 for i in 1..p_dim.levels.count loop
6251 if p_dim.levels(i).aggregated='Y' then
6252 if i=1 then /*lowest level */
6253 if p_dim.levels(i).zero_aggregated='Y' then /*lowest level and there is zero code */
6254 return true;
6255 end if;
6256 else
6257 return true;
6258 end if;
6259 end if;
6260 end loop;
6261 end if;
6262 return false;
6263 Exception when others then
6264 log_n('Exception in is_dim_aggregated '||sqlerrm);
6265 raise;
6266 End;
6267
6268 function is_calendar_aggregated(p_calendar calendar_r) return boolean is
6269 Begin
6270 for i in 1..p_calendar.periodicity.count loop
6271 if p_calendar.periodicity(i).aggregated='Y'
6272 and (p_calendar.periodicity(i).lowest_level is null or p_calendar.periodicity(i).lowest_level<>'Y') then
6273 return true;
6274 end if;
6275 end loop;
6276 return false;
6277 Exception when others then
6278 log_n('Exception in is_calendar_aggregated '||sqlerrm);
6279 raise;
6280 End;
6281
6282 function get_projection_dim(p_dim_set dim_set_r) return varchar2 is
6283 Begin
6284 for i in 1..p_dim_set.std_dim.count loop
6285 if p_dim_set.std_dim(i).dim_name='PROJECTION' then
6286 return p_dim_set.std_dim(i).dim_name;
6287 end if;
6288 end loop;
6289 return null;
6290 Exception when others then
6291 log_n('Exception in get_projection_dim '||sqlerrm);
6292 raise;
6293 End;
6294
6295 function make_display_cube_axis(p_dim_set dim_set_r,p_cube cube_r) return axis_tb is
6296 l_axis axis_tb;
6297 l_dimensions dbms_sql.varchar2_table;
6298 Begin
6299 for i in 1..p_cube.cube_axis.count loop
6300 l_dimensions.delete;
6301 if p_cube.cube_axis(i).axis_type='partition template' then
6302 l_dimensions:=get_partition_template_r(p_cube.cube_axis(i).axis_name,p_dim_set).template_dimensions;
6303 elsif p_cube.cube_axis(i).axis_type='composite' then
6304 l_dimensions:=get_composite_r(p_cube.cube_axis(i).axis_name,p_dim_set).composite_dimensions;
6305 end if;
6306 if l_dimensions.count>0 then
6307 for j in 1..l_dimensions.count loop
6308 l_axis(l_axis.count+1).axis_name:=l_dimensions(j);
6309 l_axis(l_axis.count).axis_type:='dimension';
6310 end loop;
6311 else
6312 l_axis(l_axis.count+1):=p_cube.cube_axis(i);
6313 end if;
6314 end loop;
6315 return l_axis;
6316 Exception when others then
6317 log_n('Exception in get_display_cube_axis '||sqlerrm);
6318 raise;
6319 End;
6320
6321 /*sets the sql_aggregation flag for the measures to Y or N
6322 unset is done only if the dimset is not partitioned
6323 if we have a situation where the agg_formula looks like sum(m1/m2), we have to set this as sql_aggregated=Y. for aw, if this is a formula, we want
6324 the formula to be like m1/m2. I guess this is how the metadata reader api will return the formula. we cannot have sum(m1/m2) specified. because the
6325 formula is applied as it is. like cube3=cube1/cube2.
6326 */
6327 procedure set_sql_aggregations(p_kpi in out nocopy kpi_r,p_action varchar2) is
6328 Begin
6329 for i in 1..p_kpi.dim_set.count loop
6330 if (p_action='set' and bsc_aw_utility.get_db_version>=10.2 and p_kpi.dim_set(i).targets_higher_levels<>'Y')
6331 or (p_action='unset' and p_kpi.dim_set(i).number_partitions=0 and p_kpi.dim_set(i).compressed<>'Y') then
6332 set_sql_aggregations(p_kpi,p_kpi.dim_set(i),p_action);
6333 end if;
6334 end loop;
6335 Exception when others then
6336 log_n('Exception in set_sql_aggregations '||sqlerrm);
6337 raise;
6338 End;
6339
6340 /*if action=set
6341 if there are targets, we do not set sql_aggregated to Y. we need to aggregate the measure and copy the targets
6342 */
6343 procedure set_sql_aggregations(p_kpi kpi_r,p_dim_set in out nocopy dim_set_r,p_action varchar2) is
6344 l_agg_flag varchar2(10);
6345 Begin
6346 if p_action='set' then
6347 l_agg_flag:='Y';
6348 else
6349 l_agg_flag:='N';
6350 end if;
6351 for i in 1..p_dim_set.measure.count loop
6352 if p_dim_set.measure(i).agg_formula.std_aggregation='N' then
6353 p_dim_set.measure(i).sql_aggregated:=l_agg_flag;
6354 end if;
6355 end loop;
6356 Exception when others then
6357 log_n('Exception in set_sql_aggregations '||sqlerrm);
6358 raise;
6359 End;
6360
6361 procedure reset_PT_template(p_partition_template in out nocopy partition_template_r) is
6362 Begin
6363 p_partition_template.template_name:=null;
6364 p_partition_template.template_type:=null;
6365 p_partition_template.template_use:=null;
6366 p_partition_template.template_dim:=null;
6367 p_partition_template.template_dimensions.delete;
6368 p_partition_template.template_partitions.delete;
6369 p_partition_template.hpt_data.hpt_dimensions.delete;
6370 p_partition_template.hpt_data.hpt_calendar.dim_name:=null;
6371 Exception when others then
6372 log_n('Exception in reset_PT_template '||sqlerrm);
6373 raise;
6374 End;
6375
6376 /*used in partitions to see if we can get partitions done with display cubes. data is copied into display cubes for
6377 aggregations at viewer time */
6378 function is_display_cube_required(p_dim_set dim_set_r,p_cube varchar2) return boolean is
6379 measures measure_tb;
6380 flag boolean;
6381 Begin
6382 flag:=false;
6383 if p_dim_set.number_partitions>0 then
6384 if p_dim_set.compressed='Y' then
6385 if g_debug then
6386 log('Compressed composite. partitions possible only with display cube');
6387 end if;
6388 flag:=true;
6389 end if;
6390 if flag=false then
6391 measures.delete;
6392 get_measures_for_cube(p_cube,p_dim_set,measures);
6393 for i in 1..measures.count loop
6394 if measures(i).agg_formula.std_aggregation='N' and measures(i).sql_aggregated='N' then
6395 if g_debug then
6396 log('Non std agg in dimset '||p_dim_set.dim_set||', partitions possible only with display cube');
6397 end if;
6398 flag:=true;
6399 exit;
6400 end if;
6401 if bsc_aw_utility.is_PT_aggregation_function(measures(i).agg_formula.agg_formula)='N' then
6402 if g_debug then
6403 log('Non partitionable aggregation function '||measures(i).agg_formula.agg_formula||'. Partitions possible only with '||
6404 'display cubes');
6405 end if;
6406 flag:=true;
6407 exit;
6408 end if;
6409 end loop;
6410 end if;
6411 end if;
6412 return flag;
6413 Exception when others then
6414 log_n('Exception in is_display_cube_required '||sqlerrm);
6415 raise;
6416 End;
6417
6418 function is_display_cube_possible(p_dim_set dim_set_r) return boolean is
6419 Begin
6420 if nvl(bsc_aw_utility.get_parameter_value('NO DISPLAY CUBE'),'N')='Y' then
6421 return false;
6422 end if;
6423 return true;
6424 Exception when others then
6425 log_n('Exception in is_display_cube_possible '||sqlerrm);
6426 raise;
6427 End;
6428
6429 function get_dim_set_lowest_periodicity(p_dim_set dim_set_r) return periodicity_tb is
6430 periodicity periodicity_tb;
6431 Begin
6432 for i in 1..p_dim_set.calendar.periodicity.count loop
6433 if p_dim_set.calendar.periodicity(i).lowest_level='Y' then
6434 periodicity(periodicity.count+1):=p_dim_set.calendar.periodicity(i);
6435 end if;
6436 end loop;
6437 return periodicity;
6438 Exception when others then
6439 log_n('Exception in get_dim_set_lowest_periodicity '||sqlerrm);
6440 raise;
6441 End;
6442
6443 ------------------
6444 procedure init_all is
6445 Begin
6446 g_debug:=bsc_aw_utility.g_debug;
6447 Exception when others then
6448 null;
6449 End;
6450
6451 procedure log(p_message varchar2) is
6452 Begin
6453 bsc_aw_utility.log(p_message);
6454 Exception when others then
6455 null;
6456 End;
6457
6458 procedure log_n(p_message varchar2) is
6459 Begin
6460 log(' ');
6461 log(p_message);
6462 Exception when others then
6463 null;
6464 End;
6465
6466 END BSC_AW_ADAPTER_KPI;