DBA Data[Home] [Help]

PACKAGE BODY: APPS.BSC_MO_INPUT_TABLE_PKG

Source


1 Package Body BSC_MO_INPUT_TABLE_PKG  AS
2 /* $Header: BSCMOIPB.pls 120.28 2006/04/19 16:29:18 arsantha noship $ */
3 g_newline VARCHAR2(10):= '
4 ';
5 
6 
7 FUNCTION get_measure_group(p_field_name IN VARCHAR2, p_source IN VARCHAR2) return NUMBER IS
8 cursor cMeasureGroup  IS
9 select measure_group_id from bsc_db_measure_cols_vl
10 where measure_col = p_field_name;
11 --and measure_type = 0;
12 l_measure_group number;
13 l_temp number;
14 BEGIN
15   l_temp := bsc_mo_helper_pkg.findIndex(BSC_METADATA_OPTIMIZER_PKG.gLov, p_field_name, p_source, false);
16   l_measure_group := BSC_METADATA_OPTIMIZER_PKG.gLov(l_temp).groupCode;
17   return l_measure_group;
18 END;
19 
20 
21 FUNCTION get_measures_for_table(p_table_pattern in varchar2) return  BSC_METADATA_OPTIMIZER_PKG.tab_clsDataField IS
22 l_stmt varchar2(1000):='SELECT distinct column_Name, source
23  FROM bsc_db_tables_cols
24  WHERE column_type = :1
25    AND table_name like :2
26    AND column_name not like :3';
27 cv CurTyp;
28 l_measure_col VARCHAR2(320);
29 l_source VARCHAR2(100);
30 l_datafield BSC_METADATA_OPTIMIZER_PKG.clsDataField;
31 l_data  BSC_METADATA_OPTIMIZER_PKG.tab_clsDataField;
32 BEGIN
33   OPEN cv FOR l_stmt using 'A', p_table_pattern, 'BSCIC%';
34   LOOP
35     FETCH cv INTO l_measure_col, l_source;
36     EXIT WHEN cv%NOTFOUND;
37     l_datafield.fieldName := l_measure_col;
38     l_datafield.source := l_source;
39     l_data(l_data.count+1) := l_datafield;
40   END LOOP;
41   CLOSE cv;
42   return l_data;
43    EXCEPTION WHEN OTHERS THEN
44   bsc_mo_helper_pkg.TerminateWithMsg('Exception in get_measures_for_table:'||sqlerrm);
45   raise;
46 END;
47 
48 FUNCTION get_measure_group(p_table IN VARCHAR2, p_data IN BSC_METADATA_OPTIMIZER_PKG.tab_clsDataField, p_indicator NUMBER, p_dim_set NUMBER) return NUMBER IS
49 
50 l_obj_measures BSC_METADATA_OPTIMIZER_PKG.tab_clsDataField;
51 l_table_measures  BSC_METADATA_OPTIMIZER_PKG.tab_clsDataField;
52 cursor cMeasureGroup(p_measure VARCHAR2) IS
53 select measure_group_id from bsc_db_measure_cols_vl
54 where measure_col = p_measure
55 and measure_type = 0;
56 l_measure_group number;
57 BEGIN
58   l_measure_group := -99999;
59   IF (p_data.count =0) then
60     return l_measure_group;
61   END IF;
62   l_obj_measures := get_measures_for_table('BSC_S_'||p_indicator||'_'||p_dim_set||'%');
63   bsc_mo_helper_pkg.writeTmp('# of measures in BSC_S_'||p_indicator||'_'||p_dim_set ||'% is '||l_obj_measures.count||', # in p_data='||p_data.count);
64 
65   FOR i IN p_data.first..p_data.last LOOP
66     FOR j IN 1..l_obj_measures.count LOOP
67       IF (p_data(i).fieldName = l_obj_measures(j).fieldName AND
68           p_data(i).source = l_obj_measures(j).source) THEN
69         return get_measure_group(p_data(i).fieldName, p_data(i).source);
70       END IF;
71     END LOOP;
72   END LOOP;
73   return l_measure_group;
74   EXCEPTION WHEN OTHERS THEN
75   bsc_mo_helper_pkg.TerminateWithMsg('Exception in get_measure_group:'||sqlerrm);
76   raise;
77 END;
78 
79 
80 PROCEDURE set_origin_table_from_db(KpiTable IN OUT NOCOPY BSC_METADATA_OPTIMIZER_PKG.clsTable) IS
81   TableName VARCHAR2(100);
82   SourceTableName VARCHAR2(100);
83   TablaOri VARCHAR2(1000);
84   l_stmt VARCHAR2(1000);
85   lstKeys VARCHAR2(1000);
86   l_key BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
87   l_index NUMBER;
88   l_counter NUMBER;
89   cv   CurTyp;
90   KpiTableName VARCHAR2(100);
91   l_error VARCHAR2(1000);
92   CURSOR cTable(l_src IN VARCHAR2, l_tbl IN VARCHAR2) IS
93   SELECT table_name  FROM bsc_db_tables_rels
94   WHERE source_table_name = l_src  AND table_name LIKE l_tbl;
95 
96   CURSOR cColumns(l_table IN VARCHAR2, l_column IN VARCHAR2, l_column_type IN VARCHAR2)  IS
97   SELECT source_column  FROM bsc_db_tables_cols
98   WHERE table_name = l_table AND UPPER(column_name) = l_column AND column_type = l_column_type;
99 
100 BEGIN
101 
102   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
103     bsc_mo_helper_pkg.writeTmp('set_origin_table_from_db for table='||KpiTable.name);
104   END IF;
105   l_index := bsc_mo_helper_pkg.findIndex(BSC_METADATA_OPTIMIZER_PKG.gIndicators, KpiTable.Indicator);
106   If BSC_METADATA_OPTIMIZER_PKG.gIndicators(l_index).OptimizationMode = 0 Then
107     --The indicator is pre-calculated.
108     TableName := 'BSC_S_' || KpiTable.Indicator || '_' || KpiTable.Configuration || '%';
109     If KpiTable.keys.Count = 0 Then
110       l_stmt := 'SELECT DISTINCT r.source_table_name FROM bsc_db_tables_rels r, bsc_db_tables t
111                 WHERE r.table_name LIKE  :1  AND
112                 NOT r.source_table_name LIKE :2  AND
113                 r.table_name = t.table_name AND
114                 t.periodicity_id = :3 AND
115                 r.relation_type = 0';
116     Else
117       lstKeys := null;
118       l_counter := KpiTable.keys.first;
119       LOOP
120         EXIT WHEN KpiTable.keys.count = 0;
121         l_key := KpiTable.keys(l_counter);
122         If lstKeys IS NOT NULL Then
123           lstKeys := lstKeys || ',';
124         End If;
125         lstKeys := lstKeys || ''''|| l_key.keyName ||'''';
126         EXIT WHEN l_counter = KpiTable.keys.last;
127         l_counter := KpiTable.keys.next(l_counter);
128       END LOOP;
129       l_stmt := 'SELECT DISTINCT table_name AS SOURCE_TABLE_NAME
130                 FROM bsc_db_tables_cols
131                 WHERE table_name IN (
132                 SELECT r.source_table_name
133                 FROM bsc_db_tables_rels r, bsc_db_tables t
134                 WHERE r.table_name LIKE :1 AND
135                 NOT r.source_table_name LIKE :2 AND
136                 r.table_name = t.table_name AND
137                 t.periodicity_id = :3 AND
138                 r.relation_type = 0 ) AND
139                 column_name IN (' || lstKeys || ') AND
140                 column_type = ''P''
141                 GROUP BY table_name
142                 HAVING COUNT(column_name) = ' || KpiTable.keys.Count;
143     END IF;
144   ELSE
145     --The indicator is not pre-calculated
146     If KpiTable.IsTargetTable Then
147       TableName := 'BSC_SB_' || KpiTable.Indicator || '_' || KpiTable.Configuration || '%';
148     Else
149       TableName := 'BSC_S_' || KpiTable.Indicator || '_' || KpiTable.Configuration || '%';
150     End If;
151     l_stmt := 'SELECT DISTINCT r.source_table_name
152           FROM bsc_db_tables_rels r, bsc_db_tables t
153           WHERE r.table_name LIKE :1 AND
154           NOT r.source_table_name LIKE :2 AND
155           r.table_name = t.table_name AND
156           t.periodicity_id = :3 AND r.relation_type = 0';
157   End If;
158 
159   OPEN cv FOR l_stmt using TableName,TableName, KpiTable.Periodicity;
160   LOOP
161     FETCH cv INTO SourceTableName;
162     EXIT WHEN cv%NOTFOUND;
163     --Add the table to the collection of origin tables of the table
164     IF (KpiTable.originTable IS NOT NULL) THEN
165       KpiTable.originTable := KpiTable.originTable ||',';
166     END IF;
167 	IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
168       bsc_mo_helper_pkg.writeTmp('1. Adding Origin table for '||KpiTable.name||' = '||SourceTableName);
169 	END IF;
170     KpiTable.originTable := KpiTable.originTable ||SourceTableName;
171     --Add the table to the gloabel array garrTablesUpgrade
172     If Not bsc_mo_helper_pkg.searchStringExists(
173               bsc_metadata_optimizer_pkg.garrTablesUpgradeT,
174               bsc_metadata_optimizer_pkg.gnumTablesUpgradeT,
175               SourceTableName) Then
176       bsc_metadata_optimizer_pkg.garrTablesUpgradeT(bsc_metadata_optimizer_pkg.gnumTablesUpgradeT) := SourceTableName;
177       bsc_metadata_optimizer_pkg.gnumTablesUpgradeT := bsc_metadata_optimizer_pkg.gnumTablesUpgradeT + 1;
178     End If;
179   END LOOP;
180   Close cv;
181   --Bug#3340878 Need to set the source key column of the table
182   --Get the name of the table previous to the upgrade. Remember that the name of
183   --the table was changed from BSC_S_3001_0_12345_5 to BSC_S_3001_0_0_5
184   OPEN cTable(SourceTableName, TableName);
185   FETCH cTable INTO KpiTableName;
186   Close cTable;
187   l_counter := KpiTable.keys.first;
188   LOOP
189     EXIT WHEN KpiTable.keys.count = 0;
190     l_key := KpiTable.keys(l_counter);
191     OPEN cColumns (KpiTableName, UPPER(l_key.keyName), 'P');
192     FETCH cColumns INTO l_key.origin;
193     close cColumns;
194     KpiTable.keys(l_counter) := l_key ;
195     EXIT WHEN l_counter = KpiTable.keys.last;
196     l_counter := KpiTable.keys.next(l_counter);
197   END LOOP;
198   EXCEPTION WHEN OTHERS THEN
199     l_error := sqlerrm;
200     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in set_origin_table_from_db : '||l_error);
201     raise;
202 End ;
203 
204 PROCEDURE load_upgrade_tables_db IS
205 i NUMBEr;
206 l_stmt VARCHAR2(4000);
207 l_table bsc_metadata_optimizer_pkg.clsTable;
208 l_key bsc_metadata_optimizer_pkg.clsKeyField;
209 l_measure bsc_metadata_optimizer_pkg.clsDataField;
210 TablaOri VARCHAR2(4000);
211 Target_Flag NUMBER;
212 cv   CurTyp;
213 New_clsKeyField bsc_metadata_optimizer_pkg.clsKeyField;
214 New_clsDataField bsc_metadata_optimizer_pkg.clsDataField;
215 CURSOR cTable (pTable IN VARCHAR2) IS
216 SELECT TABLE_NAME, TABLE_TYPE, PERIODICITY_ID, EDW_FLAG, CURRENT_PERIOD, TARGET_FLAG
217               FROM BSC_DB_TABLES
218               WHERE TABLE_NAME = pTable;
219 cTableRow cTable%ROWTYPE;
220 
221 CURSOR cCols (pTable IN VARCHAR2) IS
222   SELECT COLUMN_TYPE, COLUMN_NAME, SOURCE_COLUMN, SOURCE_FORMULA
223          --BSC Autogen
224          , SOURCE
225          , measure_group_id
226     FROM BSC_DB_TABLES_COLS cols, bsc_db_measure_cols_vl dbcols
227    WHERE cols.TABLE_NAME = pTable
228      AND cols.column_name = dbcols.measure_col(+);
229 cColsRow cCols%ROWTYPE;
230 
231 CURSOR cTableRels0(pTable IN VARCHAR2) IS
232   SELECT SOURCE_TABLE_NAME
233   FROM BSC_DB_TABLES_RELS
234   WHERE TABLE_NAME = pTable
235   AND RELATION_TYPE = 0
236   ORDER BY SOURCE_TABLE_NAME;
237 cTableRels0Row cTableRels0%ROWTYPE;
238 
239 CURSOR cTableRels1(pTable IN VARCHAR2) IS
240 SELECT SOURCE_TABLE_NAME
241         FROM BSC_DB_TABLES_RELS
242         WHERE TABLE_NAME = pTable
243         AND RELATION_TYPE = 1
244         ORDER BY SOURCE_TABLE_NAME;
245 cTableRels1Row cTableRels1%ROWTYPE;
246 l_error VARCHAR2(1000);
247 l_stack varchar2(32000);
248 l_table_null bsc_metadata_optimizer_pkg.clsTable;
249 BEGIN
250 
251   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
252     BSC_MO_HELPER_PKG.writeTmp('Inside load_upgrade_tables_db, upg tables = '||bsc_metadata_optimizer_pkg.gnumTablesUpgrade);
253   END IF;
254 
255   For i IN 0..bsc_metadata_optimizer_pkg.gnumTablesUpgrade - 1 LOOP
256     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
257       BSC_MO_HELPER_PKG.writeTmp('');
258       BSC_MO_HELPER_PKG.writeTmp('Processing table '||bsc_metadata_optimizer_pkg.garrTablesUpgrade(i));
259     END IF;
260     OPEN cTable(bsc_metadata_optimizer_pkg.garrTablesUpgrade(i));
261     FETCH cTable INTO cTableRow;
262     l_stack := l_stack || g_newline||'Step 1';
263     If cTable%FOUND Then
264       l_table := l_table_null;
265       l_table.Name := cTableRow.TABLE_NAME;
266       l_table.Type := cTableRow.TABLE_TYPE;
267       l_table.Periodicity := cTableRow.PERIODICITY_ID;
268       l_table.EDW_Flag := cTableRow.EDW_FLAG;
269       l_stack := l_stack || g_newline||'Step 1.1';
270       If cTableRow.TARGET_FLAG = 1 Then
271         l_table.IsTargetTable := True;
272       Else
273         l_table.IsTargetTable := False;
274       End If;
275       l_stack := l_stack || g_newline||'Step 1.2';
276       l_table.currentPeriod := cTableRow.CURRENT_PERIOD;
277       l_stack := l_stack || g_newline||'Step 2';
278       OPEN cCols(UPPER(l_table.name));
279       l_stack := l_stack || g_newline||'Step 2.1';
280       LOOP
281         l_stack := l_stack || g_newline||'Step 2.2';
282         FETCH cCols INTO cColsRow;
283         EXIT WHEN cCols%NOTFOUND;
284         l_stack := l_stack || g_newline||'Step 2.3';
285         If UPPER(cColsRow.COLUMN_TYPE) = 'P' Then
286           --Key column
287           l_stack := l_stack || g_newline||'Step 2.4';
288           l_key := New_clsKeyField;
289           l_key.keyName := cColsRow.COLUMN_NAME;
290           l_key.Origin := cColsRow.SOURCE_COLUMN;
291           l_key.NeedsCode0 := False;
292           l_key.CalculateCode0 := False;
293           l_key.FilterViewName := null;
294           l_table.keys(l_table.keys.count) :=  l_key;
295           l_stack := l_stack || g_newline||'Step 2.5';
296         Else
297           --Data column
298           l_stack := l_stack || g_newline||'Step 2.6';
299           l_measure := New_clsDataField;
300           l_measure.fieldName := cColsRow.COLUMN_NAME;
301           l_measure.source := cColsRow.source;
302           l_measure.measureGroup := cColsRow.measure_group_id;
303           l_measure.Origin := cColsRow.SOURCE_FORMULA;
304           l_measure.AggFunction := null;
305           l_table.data(l_table.data.count) := l_measure;
306           l_stack := l_stack || g_newline||'Step 2.7';
307         End If;
308       END Loop;
309       Close cCols;
310       l_stack := l_stack || g_newline||'Step 3';
311       --Source tables (Hard Relations)
312       OPEN cTableRels0 (UPPER(l_table.name));
313       l_stack := l_stack || g_newline||'Step 3.1';
314       LOOP
315         FETCH cTableRels0 INTO cTableRels0Row;
316         l_stack := l_stack || g_newline||'Step 3.2';
317         EXIT WHEN cTableRels0%NOTFOUND;
318         l_stack := l_stack || g_newline||'Step 3.3';
319         IF (l_table.originTable IS NOT NULL) THEN
320           l_table.originTable := l_table.originTable ||',';
321         END IF;
322         l_stack := l_stack || g_newline||'Step 3.4';
323         l_table.originTable := l_table.originTable || cTableRels0Row.SOURCE_TABLE_NAME;
324         IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
325           bsc_mo_helper_pkg.writeTmp('Adding Origin table '||cTableRels0Row.SOURCE_TABLE_NAME);
326         END IF;
327       END LOOP;
328       Close cTableRels0;
329       l_stack := l_stack || g_newline||'Step 4';
330       --Source table (Soft Relations)
331       OPEN cTableRels1(UPPER(l_table.Name));
332       l_stack := l_stack || g_newline||'Step 4.1';
333       LOOP
334         FETCH cTableRels1 INTO cTableRels1Row;
335         l_stack := l_stack || g_newline||'Step 4.2';
336         EXIT WHEN cTableRels1%NOTFOUND;
337         l_stack := l_stack || g_newline||'Step 4.3';
338         IF (l_table.originTable IS NOT NULL) THEN
339           l_table.originTable := l_table.originTable ||',';
340         END IF;
341         l_stack := l_stack || g_newline||'Step 4.4';
342         l_stack := l_stack || g_newline||'Adding Origin table '||cTableRels1Row.SOURCE_TABLE_NAME;
343         IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
344           bsc_mo_helper_pkg.writeTmp('Adding Origin table '||cTableRels1Row.SOURCE_TABLE_NAME);
345         END IF;
346         l_table.originTable := l_table.originTable || cTableRels1Row.SOURCE_TABLE_NAME;
347       END LOOP;
348       Close cTableRels1;
349       --The tables in garrTablesUpgrade() are not used direclty by any indicator
350       l_table.Indicator := 0;
351       l_table.Configuration := 0;
352       l_table.upgradeFlag := 1;
353       --Add table to collection
354       BSC_MO_HELPER_PKG.addTable(l_table, l_table.keys, l_table.data, 'load_upgrade_tables_db');
355       --l_table_keys.delete;
356       --l_table_measures.Delete;
357       l_table := BSC_MO_HELPER_PKG.new_clsTable;
358     End If;
359     Close cTable;
360     IF (length(l_stack) > 30000) THEN
361       l_stack := null;
362     END IF;
363   END LOOP;
364   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
365     BSC_MO_HELPER_PKG.writeTmp('Completed load_upgrade_tables_db');
366   END IF;
367   EXCEPTION WHEN OTHERS THEN
368       l_error := sqlerrm;
369       BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in load_upgrade_tables_db : '||l_error, FND_LOG.LEVEL_UNEXPECTED);
370       BSC_MO_HELPER_PKG.writeTmp('l_stack ='||l_stack, FND_LOG.LEVEL_UNEXPECTED, true);
371       raise;
372 End ;
373 
374 
375 --****************************************************************************
376 --  TodasDesagsRegistradas
377 --
378 --  DESCRIPTION:
379 --     Returns TRUE if all the dissagregations in the given collection
380 --     have been registered
381 --
382 --  PARAMETERS:
383 --     p_key_combinations: dissagregations
384 --
385 --  AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
386 --****************************************************************************
387 Function all_key_comb_registered(p_key_combinations BSC_METADATA_OPTIMIZER_PKG.tab_clsDisaggField) return Boolean IS
388 key_combination BSC_METADATA_OPTIMIZER_PKG.clsDisaggField;
389 l_index NUMBER;
390 l_error VARCHAR2(1000);
391 BEGIN
392   IF (p_key_combinations.count=0) THEN
393       return true;
394   END IF;
395   l_index := p_key_combinations.first;
396   LOOP
397     key_combination := p_key_combinations(l_index);
398     If Not key_combination.Registered Then
399       return false;
400     End If;
401     EXIT WHEN l_index = p_key_combinations.last;
402     l_index := p_key_combinations.next(l_index);
403   END LOOP;
404   return true;
405   EXCEPTION WHEN OTHERS THEN
406     l_error := sqlerrm;
407     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in all_key_comb_registered : '||l_error, FND_LOG.LEVEL_UNEXPECTED);
408     raise;
409 End;
410 
411 
412 --****************************************************************************
413 --  TableOriginExists
414 --
415 --  DESCRIPTION:
416 --     Return TRUE if the table exist in the collection. The collection
417 --     is of objects of type clsTablaOri
418 --
419 --  PARAMETERS:
420 --     p_table_origins: collection
421 --     p_table_name: table name
422 --
423 --  AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
424 --****************************************************************************
425 Function TableOriginExists(p_table_origins IN VARCHAR2,
426                 p_table_name IN VARCHAR2) RETURN Boolean IS
427   l_table VARCHAR2(100);
428   l_count1 NUMBER;
429   l_origins DBMS_SQL.VARCHAR2_TABLE;
430   l_error VARCHAR2(1000);
431 BEGIN
432   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
433     BSC_MO_HELPER_PKG.writeTmp('Inside TableOriginExists, key_combinations = ', FND_LOG.LEVEL_PROCEDURE);
434     BSC_MO_HELPER_PKG.writeTmp(' Parameter p_table_name='||p_table_name
435               ||', and p_table_origins is '||p_table_origins, FND_LOG.LEVEL_STATEMENT);
436   END IF;
437   l_origins := BSC_MO_HELPER_PKG.getDecomposedString(p_table_origins, ',');
438   IF (l_origins.count = 0) THEN
439     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
440       BSC_MO_HELPER_PKG.writeTmp('Completed TableOriginExists, returning false', FND_LOG.LEVEL_PROCEDURE);
441     END IF;
442     return false;
443   END IF;
444   l_count1 := l_origins.first;
445   LOOP
446     l_table := l_origins(l_count1);
447     If UPPER(l_table) = UPPER(p_table_name) Then
448       IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
449         BSC_MO_HELPER_PKG.writeTmp('Completed TableOriginExists, returning true', FND_LOG.LEVEL_PROCEDURE);
450       END IF;
451       return true;
452     End If;
453     EXIT WHEN l_count1= l_origins.last;
454     l_count1 := l_origins.next(l_count1);
455   END LOOP;
456   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
457     BSC_MO_HELPER_PKG.writeTmp('Completed TableOriginExists, returning false', FND_LOG.LEVEL_PROCEDURE);
458   END IF;
459   return false;
460   EXCEPTION WHEN OTHERS THEN
461     l_error := sqlerrm;
462     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in TableOriginExists : '||l_error);
463     raise;
464 End ;
465 --****************************************************************************
466 --  IndexTablaTemporalMismaDesagyCodAgrupCampo : get_matching_tables
467 --
468 --  DESCRIPTION:
469 --     Returns the index on collection p_BTTables whose table
470 --     has the given periodicity and the given key columns and the first
471 --     data field of the temporal table has the given grouping code.
472 --     Returns -1 if it is not found.
473 --
474 --  PARAMETERS:
475 --     pPeriodicity: periodicity
476 --     keyCols: key columns
477 --     dataFieldGroup: grouping code of the data fields
478 --
479 --  AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
480 --****************************************************************************
481 Function get_matching_tables(
482       p_measure_col IN VARCHAR2,
483       --BSC Autogen
484       p_measure_source IN VARCHAR2,
485       pPeriodicity IN NUMBER,
486       p_keys BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField,
487       dataFieldGroup IN NUMBER,
488       p_impl_type IN NUMBER,
489       p_BTTables IN OUT NOCOPY BSC_METADATA_OPTIMIZER_PKG.tab_ClsTable) RETURN DBMS_SQL.NUMBER_TABLE IS
490   l_table BSC_METADATA_OPTIMIZER_PKG.clsTable;
491   l_key BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
492   keysEqual Boolean;
493   i Integer;
494   toBeConsidered Boolean;
495   l_return NUMBER := 0;
496   l_index1 NUMBER;
497   l_index2 NUMBER;
498   l_temp NUMBER;
499   l_error VARCHAR2(1000);
500   l_return_table DBMS_SQL.NUMBER_TABLE ;
501 BEGIN
502   IF (p_BTTables.count = 0) THEN
503     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
504       BSC_MO_HELPER_PKG.writeTmp('Done with get_matching_tables, returning -1', FND_LOG.LEVEL_PROCEDURE);
505     END IF;
506     return l_return_table;
507   END IF;
508 
509   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
510     BSC_MO_HELPER_PKG.writeTmp('Within get_matching_tables, measure='||p_measure_col||', source='||p_measure_source||', Periodicity = '||pPeriodicity||', dataFieldGroup ='||dataFieldGroup||', impl_type='||p_impl_type);
511   END IF;
512   i := p_BTTables.first;
513   LOOP
514     toBeConsidered := True;
515 
516     If p_BTTables(i).Data.Count > 0 Then
517       l_temp := BSC_MO_HELPER_PKG.findIndex(BSC_METADATA_OPTIMIZER_PKG.gLov,
518                                             p_BTTables(i).Data(0).fieldName,
519                                             p_BTTables(i).Data(0).source);
520       If BSC_METADATA_OPTIMIZER_PKG.gLov(l_temp).groupCode <> dataFieldGroup
521         -- BSC AW
522 	     OR (p_BTTables(i).impl_type <> p_impl_type)
523 	    --BSC Autogen
524         -- If new table(not production table), column shouldnt already exist
525 	     OR (p_BTTables(i).isProductionTable=false AND BSC_MO_INDICATOR_PKG.DataFieldExists(p_BTTables(i).Data, p_measure_col) )
526 	  Then
527         toBeConsidered := False;
528       End If;
529     Else
530        toBeConsidered := false;
531     End If;
532     If toBeConsidered Then
533       If p_BTTables(i).Periodicity = pPeriodicity Then
534         If p_BTTables(i).keys.Count = p_keys.Count Then
535           keysEqual := True;
536           l_index1 := p_BTTables(i).keys.first;
537           LOOP
538             EXIT WHEN p_BTTables(i).keys.count=0;
539             l_key := p_BTTables(i).keys(l_index1);
540             If Not BSC_MO_INDICATOR_PKG.keyFieldExists(p_keys, l_key.keyName) Then
541               keysEqual := False;
542               Exit ;
543             Else
544               l_temp := BSC_MO_HELPER_PKG.findIndex(p_keys, l_key.keyName);
545               If UPPER(l_key.FilterViewName) <> UPPER(p_keys(l_temp).FilterViewName) Then
546                 keysEqual := False;
547                 Exit ;
548               End If;
549             End If;
550             EXIT WHEN l_index1 = p_BTTables(i).keys.last;
551             l_index1 := p_BTTables(i).keys.next(l_index1);
552           END LOOP;
553           If keysEqual Then -- see if this is a production table, and if so, if the column exists
554             IF (p_BTTables(i).isProductionTable) THEN
555               -- we can add a production table as a match ONLY if the column NAME doesnt exist
556               IF BSC_MO_INDICATOR_PKG.DataFieldExists(p_BTTables(i).Data, p_measure_col)=true AND
557                  BSC_MO_INDICATOR_PKG.DataFieldExistsforSource(p_BTTables(i).Data, p_measure_col, p_measure_source)=false  THEN
558                 null;
559               ELSE
560                 l_return_table(l_return_table.count) := i;
561                 bsc_mo_helper_pkg.writeTmp('Adding table '||p_BTTables(i).name);
562               END IF;
563             ELSE
564               l_return_table(l_return_table.count) := i;
565               bsc_mo_helper_pkg.writeTmp('Adding table '||p_BTTables(i).name);
566             END IF;
567           End If;
568         End If;
569       End If;
570     End If;
571     EXIT WHEN i = p_BTTables.last;
572     i := p_BTTables.next(i);
573   END LOOP;
574   return l_return_table;
575   EXCEPTION WHEN OTHERS THEN
576     l_error := sqlerrm;
577     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in get_matching_tables : '||l_error, FND_LOG.LEVEL_UNEXPECTED);
578     IF (l_temp=-1) THEN
579       BSC_MO_HELPER_PKG.writeTmp('Measure '||p_BTTables(i).Data(0).fieldName||', source=' ||p_BTTables(i).Data(0).source||' does not exist in the list of measures in bsc_sys_measures.', FND_LOG.LEVEL_STATEMENT, true);
580     END IF;
581     raise;
582 End ;
583 
584 --****************************************************************************
585 --  getMaxTableIndex : MaximoIndiceTablas
586 --
587 --    DESCRIPTION:
588 --       Look for tables whose name start with the given word in BSC_DB_TABLES
589 --       From those tables whose name end with a number, this function return
590 --       the maximun number.
591 --       Example. startsWith = 'T_'
592 --            In BSC_DB_TABLES exists the following tables that start with 'T_':
593 --            'T_1', 'T_A', 'T_2' and 'T_3'. This function return 3
594 --
595 --    PARAMETERS:
596 --       startsWith: Word by which the table name start.
597 --
598 --   AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
599 --****************************************************************************
600 Function getMaxTableIndex(startsWith IN VARCHAR2) return NUMBER IS
601   l_max  NUMBER := 0;
602   cv   CurTyp;
603   l_startsWith VARCHAR2(100);
604   cursor cTables(pStart IN VARCHAR2) IS
605   SELECT table_name from bsc_db_tables
606   where table_name like pStart;
607 
608 
609   l_str_len number := 0;
610 
611   l_error VARCHAR2(2000);
612   l_table varchar2(100);
613 BEGIN
614 
615   l_startsWith := startsWith;
616   l_max := 0;
617   IF (instr(l_startsWith, '%') = 0) THEN
618       l_startsWith := l_startsWith||'%';
619       l_str_len := length(startsWith) ;
620   ELSE
621       l_str_len := length(startsWith)-1 ;
622   END IF;
623 
624 
625   OPEN cTables(l_startsWith);
626   LOOP
627       FETCH cTables INTO l_table;
628       EXIT WHEN CTables%NOTFOUND;
629       l_table := substr(l_table, l_str_len +1);
630 
631       BEGIN
632         If to_number(l_table) > l_max Then
633           l_max := to_number(l_table);
634         End If;
635         EXCEPTION WHEN OTHERS THEN -- not a number
636           null;
637       END ;
638   END Loop;
639   close cTables;
640   IF (l_max IS NULL) THEN
641       l_max := 0;
642   END IF;
643 
644   return l_max;
645 
646   EXCEPTION WHEN OTHERS THEN
647       l_error := sqlerrm;
648       BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in getMaxTableIndex :  '||l_error);
649       raise;
650 
651 End;
652 
653 
654 
655 --****************************************************************************
656 --  HacerTablasEyConectarATablasBasicas : connect_i_to_b_tables
657 --
658 --  DESCRIPTION:
659 --     Make input tables and connect to the base tables
660 --
661 --  AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
662 --****************************************************************************
663 PROCEDURE connect_i_to_b_tables IS
664   l_table BSC_METADATA_OPTIMIZER_PKG.clsTable;
665   TablaE BSC_METADATA_OPTIMIZER_PKG.clsTable;
666 
667   Tabla_Origin DBMS_SQL.VARCHAR2_TABLE;
668 
669   TablaE_Origin DBMS_SQL.VARCHAR2_TABLE;
670 
671   l_key BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
672   l_keyE BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
673   l_measure BSC_METADATA_OPTIMIZER_PKG.clsDataField;
674   l_measureE BSC_METADATA_OPTIMIZER_PKG.clsDataField;
675 
676   l_table_origin VARCHAR2(100);
677   l_index1 NUMBER;
678   l_index2 NUMBER;
679 
680   l_error VARCHAR2(1000);
681   l_table_null BSC_METADATA_OPTIMIZER_PKG.clsTable;
682 BEGIN
683   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
684     BSC_MO_HELPER_PKG.writeTmp('Inside connect_i_to_b_tables '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
685   END IF;
686   IF (BSC_METADATA_OPTIMIZER_PKG.gTables.count=0) THEN
687     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
688       BSC_MO_HELPER_PKG.writeTmp('Completed connect_i_to_b_tables, gTables.count was 0', FND_LOG.LEVEL_PROCEDURE);
689     END IF;
690     return;
691   END IF;
692   l_index1 := BSC_METADATA_OPTIMIZER_PKG.gTables.first;
693   LOOP
694     l_table := l_Table_null;
695     l_table := BSC_METADATA_OPTIMIZER_PKG.gTables(l_index1);
696     IF (l_table.isProductionTable) THEN
697       goto ignore;
698     END IF;
699     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
700       BSC_MO_HELPER_PKG.writeTmp('');
701       BSC_MO_HELPER_PKG.writeTmp('Processing table gTables('||l_index1||
702                         ') : '||l_table.name, FND_LOG.LEVEL_STATEMENT);
703     END IF;
704     Tabla_Origin.delete;
705     Tabla_Origin := BSC_MO_HELPER_PKG.getDecomposedString(l_table.originTable, ',');
706     --For tables with no origin (base tables)
707     If Tabla_origin.Count = 0 And l_table.Type <> 0 Then
708       TablaE := bsc_mo_helper_pkg.new_clsTable;
709       TablaE.Name := 'BSC_I_' ||( BSC_METADATA_OPTIMIZER_PKG.gMaxI + 1);
710       BSC_METADATA_OPTIMIZER_PKG.gMaxI := BSC_METADATA_OPTIMIZER_PKG.gMaxI + 1;
711       TablaE.Type := 0;
712       TablaE.Periodicity := l_table.Periodicity;
713       TablaE.EDW_Flag := l_table.EDW_Flag;
714       TablaE.IsTargetTable := l_table.IsTargetTable;
715       TablaE.impl_type := l_table.impl_type;
716 
717       --Key columns
718       IF (l_table.keys.count>0)THEN
719         l_index2 := l_table.keys.first;
720         LOOP
721           l_keyE := bsc_mo_helper_pkg.new_clskeyfield;
722           l_keyE  := l_table.keys(l_index2);
723           TablaE.keys(TablaE.keys.count) := l_keyE;
724           l_table.keys(L_INDEX2).Origin := l_table.keys(L_INDEX2).keyName;
725           EXIT WHEN l_index2 = l_table.keys.last;
726           l_index2 := l_table.keys.next(l_index2);
727         END LOOP;
728         --l_table.keys := l_table_keys;
729       END IF;
730       --Data columns
731       IF (l_table.data.count>0) THEN
732         l_index2 := l_table.data.first;
733         LOOP
734           l_measureE := bsc_mo_helper_pkg.new_clsDataField;
735           l_measure := l_table.data(l_index2);
736           l_measureE.fieldName := l_measure.fieldName;
737           l_measureE.source := l_measure.source;
738           l_measureE.measureGroup := l_measure.measureGroup;
739           l_measureE.aggFunction := l_measure.aggFunction;
740           --Note: other properties for internal columns are not used in input tables
741           TablaE.Data(TablaE.Data.count) := l_measureE;
742           EXIT WHEN l_index2 = l_table.data.last;
743           l_index2 := l_table.data.next(l_index2);
744         END LOOP;
745       END IF;
746       BSC_MO_HELPER_PKG.addTable(TablaE, TablaE.keys, TablaE.Data, 'connect_i_to_b_tables');
747       l_table_origin := TablaE.Name;
748       IF (l_table.originTable IS NOT NULL ) THEN
749         l_table.originTable := l_table.originTable||',';
750       END IF;
751       IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
752         bsc_mo_helper_pkg.writeTmp('2. Adding Origin table for '||l_table.name||' = '||l_table_origin);
753       END IF;
754       l_table.originTable := l_table.originTable||l_table_origin;
755     End If;
756     BSC_METADATA_OPTIMIZER_PKG.gTables(l_index1) := l_table;
757  <<ignore>>
758     EXIT WHEN l_index1 = BSC_METADATA_OPTIMIZER_PKG.gTables.last;
759     l_index1 := BSC_METADATA_OPTIMIZER_PKG.gTables.next(l_index1);
760   END LOOP;
761   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
762     BSC_MO_HELPER_PKG.writeTmp('Completed connect_i_to_b_tables '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
763   END IF;
764   EXCEPTION WHEN OTHERS THEN
765     l_error := sqlerrm;
766     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in connect_i_to_b_tables : '||l_error, FND_LOG.LEVEL_UNEXPECTED);
767     raise;
768 End;
769 --****************************************************************************
770 --  add_to_gtables: AdicTablasTempATablasSistema
771 --
772 --    DESCRIPTION:
773 --       Add each table of the collection g_bt_tables to the collection
774 --       gTablas.
775 --
776 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
777 --****************************************************************************
778 PROCEDURE add_to_gtables(p_tables IN BSC_METADATA_OPTIMIZER_PKG.tab_clsTable) IS
779   TablaTemp BSC_METADATA_OPTIMIZER_PKG.clsTable;
780   l_table BSC_METADATA_OPTIMIZER_PKG.clsTable;
781   l_keyTemp BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
782   l_key BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
783   l_measureTemp BSC_METADATA_OPTIMIZER_PKG.clsDataField;
784   l_measure BSC_METADATA_OPTIMIZER_PKG.clsDataField;
785   l_index1 NUMBER;
786   l_index2 NUMBER;
787 
788   l_error VARCHAR2(1000);
789 BEGIN
790 
791   IF (p_tables.count =0) THEN
792 	IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
793       BSC_MO_HELPER_PKG.writeTmp('Done with add_to_gtables, p_tables.count=0',
794         FND_LOG.LEVEL_PROCEDURE);
795 	END IF;
796     return;
797   END IF;
798   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
799     BSC_MO_HELPER_PKG.writeTmp('Inside add_to_gtables '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
800   END IF;
801   l_index1 := p_tables.first;
802   LOOP
803     BSC_MO_HELPER_PKG.addTable(p_tables(l_index1), 'add_to_gtables');
804     EXIT WHEN l_index1 = p_tables.last;
805     l_index1 := p_tables.next(l_index1);
806   END LOOP;
807   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
808     BSC_MO_HELPER_PKG.writeTmp('Completed add_to_gtables '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
809   END IF;
810   EXCEPTION WHEN OTHERS THEN
811     l_error := sqlerrm;
812     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in add_to_gtables : '||l_error);
813     raise;
814 End;
815 
816 
817 --****************************************************************************
818 --  get_origin_table: GetNombreTablaTempOri
819 --
820 --    DESCRIPTION:
821 --       Return the name of the tempral table where the given field is found,
822 --       for the specified dissagregation and periodicity.
823 --       It look in the collection p_tables.
824 --       Note: By design, we know that it will be found.
825 --
826 --    PARAMETERS:
827 --       pPeriodicity: periodicity
828 --       Llaves: dissagregation
829 --       NombreCampo: field name
830 --
831 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
832 --****************************************************************************
833 Function get_origin_table(
834                 pPeriodicity IN NUMBER,
835                 keys IN BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField,
836                 fieldName IN VARCHAR2,
837                 p_source IN VARCHAR2,
838                 p_measure_group IN OUT NOCOPY NUMBER,
839 		p_impl_type IN NUMBER,
840                 p_tables IN BSC_METADATA_OPTIMIZER_PKG.tab_clsTable) return VARCHAR2 IS
841   L_Table BSC_METADATA_OPTIMIZER_PKG.clsTable;
842   l_key BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
843   keysEqual Boolean;
844   l_return VARCHAR2(300);
845   l_index1 NUMBER;
846   l_index2 NUMBER;
847   l_index3 NUMBER;
848   l_measure_index   NUMBER;
849   l_start_time date := sysdate;
850   l_error VARCHAR2(1000);
851   l_temp number;
852   l_measure_group number;
853 BEGIN
854   IF (p_tables.count=0) THEN
855     return null;
856   END IF;
857   if (p_measure_group is null) then
858     p_measure_group := get_measure_group(fieldName, p_source);
859   end if;
860   l_measure_index := BSC_MO_HELPER_PKG.findIndex(BSC_METADATA_OPTIMIZER_PKG.gLov, fieldName, p_source);
861   l_measure_group := BSC_METADATA_OPTIMIZER_PKG.gLov(l_measure_index).groupCode;
862   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
863     BSC_MO_HELPER_PKG.writeTmp('Inside get_origin_table, pPeriodicity='||pPeriodicity
864         ||', fieldName ='||fieldName||', source='||p_source||', measure_group='||p_measure_group||',  p_impl_type='||p_impl_type||', p_tables.count = '||
865         p_tables.count, FND_LOG.LEVEL_PROCEDURE);
866   END IF;
867   l_index1 := p_tables.first;
868 
869   LOOP
870     L_Table := p_tables(l_index1);
871     IF BSC_MO_INDICATOR_PKG.DataFieldExistsForSource(L_Table.Data, fieldName, p_source) AND
872        L_Table.impl_type = p_impl_type AND
873        nvl(l_table.measureGroup, -1) = nvl(p_measure_group, -1) THEN
874       If L_Table.Periodicity = pPeriodicity THEN
875         If L_Table.keys.Count = keys.Count THEN
876           keysEqual := True;
877           l_index2 := L_Table.keys.first;
878           LOOP
879             EXIT WHEN L_Table.keys.count = 0;
880             l_key := L_Table.keys(l_index2);
881             If Not BSC_MO_INDICATOR_PKG.keyFieldExists(keys, l_key.keyName) Then
882               keysEqual := False;
883             Else
884               l_temp := BSC_MO_HELPER_PKG.findIndex(keys, l_key.keyName);
885               If UPPER(l_key.FilterViewName) <> UPPER(keys(l_temp).FilterViewName) Then
886                 keysEqual := False;
887                 Exit ;
888               End If;
889             End If;
890             EXIT WHEN l_index2 = L_Table.keys.last;
891             l_index2 := L_Table.keys.next(l_index2);
892           END LOOP;
893           If keysEqual Then
894             IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
895               BSC_MO_HELPER_PKG.writeTmp('Compl get_origin_table, returning '||
896                                 L_Table.Name, FND_LOG.LEVEL_PROCEDURE);
897               BSC_MO_HELPER_PKG.writeTmp('Elapsed time (secs) '||
898                                 (sysdate-l_start_time)*86400, FND_LOG.LEVEL_STATEMENT);
899             END IF;
900             return L_Table.Name;
901           End If;
902         End If;
903       End If;
904     End If;
905     EXIT WHEN l_index1 = p_tables.last;
906     l_index1 := p_tables.next(l_index1);
907   END LOOP;
908   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
909     BSC_MO_HELPER_PKG.writeTmp('Compl get_origin_table, returning null', FND_LOG.LEVEL_PROCEDURE);
910   END IF;
911   return null;
912 
913   EXCEPTION WHEN OTHERS THEN
914         l_error := sqlerrm;
915         BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in get_origin_table : '||l_error);
916         raise;
917 End ;
918 --****************************************************************************
919 --  ConectarTablasIndicadoresConTemporales : connect_s_to_b_tables
920 --
921 --    DESCRIPTION:
922 --       Connect the base tables of the indicators with the temporal tables.
923 --
924 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
925 --****************************************************************************
926 PROCEDURE connect_s_to_b_tables IS
927   l_table BSC_METADATA_OPTIMIZER_PKG.clsTable;
928   l_table_origin VARCHAR2(100);
929   Tabla_originTable DBMS_SQL.VARCHAR2_TABLE;
930   l_key BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
931   l_measure BSC_METADATA_OPTIMIZER_PKG.clsDataField;
932   l_origin_table VARCHAR2(300);
933   l_index1 NUMBER;
934   l_index2 NUMBER;
935   l_index3 NUMBER;
936   l_temp NUMBER;
937 
938   l_start_time date := sysdate;
939   l_end date;
940   l_error VARCHAR2(1000);
941 
942 BEGIN
943   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
944     BSC_MO_HELPER_PKG.writeTmp('Inside connect_s_to_b_tables '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
945     BSC_MO_HELPER_PKG.writeTmp('System time is '||to_char(sysdate, 'hh24:mi:ss'), FND_LOG.LEVEL_STATEMENT);
946   END IF;
947   IF (BSC_METADATA_OPTIMIZER_PKG.gTables.count=0) THEN
948     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
949       BSC_MO_HELPER_PKG.writeTmp('Compl connect_s_to_b_tables, gTables.count was 0', FND_LOG.LEVEL_PROCEDURE);
950     END IF;
951     return;
952   END IF;
953   l_index1 := BSC_METADATA_OPTIMIZER_PKG.gTables.first;
954   LOOP
955     l_table := BSC_METADATA_OPTIMIZER_PKG.gTables(l_index1);
956     Tabla_originTable.delete;
957     Tabla_originTable := BSC_MO_HELPER_PKG.getDecomposedString(l_table.originTable, ',');
958     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
959       BSC_MO_HELPER_PKG.writeTmp('');
960       BSC_MO_HELPER_PKG.writeTmp('Processing table '||l_index1||' '||
961                     l_table.name||', System time is '||bsc_mo_helper_pkg.get_time,
962                     FND_LOG.LEVEL_STATEMENT);
963       BSC_MO_HELPER_PKG.writeTmp('------------------------------------------------');
964     END IF;
965     --Only consider tables with no origin
966     If Tabla_OriginTable.Count = 0 Then
967       --Key columns
968       --For each key assign the origin key name with the same key name
969       IF l_table.keys.count >0 THEN
970         FOR l_index2 IN l_table.keys.first..l_table.keys.last LOOP
971           l_table.keys(l_index2).Origin := l_table.keys(l_index2).keyName;
972          END LOOP;
973       END IF;
974       IF (l_table.data.count>0) THEN
975         FOR l_index2 IN l_table.data.first..l_table.data.last LOOP
976           l_measure := l_table.data(l_index2);
977           If l_measure.InternalColumnType = 0 Then
978             --Do not see internal columns. They are not in base or temporal tables
979             l_temp := BSC_MO_HELPER_PKG.findIndex(  BSC_METADATA_OPTIMIZER_PKG.gIndicators, l_table.Indicator);
980             If BSC_METADATA_OPTIMIZER_PKG.gIndicators(l_temp).OptimizationMode <> 0 Then
981               --non pre-calculated
982               If l_table.IsTargetTable Then
983                 l_origin_table := get_origin_table(
984 		                    l_table.Periodicity,
985                                     l_table.keys,
986                                     l_measure.fieldName,
987                                     l_measure.source,
988                                     l_measure.measureGroup,
989                                     l_table.impl_type,
990                                     BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_tgt);
991               Else
992                 l_origin_table := get_origin_table(
993 			            l_table.Periodicity,
994                                     l_table.keys,
995                                     l_measure.fieldName,
996                                     l_measure.source,
997                                     l_measure.measureGroup,
998                                     l_table.impl_type,
999                                     BSC_METADATA_OPTIMIZER_PKG.g_bt_tables);
1000               End If;
1001             Else
1002               --pre-calculated
1003               l_origin_table := get_origin_table(
1004 			          l_table.Periodicity,
1005                                   l_table.keys,
1006                                   l_measure.fieldName,
1007                                   l_measure.source,
1008                                   l_measure.MeasureGroup,
1009                                   l_table.impl_type,
1010                                   BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc);
1011             End If;
1012             IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1013               BSC_MO_HELPER_PKG.writeTmp('10. Origin = '||l_origin_table, FND_LOG.LEVEL_STATEMENT);
1014             END IF;
1015             IF (l_origin_table is null) THEN
1016                BSC_MO_HELPER_PKG.writeTmp('ERROR:connect_s_to_b_tables: Unable to find source table for '||
1017                  l_table.name||'.'||l_measure.fieldName, FND_LOG.LEVEL_EXCEPTION, true);
1018                raise bsc_metadata_optimizer_pkg.optimizer_exception;
1019             END IF;
1020             --In the Indicator tables l_measure.Origen was already set
1021             --TablasOri
1022             If Not TableOriginExists(l_table.originTable, l_origin_table) Then
1023               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1024                 BSC_MO_HELPER_PKG.writeTmp('11. Table does not have source ', FND_LOG.LEVEL_STATEMENT);
1025               END IF;
1026               l_table_origin := l_origin_table;
1027               IF (l_table.originTable IS NOT NULL) THEN
1028                 l_table.originTable := l_table.originTable||',';
1029               END IF;
1030               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1031                 bsc_mo_helper_pkg.writeTmp('3. Adding Origin table for '||l_table.name||' = '||l_table_origin);
1032               END IF;
1033               l_table.originTable := l_table.originTable||l_table_origin;
1034             End If;
1035           End If;
1036         END LOOP;
1037       END IF;
1038       IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1039         bsc_mo_helper_pkg.writeTmp('Origin count for gTables('||l_index1||') was zero, reassigning this table ');
1040       END IF;
1041       BSC_METADATA_OPTIMIZER_PKG.gTables(l_index1) := l_table;
1042     End If;
1043 
1044     EXIT WHEN l_index1 = BSC_METADATA_OPTIMIZER_PKG.gTables.last;
1045     l_index1 := BSC_METADATA_OPTIMIZER_PKG.gTables.next(l_index1);
1046   END LOOP;
1047   l_end := sysdate;
1048   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1049     BSC_MO_HELPER_PKG.writeTmp('Elapsed time (secs) '||(l_end-l_start_time)*86400, FND_LOG.LEVEL_STATEMENT);
1050   END IF;
1051   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1052     BSC_MO_HELPER_PKG.writeTmp('Completed connect_s_to_b_tables '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
1053   END IF;
1054   EXCEPTION WHEN OTHERS THEN
1055         l_error := sqlerrm;
1056         BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in connect_s_to_b_tables : '||l_error);
1057         raise;
1058 End ;
1059 
1060 
1061 --****************************************************************************
1062 --  InicListaTablasTemporalesyBasicasPreCalc : deduce_bt_tables_precalc
1063 --
1064 --    DESCRIPTION:
1065 --       Initialize the collection g_bt_tables
1066 --
1067 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
1068 --****************************************************************************
1069 PROCEDURE deduce_bt_tables_precalc IS
1070   l_table BSC_METADATA_OPTIMIZER_PKG.clsTable;
1071   uniqueField BSC_METADATA_OPTIMIZER_PKG.clsUniqueField;
1072   l_key_combination BSC_METADATA_OPTIMIZER_PKG.clsDisaggField;
1073   l_key BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
1074   iMatchingTableIndex DBMS_SQL.number_table;
1075   l_datafield BSC_METADATA_OPTIMIZER_PKG.clsDataField;
1076   needNewTable Boolean;
1077   l_index1 NUMBER;
1078   l_index2 NUMBER;
1079   l_index3 NUMBER;
1080   l_temp NUMBER;
1081 
1082   --l_key_combination_keys BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField;
1083   l_error VARCHAR2(1000);
1084   l_loop_Ctr NUMBER;
1085 BEGIN
1086 
1087   IF ( BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc.count=0) THEN
1088     return;
1089   END IF;
1090   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1091     BSC_MO_HELPER_PKG.writeTmp(g_newline||g_newline||g_newline);
1092     BSC_MO_HELPER_PKG.writeTmp('Inside deduce_bt_tables_precalc, # of precalc measures = '||BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc.count||', system time is '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
1093   END IF;
1094   l_index1 := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc.first;
1095 
1096   LOOP
1097     uniqueField := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc(l_index1);
1098     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1099       BSC_MO_HELPER_PKG.writeTmp('Looping for pre calc field = '||    uniqueField.fieldName||', has '||
1100              uniqueField.key_combinations.count||' disaggs ');
1101       bsc_mo_helper_pkg.write_this(g_unique, uniqueField);
1102 	END IF;
1103     --Until all disagregations of the unique field are registered
1104     IF NOT all_key_comb_registered(uniqueField.key_combinations)  THEN
1105       FOR l_index2 IN uniqueField.key_combinations.first..uniqueField.key_combinations.last
1106       LOOP
1107         l_key_combination := uniqueField.key_combinations(l_index2);
1108         bsc_mo_helper_pkg.writeTmp('Processing key combination '||l_index2);
1109         IF (l_key_combination.registered=false) THEN
1110           l_temp := BSC_MO_HELPER_PKG.findIndex(BSC_METADATA_OPTIMIZER_PKG.gLov, uniqueField.fieldName, uniqueField.source);
1111           iMatchingTableIndex := get_matching_tables(
1112                                uniqueField.fieldName,
1113                                uniqueField.source,
1114 	                       l_key_combination.Periodicity,
1115                                l_key_combination.keys,
1116                                BSC_METADATA_OPTIMIZER_PKG.gLov(l_temp).groupCode,
1117                                uniqueField.impl_type,
1118                                BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc);
1119           If iMatchingTableIndex.count = 0 Then
1120             IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1121               BSC_MO_HELPER_PKG.writeTmp(' No existing temporal table with the same periodicity and disagregation');
1122        	    END IF;
1123             --There was not found an existing temporal table with the same periodicity and disagregation
1124             --and filter and whose fields can be grouped with this field
1125             l_table := bsc_mo_helper_pkg.new_clsTable;
1126             l_table.Name := 'BSC_B_'||( BSC_METADATA_OPTIMIZER_PKG.gMaxB + 1);
1127             BSC_METADATA_OPTIMIZER_PKG.gMaxB := BSC_METADATA_OPTIMIZER_PKG.gMaxB + 1;
1128             l_table.Type := 1;
1129             l_table.Periodicity := l_key_combination.Periodicity;
1130             l_table.EDW_Flag := uniqueField.EDW_Flag;
1131             l_table.IsTargetTable := False;
1132             l_table.impl_type := uniqueField.impl_type;
1133             l_table.keys := l_key_combination.keys;
1134             l_table.measureGroup := get_measure_group(uniqueField.fieldname, uniqueField.source);
1135             --Data columns
1136             --It is initialized with only with the this field
1137             l_datafield := bsc_mo_helper_pkg.new_clsDataField;
1138             l_datafield.fieldName := uniqueField.fieldName;
1139             l_datafield.source := uniqueField.source;
1140             l_datafield.measureGroup := l_table.measureGroup;
1141             l_datafield.aggFunction := uniqueField.aggFunction;
1142             l_datafield.Origin := l_datafield.aggFunction || '(' ||l_datafield.fieldName ||')';
1143             --Note: other properties for internal columns are not used in input, base, temporal tables
1144             l_table.data(l_table.data.count) := l_datafield;
1145             --Add the table to the collection g_bt_tables_precalc
1146             BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc(BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc.count) := l_table;
1147             bsc_mo_helper_pkg.writeTmp('Adding following table to g_bt_tables_precalc', FND_LOG.LEVEL_STATEMENT,false);
1148             bsc_mo_helper_pkg.write_this(l_table);
1149           ELSE
1150             --Add the field to the temporal table
1151             --Data columns
1152             --Add this field
1153             l_datafield := bsc_mo_helper_pkg.new_clsDataField;
1154             l_datafield.fieldName := uniqueField.fieldName;
1155             l_datafield.source := uniqueField.source;
1156             l_datafield.measureGroup := get_measure_group(uniqueField.fieldname, uniqueField.source);
1157             l_datafield.aggFunction := uniqueField.aggFunction;
1158             l_datafield.Origin := l_datafield.aggFunction || '(' || l_datafield.fieldName || ')';
1159             --Note: other properties for internal columns are not used in input, base, temporal tables
1160             IF (BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc(iMatchingTableIndex(0)).isProductionTable) THEN
1161               BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc(iMatchingTableIndex(0)).isProductionTableAltered := true;
1162               l_datafield.changeType := 'NEW';
1163             END IF;
1164             BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc(iMatchingTableIndex(0)).data
1165               (BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc(iMatchingTableIndex(0)).data.count) := l_datafield;
1166           End If;
1167         END IF; -- if not registered
1168       END LOOP;
1169     END IF;
1170     EXIT WHEN l_index1 = BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc.last;
1171     l_index1 := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc.next(l_index1);
1172   END LOOP;
1173 
1174   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1175         BSC_MO_HELPER_PKG.writeTmp('g_bt_tables_precalc is ', FND_LOG.LEVEL_STATEMENT);
1176         BSC_MO_HELPER_PKG.write_THIS(BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc, FND_LOG.LEVEL_STATEMENT);
1177         BSC_MO_HELPER_PKG.writeTmp('Completed deduce_bt_tables_precalc, system time is '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
1178 	END IF;
1179 
1180     EXCEPTION WHEN OTHERS THEN
1181         l_error := sqlerrm;
1182         BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in deduce_bt_tables_precalc : '||l_error);
1183         raise;
1184 End;
1185 
1186 --****************************************************************************
1187 --  areDisaggsSame : SonMismasDesagregaciones
1188 --
1189 --    DESCRIPTION:
1190 --       Say if the dissagregations are the same
1191 --
1192 --    PARAMETERS:
1193 --       pPeriodicityA: periodicity A
1194 --       KeysA: Dissagregation A
1195 --       pPeriodicityB: peridiodicity B
1196 --       KeysB: Dissagregation B
1197 --
1198 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
1199 --****************************************************************************
1200 Function areDisaggsSame(
1201   pPeriodicityA   IN NUMBER,
1202   keysA       IN BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField,
1203   pPeriodicityB   IN NUMBER,
1204   keysB       IN BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField) return Boolean IS
1205   keysEqual Boolean;
1206   l_keyA BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
1207   l_index1 NUMBER ;
1208 
1209   l_error VARCHAR2(4000);
1210 BEGIN
1211   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1212     BSC_MO_HELPER_PKG.writeTmp('Inside areDisaggsSame', FND_LOG.LEVEL_PROCEDURE);
1213   END IF;
1214   If pPeriodicityA = pPeriodicityB Then
1215     If keysA.Count = keysB.Count Then
1216       keysEqual := True;
1217       IF (keysA.count> 0) THEN
1218         l_index1 := keysA.first;
1219         LOOP
1220           l_keyA := keysA(l_index1);
1221           If Not BSC_MO_INDICATOR_PKG.keyFieldExists(keysB, l_keyA.keyName) Then
1222             keysEqual := False;
1223             Exit;
1224           End If;
1225           EXIT WHEN l_index1 = keysA.last;
1226           l_index1 := keysA.next(l_index1);
1227         END LOOP;
1228       END IF;
1229       If keysEqual Then
1230 	    IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1231           BSC_MO_HELPER_PKG.writeTmp('Completed areDisaggsSame, ret true', FND_LOG.LEVEL_PROCEDURE);
1232 	    END IF;
1233         return true;
1234       End If;
1235     End If;
1236   End If;
1237 
1238   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1239     BSC_MO_HELPER_PKG.writeTmp('Completed areDisaggsSame ret false', FND_LOG.LEVEL_PROCEDURE);
1240   END IF;
1241   return false;
1242   EXCEPTION WHEN OTHERS THEN
1243     l_error := sqlerrm;
1244     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in areDisaggsSame, '||l_error);
1245     BSC_MO_HELPER_PKG.writeTmp('pPeriodicityA='||pPeriodicityA||', pPeriodicityB='||pPeriodicityB, FND_LOG.LEVEL_EXCEPTION, true);
1246     BSC_MO_HELPER_PKG.writeTmp('KeysA=', FND_LOG.LEVEL_EXCEPTION, true);
1247     BSC_MO_HELPER_PKG.write_this(keysA, FND_LOG.LEVEL_EXCEPTION, true);
1248     BSC_MO_HELPER_PKG.writeTmp('KeysB=', FND_LOG.LEVEL_EXCEPTION, true);
1249     BSC_MO_HELPER_PKG.write_this(keysB, FND_LOG.LEVEL_EXCEPTION, true);
1250     raise;
1251 End ;
1252 --****************************************************************************
1253 --  CreaLoopDesagDestOri:circular_dependency_exists
1254 --
1255 --  DESCRIPTION:
1256 --     Returns TRUE if there will be a loop when the target dissagregation
1257 --     is originated from the source dissagregation.
1258 --     Example. Desag1 --> DesagOri ---> DesagDest ---
1259 --            ^-----------------------------------
1260 --
1261 --  PARAMETERS:
1262 --     p_target_keys: Target dissagregation
1263 --     p_origin_keys: Source dissagregation
1264 --     p_key_combinations: Collection of dissagregations
1265 --
1266 --  AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
1267 --****************************************************************************
1268 Function circular_dependency_exists(
1269         p_target_keys IN NUMBER,
1270         p_origin_keys IN NUMBER,
1271         p_key_combinations BSC_METADATA_OPTIMIZER_PKG.tab_clsDisaggField) RETURN Boolean is
1272   res Boolean;
1273   l_index1 NUMBER;
1274   l_index2 NUMBER;
1275   l_error VARCHAR2(4000);
1276 begin
1277   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1278     BSC_MO_HELPER_PKG.writeTmp('Inside circular_dependency_exists for p_target_keys='||p_target_keys||', p_origin_keys='||p_origin_keys, FND_LOG.LEVEL_PROCEDURE);
1279     BSC_MO_HELPER_PKG.write_this(p_key_combinations);
1280   END IF;
1281   l_index1 := BSC_MO_HELPER_PKG.findIndex(p_key_combinations, p_origin_keys);
1282   l_index2 := BSC_MO_HELPER_PKG.findIndex(p_key_combinations, p_target_keys);
1283   If p_key_combinations(l_index1).Origin = 0 Then
1284     res := False;
1285   ElsIf p_key_combinations(l_index1).Origin = p_target_keys Then
1286     res := True;
1287   Else
1288       res := circular_dependency_exists(p_target_keys, p_key_combinations(l_index1).Origin, p_key_combinations);
1289   End If;
1290   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1291     BSC_MO_HELPER_PKG.writeTmp('Completed circular_dependency_exists, res='||
1292       bsc_mo_helper_pkg.boolean_decode(res), FND_LOG.LEVEL_PROCEDURE);
1293   END IF;
1294   return res;
1295   EXCEPTION WHEN OTHERS THEN
1296       l_error := sqlerrm;
1297       BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in circular_dependency_exists, '||l_error);
1298       raise;
1299 End ;
1300 
1301 
1302 --****************************************************************************
1303 --  can_derive_keys: SePuedeOriginarDesag
1304 --
1305 --    DESCRIPTION:
1306 --       Say if the target dissagregation can be originated from the source
1307 --       dissagregation.
1308 --       One dissagregation can be originated from another if:
1309 --       1. The periodicities are the same or can be originated.
1310 --       2. Each of the keys in the target dissagregation can be originated
1311 --          from any key of the source dissagregation.
1312 --       One key can be originated from another if they are the same or
1313 --       if the target key is parent of the sopurce key.
1314 --       There could exist several changes of dissagregation but one souce key
1315 --       can originate onlyu one target key
1316 --
1317 --    PARAMETERS:
1318 --       DesagDest: Target dissagregation
1319 --       DesagOri: Source dissagregation
1320 --
1321 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
1322 --****************************************************************************
1323 Function can_derive_keys(
1324         p_key_comb_target BSC_METADATA_OPTIMIZER_PKG.clsDisAggField,
1325         p_key_comb_targetCode NUMBER,
1326         p_key_comb_origin BSC_METADATA_OPTIMIZER_PKG.clsDisAggField,
1327         p_key_comb_originCode NUMBER,
1328         pTableName VARCHAR2)
1329         return Boolean IS
1330   l_key_origin BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
1331   l_key_target BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
1332   isDerivable Boolean;
1333   l_changed_levels BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField;
1334   changedDrill BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
1335   l_index NUMBER;
1336   l_return boolean;
1337   l_index1 number;
1338   l_index2 number;
1339   l_per_origin DBMS_SQL.NUMBER_TABLE;
1340   l_dummy NUMBER;
1341   l_error varchar2(1000);
1342 BEGIN
1343   If p_key_comb_target.Periodicity <> p_key_comb_origin.Periodicity Then
1344     l_index := BSC_MO_HELPER_PKG.FindIndex(BSC_METADATA_OPTIMIZER_PKG.gPeriodicities, p_key_comb_target.Periodicity);
1345     IF (l_index = -1) THEN -- metadata bad
1346         BSC_MO_HELPER_PKG.writeTmp('Bad Periodicities metadata for Periodicity='||p_key_comb_target.Periodicity, FND_LOG.LEVEL_EXCEPTION, true);
1347     END IF;
1348 	l_per_origin := BSC_MO_HELPER_PKG.decomposeStringtoNumber(BSC_METADATA_OPTIMIZER_PKG.gPeriodicities(l_index).PeriodicityOrigin, ',' );
1349     If BSC_MO_HELPER_PKG.findIndex(l_per_origin, p_key_comb_origin.Periodicity) = -1 Then
1350       return false;
1351     End If;
1352   End If;
1353 
1354   IF p_key_comb_target.keys.count >0 THEN
1355   FOR i IN p_key_comb_target.keys.first..p_key_comb_target.keys.last
1356   LOOP
1357     l_key_target := p_key_comb_target.keys(i);
1358     isDerivable := False;
1359     IF (p_key_comb_origin.keys.count>0) THEN
1360     FOR j IN p_key_comb_origin.keys.first..p_key_comb_origin.keys.last
1361     LOOP
1362       l_key_origin := null;
1363       l_key_origin := p_key_comb_origin.keys(j);
1364       If UPPER(l_key_target.keyName) = Upper(l_key_origin.keyName) Then
1365         isDerivable := True;
1366         Exit;
1367       End If;
1368       l_index1 := BSC_MO_HELPER_PKG.findKeyIndex(BSC_METADATA_OPTIMIZER_PKG.gMasterTable, l_key_origin.keyName);
1369       l_index2 := BSC_MO_HELPER_PKG.findKeyIndex(BSC_METADATA_OPTIMIZER_PKG.gMasterTable, l_key_target.keyName);
1370       IF (l_index1 = -1) THEN -- metadata bad
1371         BSC_MO_HELPER_PKG.writeTmp('Bad dimension metadata for key='||l_key_origin.keyName, FND_LOG.LEVEL_EXCEPTION, true);
1372       END IF;
1373       IF (l_index2 = -1) THEN -- metadata bad
1374         BSC_MO_HELPER_PKG.writeTmp('Bad dimension metadata for key='||l_key_target.keyName, FND_LOG.LEVEL_EXCEPTION, true);
1375       END IF;
1376       If BSC_MO_INDICATOR_PKG.IndexRelation1N(BSC_METADATA_OPTIMIZER_PKG.gMasterTable(l_index1).Name,
1377                                BSC_METADATA_OPTIMIZER_PKG.gMasterTable(l_index2).Name) >= 0 Then
1378         If Not BSC_MO_INDICATOR_PKG.keyFieldExists(l_changed_levels, l_key_origin.keyName) Then
1379           isDerivable := True;
1380           changedDrill := bsc_mo_helper_pkg.new_clsKeyField;
1381           changedDrill.keyName := l_key_origin.keyName;
1382           l_changed_levels(l_changed_levels.count) := changedDrill;
1383           Exit ;
1384         End If;
1385       End If;
1386     END LOOP;
1387     END IF;
1388     If Not isDerivable Then
1389       return False;
1390     End If;
1391   END LOOP;
1392   END IF;
1393   return true;
1394 
1395   EXCEPTION WHEN OTHERS THEN
1396     l_error := sqlerrm;
1397     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in can_derive_keys : '||l_error);
1398     BSC_MO_HELPER_PKG.writeTmp('p_key_comb_targetCode ='||p_key_comb_targetCode||',p_key_comb_originCode ='||p_key_comb_originCode||', pTableName='||pTableName,  FND_LOG.LEVEL_EXCEPTION, true);
1399     BSC_MO_HELPER_PKG.write_this(p_key_comb_target, 1, FND_LOG.LEVEL_EXCEPTION, true);
1400     BSC_MO_HELPER_PKG.write_this(p_key_comb_origin, 1, FND_LOG.LEVEL_EXCEPTION, true);
1401     raise;
1402 End ;
1403 --****************************************************************************
1404 --  InicListaTablasTemporalesyBasicas :deduce_bt_tables
1405 --
1406 --    DESCRIPTION:
1407 --       Initialize the collection g_bt_tables/g_bt_tables_tgt
1408 --
1409 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
1410 --****************************************************************************
1411 PROCEDURE  deduce_bt_tables(forTargets IN Boolean) IS
1412   l_table BSC_METADATA_OPTIMIZER_PKG.clsTable;
1413   uniqueField BSC_METADATA_OPTIMIZER_PKG.clsUniqueField;
1414   l_key_combination BSC_METADATA_OPTIMIZER_PKG.clsDisaggField;
1415   l_key BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
1416   toBeConsidered Boolean;
1417   iMatchingTableIndex DBMS_SQL.NUMBER_TABLE;
1418   l_origin_table VARCHAR2(300);
1419   l_measure_column BSC_METADATA_OPTIMIZER_PKG.clsDataField;
1420   needNewTable Boolean;
1421   l_unique_measures BSC_METADATA_OPTIMIZER_PKG.tab_clsUniqueField;
1422   l_BTTables BSC_METADATA_OPTIMIZER_PKG.tab_clsTable;
1423   l_count1 NUMBER;
1424   l_count2 NUMBER;
1425   l_count3 NUMBER;
1426   l_index NUMBER;
1427   l_temp NUMBER;
1428 
1429   l_temp3 NUMBER;
1430   l_BTTables_origin DBMS_SQL.VARCHAR2_TABLE;
1431   l_tablename VARCHAR2(100);
1432   l_error VARCHAR2(1000);
1433   l_loop_ctr NUMBER:=0;
1434     bMeasureLogged boolean ;
1435 BEGIN
1436   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1437     BSC_MO_HELPER_PKG.writeTmp('Inside deduce_bt_tables, forTargets = '||
1438             bsc_mo_helper_pkg.boolean_decode(forTargets)||' , system time is '||
1439             bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
1440   END IF;
1441 
1442   If forTargets Then
1443     l_unique_measures := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt;
1444     l_BTTables := BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_tgt;
1445     l_tablename := g_target;
1446   Else
1447     l_unique_measures := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures ;
1448     l_BTTables := BSC_METADATA_OPTIMIZER_PKG.g_bt_tables;
1449     l_tablename := g_unique;
1450   End If;
1451 
1452   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1453     BSC_MO_HELPER_PKG.writeTmp('Total # of unique measures = '||l_unique_measures.count||', Temp measures = '||l_BTTables.count);
1454   END IF;
1455 
1456   l_count1 := l_unique_measures.first;
1457   LOOP
1458     EXIT WHEN l_unique_measures.count=0;
1459     uniqueField := l_unique_measures(l_count1);
1460     bMeasureLogged := false;
1461     --Loop through list of dissagregations of the unique field until all have been registered
1462     WHILE NOT all_key_comb_registered(uniqueField.key_combinations) LOOP
1463       IF bMeasureLogged =false AND BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1464         BSC_MO_HELPER_PKG.writeTmp('---------------------------------');
1465         BSC_MO_HELPER_PKG.writeTmp('Looping for Measure '||l_count1||' = '|| uniqueField.fieldName ||
1466                            ', source='||uniqueField.source||', disaggs are ');
1467         BSC_MO_HELPER_PKG.writeTmp('---------------------------------');
1468         BSC_MO_HELPER_PKG.write_this(l_tablename, uniqueField.fieldName, uniqueField.key_combinations);
1469       END IF;
1470       bMeasureLogged := true;
1471       IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1472         BSC_MO_HELPER_PKG.writeTmp('Atleast one disagg is not registered', FND_LOG.LEVEL_STATEMENT);
1473       END IF;
1474       IF (uniqueField.key_combinations.count>0) THEN
1475       FOR l_count2 IN uniqueField.key_combinations.first..uniqueField.key_combinations.last
1476       LOOP
1477         l_key_combination := uniqueField.key_combinations(l_count2);
1478         If Not l_key_combination.Registered Then
1479           IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1480             BSC_MO_HELPER_PKG.writeTmp(' Considering disagg ');
1481             BSC_MO_HELPER_PKG.write_this(l_tablename, uniqueField.fieldName, l_key_combination);
1482           END IF;
1483           If (l_key_combination.Origin = 0) Then
1484             toBeConsidered := True;
1485           ElsIf (l_key_combination.Origin <> 0 And
1486             uniqueField.key_combinations(BSC_MO_HELPER_PKG.FindIndex(uniqueField.key_combinations, l_key_combination.Origin)).Registered) Then
1487             toBeConsidered := True;
1488           Else
1489             toBeConsidered := False;
1490           End If;
1491 
1492 	  IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1493             BSC_MO_HELPER_PKG.writeTmp(' To be considered = '||bsc_mo_helper_pkg.boolean_decode(toBeConsidered));
1494 	  END IF;
1495           If toBeConsidered Then
1496             l_temp := BSC_MO_HELPER_PKG.findindex(BSC_METADATA_OPTIMIZER_PKG.gLov, uniqueField.fieldName, uniqueField.source);
1497             iMatchingTableIndex := get_matching_tables(
1498                                                        uniqueField.fieldName,
1499                                                        uniqueField.source,
1500                                                        l_key_combination.Periodicity,
1501                                                        l_key_combination.keys,
1502                                                        BSC_METADATA_OPTIMIZER_PKG.gLov(l_temp).groupCode,
1503                                                        uniqueField.impl_type,
1504                                                        l_BTTables
1505                                                        );
1506             needNewTable := True;
1507             l_loop_ctr := iMatchingTableIndex.first;
1508             LOOP
1509               EXIT WHEN iMatchingTableIndex.count = 0;
1510               --It was found a existing temporal table with the same periodicity and disagregation and same field grouping.
1511               --Check if the disagregation and periodicity of the origin tables of the temporal table
1512               --are the same as origin disagregation of the current one
1513               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1514                 BSC_MO_HELPER_PKG.writeTmp('Found a existing temporal table with the same periodicity and '||
1515                                     ' disagregation and same field grouping.');
1516                 BSC_MO_HELPER_PKG.writeTmp('Table name = '||l_BTTables(iMatchingTableIndex(l_loop_ctr)).Name||
1517                                     ', origin table = '||l_BTTables(iMatchingTableIndex(l_loop_ctr)).originTable , FND_LOG.LEVEL_STATEMENT);
1518               END IF;
1519               l_BTTables_origin := BSC_MO_HELPER_PKG.getDecomposedString(l_BTTables(iMatchingTableIndex(l_loop_ctr)).originTable, ',');
1520               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1521                 BSC_MO_HELPER_PKG.writeTmp('7. l_key_combination.Origin  = '||l_key_combination.Origin ||
1522                                     ', l_BTTables_origin.Count = '||l_BTTables_origin.Count||' , system time is '||
1523                                     bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_STATEMENT);
1524               END IF;
1525               If l_key_combination.Origin = 0 Then
1526                 If l_BTTables_origin.Count = 0 -- if its a B table added in this run
1527                  -- or if its a production B table
1528 				OR (l_BTTables(iMatchingTableIndex(l_loop_ctr)).isProductionTable
1529 				    AND BSC_DBGEN_UTILS.get_table_type(l_BTTables(iMatchingTableIndex(l_loop_ctr)).Name)='B')
1530 				  Then
1531                   needNewTable := False;
1532                 End If;
1533               Else -- this key combination can be derived from another key combination
1534                 If l_BTTables_origin.Count <> 0 THEN --AND (NOT l_BTTables(l_loop_ctr).isProductionTable)Then
1535                   l_temp  := BSC_MO_HELPER_PKG.findIndex(uniqueField.key_combinations, l_key_combination.Origin);
1536                   BSC_MO_HELPER_PKG.write_to_stack('7.1 l_temp='||l_temp);
1537                   l_temp3 := BSC_MO_HELPER_PKG.findIndex(l_BTTables, l_BTTables_origin(l_BTTables_origin.first));
1538                   IF (l_temp3 = -1 AND
1539                       l_BTTables(iMatchingTableIndex(l_loop_ctr)).isProductionTable AND
1540                       BSC_DBGEN_UTILS.get_table_type(l_BTTables(iMatchingTableIndex(l_loop_ctr)).Name)='B') THEN
1541                        -- this is a production B table, but we havent loaded I table into memory
1542                     l_temp3 := iMatchingTableIndex(l_loop_ctr);
1543                   END IF;
1544                   BSC_MO_HELPER_PKG.write_to_stack('7.2 l_temp3='||l_temp3);
1545                   BSC_MO_HELPER_PKG.write_to_stack('7.3 l_BTTables(l_temp3).Keys.count='||l_BTTables(l_temp3).Keys.count);
1546                   If areDisaggsSame(uniqueField.key_combinations(l_temp).Periodicity,
1547                                     uniqueField.key_combinations(l_temp).keys,
1548                                     l_BTTables(l_temp3).Periodicity,
1549                                     l_BTTables(l_temp3).Keys) Then
1550                     needNewTable := False;
1551                     BSC_MO_HELPER_PKG.write_to_stack('7.5 needNewTable := False;');
1552                   End If;
1553                 End If;
1554               End If;
1555               IF (NOT needNewTable) THEN
1556                 exit;
1557               END IF;
1558               exit when l_loop_ctr = iMatchingTableIndex.last;
1559               l_loop_ctr:= iMatchingTableIndex.next(l_loop_ctr);
1560             END LOOP;
1561             IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1562               BSC_MO_HELPER_PKG.writeTmp('needNewTable = '||bsc_mo_helper_pkg.boolean_decode(needNewTable));
1563             END IF;
1564             If needNewTable Then
1565               --Add a new table
1566               --Name
1567               l_table := bsc_mo_helper_pkg.new_clsTable;
1568               If l_key_combination.Origin <> 0 Then
1569                 l_table.Name := 'BSC_T_' || (BSC_METADATA_OPTIMIZER_PKG.gMaxT + 1);
1570                 BSC_METADATA_OPTIMIZER_PKG.gMaxT := BSC_METADATA_OPTIMIZER_PKG.gMaxT + 1;
1571               Else
1572                 l_table.Name := 'BSC_B_' || (BSC_METADATA_OPTIMIZER_PKG.gMaxB + 1);
1573                 BSC_METADATA_OPTIMIZER_PKG.gMaxB := BSC_METADATA_OPTIMIZER_PKG.gMaxB + 1;
1574               End If;
1575               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1576                 BSC_MO_HELPER_PKG.writeTmp('Going to add table '||l_table.Name);
1577               END IF;
1578               l_table.measureGroup := get_measure_group(uniqueField.fieldname, uniqueField.source);
1579               l_table.Type := 1;
1580               l_table.Periodicity := l_key_combination.Periodicity;
1581               l_table.EDW_Flag := uniqueField.EDW_Flag;
1582               l_table.IsTargetTable := forTargets;
1583               l_table.IsProductionTable := false;
1584               l_table.impl_type := uniqueField.impl_type;
1585               -- BSC AW
1586               --l_key_combination_keys := BSC_MO_HELPER_PKG.getDisaggKeys(l_tablename, uniqueField.fieldName, l_key_combination.code);
1587               l_index := BSC_MO_HELPER_PKG.findIndex(uniqueField.key_combinations, l_key_combination.code);
1588               l_key_combination.keys := UniqueField.key_Combinations(l_index).keys;
1589               l_count3 := l_key_combination.keys.first;
1590               --Key columns
1591               l_table.keys := l_key_combination.keys;
1592               --Data columns
1593               --It is initialized only with the current field
1594               l_measure_column := bsc_mo_helper_pkg.new_clsDataField;
1595               l_measure_column.fieldName := uniqueField.fieldName;
1596               l_measure_column.source := uniqueField.source;
1597               l_measure_column.MeasureGroup := l_table.measureGroup;
1598               l_measure_column.aggFunction := uniqueField.aggFunction;
1599 
1600               If l_key_combination.Origin <> 0 Then
1601                 l_index := BSC_MO_HELPER_PKG.findIndex(uniqueField.key_combinations, l_key_combination.Origin);
1602                 l_origin_table := get_origin_table(
1603 				    uniqueField.key_combinations(l_index).Periodicity,
1604 				    uniqueField.key_combinations(l_index).keys,
1605                                     uniqueField.fieldName,
1606                                     uniqueField.source,
1607                                     uniqueField.MeasureGroup,
1608                                     uniqueField.impl_type,
1609                                     l_BTTables);
1610               End If;
1611               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1612                 BSC_MO_HELPER_PKG.writeTmp('14. l_origin_table = '||l_origin_table||' system time is '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_STATEMENT);
1613               END IF;
1614               --Note: removed the name of the table as prefix of the column
1615               --I do not see that the same column could be in two origin tables.
1616               l_measure_column.Origin := l_measure_column.aggFunction|| '('|| l_measure_column.fieldName || ')';
1617               --Note: other properties for internal columns are not used in input, base, temporal tables
1618               l_table.data(l_table.data.count) := l_measure_column;
1619               --TablasOri
1620               --It is initializes with only the name of the origin table
1621               IF l_key_combination.Origin <> 0 Then
1622                 IF (l_table.originTable IS NOT NULL) THEN
1623                   l_table.originTable := l_table.originTable||',';
1624                 END IF;
1625                 IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1626                   bsc_mo_helper_pkg.writeTmp('4. Adding Origin table for '||l_table.name||' = '||l_origin_table);
1627                 END IF;
1628                 l_table.originTable := l_table.originTable||l_origin_table;
1629               END IF;
1630 
1631               --Add the table to the collection l_BTTables
1632               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1633                 bsc_mo_helper_pkg.writeTmp('Adding table at l_BTTables('||l_BTTables.count||'), table is ');
1634                 bsc_mo_helper_pkg.write_this(l_table);
1635               END IF;
1636               l_BTTables(l_BTTables.count) := l_table;
1637               l_key_combination.Registered := True;
1638               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1639                 BSC_MO_HELPER_PKG.writeTmp('15. Registered key combination', FND_LOG.LEVEL_STATEMENT);
1640               END IF;
1641             Else -- Table already exists
1642               --Add the field to the temporal table
1643               --Data columns
1644               --Add the current field
1645               l_measure_column := bsc_mo_helper_pkg.new_clsDataField;
1646               l_measure_column.fieldName := uniqueField.fieldName;
1647               l_measure_column.source := uniqueField.source;
1648               l_measure_column.MeasureGroup := get_measure_group(uniqueField.fieldname, uniqueField.source);
1649               l_measure_column.aggFunction := uniqueField.aggFunction;
1650               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1651                 BSC_MO_HELPER_PKG.writeTmp('16. Add current field '||l_measure_column.fieldName, FND_LOG.LEVEL_STATEMENT);
1652               END IF;
1653               If l_key_combination.Origin <> 0 Then
1654                 l_index := BSC_MO_HELPER_PKG.findIndex(uniqueField.key_combinations, l_key_combination.Origin);
1655                 l_origin_table := get_origin_table(
1656 				    uniqueField.key_combinations(l_index).Periodicity,
1657 				    uniqueField.key_combinations(l_index).keys,
1658                                     uniqueField.fieldName,
1659                                     uniqueField.source,
1660                                     uniqueField.measureGroup,
1661                                     uniqueField.impl_type,
1662                                     l_BTTables);
1663               End If;
1664               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1665                 BSC_MO_HELPER_PKG.writeTmp('17. Origin table is '||l_origin_table, FND_LOG.LEVEL_STATEMENT);
1666               END IF;
1667               --Note: removed the name of the table as prefix of the column
1668               --I do not see that the same column could be in two origin tables.
1669               l_measure_column.Origin := l_measure_column.aggFunction || '(' || l_measure_column.fieldName || ')';
1670               IF (l_BTTables(iMatchingTableIndex(l_loop_ctr)).isProductionTable AND
1671 			     NOT BSC_MO_INDICATOR_PKG.DataFieldExists(l_BTTables(iMatchingTableIndex(l_loop_ctr)).Data, l_measure_column.fieldName)) THEN
1672                 l_BTTables(iMatchingTableIndex(l_loop_ctr)).isProductionTableAltered := true;
1673                 l_measure_column.changeType := 'NEW';
1674                 IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1675                   BSC_MO_HELPER_PKG.writeTmp('ChangeType for '||l_measure_column.fieldName ||' = NEW', FND_LOG.LEVEL_STATEMENT);
1676                 END IF;
1677               END IF;
1678               --Note: other properties for internal columns are not used in input, base, temporal tables
1679               -- If the field does not exist already in the table, then add it.
1680               IF( NOT BSC_MO_INDICATOR_PKG.DataFieldExists(l_BTTables(iMatchingTableIndex(l_loop_ctr)).Data, l_measure_column.fieldName))THEN
1681                 l_BTTables(iMatchingTableIndex(l_loop_ctr)).Data(l_BTTables(iMatchingTableIndex(l_loop_ctr)).Data.count) := l_measure_column;
1682                 BSC_MO_HELPER_PKG.writeTmp('18. Add origin table '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_STATEMENT);
1683                 --TablasOri
1684                 --Add to the list the name of the origin table
1685                 IF l_key_combination.Origin <> 0 Then
1686                   IF Not TableOriginExists(l_BTTables(iMatchingTableIndex(l_loop_ctr)).originTable, l_origin_table) Then
1687                     IF (l_BTTables(iMatchingTableIndex(l_loop_ctr)).originTable IS NOT NULL) THEN
1688                       l_BTTables(iMatchingTableIndex(l_loop_ctr)).originTable := l_BTTables(iMatchingTableIndex(l_loop_ctr)).originTable||',';
1689                     END IF;
1690 	                IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1691                       bsc_mo_helper_pkg.writeTmp('5. Adding Origin table for '||l_BTTables(iMatchingTableIndex(l_loop_ctr)).name||' = '||l_origin_table);
1692                     END IF;
1693                     l_BTTables(iMatchingTableIndex(l_loop_ctr)).originTable := l_BTTables(iMatchingTableIndex(l_loop_ctr)).originTable||l_origin_table;
1694                   END If;
1695                 END If;
1696               END IF;
1697 
1698               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1699                 BSC_MO_HELPER_PKG.writeTmp('19. Registered key combination', FND_LOG.LEVEL_STATEMENT);
1700               END IF;
1701               l_key_combination.Registered := True;
1702             End If; -- End of NeedNewTable
1703           End If;-- ENd of to be considered
1704           uniqueField.key_combinations(l_count2) := l_key_combination;
1705         End If; --End of registered
1706       END LOOP;
1707       END IF;
1708     END Loop; -- end of while
1709     EXIT WHEN l_count1 = l_unique_measures.last;
1710     l_count1 := l_unique_measures.next(l_count1);
1711   END LOOP;
1712 
1713 
1714   IF forTargets THEN
1715     BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt := l_unique_measures ;
1716     BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_tgt := l_BTTables;
1717     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1718       BSC_MO_HELPER_PKG.writeTmp('g_unique_measures_tgt is ');
1719       BSC_MO_HELPER_PKG.write_this(g_target, BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt);
1720       BSC_MO_HELPER_PKG.writeTmp('g_bt_tables_tgt is ');
1721       BSC_MO_HELPER_PKG.write_this(BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_tgt);
1722     END IF;
1723   ELSE
1724     BSC_METADATA_OPTIMIZER_PKG.g_unique_measures  := l_unique_measures;
1725     BSC_METADATA_OPTIMIZER_PKG.g_bt_tables := l_BTTables;
1726     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1727       BSC_MO_HELPER_PKG.writeTmp('g_unique_measures  is ');
1728       BSC_MO_HELPER_PKG.write_this(g_unique, BSC_METADATA_OPTIMIZER_PKG.g_unique_measures, FND_LOG.LEVEL_STATEMENT, false);
1729       BSC_MO_HELPER_PKG.writeTmp('g_bt_tables is ');
1730       BSC_MO_HELPER_PKG.write_this(BSC_METADATA_OPTIMIZER_PKG.g_bt_tables, FND_LOG.LEVEL_STATEMENT, false, false);
1731     END IF;
1732   END IF;
1733 
1734   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1735     BSC_MO_HELPER_PKG.writeTmp('Compl deduce_bt_tables, system time is '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
1736   END IF;
1737 
1738   EXCEPTION WHEN OTHERS THEN
1739 	l_error := sqlerrm;
1740     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in deduce_bt_tables : '||l_error);
1741     BSC_MO_HELPER_PKG.terminateWithError('BSC_RETR_TTABLES_FAILED', 'deduce_bt_tables');
1742 	raise;
1743 End ;
1744 
1745 --****************************************************************************
1746 --  ResolverOrigenDesagsCamposUnicos : resolve_key_origins
1747 --    DESCRIPTION:
1748 --       Resolve the origin of each dissagregation of each unique field
1749 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
1750 --****************************************************************************
1751 PROCEDURE resolve_key_origins(p_unique_measures IN OUT NOCOPY BSC_METADATA_OPTIMIZER_PKG.tab_clsUniqueField,
1752         pTargets IN BOOLEAN) IS
1753   uniqueField BSC_METADATA_OPTIMIZER_PKG.clsUniqueField;
1754   l_key_combination BSC_METADATA_OPTIMIZER_PKG.clsDisaggField;
1755   Desag1 BSC_METADATA_OPTIMIZER_PKG.clsDisaggField;
1756   l_key BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
1757   i NUMBER;
1758   j NUMBER;
1759   k NUMBER;
1760   l NUMBER;
1761   --l_key_combination_keys BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField;
1762   --Desag1_keys BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField;
1763   l_tableName VARCHAR2(100);
1764   l_error VARCHAR2(1000);
1765   l_index NUMBER;
1766   bMeasureLogged boolean ;
1767 BEGIN
1768   IF (pTargets) THEN
1769     l_tableName := g_target;
1770   ELSE
1771     l_tableName := g_unique;
1772   END IF;
1773   IF (p_unique_measures.count =0) THEN
1774     return;
1775   END IF;
1776   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1777     BSC_MO_HELPER_PKG.writeTmp(' ');
1778     BSC_MO_HELPER_PKG.writeTmp(' ');
1779     BSC_MO_HELPER_PKG.writeTmp('Inside resolve_key_origins '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
1780   END IF;
1781   IF (p_unique_measures.count>0) THEN
1782     FOR i IN p_unique_measures.first..p_unique_measures.last
1783     LOOP
1784       uniqueField := p_unique_measures(i);
1785       bmeasureLogged := false;
1786       --for each dissagregation look if it could be originated from another
1787       IF uniqueField.key_combinations.count>0 THEN
1788       FOR j IN uniqueField.key_combinations.first..uniqueField.key_combinations.last
1789       LOOP
1790         l_key_combination := uniqueField.key_combinations(j);
1791         IF (l_key_combination.registered = false) THEN -- ignore registered disaggs from prod. tables
1792 
1793           IF bMeasureLogged =false and BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1794             BSC_MO_HELPER_PKG.writeTmp(' ');
1795             BSC_MO_HELPER_PKG.writeTmp('Looping for unique field : '||uniqueField.fieldName||', source='||uniqueField.source, FND_LOG.LEVEL_STATEMENT);
1796             bsc_mo_helper_pkg.write_this(null, uniqueField);
1797           END IF;
1798           bMeasureLogged := true;
1799           IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1800             BSC_MO_HELPER_PKG.writeTmp('   Disagg is '||l_key_combination.code, FND_LOG.LEVEL_STATEMENT);
1801           END IF;
1802           l_index := BSC_MO_HELPER_PKG.findIndex(uniqueField.key_combinations, l_key_combination.code);
1803           l_key_combination.keys := uniqueField.key_combinations(l_index).keys;
1804           IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1805             BSC_MO_HELPER_PKG.writeTmp('   Disagg Keys are ', FND_LOG.LEVEL_STATEMENT);
1806             BSC_MO_HELPER_PKG.write_this(l_key_combination.keys);
1807           END IF;
1808           FOR k IN uniqueField.key_combinations.first..uniqueField.key_combinations.last
1809           LOOP
1810             Desag1 := uniqueField.key_combinations(k);
1811             l_index := BSC_MO_HELPER_PKG.findIndex(uniqueField.key_combinations, desag1.code);
1812             If Desag1.Code <> l_key_combination.Code Then
1813               If can_derive_keys(--uniqueField.fieldName,
1814   	  	      l_key_combination, l_key_combination.code, Desag1, Desag1.code, l_tablename) Then
1815                 IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1816                   BSC_MO_HELPER_PKG.writeTmp('   Disagg.code is '||l_key_combination.code||' and Disagg1.code is '||desag1.code, FND_LOG.LEVEL_STATEMENT);
1817                   BSC_MO_HELPER_PKG.writeTmp('Origin exists, verify there is no loop ', FND_LOG.LEVEL_STATEMENT);
1818                 END IF;
1819                 --verify that it is not creating a loop when l_key_combination is originated from Desag1
1820                 If Not circular_dependency_exists(l_key_combination.Code, Desag1.Code, uniqueField.key_combinations) Then
1821                   l_key_combination.Origin := Desag1.Code;
1822                   IF (l_key_combination.keys.count>0) THEN
1823                     FOR l IN l_key_combination.keys.first..l_key_combination.keys.last
1824                     LOOP
1825                       l_key := l_key_combination.keys(l);
1826                       l_key.Origin := BSC_MO_INDICATOR_PKG.getKeyOrigin(Desag1.keys, l_key.keyName);
1827                       IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1828                         bsc_mo_helper_pkg.writeTmp('Changing table = '||l_tableName ||', field '||uniqueField.fieldName
1829                                             ||', code = '||l_key_combination.code||'''s origin to '||l_key.Origin);
1830                       END IF;
1831                       l_key_combination.keys(l) := l_key;
1832                     END LOOP;
1833                   END IF;
1834                   uniqueField.key_combinations(j) := l_key_combination;
1835                   uniqueField.key_combinations(j) := l_key_combination;
1836                   uniqueField.key_combinations(j).keys := l_key_combination.keys;
1837                   EXIT ;
1838                 End If;
1839               End If;
1840             End If;
1841           END LOOP;
1842         END IF;
1843 	  END LOOP;
1844     END IF;
1845     p_unique_measures(i) := uniqueField;
1846   END LOOP;
1847   END IF;
1848   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
1849     BSC_MO_HELPER_PKG.writeTmp('Completed resolve_key_origins '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
1850     BSC_MO_HELPER_PKG.write_This(null,p_unique_measures, FND_LOG.LEVEL_STATEMENT, true);
1851   END IF;
1852   EXCEPTION WHEN OTHERS THEN
1853     l_error := sqlerrm;
1854     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in resolve_key_origins : '||l_error);
1855     raise;
1856 End ;
1857 
1858 
1859 --****************************************************************************
1860 --  GetCodDesagregacion : GetDisaggCode
1861 --
1862 --    DESCRIPTION:
1863 --       Returns the code of the dissagregation on collection colDesags where
1864 --       the periodicity and key columns are identical to the given ones.
1865 --       Return 0 if it is not found.
1866 --       Note: Additionally, it verify that it has the same filter.
1867 --       There is no filter defined for tables of no pre-calculated indicators,
1868 --       so the filter is not verified.
1869 --       Filter is taken into accout for tables of precalculated indicators.
1870 --       colDesags is a collection of objects of class clsdisaggField.
1871 --       p_keys is a collection of objects of class clsCampoLlave
1872 --
1873 --    PARAMETERS:
1874 --       colDesags: collection of dissagregations
1875 --       pPeriodicity: periodicity
1876 --       p_keys: key columns
1877 --
1878 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
1879 --****************************************************************************
1880 Function GetDisaggCode(pFieldName IN VARCHAR2,
1881                        colDesags IN BSC_METADATA_OPTIMIZER_PKG.tab_clsDisaggField,
1882                        pPeriodicity in number,
1883                        p_keys BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField,
1884                        pTableName IN VARCHAR2)
1885 return NUMBER IS
1886   l_key_combination BSC_METADATA_OPTIMIZER_PKG.clsDisaggField;
1887   l_key BSC_METADATA_OPTIMIZER_PKG.clskeyField;
1888   keysEqual Boolean;
1889   l_temp   NUMBER;
1890 
1891     --l_key_combination_keys BSC_METADATA_OPTIMIZER_PKG.tab_clskeyField;
1892     l_error VARCHAR2(1000);
1893     l_stack VARCHAR2(32000);
1894 
1895 BEGIN
1896 
1897   IF( colDesags.count= 0) THEN
1898     return -1;
1899   END IF;
1900   l_stack := 'Inside GetDisaggCode, pPeriodicity='||pPeriodicity;
1901   FOR i IN colDesags.first..colDesags.last
1902   LOOP
1903     IF (length(l_stack) > 31000) THEN
1904       l_stack := null;
1905     END IF;
1906     l_stack := l_stack || g_newline||'Loop1';
1907     l_key_combination := colDesags(i);
1908     --BSC AW
1909     --l_key_combination_keys := BSC_MO_HELPER_PKG.getDisaggKeys(pTableName, pFieldName, l_key_combination.Code);
1910 	--l_key_combination_keys := l_key_combination.keys;
1911 	If l_key_combination.Periodicity = pPeriodicity Then
1912       If l_key_combination.keys.Count = p_keys.Count Then
1913         keysEqual := True;
1914         IF (l_key_combination.keys.count>0) THEN
1915         FOR j IN l_key_combination.keys.first..l_key_combination.keys.last
1916         LOOP
1917           l_stack := l_stack || g_newline||'Loop2 begin';
1918           l_key := l_key_combination.keys(j);
1919           If Not BSC_MO_INDICATOR_PKG.KeyfieldExists(p_keys, l_key.keyName) Then
1920             keysEqual := False;
1921             Exit ;
1922           Else
1923             l_temp := BSC_MO_HELPER_PKG.findIndex(p_keys, l_key.keyName);
1924             If UPPER(l_key.FilterViewName) <> UPPER(p_keys(l_temp).FilterViewName) Then
1925               keysEqual := False;
1926               Exit ;
1927             End If;
1928           End If;
1929         END LOOP;
1930         END IF;
1931           l_stack := l_stack || g_newline||'Loop2 end';
1932       END IF;
1933       If keysEqual Then
1934         l_stack := l_stack || g_newline||'Compl GetDisaggCode, returning '||l_key_combination.Code;
1935         return l_key_combination.Code;
1936       End If;
1937     End If;
1938   END LOOP;
1939   l_stack := l_stack || g_newline||'Compl GetDisaggCode, returning -1';
1940   return -1;
1941 
1942   EXCEPTION WHEN OTHERS THEN
1943         l_error := sqlerrm;
1944         BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in GetDisaggCode :'||l_error);
1945             BSC_MO_HELPER_PKG.writeTmp('Stack is  :'||l_stack, FND_LOG.LEVEL_UNEXPECTED, true);
1946         raise;
1947 
1948 End ;
1949 
1950 
1951 
1952 --****************************************************************************
1953 --  ExisteuniqueField : UniqueFieldExists
1954 --
1955 --    DESCRIPTION:
1956 --       Return TRUE if the given field belongs to collection g_unique_measures .
1957 --
1958 --    PARAMETERS:
1959 --       Campo: field name
1960 --
1961 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
1962 --****************************************************************************
1963 Function UniqueFieldExists(p_measure_name IN VARCHAR2,
1964 -- BSC Autogen
1965 p_source IN VARCHAR2,
1966 p_impl_type IN NUMBER, p_unique_measure_list IN BSC_METADATA_OPTIMIZER_PKG.tab_clsUniqueField) return Boolean IS
1967   l_uniqueField BSC_METADATA_OPTIMIZER_PKG.clsUniqueField;
1968   l_count NUMBER ;
1969 BEGIN
1970   IF (p_unique_measure_list.count =0) THEN
1971       return false;
1972   END IF;
1973   l_count := p_unique_measure_list.first;
1974   LOOP
1975      l_uniqueField  := p_unique_measure_list(l_count);
1976       If UPPER(l_uniqueField.fieldName) = UPPER(p_measure_name)
1977         -- for AW
1978 	    and l_uniqueField.impl_type = p_impl_type
1979 	    --BSC Autogen
1980 		and l_uniqueField.source = p_source THEN
1981         return true;
1982       End If;
1983       EXIT WHEN l_count = p_unique_measure_list.last;
1984       l_count := p_unique_measure_list.next(l_count);
1985   END LOOP;
1986   return FALSE;
1987   EXCEPTION WHEN OTHERS THEN
1988     BSC_MO_HELPER_PKG.writeTmp('Exception in UniqueFieldExists, '||sqlerrm, FND_LOG.LEVEL_UNEXPECTED, true);
1989     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in UniqueFieldExists, '||sqlerrm);
1990     raise;
1991 End ;
1992 
1993 --****************************************************************************
1994 --  init_s_table_measures_precalc : InicListaUnicaCamposPreCalc
1995 --  DESCRIPTION:
1996 --     Initialize the collection g_unique_measures_precalc, where are the data fields
1997 --     with all the information: field name, agregation function, and the list
1998 --     of all disagregations used by the indicators for the field.
1999 --****************************************************************************
2000 PROCEDURE init_s_table_measures_precalc(p_tables IN OUT NOCOPY BSC_METADATA_OPTIMIZER_PKG.tab_clsTable )IS
2001 
2002   l_table BSC_METADATA_OPTIMIZER_PKG.clsTable;
2003   l_measure   BSC_METADATA_OPTIMIZER_PKG.clsDataField;
2004   uniqueField BSC_METADATA_OPTIMIZER_PKG.clsUniqueField;
2005   disaggField BSC_METADATA_OPTIMIZER_PKG.clsDisaggField;
2006   l_key BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
2007   disaggKeyField BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
2008   CodDesag NUMBER;
2009   l_count1 NUMBER;
2010   l_count2 NUMBER;
2011   l_count3 NUMBER;
2012   l_temp   NUMBER;
2013   l_field_index NUMBER;
2014   l_disagg_index NUMBER;
2015   l_index  NUMBER;
2016 
2017   Tabla_OriginTable DBMS_SQL.VARCHAR2_TABLE;
2018 
2019   uniqueField_disAggKeys BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField;
2020 
2021   l_stack varchar2(32000):= null;
2022   l_error varchar2(2000);
2023   l_optimizationMode NUMBER;
2024   l_impl_type number;
2025 BEGIN
2026   IF (p_tables.count=0) THEN
2027     return;
2028   END IF;
2029   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2030     BSC_MO_HELPER_PKG.writeTmp('Inside init_s_table_measures_precalc, g_unique_measures_precalc.count='||
2031       BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc.count||' '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
2032   END IF;
2033   l_count1 := p_tables.first;
2034   LOOP
2035     IF (length(l_stack) > 30000) THEN
2036       l_stack := null;
2037     END IF;
2038     l_table := p_tables(l_count1);
2039     IF (Tabla_OriginTable IS NOT NULL) THEN
2040       Tabla_OriginTable := bsc_mo_helper_pkg.getDecomposedString(l_table.originTable, ',');
2041     END IF;
2042     --Only consider tables not having origin and belong to indicators precalculated
2043     l_index := BSC_MO_HELPER_PKG.findIndex(BSC_METADATA_OPTIMIZER_PKG.gIndicators, l_table.Indicator);
2044     IF (l_index = -1) THEN
2045       l_optimizationMode := BSC_MO_HELPER_PKG.getKPIPropertyValue(l_table.Indicator, 'DB_TRANSFORM', 1);
2046       l_impl_type := BSC_MO_HELPER_PKG.getKPIPropertyValue(l_table.Indicator, BSC_METADATA_OPTIMIZER_PKG.IMPL_TYPE, 1);
2047     ELSE
2048       l_optimizationMode := BSC_METADATA_OPTIMIZER_PKG.gIndicators(l_index).OptimizationMode;
2049       l_impl_type := BSC_METADATA_OPTIMIZER_PKG.gIndicators(l_index).impl_type;
2050     END IF;
2051 
2052     IF (l_table.isProductionTable is null) THEN
2053       l_table.isProductionTable:=false;
2054     END IF;
2055     If ((l_table.originTable IS NULL AND l_table.isProductionTable=false) OR
2056         (l_table.originTable IS NOT NULL AND l_table.isProductionTable=true))
2057        And l_optimizationMode = 0 Then
2058       IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2059         BSC_MO_HELPER_PKG.writeTmp('');
2060         bsc_mo_helper_pkg.writeTmp(' Processing table '||l_table.name);
2061         bsc_mo_helper_pkg.write_this(l_table);
2062       END IF;
2063 
2064       l_count2 := l_table.data.first;
2065       LOOP
2066         EXIT WHEN l_table.data.count=0;
2067         l_measure := l_table.data(l_count2);
2068         --Do not consider internal columns. They are used only in indicator
2069         --tables and are not going to be base or input tables.
2070         If l_measure.InternalColumnType = 0 Then
2071           If Not UniqueFieldExists(l_measure.fieldName, l_measure.source, l_impl_type, BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc) Then
2072             IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2073               bsc_mo_helper_pkg.writeTmp('  '||l_measure.fieldName||'('||l_measure.source||') Field does not exist --> Add it');
2074             END IF;
2075             --Field does not exists --> Add it
2076             uniqueField := bsc_mo_helper_pkg.new_clsUniqueField;
2077             uniqueField.fieldName := l_measure.fieldName;
2078             uniqueField.source := l_measure.source;
2079             uniqueField.measureGroup := get_measure_Group(l_measure.fieldName, l_measure.source);
2080             uniqueField.aggFunction := l_measure.aggFunction;
2081             IF (l_index <> -1) THEN
2082               uniqueField.EDW_Flag := BSC_METADATA_OPTIMIZER_PKG.gIndicators(l_index).EDW_Flag;
2083             ELSE
2084               uniqueField.EDW_Flag := 0;
2085             END IF;
2086             uniqueField.impl_type := l_impl_type;
2087             --Desags. It initialized with one element that correspond to the disagregation
2088             --and periodicity of the table
2089             disaggField := bsc_mo_helper_pkg.new_clsDisAggField;
2090             disaggField.Code := 1;
2091             disaggField.Periodicity := l_table.Periodicity;
2092             --Key columns. Same as the table
2093             l_count3 := l_table.keys.first;
2094             disaggField.keys := l_table.keys;
2095             disaggField.Origin := 0;
2096             IF (l_table.isProductionTable ) THEN
2097               disaggField.Registered := True;
2098             ELSE
2099               disaggField.Registered := False;
2100             END IF;
2101             uniqueField.key_combinations(uniqueField.key_combinations.count) := disaggField;
2102             --uniqueField.key_combinations(0).keys := disaggField.Keys;
2103             --Add the unique field to the collection g_unique_measures_precalc
2104             BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc(BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc.count) := uniqueField;
2105           ELSE
2106             IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2107               bsc_mo_helper_pkg.writeTmp( l_measure.fieldName||'('||l_measure.source||') field already exists. Check periodicity and disaggregation');
2108             END IF;
2109             --The field already exists. So check if its periodicity and disagregation
2110             -- is in its list of disagregations
2111             l_field_index := BSC_MO_HELPER_PKG.findIndex(
2112                                 BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc,
2113                                 l_measure.fieldName,
2114                                 l_measure.source,
2115 				l_table.impl_type);
2116             IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2117               bsc_mo_helper_pkg.writeTmp('Field Index is '||l_field_index);
2118             END IF;
2119             uniqueField.key_combinations.delete;
2120             uniqueField.key_combinations := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc(l_field_index).key_combinations;
2121             CodDesag := GetDisaggCode(
2122                                     uniqueField.fieldName,
2123                                     uniqueField.key_combinations,
2124                                     l_table.Periodicity,
2125                                     l_table.keys,
2126                                     l_table.name);
2127             If CodDesag = -1 Then
2128               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2129                 bsc_mo_helper_pkg.writeTmp( 'Disaggregation does not exist, add it');
2130               END IF;
2131               --It does not exist --> Add it
2132               disaggField := bsc_mo_helper_pkg.new_clsDisAggField;
2133               uniqueField.key_combinations.delete;
2134               uniqueField.key_combinations := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc(l_field_index).key_combinations;
2135 	      disaggField.Code := uniqueField.key_combinations.Count + 1;
2136               disaggField.Periodicity := l_table.Periodicity;
2137               --Key columns. Same as the table
2138               disaggField.keys := l_table.keys;
2139               disaggField.Origin := 0;
2140               IF (l_table.isProductionTable ) THEN
2141                 disaggField.Registered := True;
2142               ELSE
2143                 disaggField.Registered := False;
2144               END IF;
2145               --Add the disagregation to the collection Desags of the unique field
2146               BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc(l_field_index).key_combinations
2147                 (BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc(l_field_index).key_combinations.count) := disaggField;
2148             ELSE
2149               --The dissagregation exists. We need to use the property NecesitaCod0 because
2150               --the table could need zero code in some key where the dissagregation dont need
2151               --so far.
2152               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2153                 bsc_mo_helper_pkg.writeTmp( 'Disaggregation already exists');
2154               END IF;
2155               l_disagg_index := BSC_MO_HELPER_PKG.findIndex(uniqueField.key_combinations, CodDesag);
2156               uniqueField_disAggKeys.delete;
2157               uniqueField_disAggKeys := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc(l_field_index).key_combinations(l_disagg_index).keys;
2158               IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2159                 bsc_mo_helper_pkg.writeTmp( 'Matching disagg index '||l_disagg_index);
2160               END IF;
2161               IF uniqueField_disAggKeys.count>0 THEN
2162 	        FOR l_count3 IN uniqueField_disAggKeys.first..uniqueField_disAggKeys.last
2163                 LOOP
2164                   l_key := uniqueField_disAggKeys(l_count3);
2165                   l_temp := BSC_MO_HELPER_PKG.findIndex(l_table.keys, l_key.keyName);
2166                   If l_table.keys(l_temp).NeedsCode0 Then
2167                     l_key.NeedsCode0 := l_table.keys(l_temp).NeedsCode0;
2168                   End If;
2169                   uniqueField_disAggKeys(l_count3) := l_key;
2170                 END LOOP;
2171               END IF;
2172               IF (l_table.isProductionTable) THEN
2173                   BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc (l_field_index).key_combinations(CodDesag-1).Registered := true;
2174                   BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc (l_field_index).key_combinations(CodDesag-1).isProduction := true;
2175               END IF;
2176               BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc(l_field_index).key_combinations(l_disagg_index).keys := uniqueField_disAggKeys;
2177 
2178             END IF;
2179           END IF;
2180         END IF;
2181         EXIT WHEN l_count2=l_table.data.last;
2182         l_count2 := l_table.data.next(l_count2);
2183       END LOOP;
2184       p_tables(l_count1) := l_table;
2185     End If;
2186     EXIT WHEN l_count1 = p_tables.last;
2187     l_count1 := p_tables.next(l_count1);
2188     l_stack := null;
2189   END LOOP;
2190   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2191     BSC_MO_HELPER_PKG.writeTmp('Completed init_s_table_measures_precalc, g_unique_measures_precalc.count='||
2192             BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc.count||' '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
2193   END IF;
2194    BSC_MO_HELPER_PKG.writeTmp('g_unique_measures_precalc  = ');
2195     BSC_MO_HELPER_PKG.write_this(g_unique, BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_precalc );
2196 
2197   EXCEPTION WHEN OTHERS THEN
2198     l_error := sqlerrm;
2199     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in init_s_table_measures_precalc : '||l_error);
2200     BSC_MO_HELPER_PKG.writeTmp('l_stack  : '||l_stack, FND_LOG.LEVEL_UNEXPECTED, true);
2201     BSC_MO_HELPER_PKG.TerminateWithError('BSC_RETR_PC_DATACOL_FAILED', 'init_s_table_measures_precalc');
2202     raise;
2203 End;
2204 
2205 
2206 --****************************************************************************
2207 --  InicListaUnicaCampos : init_s_table_measures
2208 --
2209 --   DESCRIPTION:
2210 --       Initialize the collection g_unique_measures /g_unique_measures_tgt,
2211 --       where are the data fields with all the information: field name,
2212 --       agregation function, and the list of all disagregations used by the
2213 --       indicators for the field.
2214 --
2215 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
2216 --****************************************************************************
2217 PROCEDURE init_s_table_measures(p_tables IN OUT NOCOPY BSC_METADATA_OPTIMIZER_PKG.tab_clsTable ) IS
2218 
2219   l_clstable           BSC_METADATA_OPTIMIZER_PKG.clsTable;
2220   l_measure          BSC_METADATA_OPTIMIZER_PKG.clsDataField;
2221   uniqueField      BSC_METADATA_OPTIMIZER_PKG.clsUniqueField ;
2222   l_unique_measures    BSC_METADATA_OPTIMIZER_PKG.tab_clsUniqueField ;
2223   disaggField      BSC_METADATA_OPTIMIZER_PKG.clsDisAggField;
2224   l_key           BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
2225   disaggKeyField   BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
2226   l_count         NUMBER := 0;
2227   l_count2        NUMBER := 0;
2228   l_count3        NUMBER := 0;
2229   l_index         NUMBER := null;
2230   l_temp          NUMBER;
2231   l_index2        NUMBER;
2232 
2233   Tabla_OriginTable DBMS_SQL.VARCHAR2_TABLE;
2234   l_tablename VARCHAR2(100) ;
2235   l_error VARCHAR2(1000);
2236 
2237   l_stack VARCHAR2(32000);
2238   l_OptimizationMode NUMBER;
2239   l_impl_type NUMBER;
2240   l_disagg_code NUMBER;
2241 BEGIN
2242   IF (p_tables.count=0) THEN
2243     return;
2244   END IF;
2245   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2246     BSC_MO_HELPER_PKG.writeTmp('Inside init_s_table_measures, p_tables.count = '||p_tables.count||', g_unique_measures .count='||
2247       BSC_METADATA_OPTIMIZER_PKG.g_unique_measures .count||
2248         ', g_unique_measures_tgt.count='||BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt.count||' '||bsc_mo_helper_pkg.get_time
2249         , FND_LOG.LEVEL_PROCEDURE);
2250   END IF;
2251   l_count := p_tables.first;
2252   LOOP
2253     l_clstable := p_tables(l_count);
2254     IF (l_clstable.IsTargetTable) THEN
2255       l_tablename := g_target;
2256     ELSE
2257       l_tablename := g_unique;
2258     END IF;
2259     --Only consider tables not having origin and belong to indicators no-precalculated
2260     --Also only consider tables that are not for targets
2261     l_temp := BSC_MO_HELPER_PKG.findIndex(BSC_METADATA_OPTIMIZER_PKG.gIndicators, l_clstable.Indicator);
2262     IF (l_temp = -1) THEN
2263       l_optimizationMode := BSC_MO_HELPER_PKG.getKPIPropertyValue(l_clstable.Indicator, 'DB_TRANSFORM', 1);
2264       l_impl_type := BSC_MO_HELPER_PKG.getKPIPropertyValue(l_clstable.Indicator, BSC_METADATA_OPTIMIZER_PKG.IMPL_TYPE, 1);
2265     ELSE
2266       l_optimizationMode := BSC_METADATA_OPTIMIZER_PKG.gIndicators(l_temp).OptimizationMode;
2267       l_impl_type := BSC_METADATA_OPTIMIZER_PKG.gIndicators(l_temp).impl_type;
2268     END IF;
2269     l_stack := l_stack ||g_newline||'Table = '||l_clstable.name||', l_optimizationMode = '||l_optimizationmode||', l_impl_type='||l_impl_type;
2270 
2271     IF (l_clstable.isProductionTable is null) THEN
2272       l_clstable.isProductionTable:=false;
2273     END IF;
2274     If ((l_clstable.originTable IS NULL AND l_clstable.isProductionTable=false) OR
2275         l_clstable.isProductionTable=true
2276 		)
2277 	    And  l_optimizationMode <> 0 Then
2278 	  BSC_MO_HELPER_PKG.writeTmp(' ');
2279       BSC_MO_HELPER_PKG.writeTmp(' ');
2280 	  BSC_MO_HELPER_PKG.writeTmp('Processing table '||l_clstable.name);
2281       --l_table_measures := l_clstable.Data;
2282       --l_table_keys := l_clstable.keys;
2283       BSC_MO_HELPER_PKG.writeTmp('  l_clstable.data.count = '||l_clstable.data.count||', l_clstable.keys.count='||l_clstable.keys.count );
2284       If l_clstable.IsTargetTable Then
2285         l_stack := l_stack||' Target table';
2286         l_unique_measures := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt;
2287       Else
2288         l_stack := l_stack||g_newline||' Not a target table';
2289         l_unique_measures := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures ;
2290       End If;
2291       l_stack := l_stack||g_newline||' l_unique_measures.count = '||l_unique_measures.count;
2292       IF length(l_stack )> 31000 THEN
2293         l_stack := substr(l_stack, 30000);
2294       END IF;
2295       --We maintain a separate collection for data fields of targets tables
2296       IF l_clstable.data.count>0 THEN
2297       FOR l_count2 in l_clstable.data.first..l_clstable.data.last
2298       LOOP
2299         l_measure := l_clstable.data(l_count2);
2300         --Do not consider internal columns. They are used only in indicator
2301         --tables and are not going to be base or input tables.
2302         If l_measure.InternalColumnType = 0 Then
2303           l_stack := l_stack||g_newline||'  Checking field '||l_measure.fieldName;
2304           l_stack := l_stack||g_newline||'  --------------------';
2305           BSC_MO_HELPER_PKG.writeTmp('  ');
2306           BSC_MO_HELPER_PKG.writeTmp('  Checking field '||l_measure.fieldName||', source='||l_measure.source);
2307           BSC_MO_HELPER_PKG.writeTmp('  --------------------------------------');
2308           IF length(l_stack )> 31000 THEN
2309             l_stack := substr(l_stack, 30000);
2310           END IF;
2311           If UniqueFieldExists(l_measure.fieldName, l_measure.source, l_impl_type, l_unique_measures)=false Then
2312             l_stack := l_stack||g_newline||'..Field does not exist';
2313             -- If its a production table, dont add the measures that are used by Indicators in this iteration
2314               BSC_MO_HELPER_PKG.writeTmp('..does not exist --> Add it');
2315               --Field does not exists --> Add it
2316               uniqueField := BSC_Mo_helper_PKG.new_clsUniqueField;
2317               uniqueField.fieldName := l_measure.fieldName;
2318               uniqueField.source := l_measure.source;
2319               uniqueField.measureGroup := get_measure_group(uniqueField.fieldName, l_measure.source);
2320               uniqueField.aggFunction := l_measure.aggFunction;
2321               l_temp := BSC_MO_HELPER_PKG.findIndex(BSC_METADATA_OPTIMIZER_PKG.gIndicators, l_clstable.Indicator);
2322               IF (l_temp <> -1) THEN
2323                 uniqueField.EDW_Flag := BSC_METADATA_OPTIMIZER_PKG.gIndicators(l_temp).EDW_Flag;
2324               END IF;
2325               l_stack := l_stack||g_newline||'l_impl_type='||l_impl_type;
2326 			  uniqueField.impl_type := l_impl_type;
2327               --Desags. It initialized with one element that correspond to the disagregation
2328               --and periodicity of the table
2329               disaggField := BSC_Mo_helper_PKG.new_clsDisAggField;
2330               disaggField.Code := 1;
2331               disaggField.Periodicity := l_clstable.Periodicity;
2332               -- Important, mark this as from existing table
2333               disaggField.isProduction := l_clsTable.isProductionTable;
2334               --Key columns. Same as the table
2335               --Dissagg_Keys.delete;
2336               l_stack := l_stack||g_newline||'Table keys.count='||l_clstable.keys.count;
2337               IF (l_clstable.keys.count>0) THEN
2338               FOR l_count3 IN l_clstable.keys.first..l_clstable.keys.last
2339               LOOP
2340                 l_key := BSC_Mo_helper_PKG.new_clsKeyField;
2341                 l_key := l_clstable.keys (l_count3);
2342                 disaggKeyField := bsc_mo_helper_pkg.new_clsKeyField;
2343                 disaggKeyField.keyName := l_key.keyName;
2344                 disaggKeyField.Origin := l_key.Origin;
2345                 disaggKeyField.NeedsCode0 := False;
2346                 disaggKeyField.CalculateCode0 := False;
2347                 disaggKeyField.FilterViewName := null;
2348                 l_stack := l_stack||g_newline||'Adding disagg key='||disaggKeyField.keyName;
2349                 disaggField.keys(disaggField.keys.count) := disaggKeyField;
2350               END LOOP;
2351               END IF;
2352               disaggField.Origin := 0;
2353               IF (l_clstable.isProductionTable) THEN
2354                 disaggField.Registered := true;
2355                 disaggField.isProduction := true;
2356               ELSE
2357                 disaggField.Registered := False;
2358                 disaggField.isProduction := False;
2359               END IF;
2360               l_stack := l_stack||g_newline||'Disagg keys = '||disaggField.keys.count;
2361               uniqueField.key_combinations(uniqueField.key_combinations.count) := disaggField;
2362               BSC_MO_HELPER_PKG.writeTmp('Adding to unique field');
2363               BSC_MO_HELPER_PKG.write_this(null, uniqueField);
2364               --Add the unique field to the collection l_unique_measures
2365               If l_clstable.IsTargetTable Then
2366                 l_index2 := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt.count;
2367                 BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt(l_index2) := uniqueField;
2368                 l_stack := l_stack||g_newline||'Added g_unique_measures ('||l_index2||'), count = '||l_index2;
2369                 BSC_MO_HELPER_PKG.writeTMp('Added '||l_measure.fieldName||', source='||l_measure.source||
2370                                    ' to g_unique_measures_tgt at index='||l_index2 );
2371               Else
2372                 l_index2 := BSC_METADATA_OPTIMIZER_PKG.g_unique_measures.count;
2373                 BSC_METADATA_OPTIMIZER_PKG.g_unique_measures (l_index2) := uniqueField;
2374                 l_stack := l_stack||g_newline||'Added g_unique_measures ('||l_index2||'), count = '||l_index2;
2375                 BSC_MO_HELPER_PKG.writeTMp('Added '||l_measure.fieldName||', source='||l_measure.source||
2376                                    ' to g_unique_measures at index='||l_index2);
2377               End If;
2378           Else
2379             --The field already exists. So check if its periodicity and disagregation
2380             -- is in its list of disagregations
2381             IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2382               BSC_MO_HELPER_PKG.writeTMp(l_measure.fieldName||'..Field already exists --> check periodicity and disagregation');
2383             END IF;
2384             l_temp := BSC_MO_HELPER_PKG.findIndex (l_unique_measures, l_measure.fieldName, l_measure.source, l_impl_type);
2385             l_disagg_code := GetDisaggCode(l_unique_measures(l_temp).fieldName,
2386                                l_unique_measures(l_temp).key_combinations,
2387                                l_clstable.Periodicity,
2388                                l_clstable.keys,
2389                                l_Tablename);
2390             IF l_disagg_code = -1 Then
2391               l_stack := l_stack||g_newline||'Disagg does not exist -> Add it ';
2392               bsc_mo_helper_pkg.writeTmp( 'Disagg does not exist -> Add it ');
2393               --It does not exist --> Add it
2394               l_temp := bsc_mo_helper_pkg.findIndex(l_unique_measures, l_measure.fieldName, l_measure.source, l_impl_type);
2395               disaggField := bsc_mo_helper_pkg.new_clsDisAggField;
2396               disaggField.Code := l_unique_measures(l_temp).key_combinations.count + 1;
2397               disaggField.Periodicity := l_clstable.Periodicity;
2398               --Key columns. Same as the table
2399               IF (l_clstable.keys.count>0) THEN
2400                 FOR l_count3 IN l_clstable.keys.first..l_clstable.keys.last LOOP
2401                   l_key := l_clstable.keys(l_count3);
2402                   disaggKeyField := bsc_mo_helper_pkg.new_clsKeyField;
2403                   disaggKeyField.keyName := l_key.keyName;
2404                   disaggKeyField.Origin := l_key.Origin;
2405                   disaggKeyField.NeedsCode0 := False;
2406                   disaggKeyField.CalculateCode0 := False;
2407                   disaggKeyField.FilterViewName := null;
2408                   disaggField.keys(disaggField.keys.count) := disaggKeyField;
2409                 END LOOP;
2410               END IF;
2411 	      --Origin
2412               disaggField.Origin := 0;
2413               --disaggField.Registered := False;
2414               IF (l_clstable.isProductionTable) THEN
2415                 disaggField.Registered := true;
2416                 disaggField.isProduction := true;
2417               ELSE
2418                 disaggField.Registered := False;
2419                 disaggField.isProduction := False;
2420               END IF;
2421               l_stack := l_stack||g_newline||'2. Disagg keys = '||disaggField.keys.count;
2422               --Add the disagregation to the collection Desags of the unique field
2423               l_temp := BSC_MO_HELPER_PKG.findIndex (l_unique_measures, l_measure.fieldName, l_measure.source, l_impl_type);
2424 	      --Copy back the unique field to the collection l_unique_measures
2425               If l_clstable.IsTargetTable Then
2426                 BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt(l_temp).key_combinations
2427                   (BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt(l_temp).key_combinations.count) := disaggField;
2428 	        bsc_mo_helper_pkg.writeTmp('Copy back disagg to g_unique_measures_tgt at index='||l_temp);
2429               Else
2430                 BSC_METADATA_OPTIMIZER_PKG.g_unique_measures (l_temp).key_combinations
2431                   (BSC_METADATA_OPTIMIZER_PKG.g_unique_measures(l_temp).key_combinations.count) := disaggField;
2432                 bsc_mo_helper_pkg.writeTmp('Copy back disagg to g_unique_measures at index='||l_temp);
2433               End If;
2434             ELSE -- disagg code is <> -1
2435               IF (l_clstable.isProductionTable) THEN
2436                 l_temp := BSC_MO_HELPER_PKG.findIndex (l_unique_measures, l_measure.fieldName, l_measure.source, l_impl_type);
2437                 If l_clstable.IsTargetTable Then
2438                   -- If another table requires this disagg, then we should still leave it as unregistered
2439                   IF BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt(l_temp).key_combinations(l_disagg_code-1).Registered = false THEN
2440                     null;
2441                   ELSE
2442                     BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt(l_temp).key_combinations(l_disagg_code-1).Registered := true;
2443 		    BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt(l_temp).key_combinations(l_disagg_code-1).isProduction := true;
2444                   END IF;
2445                 Else
2446                   IF (BSC_METADATA_OPTIMIZER_PKG.g_unique_measures (l_temp).key_combinations(l_disagg_code-1).Registered =false) THEN
2447                     null;
2448                   ELSE
2449                     BSC_METADATA_OPTIMIZER_PKG.g_unique_measures (l_temp).key_combinations(l_disagg_code-1).Registered := true;
2450                     BSC_METADATA_OPTIMIZER_PKG.g_unique_measures (l_temp).key_combinations(l_disagg_code-1).isProduction := true;
2451                   END IF;
2452                 End If;
2453               END IF;
2454             End If;
2455           End If;
2456         End If;
2457       END LOOP;
2458       END IF;
2459     End If;
2460     IF length(l_stack )> 31000 THEN
2461       l_stack := substr(l_stack, 30000);
2462     END IF;
2463     p_tables(l_count) := l_clstable;
2464     EXIT WHEN l_count = p_tables.last;
2465     l_count := p_tables.next(l_count);
2466   END LOOP;
2467   IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2468     BSC_MO_HELPER_PKG.writeTmp('Done with init_s_table_measures, writing output now');
2469     BSC_MO_HELPER_PKG.writeTmp('g_unique_measures  = ');
2470     BSC_MO_HELPER_PKG.write_this(g_unique, BSC_METADATA_OPTIMIZER_PKG.g_unique_measures );
2471     BSC_MO_HELPER_PKG.writeTmp('g_unique_measures_tgt = ');
2472     BSC_MO_HELPER_PKG.write_this(g_Target, BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt);
2473     BSC_MO_HELPER_PKG.writeTmp('Completed init_s_table_measures, system time is '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE);
2474   END IF;
2475   EXCEPTION WHEN OTHERS THEN
2476     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in init_s_table_measures : '||sqlerrm);
2477 	BSC_MO_HELPER_PKG.writeTmp('l_stack = '||l_stack, FND_LOG.LEVEL_UNEXPECTED, true);
2478     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in init_s_table_measures : '||sqlerrm);
2479     raise;
2480 End ;
2481 
2482 
2483 --****************************************************************************
2484 --  InputTables : TablasEntrada
2485 --
2486 --   DESCRIPTION:
2487 --       Deduce the input tables.
2488 --
2489 --    AUTHOR/DATE  -  MODIFICATIONS (AUTHOR/DATE/DESCRIPTION):
2490 --****************************************************************************
2491 PROCEDURE InputTables IS
2492   l_counter NUMBER;
2493   KpiTable bsc_metadata_optimizer_pkg.clsTable;
2494   l_index NUMBER;
2495   l_error VARCHAR2(3000);
2496 BEGIN
2497   BSC_MO_HELPER_PKG.writeTmp('    ', FND_LOG.LEVEL_STATEMENT, true);
2498   BSC_MO_HELPER_PKG.writeTmp('Inside InputTables '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE, true);
2499   --BSC-MV Note: If the indicator is not processed for structural changes and
2500   --the summarization level was changed from NULL to NOT NULL (upgrade)
2501   --then I need to get from the database the source table of the indicator and set
2502   --the origin in gTablas.
2503   --By doing this Metadata will not try to get new input, base and T tables for
2504   --those indicators.
2505   --Also add those tables to the global array garrTablesUpgradeT(). Those tables
2506   --will be used as start point to load all related tables from database to gTables.
2507 
2508   If bsc_metadata_optimizer_pkg.g_Sum_Level_Change = 1 Then
2509     bsc_metadata_optimizer_pkg.gnumTablesUpgradeT := 0;
2510     l_counter := bsc_metadata_optimizer_pkg.gTables.first;
2511     LOOP
2512       EXIT WHEN bsc_metadata_optimizer_pkg.gTables.count = 0;
2513       KpiTable := bsc_metadata_optimizer_pkg.gTables(l_counter);
2514       l_index := bsc_mo_helper_pkg.findIndex(bsc_metadata_optimizer_pkg.gIndicators, KpiTable.Indicator);
2515       If bsc_metadata_optimizer_pkg.gIndicators(l_index).Action_Flag <> 3 And KpiTable.originTable IS NULL Then
2516         set_origin_table_from_db(KpiTable);
2517       End If;
2518       bsc_metadata_optimizer_pkg.gTables(l_counter) := KpiTable;
2519       EXIT WHEN l_counter = bsc_metadata_optimizer_pkg.gTables.last;
2520       l_counter := bsc_metadata_optimizer_pkg.gTables.next(l_counter);
2521     END LOOP;
2522   End If;
2523 
2524     --EDW Note:
2525     --I don't need to do anything special to separate tables for EDW KPIs from
2526     --BSC Kpis because the following reasons (Actually just one of them is enough):
2527     --a. EDW KPIs and BSC KPIs dont share dimensions.
2528     --b. EDW KPIs and BSC KPIs dont share periodicities.
2529     --c. EDW KPIs and BSC KPIs dont share measures.
2530     --Initilize the list of unique measures for indicators being processed
2531     BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling init_s_table_measures');
2532     BSC_MO_HELPER_PKG.writeTmp('Calling init_s_table_measures', FND_LOG.LEVEL_STATEMENT, true);
2533     init_s_table_measures(BSC_METADATA_OPTIMIZER_PKG.gTables);
2534 
2535     --Initilize the list of unique measures for indicators being processed - Precalc
2536     BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling init_s_table_measures_precalc');
2537     BSC_MO_HELPER_PKG.writeTmp('Calling init_s_table_measures_precalc', FND_LOG.LEVEL_STATEMENT, true);
2538     init_s_table_measures_precalc(BSC_METADATA_OPTIMIZER_PKG.gTables);
2539 
2540     -- Load the existing B and T tables into memory for better optimization
2541     BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling LOAD_B_T_TABLES_FROM_DB');
2542     BSC_MO_HELPER_PKG.writeTmp('Calling LOAD_B_T_TABLES_FROM_DB', FND_LOG.LEVEL_STATEMENT, true);
2543     LOAD_B_T_TABLES_FROM_DB;
2544 
2545     --Resolve the origin of each dissagregation of each field
2546     --This is done only for non-precalculated fields
2547     BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling resolve_key_origins');
2548     BSC_MO_HELPER_PKG.writeTmp('Calling resolve_key_origins', FND_LOG.LEVEL_STATEMENT, true);
2549     resolve_key_origins (BSC_METADATA_OPTIMIZER_PKG.g_unique_measures , false);
2550 
2551     --Resolve the origin of each dissagregation for Targets
2552     BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling resolve_key_origins for Targets');
2553     BSC_MO_HELPER_PKG.writeTmp('Calling resolve_key_origins for Targets', FND_LOG.LEVEL_STATEMENT, true);
2554     resolve_key_origins ( BSC_METADATA_OPTIMIZER_PKG.g_unique_measures_tgt, true);
2555 
2556     --Make the list of temporal and base tables
2557     BSC_METADATA_OPTIMIZER_PKG.gMaxT := getMaxTableIndex('BSC_T_');
2558     BSC_METADATA_OPTIMIZER_PKG.gMaxB := getMaxTableIndex('BSC_B_');
2559     BSC_METADATA_OPTIMIZER_PKG.gMaxI := getMaxTableIndex('BSC_I_');
2560     IF (BSC_METADATA_OPTIMIZER_PKG.gMaxB>BSC_METADATA_OPTIMIZER_PKG.gMaxI) THEN
2561       BSC_METADATA_OPTIMIZER_PKG.gMaxI := BSC_METADATA_OPTIMIZER_PKG.gMaxB;
2562     ELSE
2563       BSC_METADATA_OPTIMIZER_PKG.gMaxB := BSC_METADATA_OPTIMIZER_PKG.gMaxI;
2564     END IF;
2565     BSC_MO_HELPER_PKG.writeTmp('gMaxT = '||BSC_METADATA_OPTIMIZER_PKG.gMaxT||', gMaxB is '||
2566     BSC_METADATA_OPTIMIZER_PKG.gMaxB||', gMaxI='||BSC_METADATA_OPTIMIZER_PKG.gMaxI);
2567     IF (bsc_metadata_optimizer_pkg.g_retcode <> 0) THEN
2568       return;
2569     END IF;
2570     BSC_MO_HELPER_PKG.writeTmp('Calling deduce_bt_tables - Normal', FND_LOG.LEVEL_STATEMENT, true);
2571     BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling deduce_bt_tables - Normal');
2572     deduce_bt_tables(False);
2573 
2574     BSC_MO_HELPER_PKG.writeTmp('Calling deduce_bt_tables - Targets', FND_LOG.LEVEL_STATEMENT, true);
2575     BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling deduce_bt_tables - Targets');
2576     deduce_bt_tables (True );--For targets
2577 
2578     IF (bsc_metadata_optimizer_pkg.g_retcode <> 0) THEN
2579       return;
2580     END IF;
2581     IF BSC_METADATA_OPTIMIZER_PKG.g_log THEN
2582       BSC_MO_HELPER_PKG.writeTmp('Calling deduce_bt_tables_precalc', FND_LOG.LEVEL_STATEMENT);
2583     END IF;
2584     BSC_MO_HELPER_PKG.writeTmp('Calling deduce_bt_tables_precalc', FND_LOG.LEVEL_STATEMENT, true);
2585     BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling deduce_bt_tables_precalc');
2586     deduce_bt_tables_precalc;
2587 
2588     IF (bsc_metadata_optimizer_pkg.g_retcode <> 0) THEN
2589       return;
2590     END IF;
2591 
2592     --Connect base indicator tables with temporal tables
2593     BSC_MO_HELPER_PKG.writeTmp('Calling connect_s_to_b_tables', FND_LOG.LEVEL_STATEMENT, true);
2594     BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling connect_s_to_b_tables');
2595     connect_s_to_b_tables;
2596 
2597     --Add each temporal table to the collection of system tables
2598     BSC_MO_HELPER_PKG.writeTmp('Calling add_to_gtables', FND_LOG.LEVEL_STATEMENT, true);
2599 
2600     add_to_gtables (BSC_METADATA_OPTIMIZER_PKG.g_bt_tables);
2601     add_to_gtables (BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_tgt);
2602     add_to_gtables (BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc);
2603 
2604     --Make input tables and connect them to the base tables
2605     BSC_MO_HELPER_PKG.writeTmp('Calling connect_i_to_b_tables', FND_LOG.LEVEL_STATEMENT, true);
2606     BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling connect_i_to_b_tables');
2607     connect_i_to_b_tables;
2608 
2609 
2610     --BSC-MV note: Stating from the tables in garrTablesUpgradeT()
2611     --we need to get all the origin tables until the input tables and
2612     --insert them into garrTablesUpgrade()
2613     --Then we need to add those tables in gTablas.
2614     --Loader configuration will be re-done and we need all those tables in gTablas
2615     If bsc_metadata_optimizer_pkg.g_Sum_Level_Change = 1 Then
2616         bsc_metadata_optimizer_pkg.gnumTablesUpgrade := 0;
2617         BSC_MO_LOADER_CONFIG_PKG.InsertOriginTables (bsc_metadata_optimizer_pkg.garrTablesUpgradeT,
2618                             bsc_metadata_optimizer_pkg.garrTablesUpgrade);
2619         bsc_metadata_optimizer_pkg.gnumTablesUpgrade := bsc_metadata_optimizer_pkg.garrTablesUpgrade.count;
2620         load_upgrade_tables_db;
2621     End If;
2622     BSC_MO_HELPER_PKG.writeTmp('-------------------------------------', FND_LOG.LEVEL_STATEMENT, true);
2623     BSC_MO_HELPER_PKG.writeTmp('Completed InputTables '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE, true);
2624 
2625     EXCEPTION WHEN OTHERS THEN
2626         l_error := sqlerrm;
2627         BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in InputTables : '||l_error);
2628         BSC_MO_HELPER_PKG.TerminateWithError ('BSC_ITABLE_PROD_FAILED', 'InputTables');
2629         raise;
2630 End ;
2631 
2632 
2633 -- Load the metadata for the specified table into memory variables
2634 PROCEDURE Load_Table_From_DB(p_table IN VARCHAR2, p_indicator_num NUMBER, p_dim_set NUMBER) IS
2635 
2636 CURSOR cKeys IS
2637 SELECT column_name
2638 FROM
2639 bsc_db_tables_cols cols
2640 WHERE
2641 cols.table_name = p_table
2642 AND cols.column_type = 'P'
2643 ORDER BY cols.column_name;
2644 
2645 CURSOR cData(p_owner varchar2) IS
2646 SELECT cols.column_name, nvl(cols.source, 'BSC'), nvl(dbcols.measure_group_id, -1)
2647 FROM
2648 bsc_db_tables_cols cols,
2649 all_tab_columns tabcols,
2650 bsc_sys_measures sysm,
2651 bsc_db_measure_cols_vl dbcols
2652 WHERE
2653 cols.table_name = p_table
2654 AND cols.table_name = tabcols.table_name
2655 and cols.column_name = tabcols.column_name
2656 and tabcols.owner = p_owner
2657 AND cols.column_type = 'A'
2658 AND cols.column_name = sysm.measure_col
2659 AND cols.column_name = dbcols.measure_col
2660 ORDER BY cols.column_name;
2661 
2662 CURSOR cZeroCode (p_column in varchar2) IS
2663 select source_column, nvl(calculation_type, 0) from
2664 bsc_db_Tables_cols cols,
2665 bsc_db_calculations calc
2666 where
2667 cols.table_name = calc.table_name (+)
2668 and cols.table_name = p_table
2669 and cols.column_type = 'P'
2670 and calc.calculation_type (+)= 4
2671 and cols.column_name = p_column;
2672 
2673 CURSOR cOriginTables IS
2674 SELECT source_table_name FROM
2675 BSC_DB_TABLES_RELS
2676 WHERE table_name=p_table;
2677 
2678 l_stmt varchar2(1000);
2679 l_column VARCHAR2(100);
2680 l_source VARCHAR2(100);
2681 l_measure_group number;
2682 
2683 l_kpis_using_table BSC_METADATA_OPTIMIZER_PKG.tab_clsKPIDimSet ;
2684 ------------------------------------------------------------
2685 l_key  BSC_METADATA_OPTIMIZER_PKG.clsKeyField;
2686 l_key_list  BSC_METADATA_OPTIMIZER_PKG.tab_clsKeyField;
2687 l_source_column VARCHAR2(100);
2688 l_calc_type NUMBER;
2689 l_filter_view VARCHAR2(1000);
2690 ------------------------------------------------------------
2691 l_data BSC_METADATA_OPTIMIZER_PKG.clsDataField;
2692 l_data_list BSC_METADATA_OPTIMIZER_PKG.tab_clsDataField;
2693 ------------------------------------------------------------
2694 l_index NUMBER := 0;
2695 l_table BSC_METADATA_OPTIMIZER_PKG.clsTable;
2696 l_optimizationMode NUMBER;
2697 l_src_table VARCHAR2(100);
2698 l_state varchar2(4000);
2699 
2700 BEGIN
2701   bsc_mo_helper_pkg.writeTmp('Loading table '||p_table||' '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_STATEMENT, false);
2702   l_kpis_using_table := BSC_MO_HELPER_PKG.find_objectives_for_table(p_table);
2703   IF (l_kpis_using_table.count=0) THEN
2704     return;
2705   END IF;
2706   bsc_mo_helper_pkg.writeTmp('# of objectives using this table= '||l_kpis_using_table.count||' '||bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_STATEMENT, false);
2707   OPEN cKeys;
2708   LOOP
2709     FETCH cKeys INTO l_column;
2710     EXIT WHEN cKeys%NOTFOUND;
2711     l_key.tableName := p_table;
2712     l_key.keyName := l_column;
2713     -- find out source column and zero code requirement
2714     OPEN cZeroCode(l_column);
2715     FETCH cZeroCode INTO l_source_column, l_calc_type;
2716     CLOSE cZeroCode;
2717     l_key.origin := l_source_column;
2718     IF (l_calc_type=4) THEN
2719       l_key.needsCode0 := true;
2720       l_key.calculateCode0 := true;
2721     END IF;
2722 	-- find out if filters exist
2723     IF BSC_MO_HELPER_PKG.filters_exist(
2724                       l_kpis_using_table(0).kpi_number,
2725                       l_kpis_using_table(0).dim_set_id,
2726                       l_column,
2727                       l_filter_view ) THEN
2728       l_key.filterViewName := l_filter_view;
2729     END IF;
2730     l_key_list(l_key_list.count) := l_key;
2731   END LOOP;
2732   CLOSE cKeys;
2733   l_state := 'Loaded keys '||bsc_mo_helper_pkg.get_time;
2734   -- now onto the measure columns
2735   OPEN cData(bsc_metadata_optimizer_pkg.gBSCSchema);
2736   LOOP
2737     FETCH cData INTO l_column, l_source, l_measure_group;
2738     EXIT WHEN cData%NOTFOUND;
2739     l_data.tableName := p_table;
2740     l_data.fieldName := l_column;
2741     l_data.source := l_source;
2742     l_data.InternalColumnType := 0;
2743     l_data.measureGroup := l_measure_group;
2744 
2745     l_data_list(l_data_list.count) := l_data;
2746   END LOOP;
2747   CLOSE cData;
2748   l_state := l_state||' Loaded Data.count= '||l_data_list.count;
2749   l_index := BSC_MO_HELPER_PKG.findIndex(BSC_METADATA_OPTIMIZER_PKG.gIndicators, l_kpis_using_table(0).kpi_number);
2750   IF (l_index <> -1) THEN
2751     l_optimizationMode := BSC_METADATA_OPTIMIZER_PKG.gIndicators(l_index).optimizationMode ;
2752   ELSE
2753     l_optimizationMode := BSC_MO_HELPER_PKG.getKPIPropertyValue(l_kpis_using_table(0).kpi_number, 'DB_TRANSFORM', 1);
2754   END IF;
2755   l_table.Name := p_table;
2756   l_table.Type := 1;--  base, temporal or summary
2757   l_table.keys := l_key_list;
2758   l_table.data := l_data_list;
2759   l_table.Periodicity  := BSC_MO_HELPER_PKG.getPeriodicityForTable(p_table);
2760   l_table.originTable	:= null;--BSC_MO_HELPER_PKG.getSourceTable(p_table);
2761   l_table.Indicator := l_kpis_using_table(0).kpi_number;
2762   l_table.Configuration 	:= l_kpis_using_table(0).dim_set_id;
2763   l_table.EDW_Flag 	    := 0;
2764   l_table.IsTargetTable := false;
2765   l_table.HasTargets 	:= false;
2766   l_table.UsedForTargets := false;
2767   l_table.upgradeFlag  := 0;
2768   if (l_data_list.count>0) then
2769     l_table.measureGroup := l_data_list(l_data_list.first).measureGroup;
2770   else
2771     l_table.measureGroup := get_measure_group(p_table, l_data_list, p_indicator_num, p_dim_set);
2772   end if;
2773   bsc_mo_helper_pkg.writeTmp('measure group = '||l_table.measureGroup);
2774   -- Important, flag that this is as a production table, so it isnt dropped and recreated !
2775   l_table.isProductionTable := true;
2776   l_table.isProductionTableAltered := false;
2777   l_state := l_state || '  Loaded other properties ';
2778   FOR i IN cOriginTables LOOP
2779     l_table.originTable := l_table.originTable||i.source_table_name||',';
2780   END LOOP;
2781   IF l_table.originTable IS NOT NULL THEN
2782     l_table.originTable := substr(l_table.originTable, 1, length(l_table.originTable)-1);
2783   END IF;
2784   l_state:= l_state||' Loaded origin tables ';
2785 
2786   -- For AW
2787   IF (bsc_mo_helper_pkg.getKPIPropertyValue(l_table.Indicator, BSC_METADATA_OPTIMIZER_PKG.IMPL_TYPE, 1) = 2) THEN
2788     l_table.impl_type := 2;
2789   ELSE
2790     l_table.impl_type := 1;
2791   END IF;
2792   IF (l_optimizationMode = 0 ) THEN -- precalc
2793     l_state:=l_state|| '
2794 '||' Adding table '||p_table||' to g_bt_tables_precalc';
2795     BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc(BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc.count) := l_table;
2796   ELSIF  (  l_optimizationMode = 2 ) THEN -- targets
2797     l_state := l_state||'
2798 '||'Adding table '||p_table||'  to g_bt_tables_tgt';
2799     BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_tgt(BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_tgt.count) := l_table;
2800   ELSE
2801     l_state:=l_state||'
2802 '||'Adding table  '||p_table||' to g_bt_tables';
2803     BSC_METADATA_OPTIMIZER_PKG.g_bt_tables(BSC_METADATA_OPTIMIZER_PKG.g_bt_tables.count) := l_table;
2804   END IF;
2805   l_state := l_state||'
2806 Loaded table '||p_table;
2807   EXCEPTION WHEN OTHERS THEN
2808     BSC_MO_HELPER_PKG.writeTmp('state = '||l_state, FND_LOG.LEVEL_EXCEPTION, true);
2809     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in Load_Table_From_DB : '||sqlerrm);
2810 
2811     BSC_MO_HELPER_PKG.terminateWithError('BSC_RETR_TTABLES_FAILED', 'Load_Table_From_DB');
2812 	raise;
2813 END;
2814 
2815 FUNCTION is_production_table(p_table_name IN VARCHAR2, p_indicator OUT NOCOPY NUMBER, p_dim_set OUT NOCOPY NUMBER) return boolean
2816 IS
2817 l_stmt VARCHAR2(1000) ;
2818 cv   CurTyp;
2819 BEGIN
2820   l_stmt :=
2821   '  select kpi.indicator, tmp.dim_set_id
2822        from  bsc_kpis_vl kpi,
2823           (
2824              select substr(table_name, instr(table_name, ''_'', 1, 2)+1,
2825                          instr(table_name, ''_'', 1, 3)-instr(table_name, ''_'', 1, 2)-1) indicator,
2826                     substr(table_name, instr(table_name, ''_'', 1, 3)+1,
2827                          instr(table_name, ''_'', 1, 4)-instr(table_name, ''_'', 1, 3)-1) dim_set_id
2828                from bsc_db_tables_rels
2829               where table_name like ''BSC_S%''
2830             connect by prior  table_name = source_table_name
2831               start with source_table_name = :1
2832           ) tmp
2833       where kpi.indicator = tmp.indicator
2834         and prototype_flag not in (2,3) -- no need for 4 as the B table typically doesnt get dropped for 4
2835         and kpi.share_flag<>2
2836         and rownum=1';
2837   OPEN cv FOR l_stmt USING p_table_name;
2838   FETCH cv INTO p_indicator, p_dim_set;
2839   CLOSE cv;
2840   IF (p_indicator is not null) THEN -- atleast one production table is using this
2841     return true;
2842   ELSE
2843     return false;
2844   END IF;
2845 END;
2846 -- Load the production tables which have measures belonging to indicators
2847 -- in the current metadata run
2848 PROCEDURE LOAD_B_T_TABLES_FROM_DB IS
2849   inMeasures VARCHAR2(1000);
2850   cv   CurTyp;
2851   l_table VARCHAR2(100);
2852   l_src_table VARCHAR2(100);
2853   i NUMBER;
2854   l_stmt VARCHAR2(1000);
2855   l_indicator_num number;
2856   l_dim_set number;
2857 BEGIN
2858   BSC_MO_HELPER_PKG.writeTmp('Inside LOAD_B_T_TABLES_FROM_DB, system time is '||
2859             bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE, true);
2860   l_stmt := 'select distinct table_name from bsc_db_tables where (table_name like ''BSC_B%'' or table_name like ''BSC_T%'' ) and table_type=1';
2861   OPEN cv FOR l_stmt ;
2862   LOOP
2863     FETCH cv INTO l_table;
2864     EXIT WHEN cv%NOTFOUND;
2865     IF is_production_table(l_table, l_indicator_num, l_dim_set) THEN
2866       BSC_MO_HELPER_PKG.writeTmp('Loading production table '||l_table||' into memory '||BSC_MO_HELPER_PKG.get_time, FND_LOG.LEVEL_PROCEDURE, false);
2867       Load_Table_From_DB(l_table, l_indicator_num, l_dim_set);
2868     END IF;
2869   END LOOP;
2870 
2871   -- Intialize the disaggregations in the Production tables - Targets
2872   BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling init_s_table_measures for Production tables - Targets');
2873   BSC_MO_HELPER_PKG.writeTmp('Calling init_s_table_measures for Production tables - Targets', FND_LOG.LEVEL_STATEMENT, true);
2874   init_s_table_measures(BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_tgt);
2875 
2876   -- Intialize the disaggregations in the Production tables
2877   BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling init_s_table_measures for Production tables - Normal');
2878   BSC_MO_HELPER_PKG.writeTmp('Calling init_s_table_measures for Production tables - Normal', FND_LOG.LEVEL_STATEMENT, true);
2879   init_s_table_measures(BSC_METADATA_OPTIMIZER_PKG.g_bt_tables);
2880 
2881   -- Intialize the disaggregations in the Production tables - precalc
2882   BSC_METADATA_OPTIMIZER_PKG.logProgress('INPUT', 'Calling init_s_table_measures_precalc for Production tables');
2883   BSC_MO_HELPER_PKG.writeTmp('Calling init_s_table_measures_precalc for Production tables', FND_LOG.LEVEL_STATEMENT, true);
2884   init_s_table_measures_precalc(BSC_METADATA_OPTIMIZER_PKG.g_bt_tables_precalc);
2885 
2886   BSC_MO_HELPER_PKG.writeTmp('Completed LOAD_B_T_TABLES_FROM_DB, system time is '||
2887             bsc_mo_helper_pkg.get_time, FND_LOG.LEVEL_PROCEDURE, true);
2888   EXCEPTION WHEN OTHERS THEN
2889     BSC_MO_HELPER_PKG.TerminateWithMsg('Exception in LOAD_B_T_TABLES_FROM_DB : '||sqlerrm);
2890     BSC_MO_HELPER_PKG.terminateWithError('BSC_RETR_TTABLES_FAILED', 'LOAD_B_T_TABLES_FROM_DB');
2891 	raise;
2892 END;
2893 
2894 END BSC_MO_INPUT_TABLE_PKG ;