Index on Timestamp: Functions in index expression must be marked as IMMUTABLE

后端 未结 1 917
走了就别回头了
走了就别回头了 2020-12-22 09:47

I want to create an index on my table for start_time, a timestamptz (timestamp with time zone) field in my json column called match.

Following this

相关标签:
1条回答
  • 2020-12-22 10:23

    First I thought this might be bug in the CREATE INDEX logic. But the point is that the cast from text to timestamptz itself isn't IMMUTABLE either. It depends on volatile settings like datestyle.

    In your particular case there is a workaround that's even better than what you tried. Move the cast into the function:

    CREATE OR REPLACE FUNCTION to_text(text) 
      RETURNS text AS
    $func$
    SELECT to_char($1::timestamptz AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US') 
    $func$ LANGUAGE sql IMMUTABLE;

    Just as efficient, but now CREATE INDEX won't barf:

    CREATE INDEX bar ON foo(to_text(j->>'start_time'));
    

    Obviously, you have to adjust your function calls accordingly: drop the cast ::timestamptz from the expression. Make sure that you use the same settings everywhere, or the index might lead to false results.

    Better yet

    Use an actually immutable expression with to_timestamp() instead of the cast (if your input pattern allows it):

    CREATE OR REPLACE FUNCTION to_text(text) 
      RETURNS text AS
    $func$
    SELECT to_char(to_timestamp($1, 'YYYY-MM-DD"T"HH24:MI:SS.US')  -- adapt to your pattern
                AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US') 
    $func$ LANGUAGE sql IMMUTABLE;

    Note however (quoting an error message from my test):

    "TZ"/"tz"/"OF" format patterns are not supported in to_date

    0 讨论(0)
提交回复
热议问题