Revert addition of third argument to format_type().

Including collation in the behavior of that function promotes a world view
we do not want.  Moreover, it was producing the wrong behavior for pg_dump
anyway: what we want is to dump a COLLATE clause on attributes whose
attcollation is different from the underlying type, and likewise for
domains, and the function cannot do that for us.  Doing it the hard way
in pg_dump is a bit more tedious but produces more correct output.

In passing, fix initdb so that the initial entry in pg_collation is
properly pinned.  It was droppable before :-(
This commit is contained in:
Tom Lane 2011-03-10 17:30:18 -05:00
parent 551c07d84a
commit 7564654adf
9 changed files with 92 additions and 43 deletions

View File

@ -13269,7 +13269,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<tbody>
<row>
<entry><literal><function>format_type(<parameter>type_oid</parameter> [, <parameter>typemod</> [, <parameter>collation_oid</> ]])</function></literal></entry>
<entry><literal><function>format_type(<parameter>type_oid</parameter>, <parameter>typemod</>)</function></literal></entry>
<entry><type>text</type></entry>
<entry>get SQL name of a data type</entry>
</row>
@ -13410,9 +13410,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<para>
<function>format_type</function> returns the SQL name of a data type that
is identified by its type OID and possibly a type modifier. Pass NULL
for the type modifier or omit the argument if no specific modifier is known.
If a collation is given as third argument, a <literal>COLLATE</> clause
followed by a formatted collation name is appended.
for the type modifier if no specific modifier is known.
</para>
<para>

View File

@ -693,10 +693,6 @@ COMMENT ON FUNCTION ts_debug(text) IS
-- to get filled in.)
--
CREATE OR REPLACE FUNCTION
format_type(oid, int DEFAULT NULL, oid DEFAULT NULL)
RETURNS text STABLE LANGUAGE internal AS 'format_type';
CREATE OR REPLACE FUNCTION
pg_start_backup(label text, fast boolean DEFAULT false)
RETURNS text STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup';

View File

@ -18,7 +18,6 @@
#include <ctype.h>
#include "catalog/namespace.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
@ -29,8 +28,7 @@
#define MAX_INT32_LEN 11
static char *format_type_internal(Oid type_oid, int32 typemod,
bool typemod_given, bool allow_invalid,
Oid collation_oid);
bool typemod_given, bool allow_invalid);
static char *printTypmod(const char *typname, int32 typmod, Oid typmodout);
static char *
psnprintf(size_t len, const char *fmt,...)
@ -69,7 +67,6 @@ format_type(PG_FUNCTION_ARGS)
{
Oid type_oid;
int32 typemod;
Oid collation_oid;
char *result;
/* Since this function is not strict, we must test for null args */
@ -77,14 +74,13 @@ format_type(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
type_oid = PG_GETARG_OID(0);
collation_oid = PG_ARGISNULL(2) ? InvalidOid : PG_GETARG_OID(2);
if (PG_ARGISNULL(1))
result = format_type_internal(type_oid, -1, false, true, collation_oid);
result = format_type_internal(type_oid, -1, false, true);
else
{
typemod = PG_GETARG_INT32(1);
result = format_type_internal(type_oid, typemod, true, true, collation_oid);
result = format_type_internal(type_oid, typemod, true, true);
}
PG_RETURN_TEXT_P(cstring_to_text(result));
@ -99,7 +95,7 @@ format_type(PG_FUNCTION_ARGS)
char *
format_type_be(Oid type_oid)
{
return format_type_internal(type_oid, -1, false, false, InvalidOid);
return format_type_internal(type_oid, -1, false, false);
}
/*
@ -108,15 +104,14 @@ format_type_be(Oid type_oid)
char *
format_type_with_typemod(Oid type_oid, int32 typemod)
{
return format_type_internal(type_oid, typemod, true, false, InvalidOid);
return format_type_internal(type_oid, typemod, true, false);
}
static char *
format_type_internal(Oid type_oid, int32 typemod,
bool typemod_given, bool allow_invalid,
Oid collation_oid)
bool typemod_given, bool allow_invalid)
{
bool with_typemod = typemod_given && (typemod >= 0);
HeapTuple tuple;
@ -322,12 +317,6 @@ format_type_internal(Oid type_oid, int32 typemod,
ReleaseSysCache(tuple);
if (collation_oid && collation_oid != DEFAULT_COLLATION_OID)
{
char *collstr = generate_collation_name(collation_oid);
buf = psnprintf(strlen(buf) + 10 + strlen(collstr), "%s COLLATE %s", buf, collstr);
}
return buf;
}
@ -431,7 +420,7 @@ oidvectortypes(PG_FUNCTION_ARGS)
for (num = 0; num < numargs; num++)
{
char *typename = format_type_internal(oidArray->values[num], -1,
false, true, InvalidOid);
false, true);
size_t slen = strlen(typename);
if (left < (slen + 2))

View File

@ -1388,6 +1388,8 @@ setup_depend(void)
" FROM pg_ts_template;\n",
"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
" FROM pg_ts_config;\n",
"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
" FROM pg_collation;\n",
"INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' "
" FROM pg_authid;\n",
NULL

View File

@ -54,10 +54,12 @@ static int numTables;
static int numTypes;
static int numFuncs;
static int numOperators;
static int numCollations;
static DumpableObject **tblinfoindex;
static DumpableObject **typinfoindex;
static DumpableObject **funinfoindex;
static DumpableObject **oprinfoindex;
static DumpableObject **collinfoindex;
static void flagInhTables(TableInfo *tbinfo, int numTables,
@ -105,7 +107,6 @@ getSchemaData(int *numTablesPtr)
int numCasts;
int numOpclasses;
int numOpfamilies;
int numCollations;
int numConversions;
int numTSParsers;
int numTSTemplates;
@ -187,6 +188,7 @@ getSchemaData(int *numTablesPtr)
if (g_verbose)
write_msg(NULL, "reading user-defined collations\n");
collinfo = getCollations(&numCollations);
collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo));
if (g_verbose)
write_msg(NULL, "reading user-defined conversions\n");
@ -784,6 +786,17 @@ findOprByOid(Oid oid)
return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators);
}
/*
* findCollationByOid
* finds the entry (in collinfo) of the collation with the given oid
* returns NULL if not found
*/
CollInfo *
findCollationByOid(Oid oid)
{
return (CollInfo *) findObjectByOid(oid, collinfoindex, numCollations);
}
/*
* findParentsByOid

View File

@ -5502,6 +5502,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
int i_attalign;
int i_attislocal;
int i_attoptions;
int i_attcollation;
PGresult *res;
int ntups;
bool hasdefaults;
@ -5541,13 +5542,20 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
if (g_fout->remoteVersion >= 90100)
{
/* attcollation is new in 9.1 */
/*
* attcollation is new in 9.1. Since we only want to dump
* COLLATE clauses for attributes whose collation is different
* from their type's default, we use a CASE here to suppress
* uninteresting attcollations cheaply.
*/
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
"a.attstattarget, a.attstorage, t.typstorage, "
"a.attnotnull, a.atthasdef, a.attisdropped, "
"a.attlen, a.attalign, a.attislocal, "
"pg_catalog.format_type(t.oid,a.atttypmod,a.attcollation) AS atttypname, "
"array_to_string(attoptions, ', ') AS attoptions "
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
"array_to_string(a.attoptions, ', ') AS attoptions, "
"CASE WHEN a.attcollation <> t.typcollation "
"THEN a.attcollation ELSE 0 END AS attcollation "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
@ -5563,7 +5571,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"a.attnotnull, a.atthasdef, a.attisdropped, "
"a.attlen, a.attalign, a.attislocal, "
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
"array_to_string(attoptions, ', ') AS attoptions "
"array_to_string(a.attoptions, ', ') AS attoptions, "
"0 AS attcollation "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
@ -5579,7 +5588,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"a.attnotnull, a.atthasdef, a.attisdropped, "
"a.attlen, a.attalign, a.attislocal, "
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
"'' AS attoptions "
"'' AS attoptions, 0 AS attcollation "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
@ -5600,7 +5609,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"false AS attisdropped, a.attlen, "
"a.attalign, false AS attislocal, "
"format_type(t.oid,a.atttypmod) AS atttypname, "
"'' AS attoptions "
"'' AS attoptions, 0 AS attcollation "
"FROM pg_attribute a LEFT JOIN pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::oid "
@ -5618,7 +5627,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"attlen, attalign, "
"false AS attislocal, "
"(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname, "
"'' AS attoptions "
"'' AS attoptions, 0 AS attcollation "
"FROM pg_attribute a "
"WHERE attrelid = '%u'::oid "
"AND attnum > 0::int2 "
@ -5645,6 +5654,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
i_attalign = PQfnumber(res, "attalign");
i_attislocal = PQfnumber(res, "attislocal");
i_attoptions = PQfnumber(res, "attoptions");
i_attcollation = PQfnumber(res, "attcollation");
tbinfo->numatts = ntups;
tbinfo->attnames = (char **) malloc(ntups * sizeof(char *));
@ -5660,6 +5670,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool));
tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
tbinfo->attoptions = (char **) malloc(ntups * sizeof(char *));
tbinfo->attcollation = (Oid *) malloc(ntups * sizeof(Oid));
tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
tbinfo->inhAttrDef = (bool *) malloc(ntups * sizeof(bool));
tbinfo->inhNotNull = (bool *) malloc(ntups * sizeof(bool));
@ -5685,6 +5696,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
tbinfo->attislocal[j] = (PQgetvalue(res, j, i_attislocal)[0] == 't');
tbinfo->notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
tbinfo->attoptions[j] = strdup(PQgetvalue(res, j, i_attoptions));
tbinfo->attcollation[j] = atooid(PQgetvalue(res, j, i_attcollation));
tbinfo->attrdefs[j] = NULL; /* fix below */
if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
hasdefaults = true;
@ -7359,7 +7371,7 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
"typanalyze::pg_catalog.oid AS typanalyzeoid, "
"typcategory, typispreferred, "
"typdelim, typbyval, typalign, typstorage, "
"(typcollation = (SELECT oid FROM pg_catalog.pg_collation WHERE collname = 'default')) AS typcollatable, "
"(typcollation <> 0) AS typcollatable, "
"pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault "
"FROM pg_catalog.pg_type "
"WHERE oid = '%u'::pg_catalog.oid",
@ -7736,6 +7748,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
char *typnotnull;
char *typdefn;
char *typdefault;
Oid typcollation;
bool typdefault_is_literal = false;
/* Set proper schema search path so type references list correctly */
@ -7745,11 +7758,14 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
if (g_fout->remoteVersion >= 90100)
{
/* typcollation is new in 9.1 */
appendPQExpBuffer(query, "SELECT typnotnull, "
"pg_catalog.format_type(typbasetype, typtypmod, typcollation) AS typdefn, "
"pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
"typdefault "
appendPQExpBuffer(query, "SELECT t.typnotnull, "
"pg_catalog.format_type(t.typbasetype, t.typtypmod) AS typdefn, "
"pg_catalog.pg_get_expr(t.typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
"t.typdefault, "
"CASE WHEN t.typcollation <> u.typcollation "
"THEN t.typcollation ELSE 0 END AS typcollation "
"FROM pg_catalog.pg_type t "
"LEFT JOIN pg_catalog.pg_type u ON (t.typbasetype = u.oid) "
"WHERE t.oid = '%u'::pg_catalog.oid",
tyinfo->dobj.catId.oid);
}
@ -7759,7 +7775,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
appendPQExpBuffer(query, "SELECT typnotnull, "
"pg_catalog.format_type(typbasetype, typtypmod) AS typdefn, "
"pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
"typdefault "
"typdefault, 0 AS typcollation "
"FROM pg_catalog.pg_type "
"WHERE oid = '%u'::pg_catalog.oid",
tyinfo->dobj.catId.oid);
@ -7790,6 +7806,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
}
else
typdefault = NULL;
typcollation = atooid(PQgetvalue(res, 0, PQfnumber(res, "typcollation")));
if (binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
@ -7799,6 +7816,22 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
fmtId(tyinfo->dobj.name),
typdefn);
/* Print collation only if different from base type's collation */
if (OidIsValid(typcollation))
{
CollInfo *coll;
coll = findCollationByOid(typcollation);
if (coll)
{
/* always schema-qualify, don't try to be smart */
appendPQExpBuffer(q, " COLLATE %s.",
fmtId(coll->dobj.namespace->dobj.name));
appendPQExpBuffer(q, "%s",
fmtId(coll->dobj.name));
}
}
if (typnotnull[0] == 't')
appendPQExpBuffer(q, " NOT NULL");
@ -11966,6 +11999,22 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
tbinfo->atttypmod[j]));
}
/* Add collation if not default for the type */
if (OidIsValid(tbinfo->attcollation[j]))
{
CollInfo *coll;
coll = findCollationByOid(tbinfo->attcollation[j]);
if (coll)
{
/* always schema-qualify, don't try to be smart */
appendPQExpBuffer(q, " COLLATE %s.",
fmtId(coll->dobj.namespace->dobj.name));
appendPQExpBuffer(q, "%s",
fmtId(coll->dobj.name));
}
}
if (has_default)
appendPQExpBuffer(q, " DEFAULT %s",
tbinfo->attrdefs[j]->adef_expr);

View File

@ -272,6 +272,7 @@ typedef struct _tableInfo
char *attalign; /* attribute align, used by binary_upgrade */
bool *attislocal; /* true if attr has local definition */
char **attoptions; /* per-attribute options */
Oid *attcollation; /* per-attribute collation selection */
/*
* Note: we need to store per-attribute notnull, default, and constraint
@ -510,6 +511,7 @@ extern TableInfo *findTableByOid(Oid oid);
extern TypeInfo *findTypeByOid(Oid oid);
extern FuncInfo *findFuncByOid(Oid oid);
extern OprInfo *findOprByOid(Oid oid);
extern CollInfo *findCollationByOid(Oid oid);
extern void simple_oid_list_append(SimpleOidList *list, Oid val);
extern void simple_string_list_append(SimpleStringList *list, const char *val);

View File

@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 201103061
#define CATALOG_VERSION_NO 201103101
#endif

View File

@ -1100,8 +1100,8 @@ DATA(insert OID = 1078 ( bpcharcmp PGNSP PGUID 12 1 0 0 f f f t f i 2 0 23
DESCR("less-equal-greater");
DATA(insert OID = 1080 ( hashbpchar PGNSP PGUID 12 1 0 0 f f f t f i 1 0 23 "1042" _null_ _null_ _null_ _null_ hashbpchar _null_ _null_ _null_ ));
DESCR("hash");
DATA(insert OID = 1081 ( format_type PGNSP PGUID 12 1 0 0 f f f f f s 3 0 25 "26 23 26" _null_ _null_ _null_ _null_ format_type _null_ _null_ _null_ ));
DESCR("format a type OID, atttypmod, and collation OID to canonical SQL");
DATA(insert OID = 1081 ( format_type PGNSP PGUID 12 1 0 0 f f f f f s 2 0 25 "26 23" _null_ _null_ _null_ _null_ format_type _null_ _null_ _null_ ));
DESCR("format a type oid and atttypmod to canonical SQL");
DATA(insert OID = 1084 ( date_in PGNSP PGUID 12 1 0 0 f f f t f s 1 0 1082 "2275" _null_ _null_ _null_ _null_ date_in _null_ _null_ _null_ ));
DESCR("I/O");
DATA(insert OID = 1085 ( date_out PGNSP PGUID 12 1 0 0 f f f t f s 1 0 2275 "1082" _null_ _null_ _null_ _null_ date_out _null_ _null_ _null_ ));