PostgreSQL Partitioning - Constraint exclusion not working
On closer inspection... PostgreSQL is actually functioning as expected:


my_table_master is scanned because there is no constraint on it. The master table can actually have rows, there's nothing preventing it in PostgreSQL inheritance.
my_table_3 is scanned because its check constraint (t='2013-07-01 01:00:00') doesn't have anything to do (in principle) with the condition in the WHERE clause. Even if the definition of the function my_extract makes my_extract(t) = 0 incompatible with t='2013-07-01 01:00:00', the database is clearly not "intelligent enough" to infer it. You could add, if appropriate, even if redundant, NOT (my_extract(t) = 0) in your where clause. That would prevent my_table_3 from being scanned.
my_table_2 is scanned as expected.
my_table_4 is not actually scanned.


So, the constraints prevent one table from being scanned out of the 4. 

Alternate query, adding the (my_extract(t) = 0) clause:

EXPLAIN 
    SELECT * 
    FROM my_table_master 
    WHERE t='2013-07-01 01:00:00' 
          AND NOT (my_extract(t) = 0)  /* This is the new addition */ ;


returns

Append  (cost=0.00..309.45 rows=7 width=44)
  -&gt;  Seq Scan on my_table_master  (cost=0.00..0.00 rows=1 width=44)
        Filter: ((t = '2013-07-01 01:00:00'::timestamp without time zone) AND (my_extract(t) &lt;&gt; 0))
  -&gt;  Seq Scan on my_table_2  (cost=0.00..309.45 rows=6 width=44)
        Filter: ((t = '2013-07-01 01:00:00'::timestamp without time zone) AND (my_extract(t) &lt;&gt; 0))


By adding the extra condition, the scan of my_table_3 is prevented.

NOTE: To make the trials, I've made up my_extract like this:

CREATE FUNCTION my_extract(_t timestamp without time zone) 
RETURNS integer AS
$$
begin
    return extract(day from _t)::integer ;
end
$$
LANGUAGE plpgsql IMMUTABLE /* attention! */ ;


I've used plpgsql to ensure it is not inlined (even if it could be trivially done). Notice that it is necessary that the function be labeled as IMMUTABLE (that is, its result only depends on its parameters), or it won't work as expected.

ADDENDUM

EXPLAIN 
    SELECT * FROM my_table_master 
    WHERE my_extract(t) = 0 ;

  Append  (cost=0.00..613.25 rows=13 width=44)
    -&gt;  Seq Scan on my_table_master  (cost=0.00..0.00 rows=1 width=44)
          Filter: (my_extract(t) = 0)
    -&gt;  Seq Scan on my_table_2  (cost=0.00..306.62 rows=6 width=44)
          Filter: (my_extract(t) = 0)
    -&gt;  Seq Scan on my_table_3  (cost=0.00..306.62 rows=6 width=44)
          Filter: (my_extract(t) = 0)


Works as well as expected:


my_table_master -> as before
my_table_2 -> is scanned because its constraint doesn't have any immediate relation to 
my_table_3 -> is scanned because its constraint actually match the WHERE clause.


What PostgreSQL could do (and it doesn't) is eliminate the FILTER my_extract(t)=0 when scanning table 3, because the condition is already known to be true. Let's hope this optimization is implemented at some point in the future.