gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

ははぁん大分見えてきた…けどね orz

さすがに見逃せない話が多々あったので、ちと調べてみた。
で…大分見えてきた。ポイントは多分「3つの自動化」。


まずわかりやすいのは「文字コードの自動化」。
彼ら的には、EUCとしての「おはよう」とUTF-8としての「おはよう」を、つまり

euc('おはよう') = utf-8('おはよう')

を、trueにしたいわけだ。
まぁわからんでもない。面倒起こしやすいことも多々あるのだが。


次に。「スペースパディング」の自動化。
padding(パディング)はいいよね? ゼロパディングとかあるし。雑に書くと「データ量の不足分を一定の文字で埋める」の。
で。
charとvarcharの違い。charは固定長なのに対して、varcharは可変長。んじゃ可変部分をどうやってるかって言うと、大抵は「先頭の1バイトとか2バイトとか4バイトとか8バイトとか使ってそこにlengthを埋め込んでる」の。
翻って。charは固定長。んじゃ「char(10)に8文字いれて。のこり2文字どうする?」。
大抵の場合。ここを「スペースパディング」するざます。つまり「空白で埋める」。
だとすると。このタイミングにおいては

'01234567' = '01234567  '

がtrueにならないと困る。だってスペースは「システムがシステムの都合で勝手に入れたもの」だから。
で、この考え方を応用したんだか横着したんだかして、かくして
http://dev.mysql.com/doc/refman/5.1/ja/char.html

全てのMySQL照合は PADSPACE タイプの物だと覚えておいてください。これは、MySQLの中の全ての CHAR と VARCHAR 値が後続スペースを無視して比較されるという事を意味します。

って流れになる。


最後に。………これはどうしても想像しにくいんだけど。「lowerとupperの自動化」。
少なくとも彼らの感性において、

'a' = 'A'

というのは、trueらしい。ちなみにこの延長線として、割合に容易に

'a' = 'A' = euc('A') = utf-8('a')

がtrueになるんだろうと思われる。後ろ二つはいわゆる「多バイト文字」ね。
そう考えた根拠はここ。
http://dev.mysql.com/doc/refman/5.1/ja/charset-binary-op.html

キャラクタ毎よりも、バイト毎の比較を強制的に行う簡単な方法です。

上述、キャラクタ的には同一視してると思われる。


さて。「文字コードの自動化」は、人によりけり微妙だけど、俺的にはNG。パディングと大小文字の自動化は論外。
で…対策は人生色々女も色々。


とりあえず文字コード抑制として、コンパイルオプション&my.cnfに手を入れてみる。
具体的には以下参照。
http://vivian.reverb.jp/mysql4.1.html

# MySQL4.1.12 ソースから--with-charset=binaryの指定ありでコンパイル(こうするとクライアントをbinaryで作れる)。
# my.cnfは以下。

[mysqld]
default-character-set=utf8
[mysqldump]
default-character-set=binary

これで、おそらくは「文字コードの自動化」が抑止できる。
以下、確認用のメモ。

mysql> SHOW VARIABLES LIKE "char%";
character_set_client
    クライアントから渡されるSQL文のキャラクタセット
character_set_connection
    SQL文中の文字列リテラルのキャラクタセットのデフォルト値
character_set_database
    CREATE DATABASE でキャラクタセットを指定しなかった場合にこの値が使用される
character_set_results
    クライアントへ結果を返す時のキャラクタセット
character_set_server
    character_set_database のデフォルト値に影響する
character_set_system
    テーブル名やカラム名用。どうあがいてもutf8で固定 

大文字小文字については、create tableのchar、varchar、textにbinaryをつけるのがひとつ。


で、大小文字+スペースパディングの抑止には、binaryによるキャストが有効。
ただ
http://mysql.mirrors-r-us.net/doc/refman/4.1/ja/case-sensitivity-operators.html

注意: MySQL の一部のコンテキストでは、インデックス付きのカラムを BINARY にキャストすると、インデックスを効率的に使用できなくなる。

という予想通りの文句があるので、binaryキャストは定数(シングルクォートした文字列)に対してやるほうが安全。
書式的には

カラム名 = binary '定数'
カラム名 = binary('定数')

こんな感じ。


で、最後に、すばらしくはしたないアイデア(笑
http://dev.mysql.com/doc/refman/5.1/ja/binary-varbinary.html

BINARY と VARBINARY タイプは、非バイナリ文字列ではなく、バイナリ文字列を含んでいるところ以外で CHAR と VARCHAR に似ています。それは、それらが文字の文字列ではなく、バイトの文字列を含んでいるという事です。これは、それらが文字セットを持たず、ソートと比較は値の中の数値バイトに基づいているという意味です。

http://dev.mysql.com/doc/refman/5.1/ja/blob.html

BLOB カラムはバイナリ文字列(バイト文字列)として扱われます。TEXT カラムは非バイナリ文字列(文字の文字列)として扱われます。BLOB カラムは文字セットを持たないので、ソートと比較は値の中の数値バイトに基づいています。TEXT カラムは文字セットを持つので、値は文字セットの照合に基づいてソート、比較されます。

つまりね。

sed -e s/varchar/varbinary/
sed -e s/text/blob/

ほぉらはしたないw


とりあえず……………おぢちゃん疲れたよ orz