[前][次][番号順一覧][スレッド一覧]

mysql:1792

From: とみたまさひろ <とみたまさひろ <tommy@xxxxxxxxxx>>
Date: Wed, 22 Mar 2000 01:52:02 +0900
Subject: [mysql 01792] Re: sjis & order by

とみたです。

At Tue, 21 Mar 2000 20:18:42 +0900,
takeshi@xxxxxxxxxx wrote:

> 現在の MySQL のコードでは、char 型に代入された SJIS 文字の
> 2byte 目が 0x41-0x5a (=[a-z]), 0x61-0x7a (=[A-Z]) の時に、
> 2byte 目が ケース非依存でソートされてしまいます。

ああ、SJIS にはそういう問題があったんですね。試してみると確かに "1",
"A", "B" が "B", "1", "A" の順に並んじゃいますね。気づきませんでし
た。

> MySQL を --with-charset=sjis で作成して、
> char 型(binary 属性はつけない)に sjis データを入れた時、
> order by が一部、正しく出なかったのを修正するパッチです。
> 検証してみてください。
> 3.22.32用のパッチです

いくつかまずいところがあるようです。実際に問題が発生するのを確認したわけ
ではありませんが。バッファをオーバーしてデータを読み書きする可能性があっ
たり、「\」の後に2バイトデータが来ることが考慮されてなかったり…。

# GBK という名称が残ってたり… :-)

ということで私もパッチを作ってみました(ctype-sjis.c だけ)。strnxfrm とか 
like_range とかを良く理解せずに書いているので、変かもしれません… (^^;

# ぢつわ GBK のコードの方が正しかったりして… (^^;;

-- 
とみたまさひろ <tommy@xxxxxxxxxx>

*** ctype-sjis.c.orig	Sun Apr 26 20:35:20 1998
--- ctype-sjis.c	Wed Mar 22 01:28:44 2000
***************
*** 2,7 ****
--- 2,8 ----
   */
  #include <global.h>
  #include "m_string.h"
+ #include "m_ctype.h"
  
  uchar NEAR ctype_sjis[257] =
  {
***************
*** 147,149 ****
--- 148,270 ----
    '\360','\361','\362','\363','\364','\365','\366','\367',
    '\370','\371','\372','\373','\374','\375','\376','\377',
  };
+ 
+ #define sjiscode(c,d)	(((uchar)(c) << 8) | (uchar)(d))
+ 
+ uint MY_STRXFRM_MULTIPLY=1;
+ 
+ int my_strnncoll(const uchar *s1, int len1, const uchar *s2, int len2)
+ {
+   const uchar *e1 = s1 + len1;
+   const uchar *e2 = s2 + len2;
+   while (s1 < e1 && s2 < e2) {
+     if (ismbchar(s1, e1) && ismbchar(s2, e2)) {
+       uint c1 = sjiscode(*s1, *(s1+1));
+       uint c2 = sjiscode(*s2, *(s2+1));
+       if (c1 != c2)
+ 	return c1 - c2;
+       s1 += 2;
+       s2 += 2;
+     } else {
+       if (my_sort_order[(uchar)*s1] != my_sort_order[(uchar)*s2])
+ 	return my_sort_order[(uchar)*s1] - my_sort_order[(uchar)*s2];
+       s1++;
+       s2++;
+     }
+   }
+   return len1 - len2;
+ }
+ 
+ int my_strcoll(const uchar *s1, const uchar *s2)
+ {
+   return my_strnncoll(s1, strlen(s1), s2, strlen(s2));
+ }
+ 
+ int my_strnxfrm(uchar *dest, uchar *src, int len, int srclen)
+ {
+   uchar *dend = dest + len;
+   uchar *send = src + srclen;
+   while (dest < dend && src < send) {
+     if (ismbchar(src, send)) {
+       *dest++ = *src++;
+       if (dest < dend && src < send)
+ 	*dest++ = *src++;
+     } else {
+       *dest++ = my_sort_order[(uchar)*src++];
+     }
+   }
+   return srclen;
+ }
+ 
+ int my_strxfrm(uchar *dest, uchar *src, int len)
+ {
+   return my_strnxfrm(dest, src, len, strlen(src));
+ }
+ 
+ 
+ /*
+ ** Calculate min_str and max_str that ranges a LIKE string.
+ ** Arguments:
+ ** ptr		Pointer to LIKE string.
+ ** ptr_length	Length of LIKE string.
+ ** escape	Escape character in LIKE.  (Normally '\').
+ **		All escape characters should be removed from min_str and max_str
+ ** res_length	Length of min_str and max_str.
+ ** min_str	Smallest case sensitive string that ranges LIKE.
+ **		Should be space padded to res_length.
+ ** max_str	Largest case sensitive string that ranges LIKE.
+ **		Normally padded with the biggest character sort value.
+ **
+ ** The function should return 0 if ok and 1 if the LIKE string can't be
+ ** optimized !
+ */
+ 
+ #define max_sort_char 255
+ #define wild_one '_'
+ #define wild_many '%'
+ 
+ my_bool my_like_range(const char *ptr,uint ptr_length,pchar escape,
+                       uint res_length, char *min_str,char *max_str,
+                       uint *min_length,uint *max_length)
+ {
+   const char *end=ptr+ptr_length;
+   char *min_org=min_str;
+   char *min_end=min_str+res_length;
+ 
+   while (ptr < end && min_str < min_end) {
+     if (ismbchar(ptr, end)) {
+       *min_str++ = *max_str++ = *ptr++;
+       if (min_str < min_end)
+ 	*min_str++ = *max_str++ = *ptr++;
+       continue;
+     }
+     if (*ptr == escape && ptr+1 < end) {
+       ptr++;				// Skip escape
+       if (ismbchar(ptr, end))
+ 	*min_str++ = *max_str++ = *ptr++;
+       if (min_str < min_end)
+ 	*min_str++ = *max_str++ = *ptr++;
+       continue;
+     }
+     if (*ptr == wild_one) {		// '_' in SQL
+       *min_str++ = '\0';		// This should be min char
+       *max_str++ = max_sort_char;
+       ptr++;
+       continue;
+     }
+     if (*ptr == wild_many) {		// '%' in SQL
+       *min_length = (uint)(min_str - min_org);
+       *max_length = res_length;
+       do {
+ 	*min_str++ = ' ';		// Because if key compression
+ 	*max_str++ = max_sort_char;
+       } while (min_str < min_end);
+       return 0;
+     }
+     *min_str++ = *max_str++ = *ptr++;
+   }
+   *min_length = *max_length = (uint)(min_str - min_org);
+   while (min_str < min_end)
+     *min_str++ = *max_str++ = ' ';	// Because if key compression
+   return 0;
+ }

[前][次][番号順一覧][スレッド一覧]

      1790 2000-03-21 20:18 [<takeshi@xxxxxxxxxx>] sjis &amp; order by                     
->    1792 2000-03-22 01:52 ┗[とみたまさひろ <tomm]                                       
      1794 2000-03-22 04:23  ┗[<takeshi@xxxxxxxxxx>]