简体   繁体   中英

Postgres truncates CASE statement column

I'm writing some functions for mapping a Postgres database. The functions are used to create dynamic queries for a javascript API.

I've come across a particular query that truncates the output of a column and I cannot determine why.

The width of the column in the following query seems to be truncated to 63 characters:

SELECT
  CASE
    WHEN t.column_name ~ '_[uid]*$' AND t.has_fn THEN
      format(
        'format(''%s/%%s'', %s) AS %s',
        array_to_string(ARRAY['',t.fk_schema,t.fk_name],'/'),
        t.column_name,
        regexp_replace(t.column_name, '_[uid]*$', '_link')
      )
    ELSE t.column_name
  END AS column
FROM core.map_type() t; -- core.map_type() is a set returning function

This query is used to create a select list for another query, but the string produced by format() is truncated to 63 characters.

However, if I add || '' || '' to the ELSE branch of the CASE statement, the problem goes away:

SELECT
  CASE
    WHEN t.column_name ~ '_[uid]*$' AND t.has_fn THEN
      format(
        'format(''%s/%%s'', %s) AS %s',
        array_to_string(ARRAY['',t.fk_schema,t.fk_name],'/'),
        t.column_name,
        regexp_replace(t.column_name, '_[uid]*$', '_link')
      )
    ELSE t.column_name || '' -- add empty string here
  END AS column
FROM core.map_type() t; -- core.map_type() is a set returning function

Having a column truncated like this is a worrisome problem. The fix here is a total hack and does not feel like a real solution.

Why is this happening? How can it be fixed?

In this case, the value of t.column_name in the ELSE branch of the CASE statement is of type name . name is a type used internally by Postgres for naming things. It has a fixed length of 64 bytes.

The column is truncated to suit the length of the ELSE branch.

Casting t.column_name to text will fix the problem:

SELECT
  CASE
    WHEN t.column_name ~ '_[uid]*$' AND t.has_fn THEN
      format(
        'format(''%s/%%s'', %s) AS %s',
        array_to_string(ARRAY['',t.fk_schema,t.fk_name],'/'),
        t.column_name,
        regexp_replace(t.column_name, '_[uid]*$', '_link')
      )
    ELSE t.column_name::text
  END AS column
FROM core.map_type() t;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM