Re: 7.4.1 release status - Turkish Locale

Started by Nicolai Tufaralmost 22 years ago18 messages
#1Nicolai Tufar
ntufar@pisem.net
1 attachment(s)

We might think that the Turkish-locale problem Devrim Gunduz pointed

out

is a must-fix, too. But I'm not convinced yet what to do about it.

Here is a first try to fix what Devrim Gunduz talked about.

Please be patient with me for it is the first major patch
I submit and I realize that I blatantly violated many rules
of good style in PostgreSQL source code.

First, about the problem. Turkish language has two letters "i".
One is with dot on top and the other is without. Simply as that.
The one with dot has the dot both as capital and lower-case and
the one without dot has no dot in both upper and lower case...
as opposed to English where "i" has a dot when lower-case and
has no dot when upper-case.

Problem arise when PostgreSQL, while running with "tr_TR" locale
converts to lower-case an identifier as a table, an index or
a column name. If it is written with capital "I", tolower() with
'I' as argument will return Turkish specific character:
'i'-without-a-dot what I am afraid will not be shown correctly
in your e-mail readers.

Let me give some examples.

initdb script runs apparently innocent script in file
src/backend/utils/mb/conversion_procs/conversion_create.sql
to create a couple of functions whose only fault was
to declare it their return parameters as VOID. Backend
returns error message that type "vo d" is not found and
initdb fails.

A nothing suspecting novice user was excited about
SERIAL data type he was tail is present in PostgreSQL.
It took us with Devrim a lot of time to explain why he
need to type SERIAL as SERiAL for now till a workaround
is developed.

Another case happened with me when I wanted to restore
a pg_dump dump. Restore failed because script was creating
scripts that belong to PUBLIC.

For the solution, after some research we found out that
offender is tolower() call in src/backend/parser/scan.l
in {identifier} section. tolower() works fine with any
locale and with any character save for the Turkish locale
and capital 'I' character. So, the obvious solution is
to put a check for Turkish locale and 'I' character.
Something like this:

if( <locale is Turkish> && ident[i] == 'I' )
ident[i] = 'i';
else
ident[i] = tolower((unsigned char) ident[i]);

Looks rather simple but the hard part was to figure out
what is the current locale. To do this I added

const char *get_locale_category(const char *category);

to src/backend/utils/adt/pg_locale.c that would return
locale identifier for the category specified or LC_ALL
if category is NULL. I could not find any other function
that will return what I need. Please help me to find
one because I would hate to introduce a new function.

I realize that {identifier} section is very performance
critical so I introduced a global variable

static int isturkishlocale = -1;

at the beginning of src/backend/parser/scan.l
It is set to -1 when not yet initialized, 0 if
locale is not Turkish and 1 if locale is Turkish.

It might not be the way it is usually done in PostgreSQL
source code. Could you pleas advise if the name I chose
is appropriate and whether there is a more appropriate
place to put declaration and initialization.

Best regards,
Nicolai Tufar & Devrim Gunduz

Attachments:

trpatch.diffapplication/octet-stream; name=trpatch.diffDownload
*** ./src/backend/parser/scan.l.orig	2004-01-31 22:38:45.000000000 +0200
--- ./src/backend/parser/scan.l	2004-02-01 03:13:01.000000000 +0200
***************
*** 27,32 ****
--- 27,33 ----
  /* Not needed now that this file is compiled as part of gram.y */
  /* #include "parser/parse.h" */
  #include "utils/builtins.h"
+ #include "utils/pg_locale.h"
  #include "mb/pg_wchar.h"
  
  /* No reason to constrain amount of data slurped */
***************
*** 71,76 ****
--- 72,79 ----
  
  unsigned char unescape_single_char(unsigned char c);
  
+ static int isturkishlocale = -1; /* not initialized */
+ 
  %}
  
  %option 8bit
***************
*** 550,560 ****
  					 * which seems appropriate under standard SQL rules, whereas
  					 * the keyword comparison was NOT locale-dependent.
  					 */
  					ident = pstrdup(yytext);
  					for (i = 0; ident[i]; i++)
  					{
  						if (isupper((unsigned char) ident[i]))
! 							ident[i] = tolower((unsigned char) ident[i]);
  					}
  					if (i >= NAMEDATALEN)
                      {
--- 553,576 ----
  					 * which seems appropriate under standard SQL rules, whereas
  					 * the keyword comparison was NOT locale-dependent.
  					 */
+ 					if (isturkishlocale == -1)
+ 					{
+ 						char *buf;
+ 						buf = (char *)get_locale_category((const char*)NULL);
+ 						isturkishlocale = 0;
+ 						if (buf != NULL && strlen(buf) > 2 && strncmp(buf,"tr",2) == 0)
+ 							isturkishlocale = 1;
+ 					}
  					ident = pstrdup(yytext);
  					for (i = 0; ident[i]; i++)
  					{
  						if (isupper((unsigned char) ident[i]))
! 						{
! 							if(ident[i] == 'I' && isturkishlocale == 1)
! 								ident[i] = 'i';
! 							else
! 								ident[i] = tolower((unsigned char) ident[i]);
! 						}
  					}
  					if (i >= NAMEDATALEN)
                      {
*** ./src/backend/utils/adt/pg_locale.c.orig	2004-02-01 00:53:46.000000000 +0200
--- ./src/backend/utils/adt/pg_locale.c	2004-02-01 01:06:51.000000000 +0200
***************
*** 116,121 ****
--- 116,134 ----
  	return locale_xxx_assign(LC_TIME, value, doit, interactive);
  }
  
+ const char *
+ get_locale_category(const char *category)
+ {
+ 	char	   *save;
+ 
+ 	if (category == NULL)
+ 		category == LC_ALL;
+ 	save = setlocale(category, NULL);
+ 	save = pstrdup(save);
+ 
+ 	return save;
+ }
+ 
  
  /*
   * We allow LC_MESSAGES to actually be set globally.
*** ./src/include/utils/pg_locale.h.orig	2004-02-01 02:10:35.000000000 +0200
--- ./src/include/utils/pg_locale.h	2004-02-01 01:06:49.000000000 +0200
***************
*** 27,32 ****
--- 27,35 ----
  					  bool doit, bool interactive);
  extern const char *locale_time_assign(const char *value,
  				   bool doit, bool interactive);
+ extern const char *get_locale_category(const char *category);
+ 
+ 
  
  extern bool lc_collate_is_c(void);
  
#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nicolai Tufar (#1)

"Nicolai Tufar" <ntufar@pisem.net> writes:

We might think that the Turkish-locale problem Devrim Gunduz pointed out
is a must-fix, too. But I'm not convinced yet what to do about it.

Here is a first try to fix what Devrim Gunduz talked about.

I still don't much like having a locale-specific wart in the parser
(and the code you give could not work anyway --- for starters, the
first argument of setlocale is not a pointer).

A possible compromise is to apply ASCII downcasing (same as in
keywords.c) for 7-bit-ASCII characters, and apply tolower() only
for character codes above 127. In other words

unsigned char ch = (unsigned char) ident[i];

if (ch >= 'A' && ch <= 'Z')
ch += 'a' - 'A';
else if (ch > 127 && isupper(ch))
ch = tolower(ch);
ident[i] = (char) ch;

In reasonably sane locales this will have the same effects as currently,
while in unsane locales it will ensure that basic-ASCII identifiers are
treated the way we want.

Comments?

regards, tom lane

#3Nicolai Tufar
ntufar@pisem.net
In reply to: Tom Lane (#2)

I still don't much like having a locale-specific wart in the parser
(and the code you give could not work anyway --- for starters, the
first argument of setlocale is not a pointer).

Aw, I see, my code broken. I got confused by locale_......_asign()
family
if functions. Sure, first argument need to be int. But as you said the
code
is a wart.

A possible compromise is to apply ASCII downcasing (same as in
keywords.c) for 7-bit-ASCII characters, and apply tolower() only
for character codes above 127. In other words

unsigned char ch = (unsigned char) ident[i];

if (ch >= 'A' && ch <= 'Z')
ch += 'a' - 'A';
else if (ch > 127 && isupper(ch))
ch = tolower(ch);
ident[i] = (char) ch;

In reasonably sane locales this will have the same effects as

currently,

while in unsane locales it will ensure that basic-ASCII identifiers

are

treated the way we want.

If we go this way why not make a special case only and only for 'I'
Character and not all 7-bit ASCII:

unsigned char ch = (unsigned char) ident[i];

if(ch == (unsigned char)'I')
ch = 'i';
else
ch = tolower(ch)
ident[i] = (char) ch;

Will it break any locales?

regards, tom lane

Regards
Nicolai

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nicolai Tufar (#3)

"Nicolai Tufar" <ntufar@pisem.net> writes:

A possible compromise is to apply ASCII downcasing (same as in
keywords.c) for 7-bit-ASCII characters, and apply tolower() only
for character codes above 127. In other words

If we go this way why not make a special case only and only for 'I'
Character and not all 7-bit ASCII:

It seems to me that that's too narrow a definition of the problem.
I think we should state our goal as "we don't want bizarre locale
definitions to interfere with downcasing of the basic ASCII letters".
If we put in a special case for 'I' we will fix the known problem
with Turkish, but what other strange locales might be out there?
And if we don't trust tolower() for 'I', why should we trust it
for 'A'-'Z'?

What it comes down to is that by training and experience, I always
expect that any bug might be just one example of a whole class of bugs.
You have to look for the related cases that might happen in future,
not only fix the case that's under your nose.

regards, tom lane

#5Nicolai Tufar
ntufar@pisem.net
In reply to: Tom Lane (#4)

"Tom Lane" tgl@sss.pgh.pa.us wrote:

"Nicolai Tufar" <ntufar@pisem.net> writes:

A possible compromise is to apply ASCII downcasing (same as in
keywords.c) for 7-bit-ASCII characters, and apply tolower() only
for character codes above 127. In other words

If we go this way why not make a special case only and only for 'I'
Character and not all 7-bit ASCII:

It seems to me that that's too narrow a definition of the problem.
I think we should state our goal as "we don't want bizarre locale
definitions to interfere with downcasing of the basic ASCII letters".
If we put in a special case for 'I' we will fix the known problem
with Turkish, but what other strange locales might be out there?
And if we don't trust tolower() for 'I', why should we trust it
for 'A'-'Z'?

To my knowledge no other locale have similar problems. At least nobody
complained so far while Turk users are rising their voices for many
years
now. Let try and put this very special case, together with an extensive
explanation in comment and see if someone complains. And by the way,
national characters in table, column, index or function names is
something
that never happens in production databases.

As for 'A'-'Z'^, it was pointed to me that SQL99 standard states that
identifier names need to be downcasted in locale-dependent manner.

Would you like me to create a patch that would touch only
src/backend/parser/scan.l, introduce a special case for 'I'
and include an explanation in comment?

What it comes down to is that by training and experience, I always
expect that any bug might be just one example of a whole class of

bugs.

You have to look for the related cases that might happen in future,
not only fix the case that's under your nose.

regards, tom lane

Regards,
Nicolai Tufar

#6Nicolai Tufar
ntufar@pisem.net
In reply to: Tom Lane (#4)
Turkish Locale in Identifiers (contd.)

Tom Lane <tgl@sss.pgh.pa.us> wrote:
"Nicolai Tufar" <ntufar@pisem.net> writes:

A possible compromise is to apply ASCII downcasing (same as in
keywords.c) for 7-bit-ASCII characters, and apply tolower() only
for character codes above 127. In other words

If we go this way why not make a special case only and only for 'I'
Character and not all 7-bit ASCII:

It seems to me that that's too narrow a definition of the problem.
I think we should state our goal as "we don't want bizarre locale
definitions to interfere with downcasing of the basic ASCII letters".
If we put in a special case for 'I' we will fix the known problem
with Turkish, but what other strange locales might be out there?
And if we don't trust tolower() for 'I', why should we trust it
for 'A'-'Z'?

Since nobody commented on the issue I may suggest a patch that
implements
'I' special case solution. 'A'-'Z' ASCII-only downcasting idea was
rejected
before on basis of SQL99 compliance. I hope I would have more luck with
this
one. Because PostgreSQL just does not work with Turkish locale, and it
was
so since 7.4.0. initdb just chokes on VOID identifier and quits. Devrim
Gunduz will second me on this, I am sure.

With my knowledge of Russian, Arabic and -to some degree- Hebrew
encodings
I claim that this patch will not break them. If someone who uses far
eastern
Encodings would also check it, I think it would be pretty safe to apply
this patch to the source.

Thanks,
Nicolai Tufar

#7Nicolai Tufar
ntufar@pisem.net
In reply to: Nicolai Tufar (#6)
1 attachment(s)
Re: Turkish Locale in Identifiers (contd.)

Oops, forgot the patch :)

-----Original Message-----
From: pgsql-hackers-owner@postgresql.org [mailto:pgsql-hackers-
owner@postgresql.org] On Behalf Of Nicolai Tufar
Sent: Tuesday, February 03, 2004 9:31 PM
To: pgsql-hackers@postgresql.org
Cc: 'Tom Lane'; devrim@tdmsoft.com
Subject: [HACKERS] Turkish Locale in Identifiers (contd.)

Tom Lane <tgl@sss.pgh.pa.us> wrote:
"Nicolai Tufar" <ntufar@pisem.net> writes:

A possible compromise is to apply ASCII downcasing (same as in
keywords.c) for 7-bit-ASCII characters, and apply tolower() only
for character codes above 127. In other words

If we go this way why not make a special case only and only for

'I'

Character and not all 7-bit ASCII:

It seems to me that that's too narrow a definition of the problem.
I think we should state our goal as "we don't want bizarre locale
definitions to interfere with downcasing of the basic ASCII

letters".

If we put in a special case for 'I' we will fix the known problem
with Turkish, but what other strange locales might be out there?
And if we don't trust tolower() for 'I', why should we trust it
for 'A'-'Z'?

Since nobody commented on the issue I may suggest a patch that
implements
'I' special case solution. 'A'-'Z' ASCII-only downcasting idea was
rejected
before on basis of SQL99 compliance. I hope I would have more luck

with

this
one. Because PostgreSQL just does not work with Turkish locale, and it
was
so since 7.4.0. initdb just chokes on VOID identifier and quits.

Devrim

Gunduz will second me on this, I am sure.

With my knowledge of Russian, Arabic and -to some degree- Hebrew
encodings
I claim that this patch will not break them. If someone who uses far
eastern
Encodings would also check it, I think it would be pretty safe to

apply

this patch to the source.

Thanks,
Nicolai Tufar

---------------------------(end of

broadcast)---------------------------

TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to

majordomo@postgresql.org)

Attachments:

tr20040203.diffapplication/octet-stream; name=tr20040203.diffDownload
*** ./src/backend/parser/scan.l.orig	2004-02-02 12:25:04.000000000 +0200
--- ./src/backend/parser/scan.l	2004-02-03 14:10:55.000000000 +0200
***************
*** 549,560 ****
  					 * Note: here we use a locale-dependent case conversion,
  					 * which seems appropriate under standard SQL rules, whereas
  					 * the keyword comparison was NOT locale-dependent.
  					 */
  					ident = pstrdup(yytext);
  					for (i = 0; ident[i]; i++)
  					{
  						if (isupper((unsigned char) ident[i]))
! 							ident[i] = tolower((unsigned char) ident[i]);
  					}
  					if (i >= NAMEDATALEN)
                      {
--- 549,573 ----
  					 * Note: here we use a locale-dependent case conversion,
  					 * which seems appropriate under standard SQL rules, whereas
  					 * the keyword comparison was NOT locale-dependent.
+ 					 *
+ 					 * Note: locale-dependent causes incorrect downcasting
+ 					 * of capital 'I' if used with tr_TR locale. Instead
+ 					 * of being converting to 'i' it gets converted to '\xfd'
+ 					 * or <U0131> in Unicode which, according to
+ 					 * /usr/share/i18n/charmaps/ISO-8859-9.gz
+ 					 * stands for "LATIN SMALL LETTER DOTLESS I" .
+ 					 * To prevent this, a special case is introduced.
  					 */
  					ident = pstrdup(yytext);
  					for (i = 0; ident[i]; i++)
  					{
  						if (isupper((unsigned char) ident[i]))
! 						{
! 							if (ident[i] == 'I')
! 								ident[i] = 'i';
! 							else
! 								ident[i] = tolower((unsigned char) ident[i]);
! 						}
  					}
  					if (i >= NAMEDATALEN)
                      {
#8Greg Stark
gsstark@mit.edu
In reply to: Tom Lane (#4)

Tom Lane <tgl@sss.pgh.pa.us> writes:

It seems to me that that's too narrow a definition of the problem.
I think we should state our goal as "we don't want bizarre locale
definitions to interfere with downcasing of the basic ASCII letters".
If we put in a special case for 'I' we will fix the known problem
with Turkish, but what other strange locales might be out there?
And if we don't trust tolower() for 'I', why should we trust it
for 'A'-'Z'?

But then wouldn't it be a little weird for Turkish table and column names to
treat "I and "�" (I think that's a dotted capital I) as equivalent to "i"
instead of "�" "i" respectively. (I think that first one was a dotless i).

Perhaps what really ought to be happening is that the downcasing should be
done separately for keywords, or postponed until the point where it's checked
to see if it's a keyword. Then it could be done using an entirely
ascii-centric bit-twiddling implementation.

If it matches an SQL keyword after being downcased the old fashioned way, then
it's an SQL keyword. If not then the locale-aware tolower() would be
appropriate for tables, columns, etc.

But then perhaps that's unnecessarily complex.

--
greg

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Greg Stark (#8)

Greg Stark <gsstark@mit.edu> writes:

If it matches an SQL keyword after being downcased the old fashioned way, then
it's an SQL keyword. If not then the locale-aware tolower() would be
appropriate for tables, columns, etc.

That's exactly what we do already. The complaint was that the
locale-aware downcasing is broken (not to put it too finely) in Turkish
locales, leading to unexpected/unwanted results for identifiers that are
not keywords. My own opinion is that the correct response is to fix the
Turkish locale tables, but I can see where that might be beyond the
skills of the average Postgres user. Thus I thought a reasonable
compromise would be to override the locale for the handling of A-Z,
allowing it to determine what happens to high-bit-set characters only.

regards, tom lane

#10Greg Stark
gsstark@mit.edu
In reply to: Tom Lane (#9)

Tom Lane <tgl@sss.pgh.pa.us> writes:

Greg Stark <gsstark@mit.edu> writes:

If it matches an SQL keyword after being downcased the old fashioned way, then
it's an SQL keyword. If not then the locale-aware tolower() would be
appropriate for tables, columns, etc.

That's exactly what we do already. The complaint was that the
locale-aware downcasing is broken (not to put it too finely) in Turkish
locales, leading to unexpected/unwanted results for identifiers that are
not keywords.

But the example given was "SERIAL". "serial" is an English word, not a Turkish
word. It shouldn't really be subject to Turkish locale effects at all. Perhaps
"keyword" wasn't the right word in my message.

I'm wondering if he really expects all identifiers to be subject to this ascii
downcasing. Like, if he had a G�NAYDIN column he might be surprised to when
g�nayd�n (where � is the lowercase dotless i) says column "g�nayd�n" doesn't
exist.

Or is the real problem simply that both styles of i really ought to match all
the time, ie, that they should really be considered the same letter for
matches? I wonder if there are other locales where that's an issue.

--
greg

#11Tom Lane
tgl@sss.pgh.pa.us
In reply to: Greg Stark (#10)

Greg Stark <gsstark@mit.edu> writes:

But the example given was "SERIAL". "serial" is an English word, not a
Turkish word. It shouldn't really be subject to Turkish locale effects
at all.

SERIAL is not a keyword according to the grammar. Neither are PUBLIC,
VOID, INT4, and numerous other examples. It's not appropriate to try to
fix this by making them all keywords --- that will just create other
problems. (And where do you draw the line, anyway? Should every
identifier present in the default system catalogs become a keyword?)

I'm wondering if he really expects all identifiers to be subject to
this ascii downcasing.

Without doubt it isn't ideal, but if we don't do something then a lot of
stuff starting with initdb is broken. We could perhaps work around the
problem by spelling everything in lower-case in all the commands we
issue, but I can't see that as an acceptable answer either. We can't
expect to control all the SQL sent to a database.

regards, tom lane

#12Nicolai Tufar
ntufar@pisem.net
In reply to: Tom Lane (#11)
1 attachment(s)

Sorry for rising up old issue again but the problem still persists.
And database cluster is not being created with Turkish locale

If you have any doubts about how Turkish users will react to the fact
that both "I" and "I WITH DOT" will be treated as same character, rest
assured that this behavior is de-facto standard when it comes to file
names,
identifiers and commands. Greg Stark and Devrim Gunduz will confirm
that,
no doubt. Please review and apply this patch I send you for the third
time. You will not regret and many users will be grateful. Please note
that to my knowledge it will not break any other locales.

Best regards,
Nicolai

Attachments:

tr20040203.diffapplication/octet-stream; name=tr20040203.diffDownload
*** ./src/backend/parser/scan.l.orig	2004-02-02 12:25:04.000000000 +0200
--- ./src/backend/parser/scan.l	2004-02-03 14:10:55.000000000 +0200
***************
*** 549,560 ****
  					 * Note: here we use a locale-dependent case conversion,
  					 * which seems appropriate under standard SQL rules, whereas
  					 * the keyword comparison was NOT locale-dependent.
  					 */
  					ident = pstrdup(yytext);
  					for (i = 0; ident[i]; i++)
  					{
  						if (isupper((unsigned char) ident[i]))
! 							ident[i] = tolower((unsigned char) ident[i]);
  					}
  					if (i >= NAMEDATALEN)
                      {
--- 549,573 ----
  					 * Note: here we use a locale-dependent case conversion,
  					 * which seems appropriate under standard SQL rules, whereas
  					 * the keyword comparison was NOT locale-dependent.
+ 					 *
+ 					 * Note: locale-dependent causes incorrect downcasting
+ 					 * of capital 'I' if used with tr_TR locale. Instead
+ 					 * of being converting to 'i' it gets converted to '\xfd'
+ 					 * or <U0131> in Unicode which, according to
+ 					 * /usr/share/i18n/charmaps/ISO-8859-9.gz
+ 					 * stands for "LATIN SMALL LETTER DOTLESS I" .
+ 					 * To prevent this, a special case is introduced.
  					 */
  					ident = pstrdup(yytext);
  					for (i = 0; ident[i]; i++)
  					{
  						if (isupper((unsigned char) ident[i]))
! 						{
! 							if (ident[i] == 'I')
! 								ident[i] = 'i';
! 							else
! 								ident[i] = tolower((unsigned char) ident[i]);
! 						}
  					}
  					if (i >= NAMEDATALEN)
                      {
#13Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nicolai Tufar (#12)

"Nicolai Tufar" <ntufar@pisem.net> writes:

Sorry for rising up old issue again but the problem still persists.
And database cluster is not being created with Turkish locale

I've committed the attached fix, which I believe will solve this
problem. Could you test it?

(Patch is against 7.4 branch)

regards, tom lane

#14Nicolai Tufar
ntufar@pisem.net
In reply to: Tom Lane (#13)

-----Original Message-----
From: Tom Lane [mailto:tgl@sss.pgh.pa.us]

I've committed the attached fix, which I believe will solve this
problem. Could you test it?

Thank you very much for your effort and attention!

I am not sure I am testing the right version. I am testing the
one with REL7_4_STABLE, the one with downcase_truncate_identifier()
function added.

Under locale-ignorant FreeBSD it works fine.
But under Fedora Core 1 initdb it crashes under all
locales I tested -C, en_US, tr_TR with message given below.

I remember seeing this message before, when I messed up with downcasting
Functions. See, it is downcasting "ISO" and gets "ıso" in return. Could
Someone confirm the results I got?

Regards,
Nicolai

--------------------------------------------------------
fixing permissions on existing directory /pgdata... ok
creating directory /pgdata/base... ok
creating directory /pgdata/global... ok
creating directory /pgdata/pg_xlog... ok
creating directory /pgdata/pg_clog... ok
selecting default max_connections... 10
selecting default shared_buffers... 50
creating configuration files... ok
creating template1 database in /pgdata/base/1... FATAL: XX000: failed
to initialize DateStyle to "ISO, MDY"
LOCATION: InitializeGUCOptions, guc.c:1866

initdb: failed

#15Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nicolai Tufar (#14)

"Nicolai Tufar" <ntufar@pisem.net> writes:

Under locale-ignorant FreeBSD it works fine.
But under Fedora Core 1 initdb it crashes under all
locales I tested -C, en_US, tr_TR with message given below.

Hmm. It seems that tr_TR has problems much more extensive than you've
indicated previously. I was able to get through initdb with the attached
additional patch, but the regression tests fail in several places.
It looks to me like every use of strcasecmp in the backend has to be
questioned if we're going to make this work. I'm starting to lean in
the direction of "tr_TR is hopelessly broken" again...

regards, tom lane

*** src/backend/commands/variable.c~	Mon Jan 19 14:04:40 2004
--- src/backend/commands/variable.c	Fri Feb 20 23:16:16 2004
***************
*** 82,103 ****

/* Ugh. Somebody ought to write a table driven version -- mjl */

! 		if (strcasecmp(tok, "ISO") == 0)
  		{
  			newDateStyle = USE_ISO_DATES;
  			scnt++;
  		}
! 		else if (strcasecmp(tok, "SQL") == 0)
  		{
  			newDateStyle = USE_SQL_DATES;
  			scnt++;
  		}
! 		else if (strncasecmp(tok, "POSTGRES", 8) == 0)
  		{
  			newDateStyle = USE_POSTGRES_DATES;
  			scnt++;
  		}
! 		else if (strcasecmp(tok, "GERMAN") == 0)
  		{
  			newDateStyle = USE_GERMAN_DATES;
  			scnt++;
--- 82,108 ----

/* Ugh. Somebody ought to write a table driven version -- mjl */

! 		/*
! 		 * Note: SplitIdentifierString already downcased the input, so
! 		 * we needn't use strcasecmp here.
! 		 */
! 
! 		if (strcmp(tok, "iso") == 0)
  		{
  			newDateStyle = USE_ISO_DATES;
  			scnt++;
  		}
! 		else if (strcmp(tok, "sql") == 0)
  		{
  			newDateStyle = USE_SQL_DATES;
  			scnt++;
  		}
! 		else if (strncmp(tok, "postgres", 8) == 0)
  		{
  			newDateStyle = USE_POSTGRES_DATES;
  			scnt++;
  		}
! 		else if (strcmp(tok, "german") == 0)
  		{
  			newDateStyle = USE_GERMAN_DATES;
  			scnt++;
***************
*** 105,129 ****
  			if (ocnt == 0)
  				newDateOrder = DATEORDER_DMY;
  		}
! 		else if (strcasecmp(tok, "YMD") == 0)
  		{
  			newDateOrder = DATEORDER_YMD;
  			ocnt++;
  		}
! 		else if (strcasecmp(tok, "DMY") == 0 ||
! 				 strncasecmp(tok, "EURO", 4) == 0)
  		{
  			newDateOrder = DATEORDER_DMY;
  			ocnt++;
  		}
! 		else if (strcasecmp(tok, "MDY") == 0 ||
! 				 strcasecmp(tok, "US") == 0 ||
! 				 strncasecmp(tok, "NONEURO", 7) == 0)
  		{
  			newDateOrder = DATEORDER_MDY;
  			ocnt++;
  		}
! 		else if (strcasecmp(tok, "DEFAULT") == 0)
  		{
  			/*
  			 * Easiest way to get the current DEFAULT state is to fetch
--- 110,134 ----
  			if (ocnt == 0)
  				newDateOrder = DATEORDER_DMY;
  		}
! 		else if (strcmp(tok, "ymd") == 0)
  		{
  			newDateOrder = DATEORDER_YMD;
  			ocnt++;
  		}
! 		else if (strcmp(tok, "dmy") == 0 ||
! 				 strncmp(tok, "euro", 4) == 0)
  		{
  			newDateOrder = DATEORDER_DMY;
  			ocnt++;
  		}
! 		else if (strcmp(tok, "mdy") == 0 ||
! 				 strcmp(tok, "us") == 0 ||
! 				 strncmp(tok, "noneuro", 7) == 0)
  		{
  			newDateOrder = DATEORDER_MDY;
  			ocnt++;
  		}
! 		else if (strcmp(tok, "default") == 0)
  		{
  			/*
  			 * Easiest way to get the current DEFAULT state is to fetch
***************
*** 474,480 ****
  				HasCTZSet = true;
  			}
  		}
! 		else if (strcasecmp(value, "UNKNOWN") == 0)
  		{
  			/*
  			 * UNKNOWN is the value shown as the "default" for TimeZone in
--- 479,485 ----
  				HasCTZSet = true;
  			}
  		}
! 		else if (strcasecmp(value, "unknown") == 0)
  		{
  			/*
  			 * UNKNOWN is the value shown as the "default" for TimeZone in
#16Nicolai Tufar
ntufar@pisem.net
In reply to: Tom Lane (#15)

-----Original Message-----
From: Tom Lane [mailto:tgl@sss.pgh.pa.us]
Hmm. It seems that tr_TR has problems much more extensive than you've
indicated previously. I was able to get through initdb with the

attached

additional patch, but the regression tests fail in several places.
It looks to me like every use of strcasecmp in the backend has to be
questioned if we're going to make this work. I'm starting to lean in
the direction of "tr_TR is hopelessly broken" again...

With this patch applied everything works fine. Thanks!
What do you plan to do? Apply it? And if apply, will
You apply both of the modifications to 7.5devel also?

Thanks again for your effort.

Best regards,
Nicolai

regards, tom lane

*** src/backend/commands/variable.c~	Mon Jan 19 14:04:40 2004
--- src/backend/commands/variable.c	Fri Feb 20 23:16:16 2004
***************
*** 82,103 ****

/* Ugh. Somebody ought to write a table driven version

-- mjl

*/

! 		if (strcasecmp(tok, "ISO") == 0)
{
newDateStyle = USE_ISO_DATES;
scnt++;
}
! 		else if (strcasecmp(tok, "SQL") == 0)
{
newDateStyle = USE_SQL_DATES;
scnt++;
}
! 		else if (strncasecmp(tok, "POSTGRES", 8) == 0)
{
newDateStyle = USE_POSTGRES_DATES;
scnt++;
}
! 		else if (strcasecmp(tok, "GERMAN") == 0)
{
newDateStyle = USE_GERMAN_DATES;
scnt++;
--- 82,108 ----

/* Ugh. Somebody ought to write a table driven version

-- mjl

*/

! /*
! * Note: SplitIdentifierString already downcased the

input, so

! * we needn't use strcasecmp here.
! */
!
! if (strcmp(tok, "iso") == 0)
{
newDateStyle = USE_ISO_DATES;
scnt++;
}
! else if (strcmp(tok, "sql") == 0)
{
newDateStyle = USE_SQL_DATES;
scnt++;
}
! else if (strncmp(tok, "postgres", 8) == 0)
{
newDateStyle = USE_POSTGRES_DATES;
scnt++;
}
! else if (strcmp(tok, "german") == 0)
{
newDateStyle = USE_GERMAN_DATES;
scnt++;
***************
*** 105,129 ****
if (ocnt == 0)
newDateOrder = DATEORDER_DMY;
}
! else if (strcasecmp(tok, "YMD") == 0)
{
newDateOrder = DATEORDER_YMD;
ocnt++;
}
! else if (strcasecmp(tok, "DMY") == 0 ||
! strncasecmp(tok, "EURO", 4) == 0)
{
newDateOrder = DATEORDER_DMY;
ocnt++;
}
! else if (strcasecmp(tok, "MDY") == 0 ||
! strcasecmp(tok, "US") == 0 ||
! strncasecmp(tok, "NONEURO", 7) == 0)
{
newDateOrder = DATEORDER_MDY;
ocnt++;
}
! else if (strcasecmp(tok, "DEFAULT") == 0)
{
/*
* Easiest way to get the current DEFAULT state

is to

fetch
--- 110,134 ----
if (ocnt == 0)
newDateOrder = DATEORDER_DMY;
}
! 		else if (strcmp(tok, "ymd") == 0)
{
newDateOrder = DATEORDER_YMD;
ocnt++;
}
! 		else if (strcmp(tok, "dmy") == 0 ||
! 				 strncmp(tok, "euro", 4) == 0)
{
newDateOrder = DATEORDER_DMY;
ocnt++;
}
! 		else if (strcmp(tok, "mdy") == 0 ||
! 				 strcmp(tok, "us") == 0 ||
! 				 strncmp(tok, "noneuro", 7) == 0)
{
newDateOrder = DATEORDER_MDY;
ocnt++;
}
! 		else if (strcmp(tok, "default") == 0)
{
/*
* Easiest way to get the current DEFAULT state

is to

fetch
***************
*** 474,480 ****
HasCTZSet = true;
}
}
! else if (strcasecmp(value, "UNKNOWN") == 0)
{
/*
* UNKNOWN is the value shown as the "default"

for

TimeZone in
--- 479,485 ----
HasCTZSet = true;
}
}
! 		else if (strcasecmp(value, "unknown") == 0)
{
/*
* UNKNOWN is the value shown as the "default"

for

Show quoted text

TimeZone in

#17Tom Lane
tgl@sss.pgh.pa.us
In reply to: Nicolai Tufar (#16)

"Nicolai Tufar" <ntufar@pisem.net> writes:

It looks to me like every use of strcasecmp in the backend has to be
questioned if we're going to make this work. I'm starting to lean in
the direction of "tr_TR is hopelessly broken" again...

With this patch applied everything works fine. Thanks!

Did you try running the regression tests under tr_TR locale? It seems
a few bricks short of "fine" yet :-(

regards, tom lane

#18Nicolai Tufar
ntufar@pisem.net
In reply to: Tom Lane (#17)
1 attachment(s)

-----Original Message-----
From: Tom Lane
Did you try running the regression tests under tr_TR locale? It seems
a few bricks short of "fine" yet :-(

I run regression tests under tr_TR locale. To do this I hardcoded
Turkish locale in initdb in pg_regress.sh. Three tests failed, I
attached resulting diff.

With days of the week, the same problem is with downcasting occurs. I
think it is not that crucial, but the rest of the differences in the
file seem to be important. I was not able to interpret them.

Thanks,
Nicolai

Show quoted text

regards, tom lane

Attachments:

regression.diffsapplication/octet-stream; name=regression.diffsDownload
*** ./expected/timestamp.out	Thu Sep 25 09:58:06 2003
--- ./results/timestamp.out	Sun Feb 22 00:25:55 2004
***************
*** 64,70 ****
  -- Postgres v6.0 standard output format
  INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
  INSERT INTO TIMESTAMP_TBL VALUES ('Invalid Abstime');
! ERROR:  date/time value "Invalid Abstime" is no longer supported
  INSERT INTO TIMESTAMP_TBL VALUES ('Undefined Abstime');
  ERROR:  date/time value "Undefined Abstime" is no longer supported
  -- Variations on Postgres v6.1 standard output format
--- 64,70 ----
  -- Postgres v6.0 standard output format
  INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
  INSERT INTO TIMESTAMP_TBL VALUES ('Invalid Abstime');
! ERROR:  invalid input syntax for type timestamp: "Invalid Abstime"
  INSERT INTO TIMESTAMP_TBL VALUES ('Undefined Abstime');
  ERROR:  date/time value "Undefined Abstime" is no longer supported
  -- Variations on Postgres v6.1 standard output format
***************
*** 730,736 ****
             | TUESDAY   Tuesday   tuesday   TUE Tue tue FEBRUARY  February  february  II   FEB Feb feb
             | WEDNESDAY Wednesday wednesday WED Wed wed FEBRUARY  February  february  II   FEB Feb feb
             | THURSDAY  Thursday  thursday  THU Thu thu FEBRUARY  February  february  II   FEB Feb feb
!            | FRIDAY    Friday    friday    FRI Fri fri FEBRUARY  February  february  II   FEB Feb feb
             | SATURDAY  Saturday  saturday  SAT Sat sat FEBRUARY  February  february  II   FEB Feb feb
             | SUNDAY    Sunday    sunday    SUN Sun sun FEBRUARY  February  february  II   FEB Feb feb
             | TUESDAY   Tuesday   tuesday   TUE Tue tue FEBRUARY  February  february  II   FEB Feb feb
--- 730,736 ----
             | TUESDAY   Tuesday   tuesday   TUE Tue tue FEBRUARY  February  february  II   FEB Feb feb
             | WEDNESDAY Wednesday wednesday WED Wed wed FEBRUARY  February  february  II   FEB Feb feb
             | THURSDAY  Thursday  thursday  THU Thu thu FEBRUARY  February  february  II   FEB Feb feb
!            | FR�DAY    Friday    friday    FR� Fri fri FEBRUARY  February  february  II   FEB Feb feb
             | SATURDAY  Saturday  saturday  SAT Sat sat FEBRUARY  February  february  II   FEB Feb feb
             | SUNDAY    Sunday    sunday    SUN Sun sun FEBRUARY  February  february  II   FEB Feb feb
             | TUESDAY   Tuesday   tuesday   TUE Tue tue FEBRUARY  February  february  II   FEB Feb feb
***************
*** 744,758 ****
             | SATURDAY  Saturday  saturday  SAT Sat sat FEBRUARY  February  february  II   FEB Feb feb
             | WEDNESDAY Wednesday wednesday WED Wed wed FEBRUARY  February  february  II   FEB Feb feb
             | THURSDAY  Thursday  thursday  THU Thu thu FEBRUARY  February  february  II   FEB Feb feb
!            | FRIDAY    Friday    friday    FRI Fri fri MARCH     March     march     III  MAR Mar mar
             | MONDAY    Monday    monday    MON Mon mon DECEMBER  December  december  XII  DEC Dec dec
             | TUESDAY   Tuesday   tuesday   TUE Tue tue DECEMBER  December  december  XII  DEC Dec dec
             | WEDNESDAY Wednesday wednesday WED Wed wed JANUARY   January   january   I    JAN Jan jan
!            | FRIDAY    Friday    friday    FRI Fri fri FEBRUARY  February  february  II   FEB Feb feb
             | SATURDAY  Saturday  saturday  SAT Sat sat MARCH     March     march     III  MAR Mar mar
             | TUESDAY   Tuesday   tuesday   TUE Tue tue DECEMBER  December  december  XII  DEC Dec dec
             | WEDNESDAY Wednesday wednesday WED Wed wed DECEMBER  December  december  XII  DEC Dec dec
!            | FRIDAY    Friday    friday    FRI Fri fri DECEMBER  December  december  XII  DEC Dec dec
             | SATURDAY  Saturday  saturday  SAT Sat sat JANUARY   January   january   I    JAN Jan jan
             | SUNDAY    Sunday    sunday    SUN Sun sun DECEMBER  December  december  XII  DEC Dec dec
             | MONDAY    Monday    monday    MON Mon mon JANUARY   January   january   I    JAN Jan jan
--- 744,758 ----
             | SATURDAY  Saturday  saturday  SAT Sat sat FEBRUARY  February  february  II   FEB Feb feb
             | WEDNESDAY Wednesday wednesday WED Wed wed FEBRUARY  February  february  II   FEB Feb feb
             | THURSDAY  Thursday  thursday  THU Thu thu FEBRUARY  February  february  II   FEB Feb feb
!            | FR�DAY    Friday    friday    FR� Fri fri MARCH     March     march     III  MAR Mar mar
             | MONDAY    Monday    monday    MON Mon mon DECEMBER  December  december  XII  DEC Dec dec
             | TUESDAY   Tuesday   tuesday   TUE Tue tue DECEMBER  December  december  XII  DEC Dec dec
             | WEDNESDAY Wednesday wednesday WED Wed wed JANUARY   January   january   I    JAN Jan jan
!            | FR�DAY    Friday    friday    FR� Fri fri FEBRUARY  February  february  II   FEB Feb feb
             | SATURDAY  Saturday  saturday  SAT Sat sat MARCH     March     march     III  MAR Mar mar
             | TUESDAY   Tuesday   tuesday   TUE Tue tue DECEMBER  December  december  XII  DEC Dec dec
             | WEDNESDAY Wednesday wednesday WED Wed wed DECEMBER  December  december  XII  DEC Dec dec
!            | FR�DAY    Friday    friday    FR� Fri fri DECEMBER  December  december  XII  DEC Dec dec
             | SATURDAY  Saturday  saturday  SAT Sat sat JANUARY   January   january   I    JAN Jan jan
             | SUNDAY    Sunday    sunday    SUN Sun sun DECEMBER  December  december  XII  DEC Dec dec
             | MONDAY    Monday    monday    MON Mon mon JANUARY   January   january   I    JAN Jan jan
***************
*** 800,806 ****
             | TUESDAY Tuesday tuesday FEBRUARY February february II
             | WEDNESDAY Wednesday wednesday FEBRUARY February february II
             | THURSDAY Thursday thursday FEBRUARY February february II
!            | FRIDAY Friday friday FEBRUARY February february II
             | SATURDAY Saturday saturday FEBRUARY February february II
             | SUNDAY Sunday sunday FEBRUARY February february II
             | TUESDAY Tuesday tuesday FEBRUARY February february II
--- 800,806 ----
             | TUESDAY Tuesday tuesday FEBRUARY February february II
             | WEDNESDAY Wednesday wednesday FEBRUARY February february II
             | THURSDAY Thursday thursday FEBRUARY February february II
!            | FR�DAY Friday friday FEBRUARY February february II
             | SATURDAY Saturday saturday FEBRUARY February february II
             | SUNDAY Sunday sunday FEBRUARY February february II
             | TUESDAY Tuesday tuesday FEBRUARY February february II
***************
*** 814,828 ****
             | SATURDAY Saturday saturday FEBRUARY February february II
             | WEDNESDAY Wednesday wednesday FEBRUARY February february II
             | THURSDAY Thursday thursday FEBRUARY February february II
!            | FRIDAY Friday friday MARCH March march III
             | MONDAY Monday monday DECEMBER December december XII
             | TUESDAY Tuesday tuesday DECEMBER December december XII
             | WEDNESDAY Wednesday wednesday JANUARY January january I
!            | FRIDAY Friday friday FEBRUARY February february II
             | SATURDAY Saturday saturday MARCH March march III
             | TUESDAY Tuesday tuesday DECEMBER December december XII
             | WEDNESDAY Wednesday wednesday DECEMBER December december XII
!            | FRIDAY Friday friday DECEMBER December december XII
             | SATURDAY Saturday saturday JANUARY January january I
             | SUNDAY Sunday sunday DECEMBER December december XII
             | MONDAY Monday monday JANUARY January january I
--- 814,828 ----
             | SATURDAY Saturday saturday FEBRUARY February february II
             | WEDNESDAY Wednesday wednesday FEBRUARY February february II
             | THURSDAY Thursday thursday FEBRUARY February february II
!            | FR�DAY Friday friday MARCH March march III
             | MONDAY Monday monday DECEMBER December december XII
             | TUESDAY Tuesday tuesday DECEMBER December december XII
             | WEDNESDAY Wednesday wednesday JANUARY January january I
!            | FR�DAY Friday friday FEBRUARY February february II
             | SATURDAY Saturday saturday MARCH March march III
             | TUESDAY Tuesday tuesday DECEMBER December december XII
             | WEDNESDAY Wednesday wednesday DECEMBER December december XII
!            | FR�DAY Friday friday DECEMBER December december XII
             | SATURDAY Saturday saturday JANUARY January january I
             | SUNDAY Sunday sunday DECEMBER December december XII
             | MONDAY Monday monday JANUARY January january I

======================================================================

*** ./expected/timestamptz.out	Thu Sep 25 09:58:06 2003
--- ./results/timestamptz.out	Sun Feb 22 00:25:55 2004
***************
*** 59,65 ****
  -- Postgres v6.0 standard output format
  INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
  INSERT INTO TIMESTAMPTZ_TBL VALUES ('Invalid Abstime');
! ERROR:  date/time value "Invalid Abstime" is no longer supported
  INSERT INTO TIMESTAMPTZ_TBL VALUES ('Undefined Abstime');
  ERROR:  date/time value "Undefined Abstime" is no longer supported
  -- Variations on Postgres v6.1 standard output format
--- 59,65 ----
  -- Postgres v6.0 standard output format
  INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
  INSERT INTO TIMESTAMPTZ_TBL VALUES ('Invalid Abstime');
! ERROR:  invalid input syntax for type timestamp with time zone: "Invalid Abstime"
  INSERT INTO TIMESTAMPTZ_TBL VALUES ('Undefined Abstime');
  ERROR:  date/time value "Undefined Abstime" is no longer supported
  -- Variations on Postgres v6.1 standard output format
***************
*** 724,730 ****
             | TUESDAY   Tuesday   tuesday   TUE Tue tue FEBRUARY  February  february  II   FEB Feb feb
             | WEDNESDAY Wednesday wednesday WED Wed wed FEBRUARY  February  february  II   FEB Feb feb
             | THURSDAY  Thursday  thursday  THU Thu thu FEBRUARY  February  february  II   FEB Feb feb
!            | FRIDAY    Friday    friday    FRI Fri fri FEBRUARY  February  february  II   FEB Feb feb
             | SATURDAY  Saturday  saturday  SAT Sat sat FEBRUARY  February  february  II   FEB Feb feb
             | SUNDAY    Sunday    sunday    SUN Sun sun FEBRUARY  February  february  II   FEB Feb feb
             | TUESDAY   Tuesday   tuesday   TUE Tue tue FEBRUARY  February  february  II   FEB Feb feb
--- 724,730 ----
             | TUESDAY   Tuesday   tuesday   TUE Tue tue FEBRUARY  February  february  II   FEB Feb feb
             | WEDNESDAY Wednesday wednesday WED Wed wed FEBRUARY  February  february  II   FEB Feb feb
             | THURSDAY  Thursday  thursday  THU Thu thu FEBRUARY  February  february  II   FEB Feb feb
!            | FR�DAY    Friday    friday    FR� Fri fri FEBRUARY  February  february  II   FEB Feb feb
             | SATURDAY  Saturday  saturday  SAT Sat sat FEBRUARY  February  february  II   FEB Feb feb
             | SUNDAY    Sunday    sunday    SUN Sun sun FEBRUARY  February  february  II   FEB Feb feb
             | TUESDAY   Tuesday   tuesday   TUE Tue tue FEBRUARY  February  february  II   FEB Feb feb
***************
*** 738,752 ****
             | SATURDAY  Saturday  saturday  SAT Sat sat FEBRUARY  February  february  II   FEB Feb feb
             | WEDNESDAY Wednesday wednesday WED Wed wed FEBRUARY  February  february  II   FEB Feb feb
             | THURSDAY  Thursday  thursday  THU Thu thu FEBRUARY  February  february  II   FEB Feb feb
!            | FRIDAY    Friday    friday    FRI Fri fri MARCH     March     march     III  MAR Mar mar
             | MONDAY    Monday    monday    MON Mon mon DECEMBER  December  december  XII  DEC Dec dec
             | TUESDAY   Tuesday   tuesday   TUE Tue tue DECEMBER  December  december  XII  DEC Dec dec
             | WEDNESDAY Wednesday wednesday WED Wed wed JANUARY   January   january   I    JAN Jan jan
!            | FRIDAY    Friday    friday    FRI Fri fri FEBRUARY  February  february  II   FEB Feb feb
             | SATURDAY  Saturday  saturday  SAT Sat sat MARCH     March     march     III  MAR Mar mar
             | TUESDAY   Tuesday   tuesday   TUE Tue tue DECEMBER  December  december  XII  DEC Dec dec
             | WEDNESDAY Wednesday wednesday WED Wed wed DECEMBER  December  december  XII  DEC Dec dec
!            | FRIDAY    Friday    friday    FRI Fri fri DECEMBER  December  december  XII  DEC Dec dec
             | SATURDAY  Saturday  saturday  SAT Sat sat JANUARY   January   january   I    JAN Jan jan
             | SUNDAY    Sunday    sunday    SUN Sun sun DECEMBER  December  december  XII  DEC Dec dec
             | MONDAY    Monday    monday    MON Mon mon JANUARY   January   january   I    JAN Jan jan
--- 738,752 ----
             | SATURDAY  Saturday  saturday  SAT Sat sat FEBRUARY  February  february  II   FEB Feb feb
             | WEDNESDAY Wednesday wednesday WED Wed wed FEBRUARY  February  february  II   FEB Feb feb
             | THURSDAY  Thursday  thursday  THU Thu thu FEBRUARY  February  february  II   FEB Feb feb
!            | FR�DAY    Friday    friday    FR� Fri fri MARCH     March     march     III  MAR Mar mar
             | MONDAY    Monday    monday    MON Mon mon DECEMBER  December  december  XII  DEC Dec dec
             | TUESDAY   Tuesday   tuesday   TUE Tue tue DECEMBER  December  december  XII  DEC Dec dec
             | WEDNESDAY Wednesday wednesday WED Wed wed JANUARY   January   january   I    JAN Jan jan
!            | FR�DAY    Friday    friday    FR� Fri fri FEBRUARY  February  february  II   FEB Feb feb
             | SATURDAY  Saturday  saturday  SAT Sat sat MARCH     March     march     III  MAR Mar mar
             | TUESDAY   Tuesday   tuesday   TUE Tue tue DECEMBER  December  december  XII  DEC Dec dec
             | WEDNESDAY Wednesday wednesday WED Wed wed DECEMBER  December  december  XII  DEC Dec dec
!            | FR�DAY    Friday    friday    FR� Fri fri DECEMBER  December  december  XII  DEC Dec dec
             | SATURDAY  Saturday  saturday  SAT Sat sat JANUARY   January   january   I    JAN Jan jan
             | SUNDAY    Sunday    sunday    SUN Sun sun DECEMBER  December  december  XII  DEC Dec dec
             | MONDAY    Monday    monday    MON Mon mon JANUARY   January   january   I    JAN Jan jan
***************
*** 795,801 ****
             | TUESDAY Tuesday tuesday FEBRUARY February february II
             | WEDNESDAY Wednesday wednesday FEBRUARY February february II
             | THURSDAY Thursday thursday FEBRUARY February february II
!            | FRIDAY Friday friday FEBRUARY February february II
             | SATURDAY Saturday saturday FEBRUARY February february II
             | SUNDAY Sunday sunday FEBRUARY February february II
             | TUESDAY Tuesday tuesday FEBRUARY February february II
--- 795,801 ----
             | TUESDAY Tuesday tuesday FEBRUARY February february II
             | WEDNESDAY Wednesday wednesday FEBRUARY February february II
             | THURSDAY Thursday thursday FEBRUARY February february II
!            | FR�DAY Friday friday FEBRUARY February february II
             | SATURDAY Saturday saturday FEBRUARY February february II
             | SUNDAY Sunday sunday FEBRUARY February february II
             | TUESDAY Tuesday tuesday FEBRUARY February february II
***************
*** 809,823 ****
             | SATURDAY Saturday saturday FEBRUARY February february II
             | WEDNESDAY Wednesday wednesday FEBRUARY February february II
             | THURSDAY Thursday thursday FEBRUARY February february II
!            | FRIDAY Friday friday MARCH March march III
             | MONDAY Monday monday DECEMBER December december XII
             | TUESDAY Tuesday tuesday DECEMBER December december XII
             | WEDNESDAY Wednesday wednesday JANUARY January january I
!            | FRIDAY Friday friday FEBRUARY February february II
             | SATURDAY Saturday saturday MARCH March march III
             | TUESDAY Tuesday tuesday DECEMBER December december XII
             | WEDNESDAY Wednesday wednesday DECEMBER December december XII
!            | FRIDAY Friday friday DECEMBER December december XII
             | SATURDAY Saturday saturday JANUARY January january I
             | SUNDAY Sunday sunday DECEMBER December december XII
             | MONDAY Monday monday JANUARY January january I
--- 809,823 ----
             | SATURDAY Saturday saturday FEBRUARY February february II
             | WEDNESDAY Wednesday wednesday FEBRUARY February february II
             | THURSDAY Thursday thursday FEBRUARY February february II
!            | FR�DAY Friday friday MARCH March march III
             | MONDAY Monday monday DECEMBER December december XII
             | TUESDAY Tuesday tuesday DECEMBER December december XII
             | WEDNESDAY Wednesday wednesday JANUARY January january I
!            | FR�DAY Friday friday FEBRUARY February february II
             | SATURDAY Saturday saturday MARCH March march III
             | TUESDAY Tuesday tuesday DECEMBER December december XII
             | WEDNESDAY Wednesday wednesday DECEMBER December december XII
!            | FR�DAY Friday friday DECEMBER December december XII
             | SATURDAY Saturday saturday JANUARY January january I
             | SUNDAY Sunday sunday DECEMBER December december XII
             | MONDAY Monday monday JANUARY January january I

======================================================================

*** ./expected/privileges.out	Mon Sep 15 03:26:31 2003
--- ./results/privileges.out	Sun Feb 22 00:26:07 2004
***************
*** 299,309 ****
  (1 row)
  
  select has_table_privilege(current_user,'pg_shadow','insert');
!  has_table_privilege 
! ---------------------
!  t
! (1 row)
! 
  select has_table_privilege(t2.usesysid,'pg_shadow','update')
  from (select usesysid from pg_user where usename = current_user) as t2;
   has_table_privilege 
--- 299,305 ----
  (1 row)
  
  select has_table_privilege(current_user,'pg_shadow','insert');
! ERROR:  unrecognized privilege type: "insert"
  select has_table_privilege(t2.usesysid,'pg_shadow','update')
  from (select usesysid from pg_user where usename = current_user) as t2;
   has_table_privilege 
***************
*** 343,353 ****
  select has_table_privilege(t2.usesysid,t1.oid,'insert')
  from (select oid from pg_class where relname = 'pg_shadow') as t1,
    (select usesysid from pg_user where usename = current_user) as t2;
!  has_table_privilege 
! ---------------------
!  t
! (1 row)
! 
  select has_table_privilege('pg_shadow','update');
   has_table_privilege 
  ---------------------
--- 339,345 ----
  select has_table_privilege(t2.usesysid,t1.oid,'insert')
  from (select oid from pg_class where relname = 'pg_shadow') as t1,
    (select usesysid from pg_user where usename = current_user) as t2;
! ERROR:  unrecognized privilege type: "insert"
  select has_table_privilege('pg_shadow','update');
   has_table_privilege 
  ---------------------
***************
*** 369,379 ****
  
  select has_table_privilege(t1.oid,'trigger')
  from (select oid from pg_class where relname = 'pg_shadow') as t1;
!  has_table_privilege 
! ---------------------
!  t
! (1 row)
! 
  -- non-superuser
  SET SESSION AUTHORIZATION regressuser3;
  select has_table_privilege(current_user,'pg_class','select');
--- 361,367 ----
  
  select has_table_privilege(t1.oid,'trigger')
  from (select oid from pg_class where relname = 'pg_shadow') as t1;
! ERROR:  unrecognized privilege type: "trigger"
  -- non-superuser
  SET SESSION AUTHORIZATION regressuser3;
  select has_table_privilege(current_user,'pg_class','select');
***************
*** 383,393 ****
  (1 row)
  
  select has_table_privilege(current_user,'pg_class','insert');
!  has_table_privilege 
! ---------------------
!  f
! (1 row)
! 
  select has_table_privilege(t2.usesysid,'pg_class','update')
  from (select usesysid from pg_user where usename = current_user) as t2;
   has_table_privilege 
--- 371,377 ----
  (1 row)
  
  select has_table_privilege(current_user,'pg_class','insert');
! ERROR:  unrecognized privilege type: "insert"
  select has_table_privilege(t2.usesysid,'pg_class','update')
  from (select usesysid from pg_user where usename = current_user) as t2;
   has_table_privilege 
***************
*** 427,437 ****
  select has_table_privilege(t2.usesysid,t1.oid,'insert')
  from (select oid from pg_class where relname = 'pg_class') as t1,
    (select usesysid from pg_user where usename = current_user) as t2;
!  has_table_privilege 
! ---------------------
!  f
! (1 row)
! 
  select has_table_privilege('pg_class','update');
   has_table_privilege 
  ---------------------
--- 411,417 ----
  select has_table_privilege(t2.usesysid,t1.oid,'insert')
  from (select oid from pg_class where relname = 'pg_class') as t1,
    (select usesysid from pg_user where usename = current_user) as t2;
! ERROR:  unrecognized privilege type: "insert"
  select has_table_privilege('pg_class','update');
   has_table_privilege 
  ---------------------
***************
*** 453,463 ****
  
  select has_table_privilege(t1.oid,'trigger')
  from (select oid from pg_class where relname = 'pg_class') as t1;
!  has_table_privilege 
! ---------------------
!  f
! (1 row)
! 
  select has_table_privilege(current_user,'atest1','select');
   has_table_privilege 
  ---------------------
--- 433,439 ----
  
  select has_table_privilege(t1.oid,'trigger')
  from (select oid from pg_class where relname = 'pg_class') as t1;
! ERROR:  unrecognized privilege type: "trigger"
  select has_table_privilege(current_user,'atest1','select');
   has_table_privilege 
  ---------------------
***************
*** 465,475 ****
  (1 row)
  
  select has_table_privilege(current_user,'atest1','insert');
!  has_table_privilege 
! ---------------------
!  f
! (1 row)
! 
  select has_table_privilege(t2.usesysid,'atest1','update')
  from (select usesysid from pg_user where usename = current_user) as t2;
   has_table_privilege 
--- 441,447 ----
  (1 row)
  
  select has_table_privilege(current_user,'atest1','insert');
! ERROR:  unrecognized privilege type: "insert"
  select has_table_privilege(t2.usesysid,'atest1','update')
  from (select usesysid from pg_user where usename = current_user) as t2;
   has_table_privilege 
***************
*** 509,519 ****
  select has_table_privilege(t2.usesysid,t1.oid,'insert')
  from (select oid from pg_class where relname = 'atest1') as t1,
    (select usesysid from pg_user where usename = current_user) as t2;
!  has_table_privilege 
! ---------------------
!  f
! (1 row)
! 
  select has_table_privilege('atest1','update');
   has_table_privilege 
  ---------------------
--- 481,487 ----
  select has_table_privilege(t2.usesysid,t1.oid,'insert')
  from (select oid from pg_class where relname = 'atest1') as t1,
    (select usesysid from pg_user where usename = current_user) as t2;
! ERROR:  unrecognized privilege type: "insert"
  select has_table_privilege('atest1','update');
   has_table_privilege 
  ---------------------
***************
*** 535,545 ****
  
  select has_table_privilege(t1.oid,'trigger')
  from (select oid from pg_class where relname = 'atest1') as t1;
!  has_table_privilege 
! ---------------------
!  f
! (1 row)
! 
  -- Grant options
  SET SESSION AUTHORIZATION regressuser1;
  CREATE TABLE atest4 (a int);
--- 503,509 ----
  
  select has_table_privilege(t1.oid,'trigger')
  from (select oid from pg_class where relname = 'atest1') as t1;
! ERROR:  unrecognized privilege type: "trigger"
  -- Grant options
  SET SESSION AUTHORIZATION regressuser1;
  CREATE TABLE atest4 (a int);

======================================================================