2015年11月28日土曜日

パスワード付きzipファイルを簡単に展開する (UNZIP利用)

掲題のとおりです。

unzipツールを利用して、パスワード付きzipファイルを簡単に展開します。

利用用等に応じて加工するとよいかと思います。

【必要ツール】

unzip.exe

以下サイトよりダウンロードできます。
http://gnuwin32.sourceforge.net/packages/unzip.htm

通常であればBinaries (Zip)でよいと思います。
展開されたデータをどこか、適当な場所へ保管します。(私の場合、d:\utility\unzip)


【バッチの作成】

SET unzipdir=d:\utility\unzip\bin\unzip.exe
%unzipdir% -o -P 展開したいパスワードを記載 %1

-oにて強制上書きしています。
-Pの後ろに、パスワードを指定します。


上記バッチファイルを保存後、バッチファイルへzipファイルをドラッグするだけです。


2015年11月25日水曜日

SugarCRMのチーム管理機能はProfessionalから

SugarCRM Community 6.5での確認結果です。

件名で答えが出てしまっていますが、SugarCRMでチーム管理を利用するには
Professionalが必要です。

詳しくはGoogleさんに「SugarCRM チーム管理 Professional」あたりで聞くと
きちんと比較しているサイトが見つかります。

【チーム管理】とは


SugarCRMのマニュアル によると、
「チーム管理オプションは安全な方法でレコードを管理するためにチームとしてユーザをグループ化するために使います。」とあります。
私が求めていた機能には、「取引先毎にチームで参照権限を分けたい」というものがあり、
これを実現できるのが「チーム管理」でした。

実際、チーム管理をきちんとしていけばそれ以上のことも勿論できるのでしょうが
今回必要な最低限の部分がレコードレベルの参照権限でした。


【で?】


結局は、「チーム」という名前のモジュールを追加して、
担当者との関連性を作り、取引先との関連性を作り、
「検索」の条件として使うというレベルで運用を開始することとしました。

レコードレベルの権限をきちっと使えるようになる前に、まずは基本的な機能で
運用をすることの優先度が高かったので、今後拡張するという方針となりました。


【結局は・・・】

件名で答えが出てしまっていますが、きちんと権限を運用するならProfessionalが必要です。
きちんとやらなくても、なんとなくでよいなら、「モジュール」を作ることで似たようなことはできます。


2015年10月30日金曜日

MySQLでWhere句を動的に変更する場合の実装・性能について

パフォーマンス改善が必要となり、Java(MyBatis)に実装されていたSQLのロジックを
分割、MySQLのプロシージャへもっていくことになりました。

MyBatisでは<if>タグやバインド変数#~により
動的にSQL(Where句)を組み立てていたのですが、同様のことを
MySQLで実施しようとすると、動的SQLの組み立てが必要となります。

プロシージャ側で動的SQLを組み立てるには文字列の結合が
必要となり、ソースコードの保守性が著しく低下するため
代替え案がないかを検証した記録を残しておきます。

【考えた代替え案】

Where句にパラメータがブランクかどうかの判断も入れてしまう
例) SELECT * FROM TABLE1 WHERE parameter1 = '' or column1 = parameter1

【先に結論】

Where句内でOrでパラメータ有無を指定しても、動的SQLでSQLを組み立てたときと
性能は変わらない。

【チューニングとしては】


サブクエリの一部を切り出して、テンポラリテーブルへ吐き出すようにして、その後に
そのクエリを利用してデータ取得をするようにしました。
このSQLのチューニングの肝としては、サブクエリが多すぎ、深すぎでMySQLでよく言われる
ところの「サブクエリ遅いよ」に対処した。ということになります。

【検証した内容】

・ダミーテーブルを準備。データは100万件。プライマリ、インデックスはあえて作らない。
・ストアドを2セット用意し、片方はパラメータブランクによるSQL、もう片方は動的SQLとする
・ダミーテーブルのカラム数が2つだと比較差異が出なかったため、カラムを10に
 増やした場合のケースも検証

【実コード】




-- テスト用テーブルの作成
drop table if exists test1;
create table test1 ( k varchar(10) , va varchar(10));

-- テスト用テーブルにデータを作成するプロシージャ
DROP PROCEDURE IF EXISTS test1createsampledate;
delimiter //
CREATE DEFINER=`root`@`localhost` PROCEDURE test1createsampledate()
BEGIN
    declare i decimal(10) default 0;
    while i <= 1000000 do
        insert into test1 values (i,i*10)
                                ,(i+1,(i+1)*10),(i+2,(i+2)*10),(i+3,(i+3)*10),(i+4,(i+4)*10),(i+5,(i+5)*10),(i+6,(i+6)*10),(i+7,(i+7)*10),(i+8,(i+8)*10),(i+9,(i+9)*10)
                                ,(i+11,(i+11)*10),(i+12,(i+12)*10),(i+13,(i+13)*10),(i+14,(i+14)*10),(i+15,(i+15)*10),(i+16,(i+16)*10),(i+17,(i+17)*10),(i+18,(i+18)*10),(i+19,(i+19)*10)
                                ,(i+21,(i+21)*10),(i+22,(i+22)*10),(i+23,(i+23)*10),(i+24,(i+24)*10),(i+25,(i+25)*10),(i+26,(i+26)*10),(i+27,(i+27)*10),(i+28,(i+28)*10),(i+29,(i+29)*10)
                                ,(i+31,(i+31)*10),(i+32,(i+32)*10),(i+33,(i+33)*10),(i+34,(i+34)*10),(i+35,(i+35)*10),(i+36,(i+36)*10),(i+37,(i+37)*10),(i+38,(i+38)*10),(i+39,(i+39)*10)
                                ,(i+41,(i+41)*10),(i+42,(i+42)*10),(i+43,(i+43)*10),(i+44,(i+44)*10),(i+45,(i+45)*10),(i+46,(i+46)*10),(i+47,(i+47)*10),(i+48,(i+48)*10),(i+49,(i+49)*10)
                                ,(i+51,(i+51)*10),(i+52,(i+52)*10),(i+53,(i+53)*10),(i+54,(i+54)*10),(i+55,(i+55)*10),(i+56,(i+56)*10),(i+57,(i+57)*10),(i+58,(i+58)*10),(i+59,(i+59)*10)
                                ,(i+61,(i+61)*10),(i+62,(i+62)*10),(i+63,(i+63)*10),(i+64,(i+64)*10),(i+65,(i+65)*10),(i+66,(i+66)*10),(i+67,(i+67)*10),(i+68,(i+68)*10),(i+69,(i+69)*10)
                                ,(i+71,(i+71)*10),(i+72,(i+72)*10),(i+73,(i+73)*10),(i+74,(i+74)*10),(i+75,(i+75)*10),(i+76,(i+76)*10),(i+77,(i+77)*10),(i+78,(i+78)*10),(i+79,(i+79)*10)
                                ,(i+81,(i+81)*10),(i+82,(i+82)*10),(i+83,(i+83)*10),(i+84,(i+84)*10),(i+85,(i+85)*10),(i+86,(i+86)*10),(i+87,(i+87)*10),(i+88,(i+88)*10),(i+89,(i+89)*10)
                                ,(i+91,(i+91)*10),(i+92,(i+92)*10),(i+93,(i+93)*10),(i+94,(i+94)*10),(i+95,(i+95)*10),(i+96,(i+96)*10),(i+97,(i+97)*10),(i+98,(i+98)*10),(i+99,(i+99)*10)
                                ;
    set i = i + 100;
    end while;
END;
//
DELIMITER ;

-- テスト用データの作成
call test1createsampledate();

-- テストデータ内容の確認
select count(*) from test1;
select * from test1 limit 0,100;


-- パラメータ=''を条件に使う
DROP PROCEDURE IF EXISTS getk;
delimiter //
CREATE DEFINER=`root`@`localhost` PROCEDURE getk( p_k varchar(10) , p_va varchar(10))
BEGIN
    SELECT * FROM test1
    WHERE k = p_k and ((p_va = '') OR va = p_va);
END;
//
DELIMITER ;

-- パラメータを元にSQLを組み立てる
DROP PROCEDURE IF EXISTS getk2;
delimiter //
CREATE DEFINER=`root`@`localhost` PROCEDURE getk2( p_k varchar(10) , p_va varchar(10))
BEGIN
    declare query varchar(4000);
    set query = CONCAT('SELECT * FROM test1 WHERE k = "' , p_k , '"');
    if (p_va <> '') THEN
        set query = CONCAT(query,' and va = "' , p_va , '"');
    end if;

    select query into @qry;
    PREPARE ddl_stmt from @qry;
    EXECUTE ddl_stmt;
    DEALLOCATE PREPARE ddl_stmt;

END;
//
DELIMITER ;

call getk('1','');
call getk2('1','');


-- 比較にならなそうなのでカラムを増やす
alter table test1 add va2 varchar(10);
alter table test1 add va3 varchar(10);
alter table test1 add va4 varchar(10);
alter table test1 add va5 varchar(10);
alter table test1 add va6 varchar(10);
alter table test1 add va7 varchar(10);
alter table test1 add va8 varchar(10);
alter table test1 add va9 varchar(10);

-- ダミーデータをセット
update test1 set
    va2 = va
   ,va3 = va
   ,va4 = va
   ,va5 = va
   ,va6 = va
   ,va7 = va
   ,va8 = va
   ,va9 = va
;

-- パラメータ=''を条件に使う
DROP PROCEDURE IF EXISTS getk_v2;
delimiter //
CREATE DEFINER=`root`@`localhost` PROCEDURE getk_v2( p_k varchar(10) , p_va varchar(10),p_va2 varchar(10),p_va3 varchar(10),p_va4 varchar(10),p_va5 varchar(10),p_va6 varchar(10),p_va7 varchar(10),p_va8 varchar(10),p_va9 varchar(10))
BEGIN
    SELECT * FROM test1
    WHERE k = p_k
        and ((p_va = '')  OR va  = p_va)
        and ((p_va2 = '') OR va2 = p_va2)
        and ((p_va3 = '') OR va3 = p_va3)
        and ((p_va4 = '') OR va4 = p_va4)
        and ((p_va5 = '') OR va5 = p_va5)
        and ((p_va6 = '') OR va6 = p_va6)
        and ((p_va7 = '') OR va7 = p_va7)
        and ((p_va8 = '') OR va8 = p_va8)
        and ((p_va9 = '') OR va9 = p_va9)
    ;
END;
//
DELIMITER ;

-- パラメータを元にSQLを組み立てる
DROP PROCEDURE IF EXISTS getk2_v2;
delimiter //
CREATE DEFINER=`root`@`localhost` PROCEDURE getk2_v2( p_k varchar(10) , p_va varchar(10),p_va2 varchar(10),p_va3 varchar(10),p_va4 varchar(10),p_va5 varchar(10),p_va6 varchar(10),p_va7 varchar(10),p_va8 varchar(10),p_va9 varchar(10))
BEGIN
    declare query varchar(4000);
    set query = CONCAT('SELECT * FROM test1 WHERE k = "' , p_k , '"');
    if (p_va <> '') THEN
        set query = CONCAT(query,' and va = "' , p_va , '"');
    end if;
    if (p_va2 <> '') THEN
        set query = CONCAT(query,' and va2 = "' , p_va2 , '"');
    end if;
    if (p_va3 <> '') THEN
        set query = CONCAT(query,' and va3 = "' , p_va3 , '"');
    end if;
    if (p_va4 <> '') THEN
        set query = CONCAT(query,' and va4 = "' , p_va4 , '"');
    end if;
    if (p_va5 <> '') THEN
        set query = CONCAT(query,' and va5 = "' , p_va5 , '"');
    end if;
    if (p_va6 <> '') THEN
        set query = CONCAT(query,' and va6 = "' , p_va6 , '"');
    end if;
    if (p_va7 <> '') THEN
        set query = CONCAT(query,' and va7 = "' , p_va7 , '"');
    end if;
    if (p_va8 <> '') THEN
        set query = CONCAT(query,' and va8 = "' , p_va8 , '"');
    end if;
    if (p_va9 <> '') THEN
        set query = CONCAT(query,' and va9 = "' , p_va9 , '"');
    end if;

    select query into @qry;
    PREPARE ddl_stmt from @qry;
    EXECUTE ddl_stmt;
    DEALLOCATE PREPARE ddl_stmt;

END;
//
DELIMITER ;

-- 項目1つ
call getk_v2('1','','','','','','','','','');
call getk2_v2('1','','','','','','','','','');

-- 項目2つ。
call getk_v2('1','','','','','','','','','');
call getk_v2('1','10','','','','','','','','');
call getk_v2('1','','10','','','','','','','');
call getk_v2('1','','','10','','','','','','');
call getk_v2('1','','','','10','','','','','');
call getk_v2('1','','','','','10','','','','');
call getk_v2('1','','','','','','10','','','');
call getk_v2('1','','','','','','','10','','');
call getk_v2('1','','','','','','','','10','');
call getk_v2('1','','','','','','','','','10');

call getk2_v2('1','','','','','','','','','');
call getk2_v2('1','10','','','','','','','','');
call getk2_v2('1','','10','','','','','','','');
call getk2_v2('1','','','10','','','','','','');
call getk2_v2('1','','','','10','','','','','');
call getk2_v2('1','','','','','10','','','','');
call getk2_v2('1','','','','','','10','','','');
call getk2_v2('1','','','','','','','10','','');
call getk2_v2('1','','','','','','','','10','');
call getk2_v2('1','','','','','','','','','10');

-- 結果どのフィールドで検索してもどちらで実装しても処理結果は変わらない


2015年6月3日水曜日

Google Location Historyが記録されなくなっていた件について

自己解決したのですが、数週間のあいだLocationHistoryが記録されなくなっていました。

結果としては、自分で設定をOffにした。(のだろう・・・)


対処法はこちら。
https://support.google.com/gmm/answer/3118687?hl=ja


【Googleヘルプからの転載】
Google 設定でロケーション履歴をオンまたはオフにする

端末のアプリメニューで [Google設定] アプリ  または [設定] メニュー  を開きます。
変更対象のアカウントで [位置情報] > [Googleロケーション履歴] をタップします。
アカウントまたは端末に対して、ロケーション履歴をオンまたはオフにします。
Google アカウント: 一番上のスイッチで、Google アカウントに関連付けられたすべての端末でロケーション履歴をオンまたはオフにします。
端末のみ: 一覧に表示されている端末の横にあるスイッチで、その端末でのみロケーション履歴をオンまたはオフにします。



GoogleLocationHistoryサービスはこちら
https://maps.google.com/locationhistory/b/0

2015年5月15日金曜日

Redmineにプラグインを追加する

[redmine_home]/pluginsフォルダへ、公開されているプラグインをコピー

Redmineを再起動

Redmineにテーマを反映する

Redmineにはテーマを変更できる機能があります。
テーマはネット上で色々な方が公開していますので、
今回はそれを反映する手順をメモしておきます。

●設定場所
 「管理」⇒「表示」⇒「テーマ」から選択

●任意のカスタムテーマを設定
 
公式サイト説明:http://redmine.jp/guide/HowTo_create_a_custom_Redmine_theme/

public/themes以下に、テーマを保存すると、選択できるようになります。
サブディレクトリ名がそのままテーマ名となります。

今回は、farend_fancyというテーマを利用させて頂くことにしました。


●手順
 public/themesフォルダへ移動
 git clone https://github.com/farend/redmine_theme_farend_fancy

 コピーが完了した後、「管理」⇒「表示」画面を開くと、テーマに
 追加した内容が反映されていますので、選択「保存」で完了です。


2015年4月4日土曜日

EC-CUBEをLinux(CentOS)環境へインストールする

EC-CUBEとは、オープンソースで公開されている日本発のECサイトです。

https://www.ec-cube.net/


PHPで書かれており、自由に改変ができるほか、もともとの機能も充実しているようです。

ひとまず試してみようと思い、稼働中のCentOSにインストールしたので、手順をメモしておきます。


ソフトウェアのダウンロード


EC-CUBEの公式サイトより、対象ソフトウェアをダウンロードします。
この時点では、2.1.3でした。
Linuxなので、tar.gzを選び、ダウンロードします。


対象サーバーへのアップロード


dataフォルダとhtmlフォルダをアップロードします。
今回は、/var/www/myapp/ecc/としました。

apacheへのパス通し

Alias /eccmock/ "/var/www/myapp/ecc/html/"
<directory ecc="" html="" myapp="" var="" www="">
    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</directory>



権限変更


cd /var/ww/myapp

ecc2133

chown -R ecc/


mysqlデータベースの作成


create database eccube_db CHARACTER SET utf8 COLLATE utf8_unicode_ci;
CREATE USER 'eccube_db_user'@'localhost' IDENTIFIED BY 'passwordchar';
GRANT ALL PRIVILEGES ON eccube_db.* TO 'eccube_db_user'@'localhost' IDENTIFIED BY 'passwordchar';

インストール手順に従い実行


あとは、インストール画面を開き、画面の手順に従って進めると完了です。


はまった点。


リバースプロキシ運用をしていたので、インストール画面で求められる「サイトURL」に、実URLを指定してはまりました。
リバースプロキシを経由した時点で、ドメインはLOCALのIPに変換されるため、「サイトURL」は、LOCAL IPが正解でした。

おまけ


2015年1月22日木曜日

HttpWebResponseオブジェクトを使ってループすると、無応答になってしまった現象について (IDispose)

リソース確保したら、解放しましょう。という備忘録です。

複数のサーバーにあるサービスのHTTPステータスを監視したいと思い、
表をループで処理する仕組みを作っていました。

未試験ですが、ざっと以下のようなコードです。

実装時、無応答になることがあったので、もしやと思い、Disposeのコードを追加。

さらっと、流れました。

確か、HTTPだと同時通信数が決まってましたよね。
IDisposeインターフェースを持つオブジェクトは、終わったらきちんと破棄しようと思いました。



    System.Data.DataTable dt;
    if (this.dataGridView1.DataSource != null)
    {
        dt = (System.Data.DataTable)this.dataGridView1.DataSource;

        foreach (DataRow dr in dt.Rows)
        {
            HttpWebResponse res = null;
            try
            {
                res = null;
                req = WebRequest.Create(new Uri(dr["LOGIN_URL"].ToString())) as HttpWebRequest;
                res = (HttpWebResponse)req.GetResponse();
                dr["STATUS"] = res.StatusCode.ToString();
                res.Dispose();
            }
            catch (WebException ex)
            {
                //HTTPプロトコルエラーかどうか調べる
                if (ex.Status == System.Net.WebExceptionStatus.ProtocolError)
                {
                    System.Net.HttpWebResponse errres = (System.Net.HttpWebResponse)ex.Response;

                    dr["STATUS"] = errres.StatusCode;
                } 
            }
            finally
            {

            }
        }
        dt.AcceptChanges();
    }



2015年1月20日火曜日

flickrを使いこなそう(他の人との共有)

flickrには画像共有の機能があります。

あらかじめ友達登録をしておくと、その人はいつでも見れるようになります。

ただ、友達側にもアカウントが必要なのでちょっと面倒くさい。

そんなときのために、ぱっと共有できる仕組みがありました。


https://www.flickr.com/gp/knkryo/Y2hr05/

アルバムを選択
画面右側にある、□に外向き矢印のアイコンをクリック
Grab the linkを選択
表示されるURLを、誰かに送る。

リンクを削除したい時にはGuestPasshistoryをクリックして
該当のリンクでExpireを選択

Chrome リモート デスクトップの精度が高いです。

業務クラウドのヘルプデスク体制を考えていた際に
ひょんなところから「Chrome リモート デスクトップ」というアプリを
見つけました。

能書きともかく、まず使ってみようという事でインストール。
使い勝手としては上々でしたので、iDisplayでの画面ミラーと併せて
使っていきたいと思います。


使ってみた感じ

Androidタブレット (LTE) から、LAN環境のパソコンを操作してみました。
遅延等はあまり感じませんでした。

・タブレットのタップが、マウスクリックになる。
・パソコン側がデュアルディスプレイでも、きちんと認識する。(私の場合、トリプルディスプレイですが)

私の場合には自分のパソコンの画面を見せたいシチュエーションが結構あったりするので
それだけでも、利用価値十分な感じです。

以下に、インストールして利用するまでの概略をまとめておきます。

1.Google Chromeをインストール

私の場合には既にインストールされていたので端折りますが、
Google Chromeで検索すれば、インストールのサイトへ行けると思いますので
そちらでインストールしてください。



2.ブラウザ拡張機能をインストール

Googleウェブストアからインストールします。
URLは変わるかもしれませんが、記事作成時は「こちら」でした。

3.ブラウザ拡張機能を起動

Google Chromeの、左上にある「アプリ」のアイコンを選択後、
「Chrome リモート」を選択すると、画面が開きます。
「アプリ」のアイコンが出ていない場合には、タブの「+」を押してみてください。




リモートの利用方法は、「不特定多数の誰か」と、「自分だけ」の2通りあるようです。

4.リモートサポート


よくある、パソコン間のリモート機能です。
不特定多数によるリモートで、「アクセスコード」を利用して認証を行います。

初回のみ、拡張ソフトウェアのインストールを求められます。

接続されたいパソコン上で「共有」ボタンを押すとアクセスコードが出てきます。



接続するパソコンでは「アクセス」ボタンを押して、その後、接続したいパソコンで
表示されているアクセスコードを入力します。


5.マイパソコン


自分のパソコンをgoogleアカウントに紐づける機能です。

これを設定した後に、AndroidアプリからPINを入力すると
AndroidアプリからPCを操作できるようになります。


まとめ

私的には今後のメインツールになりそうです。
Google.Inc提供のツールなので、Googleのサービスポリシーに則って使う事が
できそうです。

Google製というと、ハングアウトなんてチャットツールもあるので、
業務クラウドシステムのサポートインフラをGoogle製品で作成できるかなと思いました。


その他雑記

iOS (iPhone)でもアプリがあるようです。MacでもOKとのこと。(未検証です


2015年1月19日月曜日

Excel活用術 Tips (INDIRECT,SheetName列挙)

IT関係の仕事に勤めていると、Excelの手軽さって、あまり業務に活用されないのですが、
改めて使ってみると、大変便利なツールだなと、日々感じています。

⇒いわゆる業務システムだと、Excelの柔軟さが仇となったりするので、
 きっちりした業務がお好みのお客様には使えないのです。

ワークブックのシート名を列挙する


○名前の管理にて、以下関数を埋め込み。 (ここでは例として、名前をSheetNamesとします)

=IF(GET.WORKBOOK(4)>=ROW(),MID(INDEX(GET.WORKBOOK(1),ROW()),FIND("]",INDEX(GET.WORKBOOK(1),ROW()))+1,31)&T(NOW()),"")

○どこかのセルに、=SheetNames と記述

これだけで、シート名が出ます。
縦に並べて貼り付けると、シート名一覧の出来上がり。
※ネットで拾った情報の備忘録です。(MARBIN)さん、ありがとうございます。



別シートの参照





=IF(INDIRECT("'参照シート'!A1")="","",INDIRECT("'参照シート'!A1"))

別のシート名を動的に指定して、実装する例です。
これを、先ほどのワークシート名列挙と合わせると、全部とれたりします。

シート名をシングルクォーテーションで括ることを忘れないでください。


上記を組み合わせた使い方


=INDIRECT("'"&C3&"'!AU4")

シート名を動的に参照し、値を表示しています。
シート名列の横に並べれば、動的に全シートの指定値が取得できます。


ちょっと注意事項

関数をあれやこれや活用すると、ものすごく便利なのは確かですが、
エクセルを開いた際、または、初回に関数が評価されるときなどには
たくさんの処理が動き、かたまった状態に見える事も出てきます。

適切に使いたい分だけを使う、時には疎結合 (ブック間のリンクなど )も
意識して使うことも大事になります。


2015年1月7日水曜日

Oracleで、テーブルスペースを切り替える

今使っているtablespaceを切り替える必要が出てきたので
実施内容を纏めておきます。

データファイル名、テーブルスペース名、テーブル名などは実環境に読み替えてください。


手順概略

1.新しいテーブルスペースを作成
2.データを、新しいテーブルスペースへ移動
3.インデックスを、新しいテーブルスペースへ移動
4.ユーザーのデフォルト表領域を新しいテーブルスペースへ移動

手順

1.新しいテーブルスペースの作成

CREATE TABLESPACE "tablespacename";
DATAFILE 'D:\ORADATA\ORCL\"tablespacename";_xxx.DBF' SIZE 10240M AUTOEXTEND ON NEXT 100M MAXSIZE UNLIMITED
/


2.データを、新しいテーブルスペースへ移動

ALTER TABLE <tablename> MOVE TABLESPACE "tablespacename";

3.インデックスを新しいテーブルスペースへ移動

ALTER INDEX <indexname> REBUILD TABLESPACE "tablespacename";

4.ユーザーのデフォルトテーブルスペースを変更

alter user <username> default tablespace "tablespacename";


別アプローチとして、一旦exportして、drop user , createuserでテーブルスペースを変更 , impでテーブルスペース指定なんてこともできそうです。
→今回はデータベースの移行だったので、こちらを採用しました。

2015年1月6日火曜日

TortoirseSVNのアイコンが変わらなくなった件への対処法

今まで利用していたパソコンが、2年を経過し動きが不安定になってきたので
OS環境から再構築しなおしたところ、TortoirseSVNの状態アイコンが表示されなく
なってしまいました。

原因

アイコンオーバーレイの上限に達したようです。
Microsoft公式の情報は残念ながら見つかりませんでしたが、
15個 (そのうち4個はシステムが利用) が上限という仕様のようです。

アイコンオーバーレイって?

通常のアイコンの上に、さらに画像を重ねて見せる仕組みです。

TortoirseSVNのみならず、DropboxやGoogleDriveなど、
クラウド系アプリには結構使われています。

状態を確認してみました。

ShellExViewというツールを使って確認してみました。

レジストリを直接確認しても良いようです。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers


http://www.nirsoft.net/utils/shexview.html



DropBoxが 8個 GoogleDriveが5個 TortoirseSVNが9個となっていました。

このツール上から、「有効」「無効」を切り替えられるので、DropBoxとGoogleDriveの状態を
「無効」へ変更しました。

【変更後】



レジストリ周りの変更を行ったので、一旦ログオフして、再度ログインする事で
設定した結果が反映されました。

2015年1月5日月曜日

簡単にhtmlファイルの取得解析を行う方法 (.net)

一昔前であれば、HttpWebRequestなどを利用して自前でhttp通信を確立して
文字データを取得して、その後加工。なんて方法しか思い浮かばなかったのですが
今ではライブラリも相当充実し、簡単な記述でhtmlファイルを操作できるようになっていました。

SGMLReader

https://www.nuget.org/packages/SgmlReader/

これ以外にもライブラリはあると思いますが、個人的にはこれで十分。

HTML規格のベースであるSGMLのライブラリなので、DOM操作も容易です。

実装


using System.Xml.Linq;
using Sgml;

public System.Xml.Linq.XDocument getXml(string url)
{
  XDocument xml;
  using (var sgml = new SgmlReader() { Href = url })
  {
    sgml.IgnoreDtd = true; // DTDがなくても読み込みを続行する
    xml = XDocument.Load(sgml); // たった3行でHtml to Xml
  }
  return xml;

}

Linq To Xml

汚いコードですが、ご参考に。queryを作ってeachで抜いてDataTableへ入れています。


System.Data.DataTable dt = new System.Data.DataTable();

dt.Columns.Add("DATE", System.Type.GetType("System.String"));

dt.Columns.Add("StartValue", System.Type.GetType("System.String"));

dt.Columns.Add("MaxValue", System.Type.GetType("System.String"));

dt.Columns.Add("MinValue", System.Type.GetType("System.String"));

dt.Columns.Add("EndValue", System.Type.GetType("System.String"));

System.Xml.Linq.XDocument xml = getXml(url);

var ns = xml.Root.Name.Namespace;

var query = xml.Descendants(ns + "table").Last()
.Descendants(ns + "tr")
.Skip(1) // テーブル一行目は項目説明なので飛ばす
.Select(ee => ee.Elements(ns + "td").ToList())
.Select(es => new
{
  Date = es.First().Value,
  StartValue=es.Skip(1).First().Value,
  MaxValue = es.Skip(2).First().Value,
  MinValue = es.Skip(3).First().Value,
  EndValue = es.Last().Value
});
foreach ( var rec in query)
{
 System.Data.DataRow dr;
 dr = dt.NewRow();
 dr["DATE"] = rec.Date;
 dr["StartValue"] = rec.StartValue;
 dr["MaxValue"] = rec.MaxValue;
 dr["MinValue"] = rec.MinValue;
 dr["EndValue"] = rec.EndValue;
 dt.Rows.Add(dr);
}

その他

SGMLReaderは、NuGetにて取得できます。