Solved

Apps 9 mod to lengthen a field

  • 10 July 2023
  • 7 replies
  • 107 views

Userlevel 7
Badge +18

Has anyone built a mod to lengthen an out-of-the-box field in Apps 9? The field currently supports 11 characters, and I’d like to stretch that out to 12. Besides altering the Oracle column and updating the metadata in the many column comments and application tables, does the IEE .NET client hold this kind of metadata hard-coded? Is it hard-coded anywhere in the Java middleware?

icon

Best answer by Tomas Ruderfelt 10 July 2023, 07:19

View original

7 replies

Userlevel 7
Badge +19

The .net client field has a max length so you need to change that.

Java code might be affected depending on which field it is. If it is used in integrations or other things where we use Java like in DOCMAN.

You also need to check all PLSQL code where that field is used to see if any local variables have a length of 11.

So time and effort is highly depending on which field it is.

Userlevel 7
Badge +18

The .net client field has a max length so you need to change that.

Java code might be affected depending on which field it is. If it is used in integrations or other things where we use Java like in DOCMAN.

 

It’s the employee ID. It’s so thoroughly littered everywhere, I figured it might be easier and safer to change the length of every 11-character column to 12 characters, doing something like this…

 

(I haven’t tested any of this yet. It’s late on a Sunday night here.)

 

BEGIN
FOR rec_ IN (
SELECT 'ALTER TABLE "' || table_name || '" '
|| 'MODIFY "' || column_name || '" '
|| 'VARCHAR2(12)' AS sq
FROM user_tab_cols
WHERE table_name IN (SELECT table_name
FROM user_tables
WHERE tablespace_name IS NOT NULL)
AND table_name NOT IN (SELECT mview_name FROM user_mviews)
AND table_name NOT IN (SELECT queue_table FROM user_queues)
AND table_name NOT LIKE 'AQ$%'
AND data_type = 'VARCHAR2'
AND char_used = 'C'
AND virtual_column = 'NO'
AND char_length = 11
ORDER BY 1
) LOOP
BEGIN
EXECUTE IMMEDIATE rec_.sq;
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line(rec_.sq);
dbms_output.put_line(SQLERRM);
END;
END LOOP;
END;
/


BEGIN
FOR rec_ IN (
SELECT 'COMMENT ON COLUMN '
|| '"' || table_name || '"."' || column_name || '" '
|| 'IS q''['
|| REPLACE(comments, 'STRING(11)', 'STRING(12)')
|| ']''' AS sq
FROM user_col_comments
WHERE comments LIKE '%STRING(11)%'
ORDER BY 1
) LOOP
BEGIN
EXECUTE IMMEDIATE rec_.sq;
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line(rec_.sq);
dbms_output.put_line(SQLERRM);
END;
END LOOP;
END;
/

UPDATE dictionary_sys_view_column_tab
SET column_comment = REPLACE(column_comment, 'STRING(11)', 'STRING(12)')
WHERE column_comment LIKE '%STRING(11)%';

UPDATE dictionary_sys_view_column_tab
SET column_datatype = REPLACE(column_datatype, 'STRING(11)', 'STRING(12)')
WHERE column_datatype LIKE '%STRING(11)%';

UPDATE report_sys_column_tab
SET column_dataformat = REPLACE(column_dataformat, 'STRING(11)', 'STRING(12)')
WHERE column_dataformat LIKE '%STRING(11)%';



-- This step is the most dubious. I doubt it'll work, honestly....
DECLARE
body_ CLOB;
BEGIN
FOR rec_ IN (
SELECT object_name
FROM user_objects
WHERE object_name IN ('ABROAD_P_G_FORMAT_API',
/* ... all the affected packages I found ... */
'XLR_WRITE_BACK_TYPE_API')
AND object_type = 'PACKAGE'
ORDER BY 1
) LOOP
spec_ := NULL;
spec_ := dbms_metadata.get_ddl('PACKAGE_SPEC', rec_.object_name);
IF SUBSTR(UPPER(spec_), 1, 100) NOT LIKE '%WRAPPED%' THEN
spec_ := REPLACE(spec_, 'VARCHAR2(11)', 'VARCHAR2(12)');
spec_ := REPLACE(spec_, 'STRING(11)', 'STRING(12)');
EXECUTE IMMEDIATE spec_;
END IF;

body_ := NULL;
body_ := dbms_metadata.get_ddl('PACKAGE_BODY', rec_.object_name);
IF SUBSTR(UPPER(body_), 1, 100) NOT LIKE '%WRAPPED%' THEN
body_ := REPLACE(body_, 'VARCHAR2(11)', 'VARCHAR2(12)');
body_ := REPLACE(body_, 'STRING(11)', 'STRING(12)');
EXECUTE IMMEDIATE body_;
END IF;
END LOOP;
END;
/


 

Userlevel 7
Badge +19

It is not supported to update code directly in the database. You need to change the source code files and the models etc. And since it is employee ID I would not recommend doing it at all.

What is the purpose of making it 12 characters?

Userlevel 7
Badge +18

What is the purpose of making it 12 characters?

For years, our standard practice was to create a user ID with 8 characters, but this broke when two people had the same name. We switched to a 12-character system to resolve name conflicts, and that worked during testing. We don’t use the HR module, and only users that need to book time against projects are created as employees, so now this edge case has left us stuck. If a user ID can be 30 characters and a person ID can be 20, it makes no sense to me why an employee ID is limited to 11. What was the point of limiting that so tightly?

Userlevel 7
Badge +19

Why it is 11 characters I don’t know, that R&D might have to comment on.

But I guess the intention was to use a number serie for emplyee id. If you do not enter employee id when creating an employee I think it is using the number serie. We are using HR internally at IFS and I do not have my username as employee id, instead it is a number and then 11 characters are more than enough.

Userlevel 7
Badge +18

There’s no technical reason to limit a VARCHAR2 like this. The length is really just a constraint. It only uses the room it needs for the data.

 

-- DROP TABLE c_short_tab PURGE;
-- DROP TABLE c_long_tab PURGE;

CREATE TABLE c_short_tab (x VARCHAR2(11)) TABLESPACE ifsapp_data;
CREATE TABLE c_long_tab (x VARCHAR2(100)) TABLESPACE ifsapp_data;

DECLARE
hash_ RAW(32);
value_ VARCHAR2(11);
BEGIN
hash_ := HEXTORAW('0');
FOR i IN 0..1048575 LOOP
hash_ := dbms_crypto.hash(hash_, dbms_crypto.hash_sh256);
value_ := SUBSTR(RAWTOHEX(hash_), 1, 11);
INSERT INTO c_short_tab (x) VALUES (value_);
INSERT INTO c_long_tab (x) VALUES (value_);
END LOOP;
END;
/

COMMIT;

SELECT segment_name,
bytes,
blocks,
extents
FROM user_segments
WHERE segment_name IN ('C_LONG_TAB', 'C_SHORT_TAB');

 

 

SEGMENT_NAME BYTES BLOCKS EXTENTS
C_LONG_TAB 20971520 2560 35
C_SHORT_TAB 20971520 2560 35
Userlevel 7
Badge +18

The maximum length of an employee is hard-coded all over Ifs.Application.Person.dll and probably many others. I doubt we’ll want to take that risk.

Reply