Execute file with SQLExec containing $$ characters

后端 未结 1 387
时光取名叫无心
时光取名叫无心 2021-01-27 17:08

I\'ve created a sql dump file using pg_dump. This export file contains functions which contain $$ characters. No problem to import the file with psql -f < filename>.

1条回答
  •  迷失自我
    2021-01-27 17:55

    $$ is just the bare minimum for dollar-quoting. Make it (much!) less likely to conflict with strings in the enclosed literal by putting a string between the dollars:

    
    CREATE OR REPLACE FUNCTION time_to_sec(timepoint timestamp with time zone)
      RETURNS bigint LANGUAGE plpgsql AS
    $BODY$
    DECLARE
     seconds bigint;
     secondsFromEpoch bigint;
     secondsFromMidnight bigint;
    BEGIN
     secondsFromEpoch = EXTRACT(EPOCH FROM timepoint)::bigint;
     secondsFromMidnight = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP::date)::bigint;
     seconds = secondsFromEpoch - secondsFromMidnight;
     return seconds;
    END;
    $BODY$;
    

    More advice

    • The assignment operator in plpgsql is :=. = is undocumented and may go away in future releases. More under this related question.

    • Use CURRENT_DATE instead of CURRENT_TIMESTAMP::date.

    • It is allowed, but I would advise not to use mixed case parameter names in plpgsql. They are case insensitive.

    • Most importantly, simplify:

      CREATE OR REPLACE FUNCTION time_to_sec2(timepoint timestamp with time zone)
        RETURNS bigint LANGUAGE plpgsql STABLE AS
      $BODY$
      BEGIN
          RETURN EXTRACT(EPOCH FROM timepoint - current_date)::bigint;
      END;
      $BODY$;
      

      Or even:

      CREATE OR REPLACE FUNCTION time_to_sec3(timepoint timestamp with time zone)
        RETURNS bigint LANGUAGE sql AS
      $BODY$
          SELECT EXTRACT(EPOCH FROM timepoint - current_date)::bigint;
      $BODY$;
      
    • Can be declared STABLE!

    Also note that the current_timestamp family of functions qualify as stable, since their values do not change within a transaction.

    • There is also the closely related function age() in PostgreSQL doing almost, but not quite, the same: it returns a "symbolic" result with standard-years and months. Therefore, expression with age() can yield different results for longer periods of time.

    These are all equivalent - except for the last two deviating with longer periods of time:

    WITH x(t) AS (VALUES ('2012-07-20 03:51:26+02'::timestamptz))
    SELECT time_to_sec(t)  AS t1
          ,time_to_sec2(t) AS t2
          ,time_to_sec3(t) AS t3
          ,EXTRACT(EPOCH FROM t - current_date)::bigint AS t4
          ,EXTRACT(EPOCH FROM age(t, current_date))::bigint AS t5 -- deviates
          ,EXTRACT(EPOCH FROM age(t))::bigint * -1  AS t6  -- deviates
    FROM   x;
    

    As to the original question: this PostgreSQL error message does not necessarily mean the problem is with the dollar sign:

    ERROR: syntax error at or near "$"

    Most of the time it's a missing ; before that line. Or maybe an un-escaped special characters in XML, like < > & ? The dollar sign $ should be fine. But I am no expert with ant. There should be more context in the PostgreSQL log.

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