in ext/pg_query/pg_query_deparse.c [3251:3453]
static void deparseTypeName(StringInfo str, TypeName *type_name)
{
ListCell *lc;
bool skip_typmods = false;
if (type_name->setof)
appendStringInfoString(str, "SETOF ");
if (list_length(type_name->names) == 2 && strcmp(strVal(linitial(type_name->names)), "pg_catalog") == 0)
{
const char *name = strVal(lsecond(type_name->names));
if (strcmp(name, "bpchar") == 0)
{
appendStringInfoString(str, "char");
}
else if (strcmp(name, "varchar") == 0)
{
appendStringInfoString(str, "varchar");
}
else if (strcmp(name, "numeric") == 0)
{
appendStringInfoString(str, "numeric");
}
else if (strcmp(name, "bool") == 0)
{
appendStringInfoString(str, "boolean");
}
else if (strcmp(name, "int2") == 0)
{
appendStringInfoString(str, "smallint");
}
else if (strcmp(name, "int4") == 0)
{
appendStringInfoString(str, "int");
}
else if (strcmp(name, "int8") == 0)
{
appendStringInfoString(str, "bigint");
}
else if (strcmp(name, "real") == 0 || strcmp(name, "float4") == 0)
{
appendStringInfoString(str, "real");
}
else if (strcmp(name, "float8") == 0)
{
appendStringInfoString(str, "double precision");
}
else if (strcmp(name, "time") == 0)
{
appendStringInfoString(str, "time");
}
else if (strcmp(name, "timetz") == 0)
{
appendStringInfoString(str, "time ");
if (list_length(type_name->typmods) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc, type_name->typmods)
{
deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
if (lnext(type_name->typmods, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
appendStringInfoString(str, "with time zone");
skip_typmods = true;
}
else if (strcmp(name, "timestamp") == 0)
{
appendStringInfoString(str, "timestamp");
}
else if (strcmp(name, "timestamptz") == 0)
{
appendStringInfoString(str, "timestamp ");
if (list_length(type_name->typmods) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc, type_name->typmods)
{
deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
if (lnext(type_name->typmods, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
appendStringInfoString(str, "with time zone");
skip_typmods = true;
}
else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) == 0)
{
appendStringInfoString(str, "interval");
}
else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
{
Assert(IsA(linitial(type_name->typmods), A_Const));
Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
appendStringInfoString(str, "interval");
// This logic is based on intervaltypmodout in timestamp.c
switch (fields)
{
case INTERVAL_MASK(YEAR):
appendStringInfoString(str, " year");
break;
case INTERVAL_MASK(MONTH):
appendStringInfoString(str, " month");
break;
case INTERVAL_MASK(DAY):
appendStringInfoString(str, " day");
break;
case INTERVAL_MASK(HOUR):
appendStringInfoString(str, " hour");
break;
case INTERVAL_MASK(MINUTE):
appendStringInfoString(str, " minute");
break;
case INTERVAL_MASK(SECOND):
appendStringInfoString(str, " second");
break;
case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
appendStringInfoString(str, " year to month");
break;
case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
appendStringInfoString(str, " day to hour");
break;
case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
appendStringInfoString(str, " day to minute");
break;
case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
appendStringInfoString(str, " day to second");
break;
case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
appendStringInfoString(str, " hour to minute");
break;
case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
appendStringInfoString(str, " hour to second");
break;
case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
appendStringInfoString(str, " minute to second");
break;
case INTERVAL_FULL_RANGE:
// Nothing
break;
default:
Assert(false);
break;
}
if (list_length(type_name->typmods) == 2)
{
int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
if (precision != INTERVAL_FULL_PRECISION)
appendStringInfo(str, "(%d)", precision);
}
skip_typmods = true;
}
else
{
appendStringInfoString(str, "pg_catalog.");
appendStringInfoString(str, name);
}
}
else
{
deparseAnyName(str, type_name->names);
}
if (list_length(type_name->typmods) > 0 && !skip_typmods)
{
appendStringInfoChar(str, '(');
foreach(lc, type_name->typmods)
{
if (IsA(lfirst(lc), A_Const))
deparseAConst(str, lfirst(lc));
else if (IsA(lfirst(lc), ParamRef))
deparseParamRef(str, lfirst(lc));
else if (IsA(lfirst(lc), ColumnRef))
deparseColumnRef(str, lfirst(lc));
else
Assert(false);
if (lnext(type_name->typmods, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
foreach(lc, type_name->arrayBounds)
{
appendStringInfoChar(str, '[');
if (IsA(lfirst(lc), Integer) && intVal(lfirst(lc)) != -1)
deparseSignedIconst(str, lfirst(lc));
appendStringInfoChar(str, ']');
}
if (type_name->pct_type)
appendStringInfoString(str, "%type");
}