Skip to content

Commit 8d8bcda

Browse files
committed
Hello!
Attached to the mail is locale-patch.tar.gz. In the archive there are: file README.locale short description directory src/test/locale test suite; currently only koi8-r tests, but the suite can be easily extended file locale.patch the very patch; to apply: patch < locale.patch; should be applied to postgres-6.3.2 (at least I created it with 6.3.2 without any additional patches) Files touched by the patch: src/include/utils/builtins.h src/backend/utils/adt/char.c src/backend/utils/adt/varchar.c src/backend/utils/adt/varlena.c Oleg
1 parent 67a6369 commit 8d8bcda

21 files changed

+815
-90
lines changed

doc/README.locale

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
1998 May 25
3+
4+
I extended locale support. Now ORDER BY (if PostgreSQL configured with
5+
--enable-locale) uses strcoll() for all text fields: char(n), varchar(n),
6+
text. (I am not sure about ORDER BY char2/char4/etc.)
7+
8+
I included test suite .../src/test/locale. I didn't include this in
9+
the regression test because not so much people require locale support. Read
10+
.../src/test/locale/README for details on the test suite.
11+
12+
Many thanks to Oleg Bartunov (oleg@sai.msu.su) and Thomas G. Lockhart
13+
(lockhart@alumni.caltech.edu) for hints, tips, help and discussion.
14+
15+
Oleg.
16+
----
17+
Oleg Broytmann http://members.tripod.com/~phd2/ phd2@earthling.net

src/backend/utils/adt/varchar.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.33 1998/06/15 19:29:38 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.34 1998/06/16 06:41:50 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -475,7 +475,7 @@ bpcharlt(char *arg1, char *arg2)
475475
len1 = bcTruelen(arg1);
476476
len2 = bcTruelen(arg2);
477477

478-
cmp = strncmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
478+
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
479479
if (cmp == 0)
480480
return (len1 < len2);
481481
else
@@ -494,7 +494,7 @@ bpcharle(char *arg1, char *arg2)
494494
len1 = bcTruelen(arg1);
495495
len2 = bcTruelen(arg2);
496496

497-
cmp = strncmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
497+
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
498498
if (0 == cmp)
499499
return (bool) (len1 <= len2 ? 1 : 0);
500500
else
@@ -513,7 +513,7 @@ bpchargt(char *arg1, char *arg2)
513513
len1 = bcTruelen(arg1);
514514
len2 = bcTruelen(arg2);
515515

516-
cmp = strncmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
516+
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
517517
if (cmp == 0)
518518
return (len1 > len2);
519519
else
@@ -532,7 +532,7 @@ bpcharge(char *arg1, char *arg2)
532532
len1 = bcTruelen(arg1);
533533
len2 = bcTruelen(arg2);
534534

535-
cmp = strncmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
535+
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
536536
if (0 == cmp)
537537
return (bool) (len1 >= len2 ? 1 : 0);
538538
else
@@ -549,7 +549,7 @@ bpcharcmp(char *arg1, char *arg2)
549549
len1 = bcTruelen(arg1);
550550
len2 = bcTruelen(arg2);
551551

552-
cmp = strncmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
552+
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
553553
if ((0 == cmp) && (len1 != len2))
554554
return (int32) (len1 < len2 ? -1 : 1);
555555
else
@@ -641,7 +641,7 @@ varcharlt(char *arg1, char *arg2)
641641
len1 = VARSIZE(arg1) - VARHDRSZ;
642642
len2 = VARSIZE(arg2) - VARHDRSZ;
643643

644-
cmp = strncmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
644+
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
645645
if (cmp == 0)
646646
return (len1 < len2);
647647
else
@@ -660,7 +660,7 @@ varcharle(char *arg1, char *arg2)
660660
len1 = VARSIZE(arg1) - VARHDRSZ;
661661
len2 = VARSIZE(arg2) - VARHDRSZ;
662662

663-
cmp = strncmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
663+
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
664664
if (0 == cmp)
665665
return (bool) (len1 <= len2 ? 1 : 0);
666666
else
@@ -679,7 +679,7 @@ varchargt(char *arg1, char *arg2)
679679
len1 = VARSIZE(arg1) - VARHDRSZ;
680680
len2 = VARSIZE(arg2) - VARHDRSZ;
681681

682-
cmp = strncmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
682+
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
683683
if (cmp == 0)
684684
return (len1 > len2);
685685
else
@@ -698,7 +698,7 @@ varcharge(char *arg1, char *arg2)
698698
len1 = VARSIZE(arg1) - VARHDRSZ;
699699
len2 = VARSIZE(arg2) - VARHDRSZ;
700700

701-
cmp = strncmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
701+
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
702702
if (0 == cmp)
703703
return (bool) (len1 >= len2 ? 1 : 0);
704704
else
@@ -715,7 +715,7 @@ varcharcmp(char *arg1, char *arg2)
715715

716716
len1 = VARSIZE(arg1) - VARHDRSZ;
717717
len2 = VARSIZE(arg2) - VARHDRSZ;
718-
cmp = (strncmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2)));
718+
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
719719
if ((0 == cmp) && (len1 != len2))
720720
return (int32) (len1 < len2 ? -1 : 1);
721721
else

src/backend/utils/adt/varlena.c

Lines changed: 49 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.36 1998/06/15 19:29:38 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.37 1998/06/16 06:41:51 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -468,116 +468,87 @@ textne(text *arg1, text *arg2)
468468
return ((bool) !texteq(arg1, arg2));
469469
}
470470

471-
/* text_lt()
472-
* Comparison function for text strings.
471+
/* varstr_cmp()
472+
* Comparison function for text strings with given lengths.
473473
* Includes locale support, but must copy strings to temporary memory
474474
* to allow null-termination for inputs to strcoll().
475-
* XXX HACK code for textlen() indicates that there can be embedded nulls
476-
* but it appears that most routines (incl. this one) assume not! - tgl 97/04/07
475+
* Returns -1, 0 or 1
477476
*/
478-
bool
479-
text_lt(text *arg1, text *arg2)
477+
int
478+
varstr_cmp(unsigned char *arg1, int len1, unsigned char *arg2, int len2)
480479
{
481-
bool result;
482-
483-
#ifdef USE_LOCALE
484-
int cval;
485-
486-
#endif
487-
int len;
488-
unsigned char *a1p,
489-
*a2p;
490-
491-
if (arg1 == NULL || arg2 == NULL)
492-
return ((bool) FALSE);
493-
494-
len = (((VARSIZE(arg1) <= VARSIZE(arg2)) ? VARSIZE(arg1) : VARSIZE(arg2)) - VARHDRSZ);
480+
int result;
481+
unsigned char *a1p, *a2p;
495482

496483
#ifdef USE_LOCALE
497-
a1p = (unsigned char *) palloc(len + 1);
498-
a2p = (unsigned char *) palloc(len + 1);
484+
a1p = (unsigned char *) palloc(len1 + 1);
485+
a2p = (unsigned char *) palloc(len2 + 1);
499486

500-
memcpy(a1p, VARDATA(arg1), len);
501-
*(a1p + len) = '\0';
502-
memcpy(a2p, VARDATA(arg2), len);
503-
*(a2p + len) = '\0';
487+
memcpy(a1p, arg1, len1);
488+
*(a1p + len1) = '\0';
489+
memcpy(a2p, arg2, len2);
490+
*(a2p + len2) = '\0';
504491

505-
cval = strcoll(a1p, a2p);
506-
result = ((cval < 0) || ((cval == 0) && (VARSIZE(arg1) < VARSIZE(arg2))));
492+
result = strcoll(a1p, a2p);
507493

508494
pfree(a1p);
509495
pfree(a2p);
496+
510497
#else
511-
a1p = (unsigned char *) VARDATA(arg1);
512-
a2p = (unsigned char *) VARDATA(arg2);
513498

514-
while (len != 0 && *a1p == *a2p)
515-
{
516-
a1p++;
517-
a2p++;
518-
len--;
519-
};
499+
a1p = arg1;
500+
a2p = arg2;
520501

521-
result = (len ? (*a1p < *a2p) : (VARSIZE(arg1) < VARSIZE(arg2)));
502+
result = strncmp(a1p, a2p, Min(len1, len2));
503+
if ((result == 0) && (len1 != len2))
504+
result = (len1 < len2) ? -1 : 1;
522505
#endif
523506

524507
return (result);
525-
} /* text_lt() */
508+
} /* varstr_cmp() */
526509

527-
/* text_le()
510+
/* text_cmp()
528511
* Comparison function for text strings.
529512
* Includes locale support, but must copy strings to temporary memory
530513
* to allow null-termination for inputs to strcoll().
531514
* XXX HACK code for textlen() indicates that there can be embedded nulls
532515
* but it appears that most routines (incl. this one) assume not! - tgl 97/04/07
516+
* Returns -1, 0 or 1
533517
*/
534-
bool
535-
text_le(text *arg1, text *arg2)
518+
int
519+
text_cmp(text *arg1, text *arg2)
536520
{
537-
bool result;
538-
539-
#ifdef USE_LOCALE
540-
int cval;
541-
542-
#endif
543-
int len;
544-
unsigned char *a1p,
545-
*a2p;
521+
unsigned char *a1p, *a2p;
522+
int len1, len2;
546523

547524
if (arg1 == NULL || arg2 == NULL)
548-
return ((bool) 0);
549-
550-
len = (((VARSIZE(arg1) <= VARSIZE(arg2)) ? VARSIZE(arg1) : VARSIZE(arg2)) - VARHDRSZ);
551-
552-
#ifdef USE_LOCALE
553-
a1p = (unsigned char *) palloc(len + 1);
554-
a2p = (unsigned char *) palloc(len + 1);
555-
556-
memcpy(a1p, VARDATA(arg1), len);
557-
*(a1p + len) = '\0';
558-
memcpy(a2p, VARDATA(arg2), len);
559-
*(a2p + len) = '\0';
560-
561-
cval = strcoll(a1p, a2p);
562-
result = ((cval < 0) || ((cval == 0) && (VARSIZE(arg1) <= VARSIZE(arg2))));
525+
return ((bool) FALSE);
563526

564-
pfree(a1p);
565-
pfree(a2p);
566-
#else
567527
a1p = (unsigned char *) VARDATA(arg1);
568528
a2p = (unsigned char *) VARDATA(arg2);
569529

570-
while (len != 0 && *a1p == *a2p)
571-
{
572-
a1p++;
573-
a2p++;
574-
len--;
575-
};
530+
len1 = VARSIZE(arg1) - VARHDRSZ;
531+
len2 = VARSIZE(arg2) - VARHDRSZ;
576532

577-
result = (len ? (*a1p <= *a2p) : (VARSIZE(arg1) <= VARSIZE(arg2)));
578-
#endif
533+
return varstr_cmp(a1p, len1, a2p, len2);
534+
} /* text_cmp() */
579535

580-
return (result);
536+
/* text_lt()
537+
* Comparison function for text strings.
538+
*/
539+
bool
540+
text_lt(text *arg1, text *arg2)
541+
{
542+
return (bool)(text_cmp(arg1, arg2) < 0);
543+
} /* text_lt() */
544+
545+
/* text_le()
546+
* Comparison function for text strings.
547+
*/
548+
bool
549+
text_le(text *arg1, text *arg2)
550+
{
551+
return (bool)(text_cmp(arg1, arg2) <= 0);
581552
} /* text_le() */
582553

583554
bool

src/include/utils/builtins.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: builtins.h,v 1.43 1998/05/29 13:37:29 thomas Exp $
9+
* $Id: builtins.h,v 1.44 1998/06/16 06:41:51 momjian Exp $
1010
*
1111
* NOTES
1212
* This should normally only be included by fmgr.h.
@@ -428,6 +428,8 @@ extern char *textout(text *vlena);
428428
extern text *textcat(text *arg1, text *arg2);
429429
extern bool texteq(text *arg1, text *arg2);
430430
extern bool textne(text *arg1, text *arg2);
431+
extern int varstr_cmp(unsigned char *arg1, int len1, unsigned char *arg2, int len2);
432+
extern int text_cmp(text *arg1, text *arg2);
431433
extern bool text_lt(text *arg1, text *arg2);
432434
extern bool text_le(text *arg1, text *arg2);
433435
extern bool text_gt(text *arg1, text *arg2);

src/test/locale/Makefile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#
2+
# Makefile for example programs
3+
#
4+
5+
SRCDIR= ../..
6+
include ../../Makefile.global
7+
8+
#
9+
# And where libpq goes, so goes the authentication stuff...
10+
#
11+
ifdef KRBVERS
12+
LDFLAGS+= $(KRBLIBS)
13+
CFLAGS+= $(KRBFLAGS)
14+
endif
15+
16+
PROGS = test-pgsql-locale test-ctype
17+
DIRS = koi8-r
18+
19+
all: $(PROGS)
20+
21+
$(PROGS): % : %.c
22+
$(CC) $(CFLAGS) -o $@ $@.c $(LDFLAGS)
23+
24+
clean:
25+
rm -f $(PROGS) *.out
26+
for d in $(DIRS); do \
27+
cd $$d; \
28+
$(MAKE) clean; \
29+
cd ..; \
30+
done
31+
32+
test-%: all
33+
@cd `echo $@ | sed s/^test-//` && $(MAKE) test

src/test/locale/README

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
1998 May 25
3+
4+
This directory contains a set of tests for locales. I provided one C
5+
program test-ctype.c to test CTYPE support in libc and installed
6+
localedata. Then there are test-sort.pl and test-sort.py that tests
7+
collating. (Also there is test-sort.py but it is commented out in scripts;
8+
uncomment it if you have Python interpreter installed).
9+
To run a test for some locale (koi8, e.g) run
10+
make all test-$locale
11+
(for example)
12+
make all test-koi8
13+
14+
Currently, only tests for koi8 locale (russian cyrillic for UN*X)
15+
provided in koi8 directory. Script `runall' calls test-pgsql-locale to test
16+
whether locale support had been compiled into PotgreSQL, test-ctype to test
17+
libc and localedata, test-sort.pl (uncomment test-sort.py, if you have
18+
Python interpreter installed) and does tests on PostgreSQL with
19+
test-koi8*.sql.in.
20+
21+
To add locale tests one need to create directory $locale and create
22+
Makefile (and other files) similar to koi8-r/*. Actually, the simplest (I
23+
think) method is just copy koi8-r directory and edit/replace files.
24+
25+
Oleg.
26+
----
27+
Oleg Broytmann http://members.tripod.com/~phd2/ phd2@earthling.net

src/test/locale/koi8-r/Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#
2+
# Makefile for example programs
3+
#
4+
5+
all:
6+
-@echo "make: Nothing to be done for \`all'."
7+
8+
test:
9+
@./runall
10+
11+
clean:
12+
rm -f *.out

0 commit comments

Comments
 (0)