On entering the JOB component, the PIA generates the SQL to retrieve the job history for a particular employee. The two known keys are specified in the where clause, but all the keys were used to generate the ORDER BY clause. EFFDT and EFFSEQ are descending keys on the JOB record, so the query is in descending order on those columns.SELECT EMPLID,... FROM PS_JOB WHERE EMPLID=:1 AND EMPL_RCD=:2 ORDER BY EMPLID, EMPL_RCD, EFFDT DESC, EFFSEQ DESC
The descending key attribute has another purpose. Prior to PeopleTools 8.14, if you specified a key field as descending in Application Designer, that column would also be indexed in descending order where it appeared in indexes. However, PeopleSoft removed this functionality because of Oracle Bug 869177 which in most versions of Oracle 8.1 could cause ORA-3113 when accessing the index.
Now that Oracle has fixed the bug in the database, PeopleTools once again builds indexes with descending columns on Oracle RDBMS from PeopleTools 8.48.
However, as always, there is a snag (or I wouldn't have bothered to write this note). The name of the descending column is not reported in catalogue views. Instead the column name is replaced with a system generated column name.
SELECT table_name, index_name, column_position , column_name, descend FROM dba_ind_columns WHERE index_name = 'PS_JOB' TABLE_NAME INDEX_NAME COLUMN_POSITION COLUMN_NAME DESCEND ---------- ---------- --------------- ------------ ------------ PS_JOB PS_JOB 1 EMPLID ASC PS_JOB PS_JOB 2 EMPL_RCD ASC PS_JOB PS_JOB 3 SYS_NC00163$ DESC PS_JOB PS_JOB 4 SYS_NC00164$ DESC
This could cause problems with SQL scripts that use the catalogue views. For example, I have had to change my DDL Trigger to protect database objects not managed by Application Designer.
So how do you find the name of the underlying column? You have to look in the sys owned catalogue tables. If you look at the query in $ORACLE_HOME/rdbms/admin/catalog.sql at the code behind the view, you find that the column names are stored on sys.col$. There is another column on that table called DEFAULT$, which stores the original column name.
COLUMN property FORMAT 999999
COLUMN table_owner FORMAT a8 HEADING 'Table|Owner'
COLUMN default$ FORMAT a8
COLUMN column_name FORMAT a12 HEADING 'Column|Name'
COLUMN index_name FORMAT a6 HEADING 'Index|Name'
COLUMN table_name FORMAT a6 HEADING 'Table|Name'
COLUMN column_position FORMAT 99 HEADING 'Column|Position'
COLUMN column_length FORMAT 999 HEADING 'Column|Length'
COLUMN char_length FORMAT 999 HEADING 'Char|Length'
COLUMN descend FORMAT a7
select /*i.obj#
, io.name index_owner
, */idx.name index_name
, bo.name table_owner
, base.name table_name
, decode(bitand(c.property, 1024), 1024,
(select decode(bitand(tc.property, 1), 1, ac.name, tc.name)
from sys.col$ tc, attrcol$ ac
where tc.intcol# = c.intcol#-1
and tc.obj# = c.obj#
and tc.obj# = ac.obj#(+
and tc.intcol# = ac.intcol#(+)),
decode(ac.name, null, c.name, ac.name)) column_name
, c.property, c.default$
, ic.pos# column_position
, c.length column_length
, c.spare3 char_length
, decode(bitand(c.property, 131072), 131072, 'DESC', 'ASC') descend
from sys.col$ c, sys.obj$ idx, sys.obj$ base, sys.icol$ ic,
sys.user$ io, sys.user$ bo, sys.ind$ i, sys.attrcol$ ac
where ic.bo# = c.obj#
and decode(bitand(i.property,1024),0,ic.intcol#,ic.spare2) = c.intcol#
and ic.bo# = base.obj#
and io.user# = idx.owner#
and bo.user# = base.owner#
and ic.obj# = idx.obj#
and idx.obj# = i.obj#
and i.type# in (1, 2, 3, 4, 6, 7, 9)
and c.obj# = ac.obj#(+)
and c.intcol# = ac.intcol#(+)
and io.name = 'SYSADM'
and idx.name = 'PS_JOB'
and bo.name = 'SYSADM'
and base.name = 'PS_JOB'
/
Index Table Table Column Column Column Char
Name Owner Name Name PROPERTY DEFAULT$ Position Length Length DESCEND
------ -------- ------ ------------ -------- -------- -------- ------ ------ -------
PS_JOB SYSADM PS_JOB EMPLID 0 1 11 11 ASC
PS_JOB SYSADM PS_JOB EMPL_RCD 0 2 22 0 ASC
PS_JOB SYSADM PS_JOB SYS_NC00163$ 196904 "EFFDT" 3 12 0 DESC
PS_JOB SYSADM PS_JOB SYS_NC00164$ 196904 "EFFSEQ" 4 34 0 DESC
My thanks to Noons for pointing out that you can get the underlying column or expression from DBA_IND_EXPRESSIONS.