One of my customers that recently upgraded to 12c hit a bug (22913528) that I think is good to be aware of. Note that as the title of this post states, the problem only occur in 12.1.0.2. At least, I wasn’t able to reproduce it in any other version.

To reproduce it you simply need a composite partitioned table with a non-partitioned or global-partitioned index. In other words, if all your indexes are local, you shouldn’t be impacted by the bug.

The SQL statements I use to prepare the schema to reproduce it are the following:

CREATE TABLE t (p DATE, s number, i DATE)
PARTITION BY RANGE (p) INTERVAL(numtoyminterval(1,'MONTH')) 
SUBPARTITION BY LIST (s) SUBPARTITION TEMPLATE (
   SUBPARTITION s1 VALUES (1),
   SUBPARTITION s2 VALUES (2),
   SUBPARTITION s3 VALUES (3),
   SUBPARTITION s4 VALUES (4),
   SUBPARTITION s5 VALUES (5),
   SUBPARTITION s6 VALUES (6),
   SUBPARTITION s7 VALUES (7)
)(
  PARTITION p_others VALUES LESS THAN (to_date('2016-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'))
);
 
INSERT INTO t 
SELECT to_date('2016-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')-rownum, 
       mod(rownum,7)+1, 
       trunc(sysdate+mod(rownum,7))
FROM dual 
CONNECT BY level <= 365;
 
COMMIT;
 
CREATE INDEX i ON t (i);
REM CREATE INDEX i ON t (i) GLOBAL PARTITION BY HASH (i) PARTITIONS 4;
REM CREATE INDEX i ON t (i) LOCAL;
 
execute dbms_stats.gather_table_stats(user, 'T')

Note that the minimum value for each subpartition key is the following:

SQL> SELECT s, min(i)
  2  FROM t
  3  GROUP BY s;
 
         S MIN(I)
---------- ---------
         1 15-APR-16
         2 16-APR-16
         3 17-APR-16
         4 18-APR-16
         5 19-APR-16
         6 20-APR-16
         7 21-APR-16

The query to reproduce the bug is the following (the right answer is “17-APR-16”):

SQL> SELECT min(i) FROM t WHERE s = 3;
 
MIN(I)
---------
15-APR-16

The execution plan shows that the query optimizer “loses” the partition pruning information:

SQL> EXPLAIN PLAN FOR SELECT min(i) FROM t WHERE s = 3;
 
SQL> SELECT * FROM table(dbms_xplan.display(format=>'basic +partition'));
 
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------
Plan hash value: 1554646154
 
-------------------------------------------
| Id  | Operation                  | Name |
-------------------------------------------
|   0 | SELECT STATEMENT           |      |
|   1 |  SORT AGGREGATE            |      |
|   2 |   INDEX FULL SCAN (MIN/MAX)| I    |
-------------------------------------------

It goes without saying that when the index isn’t used the result is correct:

SQL> SELECT /*+ no_index(t) */ min(i) FROM t WHERE s = 3;
 
MIN(I)
---------
17-APR-16
 
SQL> EXPLAIN PLAN FOR SELECT /*+ no_index(t) */ min(i) FROM t WHERE s = 3;
 
SQL> SELECT * FROM table(dbms_xplan.display(format=>'basic +partition'));
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
Plan hash value: 1728811753
 
--------------------------------------------------------
| Id  | Operation               | Name | Pstart| Pstop |
--------------------------------------------------------
|   0 | SELECT STATEMENT        |      |       |       |
|   1 |  SORT AGGREGATE         |      |       |       |
|   2 |   PARTITION RANGE ALL   |      |     1 |1048575|
|   3 |    PARTITION LIST SINGLE|      |     3 |     3 |
|   4 |     TABLE ACCESS FULL   | T    |   KEY |   KEY |
--------------------------------------------------------

If you are on 12.1.0.2 (or you are thinking about upgrading to it), because of this bug I strongly advise you to check whether you have non local indexes…