Setup is inspecting your computer's hardware configuration

マシンにXPをインストールしようとしたらタイトルのエラーが出たのでメモ。

問題

Linuxを入れていたマシンに、WindowsXPをインストールしようとしたら

Setup is inspecting your computer's hardware configuration

とエラーになった。

原因

Linuxパーティションがすでに存在する事が原因

対応

MBR領域を削除

バイスを確認

df

※デバイスの確認はもっとダイレクトなコマンドないのかな。
MBR領域を削除

dd if=/dev/zero of=/dev/hda bs=512 count=1

データが存在するテーブルに not null 制約の付いたカラムが追加できる

not null に関しておかしな話を聞いたので調べてみた。

おかしな話の内容

「データが存在するテーブルにnot null制約の付いたカラムが追加できる」
…うそん!!!

前置き

発言者はmysqlの事を言っていると思う。
なぜなら、
発言者はmysqlを使っている製品に「今」関わって(昔は知らない)いて、
私の経験として、「データが存在するテーブルにnot null制約の付いたカラムが追加できる」
なんて無茶はoracle、postgresでは許された事がない。
あ、忘れてた、SQLServerも許してくれなかった。

調査

他の RDBMS の挙動は分かっているので、mysql に対してのみ確認します。

データが存在するテーブルへのnot null制約の付いたカラム追加

テーブルを作成

CREATE TABLE test_null(
    null_char_column varchar(10),
    null_int_column int,
    notnull_char_column varchar(10) NOT NULL,
    notnull_int_column int NOT NULL
);

定義を確認

desc test_null;
+---------------------+-------------+------+-----+---------+-------+
| Field               | Type        | Null | Key | Default | Extra |
+---------------------+-------------+------+-----+---------+-------+
| null_char_column    | varchar(10) | YES  |     | NULL    |       |
| null_int_column     | int(11)     | YES  |     | NULL    |       |
| notnull_char_column | varchar(10) | NO   |     | NULL    |       |
| notnull_int_column  | int(11)     | NO   |     | NULL    |       |
+---------------------+-------------+------+-----+---------+-------+

notnull_char_column、notnull_int_column の2カラム。
not null 指定したから Null のところが NO となっているのは正しく、
Default が NULL なのもOK。
データを INSERT する時に指定してなかったらNULLなのでエラー、というのは
至極全うな動きだ。

データ追加

INSERT INTO test_null
      (null_char_column,
       null_int_column,
       notnull_char_column,
       notnull_int_column)
VALUES('a',
        1,
       'b',
        2);

データを確認

select * from test_null;
+------------------+-----------------+---------------------+--------------------+
| null_char_column | null_int_column | notnull_char_column | notnull_int_column |
+------------------+-----------------+---------------------+--------------------+
| a                |               1 | b                   |                  2 |
+------------------+-----------------+---------------------+--------------------+

not null 制約の付いたカラムを追加する。

ALTER TABLE test_null ADD notnull_char_column_add varchar(10) not null;
ALTER TABLE test_null ADD notnull_char_int_add int not null;

がーん、、、エラーにならなかった・・・

定義を確認

desc test_null;
+-------------------------+-------------+------+-----+---------+-------+
| Field                   | Type        | Null | Key | Default | Extra |
+-------------------------+-------------+------+-----+---------+-------+
| null_char_column        | varchar(10) | YES  |     | NULL    |       |
| null_int_column         | int(11)     | YES  |     | NULL    |       |
| notnull_char_column     | varchar(10) | NO   |     | NULL    |       |
| notnull_int_column      | int(11)     | NO   |     | NULL    |       |
| notnull_char_column_add | varchar(10) | NO   |     | NULL    |       |
| notnull_char_int_add    | int(11)     | NO   |     | NULL    |       |
+-------------------------+-------------+------+-----+---------+-------+

CREATE TABLE の時に作成した他の not null 制約付きカラムと同じ定義で追加されてる。

データを確認

select * from test_null;
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+
| null_char_column | null_int_column | notnull_char_column | notnull_int_column | notnull_char_column_add | notnull_int_add |
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+
| a                |               1 | b                   |                  2 |                         |               0 |
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+

追加した int 型カラムのレコードに 0 が勝手に入ってる・・・。
varchar 型カラムの方は多分''かな?

確認してみる。

select * from test_null where notnull_char_column_add is null;
Empty set (0.00 sec)

select * from test_null where notnull_char_column_add is not null;
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+
| null_char_column | null_int_column | notnull_char_column | notnull_int_column | notnull_char_column_add | notnull_int_add |
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+
| a                |               1 | b                   |                  2 |                         |               0 |
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+
1 row in set (0.00 sec)

select * from test_null where notnull_char_column_add = '';
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+
| null_char_column | null_int_column | notnull_char_column | notnull_int_column | notnull_char_column_add | notnull_int_add |
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+
| a                |               1 | b                   |                  2 |                         |               0 |
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+
1 row in set (0.00 sec)

という事でやっぱり varchar 型の(勝手な)初期化に使われる値は''でした。

INSERT で not null のカラムにデータを指定しないとどうなるのか確認してみる

答えは予想がつきますが、予想外の仕様を↑で見たばかりなので念のため。

データ追加

INSERT INTO test_null
      (null_char_column,
       null_int_column)
VALUES('c',
        3);

普通に通りました。
違和感を感じるけど驚かなくなってきた。

データを確認

select * from test_null;
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+
| null_char_column | null_int_column | notnull_char_column | notnull_int_column | notnull_char_column_add | notnull_int_add |
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+
| a                |               1 | b                   |                  2 |                         |               0 |
| c                |               3 |                     |                  0 |                         |               0 |
+------------------+-----------------+---------------------+--------------------+-------------------------+-----------------+

カラム追加の時と同じですね。

まとめ

not null 制約の付いたカラムを、データが存在するテーブルに対して追加する

mysql
※その場合の初期値は int なら 0、char なら ''

oracle ×
カラム追加のDDL文に NOT NULL を付ける時は同時に DEFAULT も付ける。
ex.)
ALTER TABLE tab_name ADD col_name NOT NULL DEFAULT 0;

postgres ×
oracleと違って NOT NULL と DEFAULT を同時に付ける事ができないので、
DEFAULT だけ付けてカラムを追加した後に、ALTER COLUMN で NOT NULL を追加します。
ex.)
ALTER TABLE tab_name ALTER COLUMN col_name DEFAULT 0;
ALTER TABLE tab_name ALTER COLUMN col_name SET NOT NULL;

長所と短所

長所

  • not null を気にしなくていい。

短所

  • DDL文はともかく、INSERT文でmysqlが勝手な値を入れる

型定義のない言語で初期値が勝手に入ったりするのと同じなのかな。。。

  • テーブル設計の時に意識が低くなる

カラムのデータが必須の場合にNOT NULL付けるけど、DEFAULTを意識しない、っていうのは
初期値を考えてないみたいで嫌だな。
勝手にmysqlに値を入れられるくらいなら、エラーで返してくれた方がキレイなデータになると思う。

のこり

not null カラムにmysqlが勝手に値を入れる、って事に強烈な根拠が欲しいんだけど、
もしかして default を指定するよりも早いのかな?
また今度検証してみよう。

East Asian Ambiguous Width Character

テキストエディタなどで → など一部の記号が入っている時に表示崩れなどが発生する問題。

問題

unicodeambiguous width に分類される文字があると、以下の問題を起こす。

  • 表示の乱れ
  • カーソルの表示と内部バッファの位置のズレ

つまりまともに編集できなくなる。
(大体においては行単位でバッファの管理をしているので、行単位でおかしくなる)

原因

ambiguous width は、文字コードとして文字幅の規定がされていないのでアプリ側で表示する際の文字幅を確認して扱わないといけない。
問題が出るのは以下の2パターン。

  • ambiguous width の文字幅を設定ファイルなどで指定すれば扱える(指定しないとダメ)
  • そもそも対応が考えられていない

対応

vim

vimの場合は幸いというかもちろんというか原因として前者なので、設定ファイルで ambiguous width の文字幅を指定する。
.vimrc

set ambiwidth=double
screen

East Asian Ambiguous 対応としてパッチで提供されているので再インストールが必要。
https://savannah.gnu.org/bugs/?16666#postcomment

# すでにインストールされている場合はアンインストール
yum remove screen

# screen ソースをダウンロード
wget http://ftp.gnu.org/pub/gnu/screen/screen-4.0.3.tar.gz
tar zxvf screen-4.0.3.tar.gz
cd screen-4.0.3

# パッチのダウンロード
wget screen-4.0.2-patch-cjkwidth-cvs-2006052001

# その他のパッチもついでにダウンロード
wget ftp://www.dekaino.net/pub/screen/screen-4.0.2-deadlock-patch
wget ftp://www.dekaino.net/pub/screen/screen-4.0.2-hankanacopy-patch

# パッチを当てる
patch < screen-4.0.2-deadlock-patch
patch < screen-4.0.2-hankanacopy-patch
patch < patch-cjkwidth-cvs-2006052001

# インストール
./configure
make && make install

screenの East Asian Ambiguous 対応パッチを読んでみる

utf8の文字単位に文字幅を確認する関数内で、East Asian Ambiguous かどうかを確認する為の文字コードテーブルが追加されてる。

int
utf8_isdouble(c)
int c;
{
// 〜 中略 〜
    /* sorted list of non-overlapping intervals of East Asian Ambiguous
    * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
    static const struct interval ambiguous[] = {
        { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
        { 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
// 〜 中略 〜
        { 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
        { 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
    };