1 PACKAGE BODY FND_OAM_DSCRAM_ARGS_PKG as
2 /* $Header: AFOAMDSARGB.pls 120.7 2006/01/17 13:55 ilawler noship $ */
3
4 ----------------------------------------
5 -- Private Body Constants/Types
6 ----------------------------------------
7 PKG_NAME CONSTANT VARCHAR2(20) := 'DSCRAM_ARGS_PKG.';
8
9 -- exceptions used by INITIALZE_ARG/GET_CANONICAL_ARG_VALUE to facilitate common
10 -- cleanup actions
11 INIT_FAILED EXCEPTION;
12 GET_FAILED EXCEPTION;
13
14 --local name for common exception when dealing with binding
15 BIND_DOES_NOT_EXIST EXCEPTION;
16 PRAGMA EXCEPTION_INIT(BIND_DOES_NOT_EXIST, -1006);
17
18 --type used for bulk selects of the canonical value field
19 TYPE long_varchar2_table IS TABLE OF VARCHAR2(4000);
20
21 ----------------------------------------
22 -- Public/Private Body Methods
23 ----------------------------------------
24
25 -- Public
26 FUNCTION IS_READABLE(p_arg IN arg)
27 RETURN BOOLEAN
28 IS
29 BEGIN
30 RETURN p_arg.permissions IN (FND_OAM_DSCRAM_UTILS_PKG.G_PERMISSION_READ,
31 FND_OAM_DSCRAM_UTILS_PKG.G_PERMISSION_READ_WRITE);
32 END;
33
34 -- Public
35 FUNCTION IS_WRITABLE(p_arg IN arg)
36 RETURN BOOLEAN
37 IS
38 BEGIN
39 RETURN p_arg.permissions IN (FND_OAM_DSCRAM_UTILS_PKG.G_PERMISSION_WRITE,
40 FND_OAM_DSCRAM_UTILS_PKG.G_PERMISSION_READ_WRITE);
41 END;
42
43 -- Private helper to make sure a canonical value is proper for an arg,
44 -- validation failures are returned as exceptions
45 PROCEDURE VALIDATE_CANONICAL_VALUE(p_arg IN arg,
46 p_canonical_value IN VARCHAR2)
47 IS
48 l_ctxt VARCHAR2(60) := PKG_NAME||'VALIDATE_CANONICAL_VALUE';
49
50 l_num NUMBER;
51 l_date DATE;
52 l_rowid ROWID;
53 BEGIN
54 CASE p_arg.datatype
55 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_VARCHAR2 THEN
56 null; --no validation
57 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_NUMBER THEN
58 l_num := FND_NUMBER.CANONICAL_TO_NUMBER(p_canonical_value);
59 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_DATE THEN
60 l_date := FND_DATE.CANONICAL_TO_DATE(p_canonical_value);
61 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_ROWID THEN
62 --for some reason, this is refusing to throw an exception on invalid values
63 l_rowid := CHARTOROWID(p_canonical_value);
64 ELSE
65 --unknown datatype
66 fnd_oam_debug.log(6, l_ctxt, 'ARG ID('||p_arg.arg_id||'), unknown datatype: '||p_arg.datatype);
67 RAISE NO_DATA_FOUND;
68 END CASE;
69 END;
70
71 -- Private helper to set the canonical value and update related state.
72 -- Errors are returned as exceptions.
73 PROCEDURE SET_STATE_ARG_VALUE(p_arg IN OUT NOCOPY arg,
74 p_canonical_value IN VARCHAR2,
75 p_rowid_lbound IN ROWID DEFAULT NULL,
76 p_rowid_ubound IN ROWID DEFAULT NULL)
77 IS
78 BEGIN
79 VALIDATE_CANONICAL_VALUE(p_arg,
80 p_canonical_value);
81 p_arg.canonical_value := p_canonical_value;
82 p_arg.rowid_lbound := p_rowid_lbound;
83 p_arg.rowid_ubound := p_rowid_ubound;
84 p_arg.valid_value_flag := FND_API.G_TRUE;
85 END;
86
87 -- Private constructor helper for add_arg_to_context and add_arg_to_list to make a new physical arg entity
88 FUNCTION INTERNAL_CREATE_ARG(p_arg_id IN NUMBER,
89 p_arg_name IN VARCHAR2,
90 p_initialized_success_flag IN VARCHAR2,
91 p_allow_override_source_flag IN VARCHAR2,
92 p_binding_enabled_flag IN VARCHAR2,
93 p_permissions IN VARCHAR2,
94 p_write_policy IN VARCHAR2,
95 p_datatype IN VARCHAR2,
96 p_valid_value_flag IN VARCHAR2,
97 p_canonical_value IN VARCHAR2)
98 RETURN arg
99 IS
100 l_ctxt VARCHAR2(60) := PKG_NAME||'INTERNAL_CREATE_ARG';
101
102 l_initialized BOOLEAN := FND_OAM_DSCRAM_UTILS_PKG.FLAG_TO_BOOLEAN(p_initialized_success_flag);
103 l_allow_override_source BOOLEAN := FND_OAM_DSCRAM_UTILS_PKG.FLAG_TO_BOOLEAN(p_allow_override_source_flag);
104 l_binding_enabled BOOLEAN := FND_OAM_DSCRAM_UTILS_PKG.FLAG_TO_BOOLEAN(p_binding_enabled_flag);
105 l_valid_value BOOLEAN := FND_OAM_DSCRAM_UTILS_PKG.FLAG_TO_BOOLEAN(p_valid_value_flag);
106
107 l_arg arg;
108 l_ignore VARCHAR2(2048);
109 BEGIN
110 --init the new entry
111 l_arg.arg_id := p_arg_id;
112 l_arg.arg_name := p_arg_name;
113 l_arg.init_locally := FALSE;
114 l_arg.initialized_success_flag := p_initialized_success_flag;
115 l_arg.allow_override_source := l_allow_override_source;
116 l_arg.binding_enabled := l_binding_enabled;
117 l_arg.permissions := p_permissions;
118 l_arg.write_policy := p_write_policy;
119 l_arg.datatype := p_datatype;
120 l_arg.is_constant := FALSE; --default here, set for real in init
121 l_arg.source_cursor_id := NULL;
122 l_arg.source_sql_bind_rowids := FALSE; --default here, set for real in init
123 l_arg.source_state_key := NULL;
124 l_arg.source_use_exec_cursor := FALSE; --default here, set in init
125
126 --use separate setter for the value
127 l_arg.valid_value_flag := p_valid_value_flag;
128 IF l_initialized AND l_valid_value THEN
129 SET_STATE_ARG_VALUE(l_arg,
130 p_canonical_value);
131 END IF;
132
133 --return the completed arg
134 RETURN l_arg;
135
136 --let exceptions pass to parent
137 END;
138
139 -- Helper to FETCH_CONTEXT-like procedures to create an arg based on its attributes and
140 -- add it to a supplied arg context.
141 FUNCTION ADD_ARG_TO_CONTEXT(px_arg_ctxt IN OUT NOCOPY arg_context,
142 p_arg_id IN NUMBER,
143 p_arg_name IN VARCHAR2,
144 p_initialized_success_flag IN VARCHAR2,
145 p_allow_override_source_flag IN VARCHAR2,
146 p_binding_enabled_flag IN VARCHAR2,
147 p_permissions IN VARCHAR2,
148 p_write_policy IN VARCHAR2,
149 p_datatype IN VARCHAR2,
150 p_valid_value_flag IN VARCHAR2,
151 p_canonical_value IN VARCHAR2)
152 RETURN BOOLEAN
153 IS
154 l_ctxt VARCHAR2(60) := PKG_NAME||'ADD_ARG_TO_CONTEXT';
155
156 l_arg arg;
157 BEGIN
158 l_arg := INTERNAL_CREATE_ARG(p_arg_id,
159 p_arg_name,
160 p_initialized_success_flag,
161 p_allow_override_source_flag,
162 p_binding_enabled_flag,
163 p_permissions,
164 p_write_policy,
165 p_datatype,
166 p_valid_value_flag,
167 p_canonical_value);
168
169 --add the arg to the context
170 px_arg_ctxt(p_arg_name) := l_arg;
171
172 RETURN TRUE;
173 EXCEPTION
174 WHEN OTHERS THEN
175 fnd_oam_debug.log(6, l_ctxt, 'Argument ID: ('||p_arg_id||'), Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))');
176 RETURN FALSE;
177 END;
178
179 -- Private: similar to other add_arg_to_list but in this case we've already created an arg object
180 -- and just want it appended.
181 FUNCTION ADD_ARG_TO_LIST(px_arg_list IN OUT NOCOPY arg_list,
182 p_arg IN arg)
183 RETURN BOOLEAN
184 IS
185 l_ctxt VARCHAR2(60) := PKG_NAME||'ADD_ARG_TO_LIST';
186 BEGIN
187 --add the arg to the list
188 px_arg_list.EXTEND;
189 px_arg_list(px_arg_list.COUNT) := p_arg;
190
191 RETURN TRUE;
192 EXCEPTION
193 WHEN OTHERS THEN
194 fnd_oam_debug.log(6, l_ctxt, 'Argument ID: ('||p_arg.arg_id||'), Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))');
195 RETURN FALSE;
196 END;
197
198 -- Private helper to get_canonical_value to fetch the value for a given state key
199 PROCEDURE GET_CANONICAL_VALUE_FOR_KEY(px_arg IN OUT NOCOPY arg,
200 p_state_key IN VARCHAR2,
201 p_using_splitting IN BOOLEAN,
202 p_rowid_lbound IN ROWID,
203 p_rowid_ubound IN ROWID,
204 x_canonical_value OUT NOCOPY VARCHAR2,
205 x_return_status OUT NOCOPY VARCHAR2,
206 x_return_msg OUT NOCOPY VARCHAR2)
207 IS
208 l_ctxt VARCHAR2(60) := PKG_NAME||'GET_CANONICAL_VALUE_FOR_KEY';
209
210 l_canonical_value VARCHAR2(4000);
211 BEGIN
212 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
213 x_return_status := FND_API.G_RET_STS_ERROR;
214 x_return_msg := '';
215
216 --do a big case statement on the state key to fetch the value
217 CASE p_state_key
218 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_RUN_ID THEN
219 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(FND_OAM_DSCRAM_RUNS_PKG.GET_RUN_ID);
220
221 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_RUN_MODE THEN
222 l_canonical_value := FND_OAM_DSCRAM_RUNS_PKG.GET_RUN_MODE;
223
224 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_BUNDLE_ID THEN
225 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(FND_OAM_DSCRAM_BUNDLES_PKG.GET_BUNDLE_ID);
226
227 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_BUNDLE_WORKERS_ALLOWED THEN
228 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(FND_OAM_DSCRAM_BUNDLES_PKG.GET_WORKERS_ALLOWED);
229
230 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_BUNDLE_BATCH_SIZE THEN
231 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(FND_OAM_DSCRAM_BUNDLES_PKG.GET_BATCH_SIZE);
232
233 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_WORKER_ID THEN
234 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(FND_OAM_DSCRAM_BUNDLES_PKG.GET_WORKER_ID);
235
236 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_TASK_ID THEN
237 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(FND_OAM_DSCRAM_TASKS_PKG.GET_TASK_ID);
238
239 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_UNIT_ID THEN
240 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(FND_OAM_DSCRAM_UNITS_PKG.GET_UNIT_ID);
241
242 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_USING_SPLITTING THEN
243 l_canonical_value := FND_OAM_DSCRAM_UTILS_PKG.BOOLEAN_TO_FLAG(p_using_splitting);
244
245 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_ROWID_LBOUND THEN
246 l_canonical_value := ROWIDTOCHAR(p_rowid_lbound);
247
248 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_ROWID_UBOUND THEN
249 l_canonical_value := ROWIDTOCHAR(p_rowid_ubound);
250
251 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_UNIT_OBJECT_OWNER THEN
252 l_canonical_value := FND_OAM_DSCRAM_UNITS_PKG.GET_UNIT_OBJECT_OWNER;
253
254 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_UNIT_OBJECT_NAME THEN
255 l_canonical_value := FND_OAM_DSCRAM_UNITS_PKG.GET_UNIT_OBJECT_NAME;
256
257 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_UNIT_WORKERS_ALLOWED THEN
258 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(FND_OAM_DSCRAM_UNITS_PKG.GET_WORKERS_ALLOWED);
259
260 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_UNIT_BATCH_SIZE THEN
261 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(FND_OAM_DSCRAM_UNITS_PKG.GET_BATCH_SIZE);
262
263 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_DML_ID THEN
264 l_canonical_value := FND_OAM_DSCRAM_DMLS_PKG.GET_CURRENT_DML_ID;
265
266 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_PLSQL_ID THEN
267 l_canonical_value := FND_OAM_DSCRAM_PLSQLS_PKG.GET_CURRENT_PLSQL_ID;
268
269 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_ARGUMENT_ID THEN
270 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(px_arg.arg_id);
271
272 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_WORKERS_ALLOWED THEN
273 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(NVL(FND_OAM_DSCRAM_UNITS_PKG.GET_WORKERS_ALLOWED,
277 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(NVL(FND_OAM_DSCRAM_UNITS_PKG.GET_BATCH_SIZE,
274 FND_OAM_DSCRAM_BUNDLES_PKG.GET_WORKERS_ALLOWED));
275
276 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_KEY_BATCH_SIZE THEN
278 FND_OAM_DSCRAM_BUNDLES_PKG.GET_BATCH_SIZE));
279 ELSE
280 x_return_msg := 'ARG ID('||px_arg.arg_id||'), invalid state key: '||p_state_key;
281 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
282 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
283 RETURN;
284 END CASE;
285
286 --success
287 x_return_status := FND_API.G_RET_STS_SUCCESS;
288 x_canonical_value := l_canonical_value;
289 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
290 EXCEPTION
291 WHEN NO_DATA_FOUND THEN
292 -- since we involve no sql, this should only happen when there's missing state
293 x_return_status := FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_MISSING_STATE;
294 fnd_oam_debug.log(1, l_ctxt, 'Arg ID('||px_arg.arg_id||'), threw missing state.');
295 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
296 RETURN;
297 WHEN OTHERS THEN
298 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
299 x_return_msg := 'Arg ID('||px_arg.arg_id||') Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
300 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
301 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
302 RETURN;
303 END;
304
305 -- Private helper to get_canonical_value to fetch the value from the execution cursor. Since binds
306 -- use the arg's name field, we implicitly use this name to fetch the value.
307 PROCEDURE GET_CANONICAL_VALUE_FROM_CUR(px_arg IN OUT NOCOPY arg,
308 p_execution_cursor_id IN INTEGER,
309 x_canonical_value OUT NOCOPY VARCHAR2,
310 x_return_status OUT NOCOPY VARCHAR2,
311 x_return_msg OUT NOCOPY VARCHAR2)
312 IS
313 l_ctxt VARCHAR2(60) := PKG_NAME||'GET_CANONICAL_VALUE_FROM_CUR';
314
315 l_canonical_value VARCHAR2(4000);
316
317 l_bindvar_name VARCHAR2(120) := ':'||px_arg.arg_name;
318
319 l_number NUMBER := NULL;
320 l_date DATE := NULL;
321 l_bool BOOLEAN := NULL;
322 l_rowid ROWID := NULL;
323 BEGIN
324 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
325 x_return_status := FND_API.G_RET_STS_ERROR;
326 x_return_msg := '';
327
328 --fetch the value into the properly typed local variable then then
329 --convert it into the canonical
330 CASE px_arg.datatype
331 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_VARCHAR2 THEN
332 DBMS_SQL.VARIABLE_VALUE(p_execution_cursor_id,
333 l_bindvar_name,
334 x_canonical_value);
335
336 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_NUMBER THEN
337 DBMS_SQL.VARIABLE_VALUE(p_execution_cursor_id,
338 l_bindvar_name,
339 l_number);
340 x_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(l_number);
341
342 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_DATE THEN
343 DBMS_SQL.VARIABLE_VALUE(p_execution_cursor_id,
344 l_bindvar_name,
345 l_date);
346 x_canonical_value := FND_DATE.DATE_TO_CANONICAL(l_date);
347
348 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_ROWID THEN
349 DBMS_SQL.VARIABLE_VALUE_ROWID(p_execution_cursor_id,
350 l_bindvar_name,
351 l_rowid);
352 x_canonical_value := ROWIDTOCHAR(l_rowid);
353 ELSE
354 x_return_msg := 'Arg ('||px_arg.arg_id||') has unknown datatype:'||px_arg.datatype;
355 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
356 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
357 RETURN;
358 END CASE;
359
360 fnd_oam_debug.log(1, l_ctxt, 'Found canonical value: '||x_canonical_value);
361
362 --success
363 x_return_status := FND_API.G_RET_STS_SUCCESS;
364 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
365 EXCEPTION
366 WHEN BIND_DOES_NOT_EXIST THEN
367 --catch a common error and provide better feedback.
368 fnd_oam_debug.log(6, l_ctxt, 'Arg ID('||px_arg.arg_id||'), Bindvar('||l_bindvar_name||') does not exist');
369 x_return_msg := 'Variable Value failure: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
370 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
371 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
372 RETURN;
373 WHEN OTHERS THEN
374 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
375 x_return_msg := 'Arg ID('||px_arg.arg_id||') Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
376 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
377 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
378 RETURN;
379 END;
380
381 --Private, utility procedure for GET_CANONICAL_ARG_VALUE to execute a source sql using dynamic sql or the source_cursor and return the value as
382 --its canonical string representation. Must occur after the derived state/rowids are set by INITIALIZE_ARG.
383 PROCEDURE GET_CANONICAL_VALUE_FOR_SQL(px_arg IN OUT NOCOPY arg,
384 p_final_sql_stmt IN VARCHAR2 DEFAULT NULL,
388 x_return_status OUT NOCOPY VARCHAR2,
385 p_rowid_lbound IN ROWID,
386 p_rowid_ubound IN ROWID,
387 x_canonical_value OUT NOCOPY VARCHAR2,
389 x_return_msg OUT NOCOPY VARCHAR2)
390 IS
391 l_ctxt VARCHAR2(60) := PKG_NAME||'GET_CANONICAL_VALUE_FOR_SQL';
392
393 l_rows_fetched NUMBER;
394 l_canonical_value VARCHAR2(4000);
395
396 missing_binds EXCEPTION;
397 PRAGMA EXCEPTION_INIT(missing_binds, -1008);
398
399 l_number NUMBER;
400 l_date DATE;
401 l_rowid ROWID;
402 BEGIN
403 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
404 x_return_status := FND_API.G_RET_STS_ERROR;
405 x_return_msg := '';
406
407 --fetch the canonical value differently based on what SQL is available to us
408 IF p_final_sql_stmt IS NOT NULL THEN
409
410 --we don't support binding the rowids when using a manual sql stmt since it won't bind properly
411 --with user specified binds. Statements using binds should use the source_cursor.
412 IF px_arg.source_sql_bind_rowids THEN
413 x_return_msg := 'Cannot have a non-null final sql stmt when binding rowids. This should not happen.';
414 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
415 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
416 RETURN;
417 END IF;
418
419 --different statements depending on datatype
420 CASE px_arg.datatype
421 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_VARCHAR2 THEN
422 EXECUTE IMMEDIATE p_final_sql_stmt INTO l_canonical_value;
423 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_NUMBER THEN
424 EXECUTE IMMEDIATE p_final_sql_stmt INTO l_number;
425 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(l_number);
426 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_DATE THEN
427 EXECUTE IMMEDIATE p_final_sql_stmt INTO l_date;
428 l_canonical_value := FND_DATE.DATE_TO_CANONICAL(l_date);
429 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_ROWID THEN
430 EXECUTE IMMEDIATE p_final_sql_stmt INTO l_rowid;
431 l_canonical_value := ROWIDTOCHAR(l_rowid);
432 ELSE
433 x_return_msg := 'Arg ID('||px_arg.arg_id||'), invalid datatype: '||px_arg.datatype;
434 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
435 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
436 RETURN;
437 END CASE;
438 ELSIF px_arg.source_cursor_id IS NOT NULL THEN
439 IF NOT DBMS_SQL.IS_OPEN(px_arg.source_cursor_id) THEN
440 x_return_msg := 'Arg ID ('||px_arg.arg_id||'), source cursor is already closed. This should not happen.';
441 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
442 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
443 RETURN;
444 END IF;
445
446 --bind if we have to
447 IF px_arg.source_sql_bind_rowids THEN
448 fnd_oam_debug.log(1, l_ctxt, 'Binding Rowids');
449 DBMS_SQL.BIND_VARIABLE(px_arg.source_cursor_id,
450 FND_OAM_DSCRAM_UTILS_PKG.G_ARG_ROWID_LBOUND_NAME,
451 p_rowid_lbound);
452 DBMS_SQL.BIND_VARIABLE(px_arg.source_cursor_id,
453 FND_OAM_DSCRAM_UTILS_PKG.G_ARG_ROWID_UBOUND_NAME,
454 p_rowid_ubound);
455 END IF;
456
457 --now execute and fetch
458 fnd_oam_debug.log(1, l_ctxt, 'Executing cursor...');
459 l_rows_fetched := DBMS_SQL.EXECUTE_AND_FETCH(px_arg.source_cursor_id);
460 fnd_oam_debug.log(1, l_ctxt, '...Done');
461
462 IF l_rows_fetched <> 1 THEN
463 x_return_msg := 'Fetched '||l_rows_fetched||' rows. Args must return 1 row.';
464 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
465 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
466 RETURN;
467 END IF;
468
469 --now depending on the datatype, set our local canonical value
470 CASE px_arg.datatype
471 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_VARCHAR2 THEN
472 DBMS_SQL.COLUMN_VALUE(px_arg.source_cursor_id,
473 1,
474 l_canonical_value);
475 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_NUMBER THEN
476 DBMS_SQL.COLUMN_VALUE(px_arg.source_cursor_id,
477 1,
478 l_number);
479 l_canonical_value := FND_NUMBER.NUMBER_TO_CANONICAL(l_number);
480 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_DATE THEN
481 DBMS_SQL.COLUMN_VALUE(px_arg.source_cursor_id,
482 1,
483 l_date);
484 l_canonical_value := FND_DATE.DATE_TO_CANONICAL(l_date);
485 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_ROWID THEN
486 DBMS_SQL.COLUMN_VALUE_ROWID(px_arg.source_cursor_id,
487 1,
488 l_rowid);
489 l_canonical_value := ROWIDTOCHAR(l_rowid);
490 ELSE
491 x_return_msg := 'Arg ID('||px_arg.arg_id||'), invalid datatype: '||px_arg.datatype;
492 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
493 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
494 RETURN;
495 END CASE;
496 ELSE
497 x_return_msg := 'Source Cursor is NULL and Source Final SQL Stmt is NULL, no SQL to fetch.';
501 END IF;
498 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
499 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
500 RETURN;
502
503 --success
504 x_return_status := FND_API.G_RET_STS_SUCCESS;
505 x_canonical_value := l_canonical_value;
506 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
507 EXCEPTION
508 WHEN missing_binds THEN
509 x_return_status := FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_MISSING_BINDS;
510 fnd_oam_debug.log(1, l_ctxt, 'Arg ID('||px_arg.arg_id||'), threw missing binds.');
511 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
512 RETURN;
513 WHEN OTHERS THEN
514 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
515 x_return_msg := 'Arg ID('||px_arg.arg_id||') Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
516 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
517 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
518 RETURN;
519 END;
520
521 --Private, helper to INITIALIZE_ARG to sync up the arg's state with values INIT found. Primary responsibilities
522 --include the derived arg state and the source_cursor-related fields.
523 PROCEDURE UPDATE_STATE_USING_INIT_VALUES(px_arg IN OUT NOCOPY arg,
524 p_use_splitting IN BOOLEAN,
525 p_initialized_success_flag IN VARCHAR2,
526 p_valid_value_flag IN VARCHAR2,
527 p_canonical_value IN VARCHAR2,
528 p_source_type IN VARCHAR2,
529 p_source_text IN VARCHAR2,
530 p_source_final_text IN VARCHAR2,
531 x_return_status OUT NOCOPY VARCHAR2,
532 x_return_msg OUT NOCOPY VARCHAR2)
533 IS
534 l_ctxt VARCHAR2(60) := PKG_NAME||'UPDATE_STATE_USING_INIT_VALUES';
535
536 l_canonical_value VARCHAR2(4000);
537 l_number NUMBER;
538 l_date DATE;
539 l_rowid ROWID;
540
541 l_return_status VARCHAR2(6);
542 l_return_msg VARCHAR2(2048);
543 BEGIN
544 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
545 x_return_status := FND_API.G_RET_STS_ERROR;
546 x_return_msg := '';
547
548 --SET DERIVED ATTRIBUTES
549
550 --update the bind_rowids flag based on the source type and whether we're using splitting
551 IF (p_source_type = FND_OAM_DSCRAM_UTILS_PKG.G_SOURCE_SQL_RESTRICTABLE) THEN
552 px_arg.source_sql_bind_rowids := p_use_splitting;
553 END IF;
554
555 --set the is_constant indicator boolean based on the source_type
556 IF p_source_type = FND_OAM_DSCRAM_UTILS_PKG.G_SOURCE_CONSTANT THEN
557 px_arg.is_constant := TRUE;
558 END IF;
559
560 --if initialized was already determined, set our value-related state based on inputs
561 IF p_initialized_success_flag IS NOT NULL THEN
562 px_arg.initialized_success_flag := p_initialized_success_flag;
563 IF FND_OAM_DSCRAM_UTILS_PKG.FLAG_TO_BOOLEAN(p_initialized_success_flag) THEN
564 px_arg.valid_value_flag := p_valid_value_flag;
565 IF FND_OAM_DSCRAM_UTILS_PKG.FLAG_TO_BOOLEAN(p_valid_value_flag) THEN
566 BEGIN
567 SET_STATE_ARG_VALUE(px_arg,
568 p_canonical_value);
569 EXCEPTION
570 WHEN OTHERS THEN
571 fnd_oam_debug.log(1, l_ctxt, 'ARG ID ('||px_arg.arg_id||'), failed to set the canonical value: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))');
572 --if it didn't set properly, store that after the init to keep other threads from doing it
573 px_arg.valid_value_flag := FND_API.G_FALSE;
574 END;
575 ELSIF px_arg.is_constant AND px_arg.valid_value_flag IS NULL THEN
576 -- For constants, write the canonical value when the value flag is null because we never set it to TRUE until the get.
577 -- Invalid p_source_text values would have been caught by the first init where valid_value_flag would be set to FALSE.
578 px_arg.canonical_value := p_source_text;
579 ELSE
580 px_arg.canonical_value := NULL;
581 END IF;
582 END IF;
583 END IF;
584
585 --Before doing further init, if we've already failed the init then return because we've updated enough state
586 IF px_arg.initialized_success_flag = FND_API.G_FALSE THEN
587 px_arg.init_locally := TRUE;
588 x_return_status := FND_API.G_RET_STS_SUCCESS;
589 fnd_oam_debug.log(1, l_ctxt, 'Found initialized_success_flag was false after sync but before any sql actions.');
590 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
591 RETURN;
592 END IF;
593
594 --Since constants are rather common and they dont change, go ahead and validate the value and
595 --store it in the canonical value for quick retrieval later. We don't set the valid_value_flag because
596 --we want get_canonical_value to be able to detect the first time a constant is referenced so it can write it
597 --in the appropriate location.
598 IF p_source_type = FND_OAM_DSCRAM_UTILS_PKG.G_SOURCE_CONSTANT THEN
599
600 BEGIN
601 VALIDATE_CANONICAL_VALUE(px_arg,
602 p_source_text);
603 --set to NULL instead of TRUE to allow constants to be overridden in the get_* logic by context values
604 px_arg.valid_value_flag := NULL;
605 px_arg.canonical_value := p_source_text;
606 EXCEPTION
610
607 WHEN OTHERS THEN
608 px_arg.valid_value_flag := FND_API.G_FALSE;
609 END;
611 --always set init to true since a failed value gets caught with the valid_value_flag
612 px_arg.initialized_success_flag := FND_API.G_TRUE;
613
614 -- The following situations benefit from a source cursor:
615 -- 1) SQL source with write policies of per_range or always
616 -- However, to keep from querying the source_final_text in get_value later, all SQL-based sources use a cursor.
617 ELSIF FND_OAM_DSCRAM_UTILS_PKG.SOURCE_TYPE_USES_SQL(p_source_type) THEN
618
619 --close the last cursor, shouldn't happen but it's safe
620 IF px_arg.source_cursor_id IS NOT NULL AND DBMS_SQL.IS_OPEN(px_arg.source_cursor_id) THEN
621 DBMS_SQL.CLOSE_CURSOR(px_arg.source_cursor_id);
622 END IF;
623
624 --create a new cursor and parse the source_final_text into it
625 px_arg.source_cursor_id := DBMS_SQL.OPEN_CURSOR;
626 BEGIN
627 DBMS_SQL.PARSE(px_arg.source_cursor_id,
628 p_source_final_text,
629 DBMS_SQL.NATIVE);
630 EXCEPTION
631 WHEN OTHERS THEN
632 x_return_msg := 'ARG_ID ('||px_arg.arg_id||'), failed to parse source final text: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
633 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
634 px_arg.init_locally := TRUE;
635 fnd_oam_debug.log(1, l_ctxt, 'Source Final Text: "'||p_source_final_text||'"');
636 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
637 RETURN;
638 END;
639
640 --finally, define a column with the correct output type
641 CASE px_arg.datatype
642 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_VARCHAR2 THEN
643 DBMS_SQL.DEFINE_COLUMN(px_arg.source_cursor_id,
644 1,
645 l_canonical_value,
646 4000);
647 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_NUMBER THEN
648 DBMS_SQL.DEFINE_COLUMN(px_arg.source_cursor_id,
649 1,
650 l_number);
651 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_DATE THEN
652 DBMS_SQL.DEFINE_COLUMN(px_arg.source_cursor_id,
653 1,
654 l_date);
655 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_ROWID THEN
656 DBMS_SQL.DEFINE_COLUMN_ROWID(px_arg.source_cursor_id,
657 1,
658 l_rowid);
659 ELSE
660 x_return_msg := 'Unknown Arg Dataype: '||px_arg.datatype;
661 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
662 px_arg.init_locally := TRUE;
663 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
664 RETURN;
665 END CASE;
666
667 --set these sorts of args to be initialized
668 px_arg.initialized_success_flag := FND_API.G_TRUE;
669 ELSIF p_source_type = FND_OAM_DSCRAM_UTILS_PKG.G_SOURCE_STATE THEN
670 --set the source state key using the first 30 chars of the source_text
671 px_arg.source_state_key := SUBSTR(p_source_text, 1, 30);
672 px_arg.initialized_success_flag := FND_API.G_TRUE;
673 ELSIF p_source_type = FND_OAM_DSCRAM_UTILS_PKG.G_SOURCE_EXECUTION_CURSOR THEN
674 --set the use_exec_cursor indicator variable for the arg
675 px_arg.source_use_exec_cursor := TRUE;
676 px_arg.initialized_success_flag := FND_API.G_TRUE;
677 ELSIF p_source_type IS NULL THEN
678 --if there's no source, we're done initializing.
679 px_arg.initialized_success_flag := FND_API.G_TRUE;
680 END IF;
681
682 --return success
683 x_return_status := FND_API.G_RET_STS_SUCCESS;
684 px_arg.init_locally := TRUE;
685 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
686 EXCEPTION
687 WHEN OTHERS THEN
688 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
689 x_return_msg := 'Arg ID('||px_arg.arg_id||') Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
690 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
691 px_arg.init_locally := TRUE;
692 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
693 END;
694
695 -- Private: used to set up the arg state and perform any pre-GET operations to make sure that all GETS
696 -- proceed in the same way. Only messes with the value fields in the case of constants so we don't have to select out
697 -- the source text again later.
698 PROCEDURE INITIALIZE_ARG(px_arg IN OUT NOCOPY arg,
699 p_arg_context IN arg_context,
700 p_using_splitting IN BOOLEAN,
701 x_return_status OUT NOCOPY VARCHAR2,
702 x_return_msg OUT NOCOPY VARCHAR2)
703 IS
704 PRAGMA AUTONOMOUS_TRANSACTION;
705
706 l_ctxt VARCHAR2(60) := PKG_NAME||'INITIALIZE_ARG';
707
708 l_initialized_success_flag VARCHAR2(3);
709 l_valid_value_flag VARCHAR2(3);
710 l_canonical_value VARCHAR2(4000);
711 l_source_type VARCHAR2(30);
712 l_source_text VARCHAR2(4000);
713 l_source_where_clause VARCHAR2(4000);
714 l_source_final_text VARCHAR2(4000);
715 l_append_rowid_clause BOOLEAN;
716
717 l_return_status VARCHAR2(6);
718 l_return_msg VARCHAR2(2048);
719 BEGIN
720 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
724 fnd_oam_debug.log(1, l_ctxt, 'Argument(Splitting?): '||px_arg.arg_name||'('||FND_OAM_DSCRAM_UTILS_PKG.BOOLEAN_TO_FLAG(p_using_splitting)||')');
721 x_return_status := FND_API.G_RET_STS_ERROR;
722 x_return_msg := '';
723
725
726 --check if we've already done the local init
727 IF px_arg.init_locally THEN
728 x_return_status := FND_API.G_RET_STS_SUCCESS;
729 fnd_oam_debug.log(1, l_ctxt, 'Already locally initialized');
730 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
731 RETURN;
732 END IF;
733
734 --before locking the arg, select to see if its initialized already by another thread
735 SELECT initialized_success_flag, valid_value_flag, canonical_value, source_type, source_text, source_final_text
736 INTO l_initialized_success_flag, l_valid_value_flag, l_canonical_value, l_source_type, l_source_text, l_source_final_text
737 FROM fnd_oam_dscram_args_b
738 WHERE arg_id = px_arg.arg_id;
739
740 -- if init success already determined, update our local state variables and return
741 IF l_initialized_success_flag IS NOT NULL THEN
742 UPDATE_STATE_USING_INIT_VALUES(px_arg,
743 p_using_splitting,
744 l_initialized_success_flag,
745 l_valid_value_flag,
746 l_canonical_value,
747 l_source_type,
748 l_source_text,
749 l_source_final_text,
750 x_return_status,
751 x_return_msg);
752 fnd_oam_debug.log(1, l_ctxt, 'Pre-Lock select found already initialized.');
753 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
754 RETURN;
755 END IF;
756
757 -- if we got here, we'll probably be updating the arg so lock it and make sure we still need to update it
758 SELECT initialized_success_flag, valid_value_flag, canonical_value, source_type, source_text, source_where_clause, source_final_text
759 INTO l_initialized_success_flag, l_valid_value_flag, l_canonical_value, l_source_type, l_source_text, l_source_where_clause, l_source_final_text
760 FROM fnd_oam_dscram_args_b
761 WHERE arg_id = px_arg.arg_id
762 FOR UPDATE;
763
764 --check again after the locking select to see if somebody else has already done the init
765 IF l_initialized_success_flag IS NOT NULL THEN
766 UPDATE_STATE_USING_INIT_VALUES(px_arg,
767 p_using_splitting,
768 l_initialized_success_flag,
769 l_valid_value_flag,
770 l_canonical_value,
771 l_source_type,
772 l_source_text,
773 l_source_final_text,
774 x_return_status,
775 x_return_msg);
776 fnd_oam_debug.log(1, l_ctxt, 'Locking select found already initialized.');
777 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
778 ROLLBACK;
779 RETURN;
780 END IF;
781
782 --at this point it's up to this function to do the init, reset the valid value flag to unknown
783 l_valid_value_flag := NULL;
784
785 --for sqls, compose our final source statement from its component parts
786 IF FND_OAM_DSCRAM_UTILS_PKG.SOURCE_TYPE_USES_SQL(l_source_type) THEN
787
788 --see whether we'll be appending the rowid clause or not
789 l_append_rowid_clause := FALSE;
790 IF l_source_type = FND_OAM_DSCRAM_UTILS_PKG.G_SOURCE_SQL_RESTRICTABLE THEN
791 l_append_rowid_clause := p_using_splitting;
792 END IF;
793
794 --prepare the final text from the source_text/where clause
795 FND_OAM_DSCRAM_UTILS_PKG.MAKE_FINAL_SQL_STMT(p_arg_context,
796 l_source_text,
797 l_source_where_clause,
798 l_append_rowid_clause,
799 l_source_final_text,
800 l_return_status,
801 l_return_msg);
802 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
803 fnd_oam_debug.log(6, l_ctxt, 'ARG ID('||px_arg.arg_id||'), failed to create final sql stmt: '||l_return_msg);
804 px_arg.initialized_success_flag := FND_API.G_FALSE;
805 END IF;
806 END IF;
807
808 --After initializing stuff into our local values, try to roll these local values into our state
809 UPDATE_STATE_USING_INIT_VALUES(px_arg,
810 p_using_splitting,
811 l_initialized_success_flag,
812 l_valid_value_flag,
813 l_canonical_value,
814 l_source_type,
815 l_source_text,
816 l_source_final_text,
817 l_return_status,
818 l_return_msg);
819 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
820 x_return_status := l_return_status;
821 x_return_msg := l_return_msg;
822 RAISE INIT_FAILED;
823 END IF;
824
825 --Finally, if we ended up initializing the arg, write out that new state
826 IF px_arg.initialized_success_flag IS NOT NULL THEN
827 UPDATE fnd_oam_dscram_args_b
831 last_update_login = fnd_global.user_id,
828 SET initialized_success_flag = px_arg.initialized_success_flag,
829 source_final_text = l_source_final_text,
830 last_updated_by = fnd_global.user_id,
832 last_update_date = SYSDATE
833 WHERE arg_id = px_arg.arg_id;
834
835 --if the arg is writable and we determined if it has a valid value or not, write out the canonical value and valid_value_flag
836 --For constants, we bend the rules and write them even if it's not writable because otherwise get must incur the cost of messing
837 --with the source_text.
838 IF (px_arg.valid_value_flag IS NOT NULL AND IS_WRITABLE(px_arg)) THEN
839 fnd_oam_debug.log(1, l_ctxt, 'Pre-emptively writing the arg value');
840 UPDATE fnd_oam_dscram_args_b
841 SET valid_value_flag = px_arg.valid_value_flag,
842 canonical_value = px_arg.canonical_value
843 WHERE arg_id = px_arg.arg_id;
844 END IF;
845
846 COMMIT;
847
848 --return success
849 x_return_status := FND_API.G_RET_STS_SUCCESS;
850 ELSE
851 x_return_msg := 'ARG ID('||px_arg.arg_id||'), got to the end but arg was not initialized. This should not happen.';
852 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
853 RAISE INIT_FAILED;
854 END IF;
855
856 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
857 EXCEPTION
858 WHEN INIT_FAILED THEN
859 --x_return_* already set, only raised after locking select
860 BEGIN
861 UPDATE fnd_oam_dscram_args_b
862 SET initialized_success_flag = FND_API.G_FALSE,
863 last_updated_by = fnd_global.user_id,
864 last_update_login = fnd_global.user_id,
865 last_update_date = SYSDATE
866 WHERE arg_id = px_arg.arg_id;
867 COMMIT;
868 px_arg.initialized_success_flag := FND_API.G_FALSE;
869 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
870 EXCEPTION
871 WHEN OTHERS THEN
872 x_return_msg := 'Unexpected Error while processing init_failed: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
873 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
874 ROLLBACK;
875 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
876 END;
877 WHEN OTHERS THEN
878 --here we can't assume we have a lock so leave out update of DB but do update our local state
879 px_arg.initialized_success_flag := FND_API.G_FALSE;
880 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
881 x_return_msg := 'Arg ID('||px_arg.arg_id||'), unexpected error while initializing: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
882 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
883 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
884 ROLLBACK;
885 END;
886
887 -- Private, helper to STORE_CANONICAL_ARG_VALUE to perform an insert into the ARG_VALUES table
888 PROCEDURE INSERT_ARG_VALUE(p_arg_id IN NUMBER,
889 p_valid_value_flag IN VARCHAR2,
890 p_canonical_value IN VARCHAR2,
891 p_parent_type IN VARCHAR2,
892 p_parent_id IN NUMBER DEFAULT NULL,
893 p_rowid_lbound IN ROWID DEFAULT NULL,
894 p_rowid_ubound IN ROWID DEFAULT NULL,
895 p_id_lbound IN NUMBER DEFAULT NULL,
896 p_id_ubound IN NUMBER DEFAULT NULL,
897 x_arg_val_id OUT NOCOPY NUMBER)
898 IS
899 l_id NUMBER;
900 BEGIN
901 INSERT INTO FND_OAM_DSCRAM_ARG_VALUES (ARG_VALUE_ID,
902 ARG_ID,
903 PARENT_TYPE,
904 PARENT_ID,
905 ROWID_LBOUND,
906 ROWID_UBOUND,
907 ID_LBOUND,
908 ID_UBOUND,
909 VALID_VALUE_FLAG,
910 CANONICAL_VALUE,
911 CREATED_BY,
912 CREATION_DATE,
913 LAST_UPDATED_BY,
914 LAST_UPDATE_DATE,
915 LAST_UPDATE_LOGIN)
916 VALUES
917 (fnd_oam_dscram_arg_values_s.nextval,
918 p_arg_id,
919 p_parent_type,
920 p_parent_id,
921 p_rowid_lbound,
922 p_rowid_ubound,
923 p_id_lbound,
924 p_id_ubound,
925 p_valid_value_flag,
926 p_canonical_value,
927 FND_GLOBAL.USER_ID,
928 SYSDATE,
929 FND_GLOBAL.USER_ID,
930 SYSDATE,
931 FND_GLOBAL.USER_ID)
932 RETURNING ARG_VALUE_ID INTO l_id;
933 x_arg_val_id := l_id;
934
935 --exceptions passed to store
936 END;
937
938 -- Private, used by GET_CANONICAL_ARG_VALUE to write an arg's canonical value to the DB in the proper place
939 -- Assume conditions surrounding whether we should be writing the arg have already been evaluated.
940 PROCEDURE STORE_ARG_VALUE(px_arg IN OUT NOCOPY arg,
941 x_return_status OUT NOCOPY VARCHAR2,
942 x_return_msg OUT NOCOPY VARCHAR2)
946
943 IS
944
945 l_ctxt VARCHAR2(60) := PKG_NAME||'STORE_ARG_VALUE';
947 l_arg_val_id NUMBER;
948 BEGIN
949 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
950 x_return_status := FND_API.G_RET_STS_ERROR;
951 x_return_msg := '';
952
953 IF px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_ONCE THEN
954 --update the main args_b row
955 UPDATE fnd_oam_dscram_args_b
956 SET valid_value_flag = px_arg.valid_value_flag,
957 canonical_value = px_arg.canonical_value,
958 last_updated_by = fnd_global.user_id,
959 last_update_login = fnd_global.user_id,
960 last_update_date = SYSDATE
961 WHERE arg_id = px_arg.arg_id;
962 ELSIF px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_PER_WORKER THEN
963 --try to update arg_values with parent_type=worker, failing that insert
964 UPDATE fnd_oam_dscram_arg_values
965 SET valid_value_flag = px_arg.valid_value_flag,
966 canonical_value = px_arg.canonical_value,
967 last_updated_by = fnd_global.user_id,
968 last_update_login = fnd_global.user_id,
969 last_update_date = SYSDATE
970 WHERE arg_id = px_arg.arg_id
971 AND parent_type = FND_OAM_DSCRAM_UTILS_PKG.G_TYPE_WORKER AND
972 parent_id = FND_OAM_DSCRAM_BUNDLES_PKG.GET_WORKER_ID;
973 IF SQL%ROWCOUNT = 0 THEN
974 fnd_oam_debug.log(1, l_ctxt, 'Inserting per-worker arg value.');
975 INSERT_ARG_VALUE(px_arg.arg_id,
976 px_arg.valid_value_flag,
977 px_arg.canonical_value,
978 FND_OAM_DSCRAM_UTILS_PKG.G_TYPE_WORKER,
979 FND_OAM_DSCRAM_BUNDLES_PKG.GET_WORKER_ID,
980 x_arg_val_id => l_arg_val_id);
981 END IF;
982 ELSIF px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_PER_RANGE THEN
983 --update arg_values with range values and parent_type = range
984 UPDATE fnd_oam_dscram_arg_values
985 SET valid_value_flag = px_arg.valid_value_flag,
986 canonical_value = px_arg.canonical_value,
987 rowid_lbound = px_arg.rowid_lbound,
988 rowid_ubound = px_arg.rowid_ubound,
989 last_updated_by = fnd_global.user_id,
990 last_update_login = fnd_global.user_id,
991 last_update_date = SYSDATE
992 WHERE arg_id = px_arg.arg_id AND
993 parent_type = FND_OAM_DSCRAM_UTILS_PKG.G_TYPE_RANGE AND
994 rowid_lbound = px_arg.rowid_lbound AND
995 rowid_ubound = px_arg.rowid_ubound;
996 IF SQL%ROWCOUNT = 0 THEN
997 fnd_oam_debug.log(1, l_ctxt, 'Inserting per-range arg value.');
998 INSERT_ARG_VALUE(px_arg.arg_id,
999 px_arg.valid_value_flag,
1000 px_arg.canonical_value,
1001 FND_OAM_DSCRAM_UTILS_PKG.G_TYPE_RANGE,
1002 p_rowid_lbound => px_arg.rowid_lbound,
1003 p_rowid_ubound => px_arg.rowid_ubound,
1004 x_arg_val_id => l_arg_val_id);
1005 END IF;
1006 ELSIF px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_ALWAYS THEN
1007 fnd_oam_debug.log(1, l_ctxt, 'Inserting always arg value.');
1008 INSERT_ARG_VALUE(px_arg.arg_id,
1009 px_arg.valid_value_flag,
1010 px_arg.canonical_value,
1011 NULL,
1012 p_rowid_lbound => px_arg.rowid_lbound,
1013 p_rowid_ubound => px_arg.rowid_ubound,
1014 x_arg_val_id => l_arg_val_id);
1015 ELSE
1016 x_return_msg := 'Invalid write policy: '||px_arg.write_policy;
1017 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1018 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1019 RETURN;
1020 END IF;
1021
1022 x_return_status := FND_API.G_RET_STS_SUCCESS;
1023 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1024 EXCEPTION
1025 WHEN OTHERS THEN
1026 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1027 x_return_msg := 'Arg ID('||px_arg.arg_id||'), unexpected error while storing canonical value: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
1028 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1029 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1030 END;
1031
1032 -- Private Wrapper: STORE in an autonomous transaction for cases such as context args where we can't roll back or
1033 -- failure cases where we're going to roll back but we don't want future get_args to keep failing.
1034 PROCEDURE STORE_ARG_VALUE_AUTONOMOUSLY(px_arg IN OUT NOCOPY arg,
1035 x_return_status OUT NOCOPY VARCHAR2,
1036 x_return_msg OUT NOCOPY VARCHAR2)
1037 IS
1038 PRAGMA AUTONOMOUS_TRANSACTION;
1039 BEGIN
1040 STORE_ARG_VALUE(px_arg,
1041 x_return_status,
1042 x_return_msg);
1043 IF x_return_status = FND_API.G_RET_STS_SUCCESS THEN
1044 COMMIT;
1045 ELSE
1046 ROLLBACK;
1047 END IF;
1048 END;
1049
1050 -- Declaration to allow GET_CANONICAL_ARG_VALUE to get values for context args.
1051 PROCEDURE GET_CANONICAL_CTXT_ARG_VALUE(px_arg IN OUT NOCOPY arg,
1052 p_using_splitting IN BOOLEAN,
1053 p_rowid_lbound IN ROWID,
1054 p_rowid_ubound IN ROWID,
1055 p_execution_cursor_id IN INTEGER,
1059 x_arg_lock_handle OUT NOCOPY VARCHAR2,
1056 p_force_store_autonomously IN BOOLEAN,
1057 p_allow_sourcing IN BOOLEAN,
1058 p_release_arg_lock IN BOOLEAN,
1060 x_value OUT NOCOPY VARCHAR2,
1061 x_return_status OUT NOCOPY VARCHAR2,
1062 x_return_msg OUT NOCOPY VARCHAR2);
1063
1064 -- Private: obtains value for the argument using either the local state, external sources or the arg context.
1065 -- If it's writable, also writes out retrieved value to proper location based on write_policy using STORE.
1066 -- For locking the arg, we use a dbms_lock based lock instead of a FOR UPDATE to allow all of the sources/stores to happen in the parent
1067 -- transaction so that stored values are discarded if the results are discarded. Values are stored autonomously if p_force_store_autonomously is set.
1068 -- Allow_sourcing and release_arg_lock can be manipulated to perform a shallow get to see if an arg already has a value and if not, maintain the lock
1069 -- so that the caller can update the arg and release the lock. This is used in the UPDATE_WRITABLE-like procedures to default values.
1070 PROCEDURE GET_CANONICAL_ARG_VALUE(px_arg IN OUT NOCOPY arg,
1071 px_arg_context IN OUT NOCOPY arg_context,
1072 p_using_splitting IN BOOLEAN,
1073 p_rowid_lbound IN ROWID,
1074 p_rowid_ubound IN ROWID,
1075 p_execution_cursor_id IN INTEGER,
1076 p_force_store_autonomously IN BOOLEAN,
1077 p_allow_sourcing IN BOOLEAN,
1078 p_release_arg_lock IN BOOLEAN,
1079 x_arg_lock_handle OUT NOCOPY VARCHAR2,
1080 x_value OUT NOCOPY VARCHAR2,
1081 x_return_status OUT NOCOPY VARCHAR2,
1082 x_return_msg OUT NOCOPY VARCHAR2)
1083 IS
1084 l_ctxt VARCHAR2(60) := PKG_NAME||'GET_CANONICAL_ARG_VALUE';
1085
1086 l_determined_value BOOLEAN;
1087 l_value_requires_store BOOLEAN;
1088 l_valid_value_flag VARCHAR2(3);
1089 l_canonical_value VARCHAR2(2048);
1090 l_lock_handle VARCHAR2(128) := NULL;
1091 l_retval INTEGER;
1092
1093 l_temp NUMBER;
1094 l_ignore VARCHAR2(128);
1095 l_return_status VARCHAR2(6);
1096 l_return_msg VARCHAR2(2048);
1097 BEGIN
1098 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
1099 x_return_status := FND_API.G_RET_STS_ERROR;
1100 x_return_msg := '';
1101
1102 fnd_oam_debug.log(1, l_ctxt, 'Argument(ID): '||px_arg.arg_name||'('||px_arg.arg_id||')');
1103
1104 --initialize the argument if it hasn't been initialized locally yet (sets up source_cursor/derived state)
1105 IF NOT px_arg.init_locally THEN
1106 INITIALIZE_ARG(px_arg,
1107 px_arg_context,
1108 p_using_splitting,
1109 l_return_status,
1110 l_return_msg);
1111 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1112 x_return_status := l_return_status;
1113 x_return_msg := l_return_msg;
1114 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1115 END IF;
1116 END IF;
1117
1118 --if the arg went through init before and we stored that it failed, return an error, this is less likely
1119 IF px_arg.initialized_success_flag = FND_API.G_FALSE THEN
1120 x_return_msg := 'Arg ID ('||px_arg.arg_id||'), previous call to init stored that it failed. Get cannot continue.';
1121 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1122 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1123 RETURN;
1124 END IF;
1125
1126 --at this point, we should have a sucessfully initialized arg, try to determine its value
1127 l_determined_value := FALSE;
1128 l_value_requires_store := FALSE;
1129
1130 --now check if valid_value_flag's been set to false meaning we have no value and sourcing fails
1131 IF px_arg.valid_value_flag = FND_API.G_FALSE THEN
1132 --note: this means that a malformed constant will not be overrideable by the arg_context, should be a very infrequent corner case.
1133 x_return_msg := 'Arg ID ('||px_arg.arg_id||'), previous call to get_value stored that fetching the value fails. Exiting.';
1134 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1135 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1136 RETURN;
1137 -- see if we already have a value, skip the check if we write always
1138 ELSIF px_arg.valid_value_flag = FND_API.G_TRUE AND
1139 (NOT (IS_WRITABLE(px_arg)) OR
1140 NOT (px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_ALWAYS)) THEN
1141 --if we already know the local value is valid then make sure we match the supplied rowid range as well
1142 IF (px_arg.rowid_lbound IS NOT NULL OR px_arg.rowid_ubound IS NOT NULL) THEN
1143 IF ((px_arg.rowid_lbound IS NULL OR (px_arg.rowid_lbound = p_rowid_lbound)) AND
1144 (px_arg.rowid_ubound IS NULL OR (px_arg.rowid_ubound = p_rowid_ubound))) THEN
1145
1146 x_return_status := FND_API.G_RET_STS_SUCCESS;
1147 x_value := px_arg.canonical_value;
1148 fnd_oam_debug.log(1, l_ctxt, 'Ranged Value cached');
1149 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1153 --if not contingent on a range, the value is the arg's stored canonical value
1150 RETURN;
1151 END IF;
1152 ELSE
1154 x_return_status := FND_API.G_RET_STS_SUCCESS;
1155 x_value := px_arg.canonical_value;
1156 fnd_oam_debug.log(1, l_ctxt, 'Value cached');
1157 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1158 RETURN;
1159 END IF;
1160 ELSE
1161 -- we haven't cached that the value's valid somewhere, but it may have been calculated and stored already in the DB
1162 -- use different select statements to find the latest valid_value_flag and canonical_value
1163 l_valid_value_flag := NULL;
1164 IF px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_ONCE THEN
1165 --query the main args_b row
1166 SELECT valid_value_flag, canonical_value
1167 INTO l_valid_value_flag, l_canonical_value
1168 FROM fnd_oam_dscram_args_b
1169 WHERE arg_id = px_arg.arg_id;
1170 fnd_oam_debug.log(1, l_ctxt, 'Write Policy Once: first query valid_value_flag: '||l_valid_value_flag);
1171 ELSIF px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_PER_WORKER THEN
1172 --Needed in the case of restart to get the value we may have comitted for this worker
1173 --query arg_values with parent_type=worker
1174 BEGIN
1175 SELECT valid_value_flag, canonical_value
1176 INTO l_valid_value_flag, l_canonical_value
1177 FROM fnd_oam_dscram_arg_values
1178 WHERE arg_id = px_arg.arg_id AND
1179 parent_type = FND_OAM_DSCRAM_UTILS_PKG.G_TYPE_WORKER AND
1180 parent_id = FND_OAM_DSCRAM_BUNDLES_PKG.GET_WORKER_ID;
1181 EXCEPTION
1182 WHEN OTHERS THEN
1183 l_valid_value_flag := NULL;
1184 END;
1185 fnd_oam_debug.log(1, l_ctxt, 'Write Policy Per-Worker: first query valid_value_flag: '||l_valid_value_flag);
1186 ELSIF px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_PER_RANGE THEN
1187 --Since we don't share ranges, this won't happen on the initial execute, but it may be necessary on restart
1188 --if the arg's value was comitted since we won't read it back on initialize.
1189 --query arg_values with range values and parent_type = range
1190 BEGIN
1191 SELECT valid_value_flag, canonical_value
1192 INTO l_valid_value_flag, l_canonical_value
1193 FROM fnd_oam_dscram_arg_values
1194 WHERE arg_id = px_arg.arg_id AND
1195 parent_type = FND_OAM_DSCRAM_UTILS_PKG.G_TYPE_RANGE AND
1196 rowid_lbound = p_rowid_lbound AND
1197 rowid_ubound = p_rowid_ubound;
1198 EXCEPTION
1199 WHEN OTHERS THEN
1200 l_valid_value_flag := NULL;
1201 END;
1202 fnd_oam_debug.log(1, l_ctxt, 'Write Policy Per-Range: first query valid_value_flag: '||l_valid_value_flag);
1203 END IF;
1204
1205 --if we found a value for valid_value_flag, we've determined a value or a failure
1206 IF l_valid_value_flag = FND_API.G_TRUE THEN
1207 l_determined_value := TRUE;
1208 ELSIF l_valid_value_flag = FND_API.G_FALSE THEN
1209 --A false means sourcing failes
1210 x_return_msg := 'Arg ID ('||px_arg.arg_id||'), non-locking select: previous call to get_value stored that fetching the value fails. Exiting.';
1211 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1212 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1213 RETURN;
1214 END IF;
1215 END IF;
1216
1217 --for write_once, we need to lock the arg and check again, the rest don't need a lock because there's no cross-worker contention.
1218 IF NOT l_determined_value AND
1219 IS_WRITABLE(px_arg) AND
1220 px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_ONCE THEN
1221
1222 --lock the arg
1223 IF FND_OAM_DSCRAM_UTILS_PKG.LOCK_ARG(px_arg.arg_id,
1224 l_lock_handle) THEN
1225 --do a normal select instead of a locking select since the above lock will hold for write_once args even if release_lock
1226 --is set when a worker is the first to determine a value for the arg. The lock will be released when the first worker
1227 --to set the arg commits or rolls back.
1228 --Known Issue: when the run is in a non-normal mode, write-once args will be written by each worker because the batch
1229 --is never comitted. In the normal mode, the first successful batch is the only one to write the arg value.
1230 SELECT valid_value_flag, canonical_value
1231 INTO l_valid_value_flag, l_canonical_value
1232 FROM fnd_oam_dscram_args_b
1233 WHERE arg_id = px_arg.arg_id;
1234 fnd_oam_debug.log(1, l_ctxt, 'Write Policy Once, locking query valid_value_flag: '||l_valid_value_flag);
1235
1236 --re-check the valid value flag
1237 IF l_valid_value_flag = FND_API.G_TRUE THEN
1238 l_determined_value := TRUE;
1239 ELSIF l_valid_value_flag = FND_API.G_FALSE THEN
1240 --A false means sourcing failed previously
1241 px_arg.valid_value_flag := FND_API.G_FALSE;
1242 x_return_msg := 'Arg ID ('||px_arg.arg_id||'), locking select: previous call to get_value stored that fetching the value fails. Exiting.';
1243 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1244 RAISE GET_FAILED;
1245 END IF;
1246 END IF;
1247 END IF;
1248
1249 --at this point, we know whether the arg currently has a valid value based on the write policy. If we haven't
1253 px_arg_context.EXISTS(px_arg.arg_name) THEN
1250 --determined a value, before sourcing it using the source_* fields, try to obtain it from the context if the arg allows override.
1251 IF NOT l_determined_value AND
1252 px_arg.allow_override_source AND
1254
1255 IF IS_READABLE(px_arg_context(px_arg.arg_name)) AND
1256 px_arg_context(px_arg.arg_name).datatype = px_arg.datatype THEN
1257
1258 GET_CANONICAL_CTXT_ARG_VALUE(px_arg_context(px_arg.arg_name),
1259 p_using_splitting,
1260 p_rowid_lbound,
1261 p_rowid_ubound,
1262 p_execution_cursor_id,
1263 p_force_store_autonomously,
1264 TRUE,
1265 TRUE,
1266 l_ignore,
1267 l_canonical_value,
1268 l_return_status,
1269 l_return_msg);
1270 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
1271 l_valid_value_flag := FND_API.G_TRUE;
1272 l_determined_value := TRUE;
1273 l_value_requires_store := TRUE;
1274 END IF;
1275 END IF;
1276 END IF;
1277
1278 -- skip the sourcing section if we disallow it
1279 IF p_allow_sourcing THEN
1280
1281 --This is a bit of a hack, but constants have the valid_value flag set to NULL to allow the above logic to try and fetch values from
1282 --different locations based on the write_policy so that arg_contexts can be used to get values. The correct constant value is stored
1283 --in the canonical value. This represents one case where the valid_value_flag does not need to be true to use the value of the
1284 --canonical value.
1285 IF NOT l_determined_value AND px_arg.is_constant AND l_valid_value_flag IS NULL THEN
1286 l_valid_value_flag := FND_API.G_TRUE;
1287 l_canonical_value := px_arg.canonical_value;
1288 l_determined_value := TRUE;
1289 l_value_requires_store := TRUE;
1290 END IF;
1291
1292 --if the value is still unknown, first try state sourcing since it's cheap
1293 IF NOT l_determined_value AND px_arg.source_state_key IS NOT NULL THEN
1294 GET_CANONICAL_VALUE_FOR_KEY(px_arg,
1295 px_arg.source_state_key,
1296 p_using_splitting,
1297 p_rowid_lbound,
1298 p_rowid_ubound,
1299 l_canonical_value,
1300 l_return_status,
1301 l_return_msg);
1302 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
1303 BEGIN
1304 VALIDATE_CANONICAL_VALUE(px_arg,
1305 l_canonical_value);
1306 l_valid_value_flag := FND_API.G_TRUE;
1307 EXCEPTION
1308 WHEN OTHERS THEN
1309 l_valid_value_flag := FND_API.G_FALSE;
1310 END;
1311 l_determined_value := TRUE;
1312 l_value_requires_store := TRUE;
1313 ELSIF l_return_status = FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_MISSING_STATE THEN
1314 -- if we didn't fail as much as we were called under the wrong circumstances, don't store this as a failure either
1315 x_return_status := l_return_status;
1316 x_return_msg := l_return_msg;
1317 RAISE GET_FAILED;
1318 ELSE
1319 --here we really did fail
1320 l_valid_value_flag := FND_API.G_FALSE;
1321 l_determined_value := TRUE;
1322 l_value_requires_store := TRUE;
1323 END IF;
1324
1325 END IF;
1326
1327 --if the value is still unknown, next try execution cursor sourcing since it's also relatively cheap
1328 IF NOT l_determined_value AND px_arg.source_use_exec_cursor AND p_execution_cursor_id IS NOT NULL THEN
1329 GET_CANONICAL_VALUE_FROM_CUR(px_arg,
1330 p_execution_cursor_id,
1331 l_canonical_value,
1332 l_return_status,
1333 l_return_msg);
1334 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
1335 --don't validate, the cursor get is strongly typed
1336 l_valid_value_flag := FND_API.G_TRUE;
1337 l_determined_value := TRUE;
1338 l_value_requires_store := TRUE;
1339 ELSE
1340 --failed
1341 l_valid_value_flag := FND_API.G_FALSE;
1342 l_determined_value := TRUE;
1343 l_value_requires_store := TRUE;
1344 END IF;
1345 END IF;
1346
1347 --if the value is still unknown, try to do sql-based sourcing
1348 IF NOT l_determined_value AND px_arg.source_cursor_id IS NOT NULL THEN
1349 --now source the value for sql using the source_cursor_id, constants should have already been rolled into the value by init
1350 GET_CANONICAL_VALUE_FOR_SQL(px_arg,
1351 NULL,
1352 p_rowid_lbound,
1353 p_rowid_ubound,
1354 l_canonical_value,
1355 l_return_status,
1356 l_return_msg);
1357 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
1358 BEGIN
1362 EXCEPTION
1359 VALIDATE_CANONICAL_VALUE(px_arg,
1360 l_canonical_value);
1361 l_valid_value_flag := FND_API.G_TRUE;
1363 WHEN OTHERS THEN
1364 l_valid_value_flag := FND_API.G_FALSE;
1365 END;
1366 l_determined_value := TRUE;
1367 l_value_requires_store := TRUE;
1368 ELSIF l_return_status = FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_MISSING_BINDS THEN
1369 -- if we didn't fail as much as we were called under the wrong circumstances, don't store this as a failure either
1370 x_return_status := l_return_status;
1371 x_return_msg := l_return_msg;
1372 RAISE GET_FAILED;
1373 ELSE
1374 --here we really did fail
1375 l_valid_value_flag := FND_API.G_FALSE;
1376 l_determined_value := TRUE;
1377 l_value_requires_store := TRUE;
1378 END IF;
1379 END IF;
1380
1381 END IF; --end p_allow_sourcing check
1382
1383 --if we don't have a value here, any arg can try to source from the context before being flagged as a failure.
1384 --This allows placeholder args for dmls where there is no source, just the expectation of inheriting a value from the context
1385 IF NOT l_determined_value AND
1386 px_arg_context.EXISTS(px_arg.arg_name) THEN
1387 fnd_oam_debug.log(1, l_ctxt, 'Doing Last ditch context check.');
1388 IF IS_READABLE(px_arg_context(px_arg.arg_name)) AND
1389 px_arg_context(px_arg.arg_name).datatype = px_arg.datatype THEN
1390
1391 GET_CANONICAL_CTXT_ARG_VALUE(px_arg_context(px_arg.arg_name),
1392 p_using_splitting,
1393 p_rowid_lbound,
1394 p_rowid_ubound,
1395 p_execution_cursor_id,
1396 p_force_store_autonomously,
1397 TRUE,
1398 TRUE,
1399 l_ignore,
1400 l_canonical_value,
1401 l_return_status,
1402 l_return_msg);
1403 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
1404 l_valid_value_flag := FND_API.G_TRUE;
1405 l_determined_value := TRUE;
1406 l_value_requires_store := TRUE;
1407 ELSIF l_return_status = FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_MISSING_BINDS THEN
1408 --since this is the last thing before failure, let missing binds return
1409 x_return_status := l_return_status;
1410 x_return_msg := l_return_msg;
1411 fnd_oam_debug.log(1, l_ctxt, 'Returning Missing Binds');
1412 RETURN;
1413 END IF;
1414 END IF;
1415 END IF;
1416
1417 --at this point, we've done everything we can to determine the value, if we haven't and we allowed sourcing then the get's a failure
1418 IF NOT l_determined_value AND p_allow_sourcing THEN
1419 fnd_oam_debug.log(6, l_ctxt, 'Arg ID ('||px_arg.arg_id||'), failed to determine a value.');
1420 l_valid_value_flag := FND_API.G_FALSE;
1421 l_determined_value := TRUE;
1422 l_value_requires_store := TRUE;
1423 END IF;
1424
1425 -- if we found a value, sync up the value state with the get even if we're not going to write it out
1426 IF l_determined_value THEN
1427 px_arg.valid_value_flag := l_valid_value_flag;
1428 IF FND_OAM_DSCRAM_UTILS_PKG.FLAG_TO_BOOLEAN(l_valid_value_flag) THEN
1429 px_arg.canonical_value := l_canonical_value;
1430 ELSE
1431 px_arg.canonical_value := NULL;
1432 END IF;
1433
1434 --if we determined a value and we're fetching values for each range, store the range used.
1435 IF l_determined_value AND px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_PER_RANGE THEN
1436 px_arg.rowid_lbound := p_rowid_lbound;
1437 px_arg.rowid_ubound := p_rowid_ubound;
1438 END IF;
1439 END IF;
1440
1441 --if the get fetched a new value that needs to be stored, do that also
1442 IF IS_WRITABLE(px_arg) AND l_value_requires_store THEN
1443 --store the value autonomously when instructed. We don't need to write autonomously for
1444 --write once args because other workers will hang on the write once lock and we don't want to
1445 --give up the value until we're sure it works for this range. Also, it messes up the print_arg_context.
1446 IF p_force_store_autonomously THEN
1447 STORE_ARG_VALUE_AUTONOMOUSLY(px_arg,
1448 l_return_status,
1449 l_return_msg);
1450 ELSE
1451 STORE_ARG_VALUE(px_arg,
1452 l_return_status,
1453 l_return_msg);
1454 END IF;
1455 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1456 px_arg.valid_value_flag := FND_API.G_FALSE;
1457 x_return_status := l_return_status;
1458 x_return_msg := l_return_msg;
1459 RAISE GET_FAILED;
1460 END IF;
1461 END IF;
1462
1463 --release the lock on the arg if told to do so and the arg isn't a just-stored write-once value.
1464 --Just-written, write-once args hold onto the lock until the batch is comitted or rolled back so that other
1465 --workers don't compute a new value. These args are treated as possible synchronization points.
1466 IF p_release_arg_lock AND
1467 ((px_arg.write_policy <> FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_ONCE) OR
1471 IF l_retval <> 0 THEN
1468 (px_arg.write_policy = FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_ONCE AND NOT l_value_requires_store)) THEN
1469 IF l_lock_handle IS NOT NULL THEN
1470 l_retval := DBMS_LOCK.RELEASE(l_lock_handle);
1472 fnd_oam_debug.log(6, l_ctxt, 'Failed to release arg lock: '||l_retval);
1473 END IF;
1474 END IF;
1475 x_arg_lock_handle := NULL;
1476 ELSE
1477 x_arg_lock_handle := l_lock_handle;
1478 END IF;
1479
1480 --done, change return status based on whether we found a valid value even if we didn't store it
1481 IF FND_OAM_DSCRAM_UTILS_PKG.FLAG_TO_BOOLEAN(l_valid_value_flag) THEN
1482 x_return_status := FND_API.G_RET_STS_SUCCESS;
1483 x_value := l_canonical_value;
1484 ELSIF (NOT p_allow_sourcing AND l_valid_value_flag IS NULL) THEN
1485 --return success if something which was unallowed to source ended up without a value, since we're only
1486 --doing a shallow test to see if it has a value. Caller must check px_arg's valid value flag to see if
1487 --it's a real successful get or just a sucessful lack of failure.
1488 x_return_status := FND_API.G_RET_STS_SUCCESS;
1489 x_value := NULL;
1490 END IF;
1491 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1492 EXCEPTION
1493 WHEN GET_FAILED THEN
1494 IF l_lock_handle IS NOT NULL THEN
1495 l_retval := DBMS_LOCK.RELEASE(l_lock_handle);
1496 IF l_retval <> 0 THEN
1497 fnd_oam_debug.log(6, l_ctxt, 'Failed to release arg lock: '||l_retval);
1498 END IF;
1499 END IF;
1500
1501 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1502 RETURN;
1503 WHEN OTHERS THEN
1504 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1505 x_return_msg := 'Arg ID('||px_arg.arg_id||'), unexpected error while getting canonical value: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
1506 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1507
1508 --store that the arg's value yields failure
1509 BEGIN
1510 IF IS_WRITABLE(px_arg) THEN
1511 px_arg.valid_value_flag := FND_API.G_FALSE;
1512 px_arg.canonical_value := NULL;
1513 px_arg.rowid_lbound := p_rowid_lbound;
1514 px_arg.rowid_ubound := p_rowid_ubound;
1515 STORE_ARG_VALUE_AUTONOMOUSLY(px_arg,
1516 l_return_status,
1517 l_return_msg);
1518 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1519 fnd_oam_debug.log(6, l_ctxt, 'Store failure failed('||l_return_status||'): '||l_return_msg);
1520 END IF;
1521 END IF;
1522 EXCEPTION
1523 WHEN OTHERS THEN
1524 fnd_oam_debug.log(6, l_ctxt, 'Exception while storing failed arg fetch: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))');
1525 END;
1526 IF l_lock_handle IS NOT NULL THEN
1527 l_retval := DBMS_LOCK.RELEASE(l_lock_handle);
1528 IF l_retval <> 0 THEN
1529 fnd_oam_debug.log(6, l_ctxt, 'Failed to release arg lock: '||l_retval);
1530 END IF;
1531 END IF;
1532 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1533 END;
1534
1535 -- Private Wrapper for context args
1536 PROCEDURE GET_CANONICAL_CTXT_ARG_VALUE(px_arg IN OUT NOCOPY arg,
1537 p_using_splitting IN BOOLEAN,
1538 p_rowid_lbound IN ROWID,
1539 p_rowid_ubound IN ROWID,
1540 p_execution_cursor_id IN INTEGER,
1541 p_force_store_autonomously IN BOOLEAN,
1542 p_allow_sourcing IN BOOLEAN,
1543 p_release_arg_lock IN BOOLEAN,
1544 x_arg_lock_handle OUT NOCOPY VARCHAR2,
1545 x_value OUT NOCOPY VARCHAR2,
1546 x_return_status OUT NOCOPY VARCHAR2,
1547 x_return_msg OUT NOCOPY VARCHAR2)
1548 IS
1549 l_empty_arg_context arg_context;
1550 BEGIN
1551 GET_CANONICAL_ARG_VALUE(px_arg,
1552 l_empty_arg_context,
1553 p_using_splitting,
1554 p_rowid_lbound,
1555 p_rowid_ubound,
1556 p_execution_cursor_id,
1557 p_force_store_autonomously,
1558 p_allow_sourcing,
1559 p_release_arg_lock,
1560 x_arg_lock_handle,
1561 x_value,
1562 x_return_status,
1563 x_return_msg);
1564 END;
1565
1566 --Another, simpler wrapper used by internal_print_arg_context
1567 PROCEDURE GET_CANONICAL_CTXT_ARG_VALUE(px_arg IN OUT NOCOPY arg,
1568 p_using_splitting IN BOOLEAN,
1569 x_value OUT NOCOPY VARCHAR2,
1570 x_return_status OUT NOCOPY VARCHAR2,
1571 x_return_msg OUT NOCOPY VARCHAR2)
1572 IS
1573 l_empty_arg_context arg_context;
1574 l_ignore VARCHAR2(128);
1575 BEGIN
1576 GET_CANONICAL_ARG_VALUE(px_arg,
1577 l_empty_arg_context,
1581 NULL,
1578 p_using_splitting,
1579 NULL,
1580 NULL,
1582 FALSE,
1583 TRUE,
1584 TRUE,
1585 l_ignore,
1586 x_value,
1587 x_return_status,
1588 x_return_msg);
1589 END;
1590
1591 -- Public, getter for type VARCHAR2
1592 PROCEDURE GET_ARG_VALUE(px_arg IN OUT NOCOPY arg,
1593 px_arg_context IN OUT NOCOPY arg_context,
1594 p_using_splitting IN BOOLEAN,
1595 p_rowid_lbound IN ROWID,
1596 p_rowid_ubound IN ROWID,
1597 p_execution_cursor_id IN INTEGER,
1598 x_value OUT NOCOPY VARCHAR2,
1599 x_return_status OUT NOCOPY VARCHAR2,
1600 x_return_msg OUT NOCOPY VARCHAR2)
1601 IS
1602 l_ctxt VARCHAR2(60) := PKG_NAME||'GET_ARG_VALUE(VARCHAR2)';
1603
1604 l_ignore VARCHAR2(128);
1605 l_varchar2 VARCHAR2(4000);
1606 l_return_status VARCHAR2(6);
1607 l_return_msg VARCHAR2(2048);
1608 BEGIN
1609 x_return_status := FND_API.G_RET_STS_ERROR;
1610 x_return_msg := '';
1611 GET_CANONICAL_ARG_VALUE(px_arg,
1612 px_arg_context,
1613 p_using_splitting,
1614 p_rowid_lbound,
1615 p_rowid_ubound,
1616 p_execution_cursor_id,
1617 FALSE,
1618 TRUE,
1619 TRUE,
1620 l_ignore,
1621 l_varchar2,
1622 l_return_status,
1623 l_return_msg);
1624 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1625 x_return_status := l_return_status;
1626 x_return_msg := l_return_msg;
1627 x_value := NULL;
1628 RETURN;
1629 END IF;
1630 x_value := l_varchar2;
1631
1632 --return success
1633 x_return_status := FND_API.G_RET_STS_SUCCESS;
1634 RETURN;
1635 EXCEPTION
1636 WHEN OTHERS THEN
1637 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1638 x_return_msg := 'Unexpected Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
1639 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1640 x_value := NULL;
1641 END;
1642
1643 -- Public, getter for type NUMBER
1644 PROCEDURE GET_ARG_VALUE(px_arg IN OUT NOCOPY arg,
1645 px_arg_context IN OUT NOCOPY arg_context,
1646 p_using_splitting IN BOOLEAN,
1647 p_rowid_lbound IN ROWID,
1648 p_rowid_ubound IN ROWID,
1649 p_execution_cursor_id IN INTEGER,
1650 x_value OUT NOCOPY NUMBER,
1651 x_return_status OUT NOCOPY VARCHAR2,
1652 x_return_msg OUT NOCOPY VARCHAR2)
1653 IS
1654 l_ctxt VARCHAR2(60) := PKG_NAME||'GET_ARG_VALUE(NUMBER)';
1655
1656 l_ignore VARCHAR2(128);
1657 l_varchar2 VARCHAR2(4000);
1658 l_return_status VARCHAR2(6);
1659 l_return_msg VARCHAR2(2048);
1660 BEGIN
1661 x_return_status := FND_API.G_RET_STS_ERROR;
1662 x_return_msg := '';
1663 GET_CANONICAL_ARG_VALUE(px_arg,
1664 px_arg_context,
1665 p_using_splitting,
1666 p_rowid_lbound,
1667 p_rowid_ubound,
1668 p_execution_cursor_id,
1669 FALSE,
1670 TRUE,
1671 TRUE,
1672 l_ignore,
1673 l_varchar2,
1674 l_return_status,
1675 l_return_msg);
1676 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1677 x_return_status := l_return_status;
1678 x_return_msg := l_return_msg;
1679 x_value := NULL;
1680 RETURN;
1681 END IF;
1682 x_value := FND_NUMBER.CANONICAL_TO_NUMBER(l_varchar2);
1683
1684 --return success
1685 x_return_status := FND_API.G_RET_STS_SUCCESS;
1686 RETURN;
1687 EXCEPTION
1688 WHEN OTHERS THEN
1689 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1690 x_return_msg := 'Unexpected Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
1691 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1692 x_value := NULL;
1693 END;
1694
1695 -- Public, getter for type DATE
1696 PROCEDURE GET_ARG_VALUE(px_arg IN OUT NOCOPY arg,
1697 px_arg_context IN OUT NOCOPY arg_context,
1698 p_using_splitting IN BOOLEAN,
1699 p_rowid_lbound IN ROWID,
1700 p_rowid_ubound IN ROWID,
1701 p_execution_cursor_id IN INTEGER,
1702 x_value OUT NOCOPY DATE,
1706 l_ctxt VARCHAR2(60) := PKG_NAME||'GET_ARG_VALUE(DATE)';
1703 x_return_status OUT NOCOPY VARCHAR2,
1704 x_return_msg OUT NOCOPY VARCHAR2)
1705 IS
1707
1708 l_ignore VARCHAR2(128);
1709 l_varchar2 VARCHAR2(4000);
1710 l_return_status VARCHAR2(6);
1711 l_return_msg VARCHAR2(2048);
1712 BEGIN
1713 x_return_status := FND_API.G_RET_STS_ERROR;
1714 x_return_msg := '';
1715 GET_CANONICAL_ARG_VALUE(px_arg,
1716 px_arg_context,
1717 p_using_splitting,
1718 p_rowid_lbound,
1719 p_rowid_ubound,
1720 p_execution_cursor_id,
1721 FALSE,
1722 TRUE,
1723 TRUE,
1724 l_ignore,
1725 l_varchar2,
1726 l_return_status,
1727 l_return_msg);
1728 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1729 x_return_status := l_return_status;
1730 x_return_msg := l_return_msg;
1731 x_value := NULL;
1732 RETURN;
1733 END IF;
1734 x_value := FND_DATE.CANONICAL_TO_DATE(l_varchar2);
1735
1736 --return success
1737 x_return_status := FND_API.G_RET_STS_SUCCESS;
1738 RETURN;
1739 EXCEPTION
1740 WHEN OTHERS THEN
1741 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1742 x_return_msg := 'Unexpected Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
1743 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1744 x_value := NULL;
1745 END;
1746
1747 -- Public, getter for type ROWID
1748 PROCEDURE GET_ARG_VALUE_ROWID(px_arg IN OUT NOCOPY arg,
1749 px_arg_context IN OUT NOCOPY arg_context,
1750 p_using_splitting IN BOOLEAN,
1751 p_rowid_lbound IN ROWID,
1752 p_rowid_ubound IN ROWID,
1753 p_execution_cursor_id IN INTEGER,
1754 x_value OUT NOCOPY ROWID,
1755 x_return_status OUT NOCOPY VARCHAR2,
1756 x_return_msg OUT NOCOPY VARCHAR2)
1757 IS
1758 l_ctxt VARCHAR2(60) := PKG_NAME||'GET_ARG_VALUE_ROWID()';
1759
1760 l_ignore VARCHAR2(128);
1761 l_varchar2 VARCHAR2(4000);
1762 l_return_status VARCHAR2(6);
1763 l_return_msg VARCHAR2(2048);
1764 BEGIN
1765 x_return_status := FND_API.G_RET_STS_ERROR;
1766 x_return_msg := '';
1767 GET_CANONICAL_ARG_VALUE(px_arg,
1768 px_arg_context,
1769 p_using_splitting,
1770 p_rowid_lbound,
1771 p_rowid_ubound,
1772 p_execution_cursor_id,
1773 FALSE,
1774 TRUE,
1775 TRUE,
1776 l_ignore,
1777 l_varchar2,
1778 l_return_status,
1779 l_return_msg);
1780 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1781 x_return_status := l_return_status;
1782 x_return_msg := l_return_msg;
1783 x_value := NULL;
1784 RETURN;
1785 END IF;
1786 x_value := CHARTOROWID(l_varchar2);
1787
1788 --return success
1789 x_return_status := FND_API.G_RET_STS_SUCCESS;
1790 RETURN;
1791 EXCEPTION
1792 WHEN OTHERS THEN
1793 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1794 x_return_msg := 'Unexpected Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
1795 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1796 x_value := NULL;
1797 END;
1798
1799 --Private, used by internal_print_arg_context to reset an arg to an unknown initialized status
1800 PROCEDURE RESET_INITIALIZED_AUTONOMOUSLY(p_arg_id IN NUMBER)
1801 IS
1802 PRAGMA AUTONOMOUS_TRANSACTION;
1803
1804 l_ctxt VARCHAR2(60) := PKG_NAME||'RESET_INITIALIZED_AUTONOMOUSLY';
1805 BEGIN
1806 UPDATE fnd_oam_dscram_args_b
1807 SET initialized_success_flag = NULL,
1808 last_updated_by = fnd_global.user_id,
1809 last_update_login = fnd_global.user_id,
1810 last_update_date = SYSDATE
1811 WHERE arg_id = p_arg_id;
1812 COMMIT;
1813 EXCEPTION
1814 WHEN OTHERS THEN
1815 fnd_oam_debug.log(6, l_ctxt, 'Arg ID('||p_arg_id||'), failed to reset initialized flag: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))');
1816 ROLLBACK;
1817 END;
1818
1819 -- Private
1820 -- Debug method to print out an arg context.
1821 -- *WARNING*: performs rollbacks when p_get_values=TRUE to keep from comitting changes. Should only be called
1822 -- when not in the middle of a transaction that did work. If p_get_values=FALSE, can be called whenever.
1823 PROCEDURE INTERNAL_PRINT_ARG_CONTEXT(p_arg_ctxt IN OUT NOCOPY arg_context,
1824 p_get_values IN BOOLEAN DEFAULT FALSE,
1825 p_using_splitting IN BOOLEAN DEFAULT FALSE,
1826 x_return_status OUT NOCOPY VARCHAR2,
1827 x_return_msg OUT NOCOPY VARCHAR2)
1828 IS
1832 l_val VARCHAR2(4000);
1829 l_ctxt VARCHAR2(60) := PKG_NAME||'INTERNAL_PRINT_ARG_CONTEXT';
1830
1831 l_s VARCHAR2(60);
1833 l_prev_init_flag VARCHAR2(3);
1834 l_prev_val VARCHAR2(4000);
1835 l_prev_valid_value_flag VARCHAR2(3);
1836 l_return_status VARCHAR2(6);
1837 l_return_msg VARCHAR2(2048);
1838 BEGIN
1839 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
1840 x_return_status := FND_API.G_RET_STS_ERROR;
1841 x_return_msg := '';
1842
1843 l_s := p_arg_ctxt.FIRST;
1844 WHILE l_s IS NOT NULL LOOP
1845 fnd_oam_debug.log(1, l_ctxt, 'Arg Name(Permissions): '||p_arg_ctxt(l_s).arg_name||'('||p_arg_ctxt(l_s).permissions||')');
1846 IF p_get_values AND
1847 IS_READABLE(p_arg_ctxt(l_s)) THEN
1848
1849 --go ahead and fetch the value
1850 l_prev_init_flag := p_arg_ctxt(l_s).initialized_success_flag;
1851 l_prev_valid_value_flag := p_arg_ctxt(l_s).valid_value_flag;
1852 l_prev_val := p_arg_ctxt(l_s).canonical_value;
1853 GET_CANONICAL_CTXT_ARG_VALUE(p_arg_ctxt(l_s),
1854 p_using_splitting,
1855 l_val,
1856 l_return_status,
1857 l_return_msg);
1858 --drop any arg state/values we just computed in the transaction
1859 ROLLBACK;
1860
1861 --print the value if we suceeded
1862 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
1863 fnd_oam_debug.log(1, l_ctxt, 'Value: '||l_val);
1864 END IF;
1865
1866 --reset the arg's local state
1867 p_arg_ctxt(l_s).init_locally := FALSE;
1868 p_arg_ctxt(l_s).initialized_success_flag := l_prev_init_flag;
1869 p_arg_ctxt(l_s).valid_value_flag := l_prev_valid_value_flag;
1870 p_arg_ctxt(l_s).canonical_value := l_prev_val;
1871 IF l_prev_init_flag IS NULL THEN
1872 --reset state set autonomously
1873 RESET_INITIALIZED_AUTONOMOUSLY(p_arg_ctxt(l_s).arg_id);
1874 END IF;
1875
1876 --fail if the context arg was not failed sucessfully, ignore missing bind cases
1877 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS,
1878 FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_MISSING_BINDS) THEN
1879 x_return_status := l_return_status;
1880 x_return_msg := l_return_msg;
1881 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1882 ROLLBACK;
1883 RETURN;
1884 END IF;
1885 ELSE
1886 IF p_arg_ctxt(l_s).valid_value_flag = FND_API.G_TRUE THEN
1887 fnd_oam_debug.log(1, l_ctxt, 'Value: '||p_arg_ctxt(l_s).canonical_value);
1888 ELSE
1889 fnd_oam_debug.log(1, l_ctxt, 'Value: ?');
1890 END IF;
1891 END IF;
1892
1893 l_s := p_arg_ctxt.NEXT(l_s);
1894 END LOOP;
1895
1896 x_return_status := FND_API.G_RET_STS_SUCCESS;
1897 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1898 EXCEPTION
1899 WHEN OTHERS THEN
1900 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1901 x_return_msg := 'Unexpected Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
1902 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1903 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1904 END;
1905
1906 -- Public
1907 PROCEDURE PRINT_ARG_CONTEXT(px_arg_context IN OUT NOCOPY arg_context)
1908 IS
1909 l_return_status VARCHAR2(6);
1910 l_return_msg VARCHAR2(2048);
1911 BEGIN
1912 --call the internal print_arg_context but don't allow it to fetch values
1913 INTERNAL_PRINT_ARG_CONTEXT(px_arg_context,
1914 FALSE,
1915 FALSE,
1916 l_return_status,
1917 l_return_msg);
1918 END;
1919
1920 --Private, used for debug to print an arg list
1921 PROCEDURE PRINT_ARG_LIST(p_arg_list IN OUT NOCOPY arg_list,
1922 x_return_status OUT NOCOPY VARCHAR2,
1923 x_return_msg OUT NOCOPY VARCHAR2)
1924 IS
1925 l_ctxt VARCHAR2(60) := PKG_NAME||'PRINT_ARG_LIST';
1926
1927 k NUMBER;
1928 l_prev_init_flag VARCHAR2(3);
1929 l_prev_val VARCHAR2(4000);
1930 l_prev_valid_value_flag VARCHAR2(3);
1931 l_val VARCHAR2(4000);
1932 l_ignore VARCHAR2(128);
1933
1934 l_return_status VARCHAR2(6);
1935 l_return_msg VARCHAR2(2048);
1936 BEGIN
1937 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
1938 x_return_status := FND_API.G_RET_STS_ERROR;
1939 x_return_msg := '';
1940
1941 k := p_arg_list.FIRST;
1942 WHILE k IS NOT NULL LOOP
1943 fnd_oam_debug.log(1, l_ctxt, 'Arg Name(Permissions): '||p_arg_list(k).arg_name||'('||p_arg_list(k).permissions||')');
1944
1945 --skip fetching the value since this is typically proceeded by a call to bind_args which does the gets
1946 IF p_arg_list(k).valid_value_flag = FND_API.G_TRUE THEN
1947 fnd_oam_debug.log(1, l_ctxt, 'Value: '||l_val);
1948 ELSE
1949 fnd_oam_debug.log(1, l_ctxt, 'Value: ?');
1950 END IF;
1951
1952 k := p_arg_list.NEXT(k);
1953 END LOOP;
1954
1955 x_return_status := FND_API.G_RET_STS_SUCCESS;
1956 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1957 EXCEPTION
1958 WHEN OTHERS THEN
1964
1959 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1960 x_return_msg := 'Unexpected Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
1961 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
1962 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
1963 END;
1965 -- Public
1966 PROCEDURE FETCH_RUN_ARG_CONTEXT(p_run_id IN NUMBER,
1967 x_arg_context OUT NOCOPY arg_context,
1968 x_return_status OUT NOCOPY VARCHAR2,
1969 x_return_msg OUT NOCOPY VARCHAR2)
1970 IS
1971 l_ctxt VARCHAR2(60) := PKG_NAME||'FETCH_RUN_ARG_CONTEXT';
1972
1973 l_empty_arg_context arg_context;
1974 l_arg_ctxt arg_context;
1975 l_arg arg;
1976
1977 l_arg_ids dbms_sql.number_table;
1978 l_arg_names dbms_sql.varchar2_table;
1979 l_initialized_success_flags dbms_sql.varchar2_table;
1980 l_allow_override_source_flags dbms_sql.varchar2_table;
1981 l_binding_enabled_flags dbms_sql.varchar2_table;
1982 l_permissions dbms_sql.varchar2_table;
1983 l_write_policies dbms_sql.varchar2_table;
1984 l_datatypes dbms_sql.varchar2_table;
1985 l_valid_value_flags dbms_sql.varchar2_table;
1986 l_canonical_values long_varchar2_table;
1987
1988 l_return_status VARCHAR2(6);
1989 l_return_msg VARCHAR2(2048);
1990 k NUMBER;
1991 l_ignore BOOLEAN;
1992 BEGIN
1993 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
1994 x_return_status := FND_API.G_RET_STS_ERROR;
1995 x_return_msg := '';
1996
1997 -- grab all the global and run args, global before run to allow run to override
1998 -- put both readable and writable args in the context
1999 SELECT arg_id, arg_name, initialized_success_flag, allow_override_source_flag, binding_enabled_flag, permissions, write_policy, datatype, valid_value_flag, canonical_value
2000 BULK COLLECT INTO l_arg_ids, l_arg_names, l_initialized_success_flags, l_allow_override_source_flags, l_binding_enabled_flags, l_permissions,
2001 l_write_policies, l_datatypes, l_valid_value_flags, l_canonical_values
2002 FROM fnd_oam_dscram_args_b
2003 WHERE ((parent_type = FND_OAM_DSCRAM_UTILS_PKG.G_TYPE_GLOBAL) OR
2004 ((parent_type = FND_OAM_DSCRAM_UTILS_PKG.G_TYPE_RUN) AND
2005 (parent_id = p_run_id)))
2006 AND enabled_flag = FND_API.G_TRUE
2007 ORDER BY parent_type ASC;
2008
2009 k := l_arg_ids.FIRST;
2010 WHILE k IS NOT NULL LOOP
2011 --add the arg to the context
2012 l_ignore := ADD_ARG_TO_CONTEXT(l_arg_ctxt,
2013 l_arg_ids(k),
2014 l_arg_names(k),
2015 l_initialized_success_flags(k),
2016 l_allow_override_source_flags(k),
2017 l_binding_enabled_flags(k),
2018 l_permissions(k),
2019 l_write_policies(k),
2020 l_datatypes(k),
2021 l_valid_value_flags(k),
2022 l_canonical_values(k));
2023
2024 k := l_arg_ids.NEXT(k);
2025 END LOOP;
2026
2027 IF FND_OAM_DSCRAM_UTILS_PKG.RUN_IS_DIAGNOSTIC THEN
2028 --print the arg context and allow failures here to indicate an overall failure so
2029 --a diagnostic test can detect it
2033 l_return_status,
2030 internal_print_arg_context(l_arg_ctxt,
2031 TRUE,
2032 FALSE,
2034 l_return_msg);
2035 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
2036 x_return_status := l_return_status;
2037 x_return_msg := l_return_msg;
2038 x_arg_context := l_empty_arg_context;
2039 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2040 RETURN;
2041 END IF;
2042 ELSIF fnd_oam_debug.test(1, l_ctxt) THEN
2043 --try to print the arg context but don't init or fail if bad.
2044 print_arg_context(l_arg_ctxt);
2045 END IF;
2046
2047 --return the context
2048 x_return_status := FND_API.G_RET_STS_SUCCESS;
2049 x_arg_context := l_arg_ctxt;
2050 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2051 EXCEPTION
2052 WHEN OTHERS THEN
2053 x_arg_context := l_empty_arg_context;
2054 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
2055 x_return_msg := 'Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
2056 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
2057 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2058 END;
2059
2060 -- Public
2061 PROCEDURE FETCH_ARG_LIST(p_parent_type IN VARCHAR2,
2062 p_parent_id IN NUMBER,
2063 x_arg_list OUT NOCOPY arg_list,
2064 x_has_writable OUT NOCOPY BOOLEAN,
2065 x_return_status OUT NOCOPY VARCHAR2,
2066 x_return_msg OUT NOCOPY VARCHAR2)
2067 IS
2068 l_ctxt VARCHAR2(60) := PKG_NAME||'FETCH_ARG_LIST';
2069
2070 l_arg arg;
2071 l_arg_list arg_list := arg_list();
2072 l_empty_arg_list arg_list := arg_list();
2073 l_has_writable BOOLEAN := FALSE;
2074
2075 l_arg_ids dbms_sql.number_table;
2076 l_arg_names dbms_sql.varchar2_table;
2077 l_initialized_success_flags dbms_sql.varchar2_table;
2078 l_allow_override_source_flags dbms_sql.varchar2_table;
2079 l_binding_enabled_flags dbms_sql.varchar2_table;
2080 l_permissions dbms_sql.varchar2_table;
2081 l_write_policies dbms_sql.varchar2_table;
2082 l_datatypes dbms_sql.varchar2_table;
2083 l_valid_value_flags dbms_sql.varchar2_table;
2084 l_canonical_values long_varchar2_table;
2085
2086 k NUMBER;
2087 l_ignore BOOLEAN;
2088 l_arg_name VARCHAR2(60);
2089
2090 l_return_status VARCHAR2(6);
2091 l_return_msg VARCHAR2(2048);
2092 BEGIN
2093 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
2094 x_return_status := FND_API.G_RET_STS_ERROR;
2095 x_return_msg := '';
2096
2097 --get all the args attached to the specified parent type/id
2098 --includes an order_by clause to prevent deadlock which would be caused if two workers try to init
2099 --and bind the args in different orders.
2100 SELECT arg_id, arg_name, initialized_success_flag, allow_override_source_flag, binding_enabled_flag, permissions, write_policy, datatype, valid_value_flag, canonical_value
2101 BULK COLLECT INTO l_arg_ids, l_arg_names, l_initialized_success_flags, l_allow_override_source_flags, l_binding_enabled_flags, l_permissions,
2102 l_write_policies, l_datatypes, l_valid_value_flags, l_canonical_values
2103 FROM fnd_oam_dscram_args_b
2104 WHERE parent_type = p_parent_type
2105 AND parent_id = p_parent_id
2106 AND enabled_flag = FND_API.G_TRUE
2107 ORDER BY arg_id ASC;
2108
2109 --allocate the array
2110 l_arg_list.EXTEND(l_arg_ids.COUNT);
2111
2112 --loop through the results
2113 k := l_arg_ids.FIRST;
2114 WHILE k IS NOT NULL LOOP
2115 --create a representative 'arg' structure
2116 l_arg := INTERNAL_CREATE_ARG(l_arg_ids(k),
2117 l_arg_names(k),
2118 l_initialized_success_flags(k),
2119 l_allow_override_source_flags(k),
2120 l_binding_enabled_flags(k),
2121 l_permissions(k),
2122 l_write_policies(k),
2123 l_datatypes(k),
2124 l_valid_value_flags(k),
2125 l_canonical_values(k));
2126
2127 --update our indicator variable if we found our condition
2128 IF IS_WRITABLE(l_arg) THEN
2129 l_has_writable := TRUE;
2130 END IF;
2131
2132 --add the arg to the arg list
2133 l_arg_list(k) := l_arg;
2134
2135 k := l_arg_ids.NEXT(k);
2136 END LOOP;
2137
2138 --debug
2139 IF FND_OAM_DSCRAM_UTILS_PKG.RUN_IS_DIAGNOSTIC THEN
2140 --print the arg list and allow failures here to indicate an overall failure so
2141 --a diagnostic test can detect it. We don't get the values for args because it screws up
2142 --operations too much and bind_args will get them all when the time is right anyway.
2143 print_arg_list(l_arg_list,
2144 l_return_status,
2145 l_return_msg);
2146 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
2147 x_return_status := l_return_status;
2148 x_return_msg := l_return_msg;
2149 x_arg_list := l_empty_arg_list;
2153 ELSIF fnd_oam_debug.test(1, l_ctxt) THEN
2150 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2151 RETURN;
2152 END IF;
2154 --print the arg list
2155 print_arg_list(l_arg_list,
2156 l_return_status,
2157 l_return_msg);
2158 END IF;
2159
2160 --return the final list
2161 x_return_status := FND_API.G_RET_STS_SUCCESS;
2162 x_arg_list := l_arg_list;
2163 x_has_writable := l_has_writable;
2164 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2165 EXCEPTION
2166 WHEN OTHERS THEN
2167 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
2168 x_return_msg := 'Parent Type ('||p_parent_type||'), ID('||p_parent_id||'), while fetching arg list: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
2169 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
2170 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2171 END;
2172
2173 -- Public
2174 PROCEDURE BIND_ARG_LIST_TO_CURSOR(p_arg_list IN OUT NOCOPY arg_list,
2175 px_arg_context IN OUT NOCOPY arg_context,
2176 p_cursor_id IN INTEGER,
2177 p_using_splitting IN BOOLEAN,
2178 p_rowid_lbound IN ROWID,
2179 p_rowid_ubound IN ROWID,
2180 x_return_status OUT NOCOPY VARCHAR2,
2181 x_return_msg OUT NOCOPY VARCHAR2)
2182 IS
2183 l_ctxt VARCHAR2(60) := PKG_NAME||'BIND_ARG_LIST_TO_CURSOR';
2184
2185 k NUMBER;
2186 l_bindvar_name VARCHAR2(120);
2187 l_varchar2 VARCHAR2(4000) := NULL;
2188 l_number NUMBER := NULL;
2189 l_date DATE := NULL;
2190 l_rowid ROWID := NULL;
2191
2192 l_return_status VARCHAR2(6);
2193 l_return_msg VARCHAR2(2048);
2194 BEGIN
2195 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
2196 x_return_status := FND_API.G_RET_STS_ERROR;
2197 x_return_msg := '';
2198
2199 --traverse the arg list, everything that's readable MUST be bound, otherwise it wouldn't be in the list
2200 k := p_arg_list.FIRST;
2201 WHILE k IS NOT NULL LOOP
2202
2203 --only bind args with binding enabled, these can be input and/or output args args
2204 IF p_arg_list(k).binding_enabled THEN
2205
2206 --reset our placeholder vars so we don't carry over from the last arg
2207 l_varchar2 := NULL;
2208 l_number := NULL;
2209 l_date := NULL;
2210 l_rowid := NULL;
2211
2212 fnd_oam_debug.log(1, l_ctxt, 'Binding Arg: '||p_arg_list(k).arg_name);
2213
2214 --prep the name of the bind variable
2215 l_bindvar_name := ':'||p_arg_list(k).arg_name;
2216
2217 --first do the fetch if its readable
2218 IF IS_READABLE(p_arg_list(k)) THEN
2219 CASE p_arg_list(k).datatype
2220 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_VARCHAR2 THEN
2221 --fetch
2222 GET_ARG_VALUE(p_arg_list(k),
2223 px_arg_context,
2224 p_using_splitting,
2225 p_rowid_lbound,
2226 p_rowid_ubound,
2227 NULL,
2228 l_varchar2,
2229 l_return_status,
2230 l_return_msg);
2231 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
2232 fnd_oam_debug.log(1, l_ctxt, 'Value(VARCHAR2): '||l_varchar2);
2233 ELSE
2234 x_return_status := l_return_status;
2235 x_return_msg := l_return_msg;
2236 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2237 RETURN;
2238 END IF;
2239
2240 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_NUMBER THEN
2241 --fetch
2242 GET_ARG_VALUE(p_arg_list(k),
2243 px_arg_context,
2244 p_using_splitting,
2245 p_rowid_lbound,
2246 p_rowid_ubound,
2247 NULL,
2248 l_number,
2249 l_return_status,
2250 l_return_msg);
2251 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
2252 fnd_oam_debug.log(1, l_ctxt, 'Value(NUMBER): '||FND_NUMBER.NUMBER_TO_CANONICAL(l_number));
2253 ELSE
2254 --or fail
2255 x_return_status := l_return_status;
2256 x_return_msg := l_return_msg;
2257 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2258 RETURN;
2259 END IF;
2260
2261 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_DATE THEN
2262 --fetch
2263 GET_ARG_VALUE(p_arg_list(k),
2264 px_arg_context,
2265 p_using_splitting,
2266 p_rowid_lbound,
2267 p_rowid_ubound,
2268 NULL,
2269 l_date,
2270 l_return_status,
2274 ELSE
2271 l_return_msg);
2272 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
2273 fnd_oam_debug.log(1, l_ctxt, 'Value(DATE): '||FND_DATE.DATE_TO_CANONICAL(l_date));
2275 --or fail
2276 x_return_status := l_return_status;
2277 x_return_msg := l_return_msg;
2278 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2279 RETURN;
2280 END IF;
2281
2282 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_ROWID THEN
2283 --fetch
2284 GET_ARG_VALUE_ROWID(p_arg_list(k),
2285 px_arg_context,
2286 p_using_splitting,
2287 p_rowid_lbound,
2288 p_rowid_ubound,
2289 NULL,
2290 l_rowid,
2291 l_return_status,
2292 l_return_msg);
2293 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
2294 fnd_oam_debug.log(1, l_ctxt, 'Value(ROWID): '||ROWIDTOCHAR(l_rowid));
2295 ELSE
2296 --or fail
2297 x_return_status := l_return_status;
2298 x_return_msg := l_return_msg;
2299 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2300 RETURN;
2301 END IF;
2302 ELSE
2303 x_return_msg := 'Arg ('||p_arg_list(k).arg_id||') has unknown datatype:'||p_arg_list(k).datatype;
2304 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
2305 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2306 RETURN;
2307 END CASE;
2308 END IF;
2309
2310 --even if we didn't get a value, do a binding - required for output args.
2311 BEGIN
2312 CASE p_arg_list(k).datatype
2313 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_VARCHAR2 THEN
2314 DBMS_SQL.BIND_VARIABLE(p_cursor_id,
2315 l_bindvar_name,
2316 l_varchar2,
2317 4000);
2318
2319 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_NUMBER THEN
2320 DBMS_SQL.BIND_VARIABLE(p_cursor_id,
2321 l_bindvar_name,
2322 l_number);
2323
2324 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_DATE THEN
2325 DBMS_SQL.BIND_VARIABLE(p_cursor_id,
2326 l_bindvar_name,
2327 l_date);
2328
2329 WHEN FND_OAM_DSCRAM_UTILS_PKG.G_DATATYPE_ROWID THEN
2330 DBMS_SQL.BIND_VARIABLE_ROWID(p_cursor_id,
2331 l_bindvar_name,
2332 l_rowid);
2333 ELSE
2334 x_return_msg := 'Arg ('||p_arg_list(k).arg_id||') has unknown datatype:'||p_arg_list(k).datatype;
2335 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
2336 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2337 RETURN;
2338 END CASE;
2339 EXCEPTION
2340 WHEN BIND_DOES_NOT_EXIST THEN
2341 --catch a common error and provide better feedback.
2342 fnd_oam_debug.log(1, l_ctxt, 'Arg ID('||p_arg_list(k).arg_id||'), Bindvar('||l_bindvar_name||') does not exist');
2343 x_return_msg := 'Arg ID('||p_arg_list(k).arg_id||'), Bind Variable ('||l_bindvar_name||') failure: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
2344 RETURN;
2345 WHEN OTHERS THEN
2346 RAISE;
2347 END;
2348
2349 END IF;
2350
2351 k := p_arg_list.NEXT(k);
2352 END LOOP;
2353
2354 --all bound, return success
2355 x_return_status := FND_API.G_RET_STS_SUCCESS;
2356 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2357 EXCEPTION
2358 WHEN OTHERS THEN
2359 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
2360 x_return_msg := 'Unhandled Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
2361 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
2362 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2363 END;
2364
2365 -- Public
2366 PROCEDURE UPDATE_WRITABLE_ARG_VALUES(px_arg_list IN OUT NOCOPY arg_list,
2367 px_arg_context IN OUT NOCOPY arg_context,
2368 p_entity_finished IN BOOLEAN,
2369 p_using_splitting IN BOOLEAN,
2370 p_rowid_lbound IN ROWID,
2371 p_rowid_ubound IN ROWID,
2372 p_execution_cursor_id IN INTEGER,
2373 x_return_status OUT NOCOPY VARCHAR2,
2374 x_return_msg OUT NOCOPY VARCHAR2)
2375 IS
2376 l_ctxt VARCHAR2(60) := PKG_NAME||'UPDATE_WRITABLE_ARG_VALUES';
2377
2378 l_canonical_value VARCHAR2(4000);
2379 l_force_store_autonomously BOOLEAN := FALSE;
2380
2381 k NUMBER;
2382 l_ignore VARCHAR2(128);
2383
2384 l_return_status VARCHAR2(6);
2388 x_return_status := FND_API.G_RET_STS_ERROR;
2385 l_return_msg VARCHAR2(2048);
2386 BEGIN
2387 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
2389 x_return_msg := '';
2390
2391 --if we're in a non-normal mode, store the values we get autonomously to keep them from
2392 --getting rolled back
2393 IF NOT FND_OAM_DSCRAM_UTILS_PKG.RUN_IS_NORMAL THEN
2394 l_force_store_autonomously := TRUE;
2395 END IF;
2396
2397 --loop through the arg list
2398 k := px_arg_list.FIRST;
2399 WHILE k IS NOT NULL LOOP
2400 --if the arg is writable, perform a get canonical value which does
2401 --an implicit store in an autonomous transaction. If the arg has already read
2402 --a value then get will not replace it
2403 IF IS_WRITABLE(px_arg_list(k)) THEN
2404 --include an additional condition to keep ONCE/PER_WORKER args from being
2405 --executed until the arg is finished and execute PER_RANGE/ALWAYS when not finished or
2406 --we're finished and not using splitting.
2407 IF ((p_entity_finished AND
2408 (NOT p_using_splitting OR
2409 (px_arg_list(k).write_policy IN (FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_ONCE,
2410 FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_PER_WORKER)))) OR
2411 (NOT p_entity_finished AND
2412 (px_arg_list(k).write_policy IN (FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_PER_RANGE,
2413 FND_OAM_DSCRAM_UTILS_PKG.G_WRITE_POLICY_ALWAYS)))) THEN
2414
2415 GET_CANONICAL_ARG_VALUE(px_arg_list(k),
2416 px_arg_context,
2417 p_using_splitting,
2418 p_rowid_lbound,
2419 p_rowid_ubound,
2420 p_execution_cursor_id,
2421 l_force_store_autonomously,
2422 TRUE,
2423 TRUE,
2424 l_ignore,
2425 l_canonical_value,
2426 l_return_status,
2427 l_return_msg);
2428 IF l_return_status <> FND_API.G_RET_STS_SUCCESS AND
2429 l_return_status <> FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_MISSING_BINDS THEN
2430
2431 --if an arg failed to get a value, return it as an error, stop fetching other args
2432 x_return_status := l_return_status;
2433 x_return_msg := l_return_msg;
2434 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2435 RETURN;
2436 ELSE
2437 fnd_oam_debug.log(1, l_ctxt, 'Value: '||l_canonical_value);
2438 END IF;
2439 END IF;
2440 END IF;
2441
2442 k := px_arg_list.NEXT(k);
2443 END LOOP;
2444
2445 --return the final list
2446 x_return_status := FND_API.G_RET_STS_SUCCESS;
2447 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2448 EXCEPTION
2449 WHEN OTHERS THEN
2450 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
2451 x_return_msg := 'Unexpected Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
2452 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
2453 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2454 END;
2455
2456 -- Public
2457 PROCEDURE UPDATE_CONTEXT_USING_ARG_LIST(px_arg_context IN OUT NOCOPY arg_context,
2458 p_arg_list IN arg_list,
2459 p_using_splitting IN BOOLEAN)
2460 IS
2461 l_ctxt VARCHAR2(60) := PKG_NAME||'UPDATE_CONTEXT_USING_ARG_LIST';
2462 k NUMBER;
2463 l_arg_name VARCHAR2(60);
2464 l_canonical_value VARCHAR2(4000);
2465 l_lock_handle VARCHAR2(128) := NULL;
2466 l_retval INTEGER;
2467
2468 l_return_status VARCHAR2(6);
2469 l_return_msg VARCHAR2(2048);
2470 BEGIN
2471 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
2472
2473 --loop over each item in the arg list since its easier to lookup a match in the context
2474 k := p_arg_list.FIRST;
2475 WHILE k IS NOT NULL LOOP
2476 IF IS_READABLE(p_arg_list(k)) AND
2477 p_arg_list(k).valid_value_flag = FND_API.G_TRUE AND
2478 px_arg_context.EXISTS(p_arg_list(k).arg_name) THEN
2479
2480 l_arg_name := p_arg_list(k).arg_name;
2481 -- do a cursory check of compatiblity before calling the context arg's get to check the db for its latest value
2482 IF (px_arg_context(l_arg_name).allow_override_source AND
2483 px_arg_context(l_arg_name).valid_value_flag IS NULL AND
2484 IS_WRITABLE(px_arg_context(l_arg_name)) AND
2485 p_arg_list(k).datatype = px_arg_context(l_arg_name).datatype) THEN
2486
2487 --first fetch the latest value for the context arg without sourcing it and keeping the lock if we get one
2488 GET_CANONICAL_CTXT_ARG_VALUE(px_arg_context(l_arg_name),
2489 p_using_splitting,
2490 p_arg_list(k).rowid_lbound,
2491 p_arg_list(k).rowid_ubound,
2492 NULL,
2493 FALSE,
2494 FALSE,
2495 FALSE,
2496 l_lock_handle,
2497 l_canonical_value,
2501 --the get should succeed without finding a valid value for us to default in the arg list's value
2498 l_return_status,
2499 l_return_msg);
2500 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
2502 IF px_arg_context(l_arg_name).valid_value_flag IS NULL THEN
2503 --this means we can default from the arg list
2504 BEGIN
2505 SET_STATE_ARG_VALUE(px_arg_context(l_arg_name),
2506 p_arg_list(k).canonical_value,
2507 p_arg_list(k).rowid_lbound,
2508 p_arg_list(k).rowid_ubound);
2509 --and we should also store the context arg's new value
2510 STORE_ARG_VALUE_AUTONOMOUSLY(px_arg_context(l_arg_name),
2511 l_return_status,
2512 l_return_msg);
2513 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
2514 fnd_oam_debug.log(1, l_ctxt, 'Set the context arg to value: '||p_arg_list(k).canonical_value);
2515 ELSE
2516 --if we didn't store correctly, reset the context arg to unknown
2517 px_arg_context(l_arg_name).valid_value_flag := NULL;
2518 END IF;
2519 EXCEPTION
2520 WHEN OTHERS THEN
2521 --if the set or store fail, reset the context arg's value to unknown
2522 px_arg_context(l_arg_name).valid_value_flag := NULL;
2523 END;
2524 ELSE
2525 fnd_oam_debug.log(1, l_ctxt, 'Context already has value: '||l_canonical_value);
2526 END IF;
2527
2528 --release the lock if we have one
2529 IF l_lock_handle IS NOT NULL THEN
2530 l_retval := DBMS_LOCK.RELEASE(l_lock_handle);
2531 IF l_retval <> 0 THEN
2532 fnd_oam_debug.log(6, l_ctxt, 'Failed to release arg lock: '||l_retval);
2533 END IF;
2534 END IF;
2535 END IF;
2536 END IF;
2537 END IF;
2538 k := p_arg_list.NEXT(k);
2539 END LOOP;
2540
2541 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2542 EXCEPTION
2543 WHEN OTHERS THEN
2544 --make sure there isn't a lock hanging around
2545 IF l_lock_handle IS NOT NULL THEN
2546 l_retval := DBMS_LOCK.RELEASE(l_lock_handle);
2547 IF l_retval <> 0 THEN
2548 fnd_oam_debug.log(6, l_ctxt, 'Failed to release arg lock: '||l_retval);
2549 END IF;
2550 END IF;
2551
2552 fnd_oam_debug.log(6, l_ctxt, 'Unexpected Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))');
2553 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2554 RETURN;
2555 END;
2556
2557 -- Public
2558 PROCEDURE DESTROY_ARG_LIST(px_arg_list IN OUT NOCOPY arg_list,
2559 x_return_status OUT NOCOPY VARCHAR2,
2560 x_return_msg OUT NOCOPY VARCHAR2)
2561 IS
2562 l_ctxt VARCHAR2(60) := PKG_NAME||'DESTROY_ARG_LIST';
2563
2564 k NUMBER;
2565
2566 l_return_status VARCHAR2(6);
2567 l_return_msg VARCHAR2(2048);
2568 BEGIN
2569 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
2570 x_return_status := FND_API.G_RET_STS_ERROR;
2571 x_return_msg := '';
2572
2573 k := px_arg_list.FIRST;
2574 WHILE k IS NOT NULL LOOP
2575
2576 --close up the cursor if it exists
2577 IF px_arg_list(k).source_cursor_id IS NOT NULL AND
2578 DBMS_SQL.IS_OPEN(px_arg_list(k).source_cursor_id) THEN
2579 DBMS_SQL.CLOSE_CURSOR(px_arg_list(k).source_cursor_id);
2580 END IF;
2581
2582 k := px_arg_list.NEXT(k);
2583 END LOOP;
2584
2585 --delete the arg list
2586 px_arg_list.DELETE;
2587
2588 x_return_status := FND_API.G_RET_STS_SUCCESS;
2589 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2590 EXCEPTION
2591 WHEN OTHERS THEN
2592 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
2593 x_return_msg := 'Unexpected Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
2594 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
2595 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2596 END;
2597
2598 -- Public
2599 PROCEDURE DESTROY_ARG_CONTEXT(px_arg_context IN OUT NOCOPY arg_context,
2600 x_return_status OUT NOCOPY VARCHAR2,
2601 x_return_msg OUT NOCOPY VARCHAR2)
2602 IS
2603 l_ctxt VARCHAR2(60) := PKG_NAME||'DESTROY_ARG_CONTEXT';
2604
2605 l_s VARCHAR2(60);
2606 l_ignore VARCHAR2(128);
2607 l_canonical_value VARCHAR2(4000);
2608
2609 l_return_status VARCHAR2(6);
2610 l_return_msg VARCHAR2(2048);
2611 BEGIN
2612 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
2613 x_return_status := FND_API.G_RET_STS_ERROR;
2614 x_return_msg := '';
2615
2616 --go through the args
2617 l_s := px_arg_context.FIRST;
2618 WHILE l_s IS NOT NULL LOOP
2619 --if it's writable then try to let it store a value before we remove the arg
2620 IF IS_WRITABLE(px_arg_context(l_s)) THEN
2621 GET_CANONICAL_CTXT_ARG_VALUE(px_arg_context(l_s),
2622 FALSE,
2626 TRUE,
2623 NULL,
2624 NULL,
2625 NULL,
2627 TRUE,
2628 TRUE,
2629 l_ignore,
2630 l_canonical_value,
2631 l_return_status,
2632 l_return_msg);
2633 IF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
2634 fnd_oam_debug.log(1, l_ctxt, 'Arg('||l_s||'), stored final context value: '||l_canonical_value);
2635 END IF;
2636 END IF;
2637
2638 --close up the arg's cursor if it exists
2639 IF px_arg_context(l_s).source_cursor_id IS NOT NULL AND
2640 DBMS_SQL.IS_OPEN(px_arg_context(l_s).source_cursor_id) THEN
2641 DBMS_SQL.CLOSE_CURSOR(px_arg_context(l_s).source_cursor_id);
2642 END IF;
2643
2644 l_s := px_arg_context.NEXT(l_s);
2645 END LOOP;
2646
2647 --delete the arg context
2648 px_arg_context.DELETE;
2649
2650 x_return_status := FND_API.G_RET_STS_SUCCESS;
2651 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2652 EXCEPTION
2653 WHEN OTHERS THEN
2654 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
2655 x_return_msg := 'Unexpected Error: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
2656 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
2657 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
2658 END;
2659
2660 -- Public
2661 -- Copied from FND_OAM_DS_PSETS_PKG, seems to mimic standard syntax of calls
2662 -- made from FND_TOP/sql/FNDNLINS.sql.
2663 PROCEDURE ADD_LANGUAGE
2664 IS
2665 BEGIN
2666
2667 delete from FND_OAM_DSCRAM_ARGS_TL T
2668 where not exists
2669 (select NULL
2670 from FND_OAM_DSCRAM_ARGS_B B
2671 where B.ARG_ID = T.ARG_ID
2672 );
2673
2674 update FND_OAM_DSCRAM_ARGS_TL T set (
2675 DISPLAY_NAME,
2676 DESCRIPTION
2677 ) = (select
2678 B.DISPLAY_NAME,
2679 B.DESCRIPTION
2680 from FND_OAM_DSCRAM_ARGS_TL B
2681 where B.ARG_ID = T.ARG_ID
2682 and B.LANGUAGE = T.SOURCE_LANG)
2683 where (
2684 T.ARG_ID,
2685 T.LANGUAGE
2686 ) in (select
2687 SUBT.ARG_ID,
2688 SUBT.LANGUAGE
2689 from FND_OAM_DSCRAM_ARGS_TL SUBB, FND_OAM_DSCRAM_ARGS_TL SUBT
2690 where SUBB.ARG_ID = SUBT.ARG_ID
2691 and SUBB.LANGUAGE = SUBT.SOURCE_LANG
2692 and (SUBB.DISPLAY_NAME <> SUBT.DISPLAY_NAME
2693 or SUBB.DESCRIPTION <> SUBT.DESCRIPTION
2694 or (SUBB.DESCRIPTION is null and SUBT.DESCRIPTION is not null)
2695 or (SUBB.DESCRIPTION is not null and SUBT.DESCRIPTION is null)
2696 ));
2697
2698 insert into FND_OAM_DSCRAM_ARGS_TL (
2699 ARG_ID,
2700 DISPLAY_NAME,
2701 DESCRIPTION,
2702 CREATED_BY,
2703 CREATION_DATE,
2704 LAST_UPDATED_BY,
2705 LAST_UPDATE_DATE,
2706 LAST_UPDATE_LOGIN,
2707 LANGUAGE,
2708 SOURCE_LANG
2709 ) select /*+ ORDERED */
2710 B.ARG_ID,
2711 B.DISPLAY_NAME,
2712 B.DESCRIPTION,
2713 B.CREATED_BY,
2714 B.CREATION_DATE,
2715 B.LAST_UPDATED_BY,
2716 B.LAST_UPDATE_DATE,
2717 B.LAST_UPDATE_LOGIN,
2718 L.LANGUAGE_CODE,
2719 B.SOURCE_LANG
2720 from FND_OAM_DSCRAM_ARGS_TL B, FND_LANGUAGES L
2721 where L.INSTALLED_FLAG in ('I', 'B')
2722 and B.LANGUAGE = userenv('LANG')
2723 and not exists
2724 (select NULL
2725 from FND_OAM_DSCRAM_ARGS_TL T
2726 where T.ARG_ID = B.ARG_ID
2727 and T.LANGUAGE = L.LANGUAGE_CODE);
2728
2729 END ADD_LANGUAGE;
2730
2731 END FND_OAM_DSCRAM_ARGS_PKG;