Improve reporting of run-time-detected indeterminate-collation errors.
pg_newlocale_from_collation does not have enough context to give an error message that's even a little bit useful, so move the responsibility for complaining up to its callers. Also, reword ERRCODE_INDETERMINATE_COLLATION error messages in a less jargony, more message-style-guide-compliant fashion.
This commit is contained in:
parent
37d6d07dda
commit
6e197cb2e5
|
@ -141,7 +141,7 @@ DefineCollation(List *names, List *parameters)
|
||||||
|
|
||||||
/* check that the locales can be loaded */
|
/* check that the locales can be loaded */
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
pg_newlocale_from_collation(newoid);
|
(void) pg_newlocale_from_collation(newoid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -899,7 +899,7 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
|
||||||
if (!OidIsValid(attcollation))
|
if (!OidIsValid(attcollation))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
||||||
errmsg("no collation was derived for the index expression"),
|
errmsg("could not determine which collation to use for index expression"),
|
||||||
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -139,7 +139,7 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
|
||||||
if (!OidIsValid(def->collOid))
|
if (!OidIsValid(def->collOid))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
||||||
errmsg("no collation was derived for view column \"%s\"",
|
errmsg("could not determine which collation to use for view column \"%s\"",
|
||||||
def->colname),
|
def->colname),
|
||||||
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1503,7 +1503,20 @@ str_tolower(const char *buff, size_t nbytes, Oid collid)
|
||||||
size_t result_size;
|
size_t result_size;
|
||||||
|
|
||||||
if (collid != DEFAULT_COLLATION_OID)
|
if (collid != DEFAULT_COLLATION_OID)
|
||||||
|
{
|
||||||
|
if (!OidIsValid(collid))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This typically means that the parser could not resolve a
|
||||||
|
* conflict of implicit collations, so report it that way.
|
||||||
|
*/
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
||||||
|
errmsg("could not determine which collation to use for lower() function"),
|
||||||
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
||||||
|
}
|
||||||
mylocale = pg_newlocale_from_collation(collid);
|
mylocale = pg_newlocale_from_collation(collid);
|
||||||
|
}
|
||||||
|
|
||||||
/* Overflow paranoia */
|
/* Overflow paranoia */
|
||||||
if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
|
if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
|
||||||
|
@ -1540,7 +1553,20 @@ str_tolower(const char *buff, size_t nbytes, Oid collid)
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (collid != DEFAULT_COLLATION_OID)
|
if (collid != DEFAULT_COLLATION_OID)
|
||||||
|
{
|
||||||
|
if (!OidIsValid(collid))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This typically means that the parser could not resolve a
|
||||||
|
* conflict of implicit collations, so report it that way.
|
||||||
|
*/
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
||||||
|
errmsg("could not determine which collation to use for lower() function"),
|
||||||
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
||||||
|
}
|
||||||
mylocale = pg_newlocale_from_collation(collid);
|
mylocale = pg_newlocale_from_collation(collid);
|
||||||
|
}
|
||||||
|
|
||||||
result = pnstrdup(buff, nbytes);
|
result = pnstrdup(buff, nbytes);
|
||||||
|
|
||||||
|
@ -1598,7 +1624,20 @@ str_toupper(const char *buff, size_t nbytes, Oid collid)
|
||||||
size_t result_size;
|
size_t result_size;
|
||||||
|
|
||||||
if (collid != DEFAULT_COLLATION_OID)
|
if (collid != DEFAULT_COLLATION_OID)
|
||||||
|
{
|
||||||
|
if (!OidIsValid(collid))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This typically means that the parser could not resolve a
|
||||||
|
* conflict of implicit collations, so report it that way.
|
||||||
|
*/
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
||||||
|
errmsg("could not determine which collation to use for upper() function"),
|
||||||
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
||||||
|
}
|
||||||
mylocale = pg_newlocale_from_collation(collid);
|
mylocale = pg_newlocale_from_collation(collid);
|
||||||
|
}
|
||||||
|
|
||||||
/* Overflow paranoia */
|
/* Overflow paranoia */
|
||||||
if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
|
if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
|
||||||
|
@ -1635,7 +1674,20 @@ str_toupper(const char *buff, size_t nbytes, Oid collid)
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (collid != DEFAULT_COLLATION_OID)
|
if (collid != DEFAULT_COLLATION_OID)
|
||||||
|
{
|
||||||
|
if (!OidIsValid(collid))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This typically means that the parser could not resolve a
|
||||||
|
* conflict of implicit collations, so report it that way.
|
||||||
|
*/
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
||||||
|
errmsg("could not determine which collation to use for upper() function"),
|
||||||
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
||||||
|
}
|
||||||
mylocale = pg_newlocale_from_collation(collid);
|
mylocale = pg_newlocale_from_collation(collid);
|
||||||
|
}
|
||||||
|
|
||||||
result = pnstrdup(buff, nbytes);
|
result = pnstrdup(buff, nbytes);
|
||||||
|
|
||||||
|
@ -1705,7 +1757,20 @@ str_initcap(const char *buff, size_t nbytes, Oid collid)
|
||||||
size_t result_size;
|
size_t result_size;
|
||||||
|
|
||||||
if (collid != DEFAULT_COLLATION_OID)
|
if (collid != DEFAULT_COLLATION_OID)
|
||||||
|
{
|
||||||
|
if (!OidIsValid(collid))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This typically means that the parser could not resolve a
|
||||||
|
* conflict of implicit collations, so report it that way.
|
||||||
|
*/
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
||||||
|
errmsg("could not determine which collation to use for initcap() function"),
|
||||||
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
||||||
|
}
|
||||||
mylocale = pg_newlocale_from_collation(collid);
|
mylocale = pg_newlocale_from_collation(collid);
|
||||||
|
}
|
||||||
|
|
||||||
/* Overflow paranoia */
|
/* Overflow paranoia */
|
||||||
if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
|
if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
|
||||||
|
@ -1754,7 +1819,20 @@ str_initcap(const char *buff, size_t nbytes, Oid collid)
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (collid != DEFAULT_COLLATION_OID)
|
if (collid != DEFAULT_COLLATION_OID)
|
||||||
|
{
|
||||||
|
if (!OidIsValid(collid))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This typically means that the parser could not resolve a
|
||||||
|
* conflict of implicit collations, so report it that way.
|
||||||
|
*/
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
||||||
|
errmsg("could not determine which collation to use for initcap() function"),
|
||||||
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
||||||
|
}
|
||||||
mylocale = pg_newlocale_from_collation(collid);
|
mylocale = pg_newlocale_from_collation(collid);
|
||||||
|
}
|
||||||
|
|
||||||
result = pnstrdup(buff, nbytes);
|
result = pnstrdup(buff, nbytes);
|
||||||
|
|
||||||
|
|
|
@ -932,21 +932,13 @@ pg_newlocale_from_collation(Oid collid)
|
||||||
{
|
{
|
||||||
collation_cache_entry *cache_entry;
|
collation_cache_entry *cache_entry;
|
||||||
|
|
||||||
|
/* Callers must pass a valid OID */
|
||||||
|
Assert(OidIsValid(collid));
|
||||||
|
|
||||||
/* Return 0 for "default" collation, just in case caller forgets */
|
/* Return 0 for "default" collation, just in case caller forgets */
|
||||||
if (collid == DEFAULT_COLLATION_OID)
|
if (collid == DEFAULT_COLLATION_OID)
|
||||||
return (pg_locale_t) 0;
|
return (pg_locale_t) 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* This is where we'll fail if a collation-aware function is invoked
|
|
||||||
* and no collation OID is passed. This typically means that the
|
|
||||||
* parser could not resolve a conflict of implicit collations, so
|
|
||||||
* report it that way.
|
|
||||||
*/
|
|
||||||
if (!OidIsValid(collid))
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
|
||||||
errmsg("locale operation to be invoked, but no collation was derived")));
|
|
||||||
|
|
||||||
cache_entry = lookup_collation_cache(collid, false);
|
cache_entry = lookup_collation_cache(collid, false);
|
||||||
|
|
||||||
if (cache_entry->locale == 0)
|
if (cache_entry->locale == 0)
|
||||||
|
|
|
@ -1302,7 +1302,20 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2, Oid collid)
|
||||||
pg_locale_t mylocale = 0;
|
pg_locale_t mylocale = 0;
|
||||||
|
|
||||||
if (collid != DEFAULT_COLLATION_OID)
|
if (collid != DEFAULT_COLLATION_OID)
|
||||||
|
{
|
||||||
|
if (!OidIsValid(collid))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This typically means that the parser could not resolve a
|
||||||
|
* conflict of implicit collations, so report it that way.
|
||||||
|
*/
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
||||||
|
errmsg("could not determine which collation to use for string comparison"),
|
||||||
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
||||||
|
}
|
||||||
mylocale = pg_newlocale_from_collation(collid);
|
mylocale = pg_newlocale_from_collation(collid);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
/* Win32 does not have UTF-8, so we need to map to UTF-16 */
|
/* Win32 does not have UTF-8, so we need to map to UTF-16 */
|
||||||
|
|
|
@ -586,7 +586,8 @@ SELECT a, b FROM collate_test3 EXCEPT SELECT a, b FROM collate_test3 WHERE a < 2
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
SELECT a, b FROM collate_test1 UNION ALL SELECT a, b FROM collate_test3 ORDER BY 2; -- fail
|
SELECT a, b FROM collate_test1 UNION ALL SELECT a, b FROM collate_test3 ORDER BY 2; -- fail
|
||||||
ERROR: locale operation to be invoked, but no collation was derived
|
ERROR: could not determine which collation to use for string comparison
|
||||||
|
HINT: Use the COLLATE clause to set the collation explicitly.
|
||||||
SELECT a, b FROM collate_test1 UNION ALL SELECT a, b FROM collate_test3; -- ok
|
SELECT a, b FROM collate_test1 UNION ALL SELECT a, b FROM collate_test3; -- ok
|
||||||
a | b
|
a | b
|
||||||
---+-----
|
---+-----
|
||||||
|
@ -629,7 +630,8 @@ ERROR: no collation was derived for column "b" with collatable type text
|
||||||
HINT: Use the COLLATE clause to set the collation explicitly.
|
HINT: Use the COLLATE clause to set the collation explicitly.
|
||||||
-- ideally this would be a parse-time error, but for now it must be run-time:
|
-- ideally this would be a parse-time error, but for now it must be run-time:
|
||||||
select x < y from collate_test10; -- fail
|
select x < y from collate_test10; -- fail
|
||||||
ERROR: locale operation to be invoked, but no collation was derived
|
ERROR: could not determine which collation to use for string comparison
|
||||||
|
HINT: Use the COLLATE clause to set the collation explicitly.
|
||||||
select x || y from collate_test10; -- ok, because || is not collation aware
|
select x || y from collate_test10; -- ok, because || is not collation aware
|
||||||
?column?
|
?column?
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -392,7 +392,8 @@ SELECT a, b FROM collate_test2 EXCEPT SELECT a, b FROM collate_test2 WHERE a < 2
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
SELECT a, b FROM collate_test1 UNION ALL SELECT a, b FROM collate_test2 ORDER BY 2; -- fail
|
SELECT a, b FROM collate_test1 UNION ALL SELECT a, b FROM collate_test2 ORDER BY 2; -- fail
|
||||||
ERROR: locale operation to be invoked, but no collation was derived
|
ERROR: could not determine which collation to use for string comparison
|
||||||
|
HINT: Use the COLLATE clause to set the collation explicitly.
|
||||||
SELECT a, b FROM collate_test1 UNION ALL SELECT a, b FROM collate_test2; -- ok
|
SELECT a, b FROM collate_test1 UNION ALL SELECT a, b FROM collate_test2; -- ok
|
||||||
a | b
|
a | b
|
||||||
---+-----
|
---+-----
|
||||||
|
@ -435,7 +436,8 @@ ERROR: no collation was derived for column "b" with collatable type text
|
||||||
HINT: Use the COLLATE clause to set the collation explicitly.
|
HINT: Use the COLLATE clause to set the collation explicitly.
|
||||||
-- ideally this would be a parse-time error, but for now it must be run-time:
|
-- ideally this would be a parse-time error, but for now it must be run-time:
|
||||||
select x < y from collate_test10; -- fail
|
select x < y from collate_test10; -- fail
|
||||||
ERROR: locale operation to be invoked, but no collation was derived
|
ERROR: could not determine which collation to use for string comparison
|
||||||
|
HINT: Use the COLLATE clause to set the collation explicitly.
|
||||||
select x || y from collate_test10; -- ok, because || is not collation aware
|
select x || y from collate_test10; -- ok, because || is not collation aware
|
||||||
?column?
|
?column?
|
||||||
----------
|
----------
|
||||||
|
|
Loading…
Reference in New Issue