Access 2003からMariaDBに移行

内製のAccess 2003アプリを、DB部分はMariaDBに移行している。 フロントは.Net(C#) ツールを使って工数を削減できないかと模索したが、以下のような正攻法で攻めるしかないと言う結論に達した。 Access側のテーブルにて、極力Not Null制約を適用する… 後述のデータ移行クエリ実行の際、NullがあるとINSERT SELECT 文がこけるため、Nullの場合とそうで無い場合で別クエリを実行する必要が出てくるため。 文字列型は、NULL=空文字と考えて問題ない場合がほとんどと想定されるので、以下の手順を機械的に実行する。 文字列でない場合はNULLを置き換えるべき値が自明でない場合も多いので、一旦NULL値固定で移行し、列ごとに個別で移行(UPDATE DEST.COL=SRC.COL WHERE SRC.COL IS NOT NULL) 対象列の空文字を許可する。 該当列を更新する部分にてNULLの場合は空文字に置き換える処理を追加 画面のフォームがデータと連結していてSQLではなくDoCmdで処理している場合、後付でSQLを組み込むと競合エラーが面倒なので、単純にフォームの値をNz関数でNullを置換してやれば良い ウィザードに従って作成した画面などで、データ更新処理を明示的に記載されていない場合は、フォームの追加・更新前処理イベントにてNz関数を適用する UPDATE文で該当列のNULLを空文字に置換 該当列にNOT NULL制約を適用。 MariaDB側に、同一レイアウトのテーブルを新規作成。参照制約も実装。 MariaDBのODBCドライバをインストールし、対象のMariaDBをODBC登録。 AccessのリンクテーブルとしてMariaDBのテーブルを登録 AccessのテーブルからMariaDBのテーブルにデータを流し込む(INSERT SELECT)クエリを作成、初回の移行を行う。 参照整合性制約から、移行可能な順番がはっきりする。 MariaDBのデータに対してアクセスするフロントプログラムを作成する。 移行後のテーブルレイアウトそのものでプログラムの動作検証が可能。 フロントプログラムの作成が完了したら、MariaDBの全データをTruncateしてデータの本番移行を行う。 データ移行の逆順で実行しても参照整合性制約からデータを削除できない場合がある。素直に参照整合性制約を一時削除し、データの削除完了後に再度作成する。 テーブル名や列名にスペースやマルチバイト文字が入ってて命名規則を満たしていない、明らかに数量データなのに文字列型になっている…といった問題はこれ以降にじっくりリファクタリングしていく。上記の手順とリファクタリングを同時に行うのはリスクが大きい。

<span title='2018-08-19 00:00:00 +0900 +0900'>August 19, 2018</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;tack41

CentOS7のDocker構築ではまったこと

storage driverがdevice mapperの場合のディスク容量 device mapperの場合は、既定のディスク容量が10GBほどとなる。Oracle DatabaseのDockerコンテナをbuildするとこける。 storage driverを最初からoverlay2 にするための方法 インストール時にデバイスタイプにLVMを指定すると、Dockerのstorage dirverはdevice mapperになる。 https://docs.docker.com/storage/storagedriver/select-storage-driver/#supported-backing-filesystems 基本ディスクを選んで、xfsを選んでやる必要がある。 さらに、CentOS7 1511(minimal)の場合は上記の手順でもやはりdevice mapperが既定となる。overlayを使用するための設定がされていないためと想像される。 https://docs.docker.com/storage/storagedriver/overlayfs-driver/ CentOS7 1804(minimal)で基本ディスク(xfs)でインストールすれば、overlay2がstorage driverとして設定される。

<span title='2018-08-16 00:00:00 +0900 +0900'>August 16, 2018</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;tack41

箱入り娘のプログラムを書いて思う

実家に帰った際に箱入り娘のパズルがあったのでやっていた。 https://ja.m.wikipedia.org/wiki/%E7%AE%B1%E5%85%A5%E3%82%8A%E5%A8%98_(%E3%83%91%E3%82%BA%E3%83%AB) 全然解けなかったが、プログラムで力技で解きたいと思い、やってみた 結論として、解けずに終わった。 Pythonで再帰関数で解こうとして、再帰呼び出しの上限に引っかかって30sほどでエラーとなった。 将棋などと比較すると取ることができる手ににかなりきつい制限があるので、全探索余裕と思ってしまったのだが、完全に間違っていた。 一応、盤面を都度記録し、同じ盤面になったらそれ以上は探索しないようにしたのだが、それでも解空間は大きかった。 まず、再帰による解法の選択について。現代のプログラムにおいては、上限の大きさは違えど再帰呼出の階数には制限がある。ので、対象としている問題で想定される階数に比較してプログラミング言語の制約が十分かどうか判断しなければいけなかった。あるいは、階数をパラメータとして保持しておき、起動時に何階層まで探索するか指定するような形にすればよかった。 再帰ではなく、盤面をメモリかファイルに記録し、都度記録から次の盤面を探してスタックを使用しない形にしても良かった。 そもそも論で行くと、パズルは頭の体操として娯楽としてあるもので、力技で解くことに意味あるのか? というのもある。 今回は、初めてPythonを使って割としっかりとしたプログラムが書けたので、練習として良かったということにした。

<span title='2018-08-15 00:00:00 +0900 +0900'>August 15, 2018</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;tack41

Excelで「このワークシート内にある1つ以上の式の参照に問題が見つかりました」

Excelで解決がとてもめんどくさいエラー。 このワークシート内にある1つ以上の式の参照に問題がみつかりました。数式内のセル参照、範囲名、定義名、および他のブックへのリンクがすべて正しいことをご確認ください。 Excel 2013で発生し、どう考えても参照する箇所がなくなるくらい該当シート、セルを削除しても保存のたびにエラーが出る。 で、一旦保存して終了して開き直すと出なくなることも… 全てではないのだが、エラー箇所を修正しても保存して開き直すまでエラーが出続けることがあるらしい… そもそも、エラーを出すのだからそのエラー箇所を素直に指摘してくれよと思うのだが…

<span title='2018-08-03 00:00:00 +0900 +0900'>August 3, 2018</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;tack41

64bit OSでのレジストリ操作時の注意事項

http://tack41tu.hatenablog.com/entry/2018/07/30/214927 でClickOnceアプリをインストールする際にレジストリを編集する必要がある事を書いた。 レジストリエディタで編集するのは面倒だし運用も大変なので、レジストリを編集するアプリを作成した。 https://msdn.microsoft.com/en-us/library/ee308453.aspx にある以下のコードを書いて実行し、正常終了するのだがレジストリエディタで確認すると変更が反映されておらず、ClickOnceの動作も変わらない。 Microsoft.Win32.RegistryKey key; key = Microsoft.Win32.Registry.LocalMachine.CreateSubKey("SOFTWARE\\MICROSOFT\\.NETFramework\\Security\\TrustManager\\PromptingLevel"); key.SetValue("LocalIntranet", "Enabled"); key.Close(); どうもレジストリは32bit, 64bitで別の領域らしく、プログラム作成時にターゲットCPUをAnyとし、x86優先とした結果、32bitの領域を更新してしまっているらしい。 https://aonasuzutsuki.hatenablog.jp/entry/2015/12/08/173819 を参考に以下のように記載したところ、想定通りに動作するようになった。 Microsoft.Win32.RegistryKey key_base, key; key_base = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); var key = prerKey.CreateSubKey("SOFTWARE\\MICROSOFT\\.NETFramework\\Security\\TrustManager\\PromptingLevel",); key.SetValue("LocalIntranet", "Enabled"); key.Close();

<span title='2018-07-30 02:00:00 +0900 +0900'>July 30, 2018</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;tack41