MySQL のストアドプロシージャで日付ディメンションテーブルをつくる

--
-- 日付ディメンションテーブル
--
drop table if exists dates;

create table dates (
id integer primary key auto_increment,
date date,
year integer,
month integer,
day integer,
week integer,
index date(date),
index year(year),
index month(month),
index day(day),
index week(day)
);



<pre class="prettyprint">drop procedure if exists update_dates_table;

delimiter //
create procedure update_dates_table()
begin
declare currentdate date default ‘2008-12-01’;
truncate dates;
while currentdate <= curdate() do
insert into dates(date, year, month, day, week)
values(
currentdate,
year(currentdate),
month(currentdate),
day(currentdate),
week(currentdate, 0)
);
set currentdate = date_add(currentdate, interval 1 day);
end while;
end
//
delimiter ;
</pre>

メールフォームで受けたアンケートを DB に保存する

MODx の eForm から eform2db のような手法で直接 DB

に入れようと思っていたが、ビジネス上の都合で叶わず、メールで受け取ることになった。まあ、そんなにアンケートに答えてくれる人がいるわけじゃないから、いいでしょ。と思っていたら大量のメールが送られていた。あら~。



<p>仕方がないので、メールを読み取って DB に格納することにした。</p>

<pre class="prettyprint">#!/usr/bin/ruby

# ■ 使い方
#
# 引数にメールファイル名を渡す。1メール1ファイル。
# ruby ./mail2db.rb mail/*
#
# すると、DB に格納される。
#
# ■ メール本文の形式
#
# —– ここから —–
# アンケートへの回答がありました♪
#
# 日時: 15-05-2009 14:07:27
# おなまえ:xxxx
# メールアドレス:xxxxx@xxx.com
# 参加可能日時:0523_1000, 0530_1000
# 利用頻度:8-19
# きっかけ:きっかけきっかけきっかけきっかけきっかけきっかけきっかけ
# きっかけきっかけきっかけきっかけきっかけきっかけきっかけきっかけ。
# 要望:ようぼうようぼうようぼうようぼうようぼうようぼうようぼうようぼう。
# —– ここまで —–
#

require ‘date’
require ‘parsedate’
require ‘rubygems’
require ‘tmail’
require ‘dbi’

def process_files(files, dbh)
converter = Iconv.new(‘SHIFT_JIS’, ‘UTF-8’)
files.each { |file|
raw_email = File.open(file, ‘r’) { |f| @mail = f.read }
email = TMail::Mail.parse(raw_email)
enquete = parse(email.body)
save(enquete, dbh)
puts enquete[:postdate]
}
end

def parse(body)
result = {}

# 改行されている項目をつなげる
lines = []
item = nil
body.each_line { |line|
line.chomp!
if (line.index(“:”))
if item
lines « item # 前の項目があるなら lines に保存する
end
item = line # 新しい項目をみつけた
else
if item
item « line # この行は前の項目の続き
end
end
}
lines « item # 最後の項目
lines.each { |line|
elements = line.split(‘:’)
if elements.size == 2
value = elements[1]
case elements[0]
when ‘日時’
result[:postdate] = value
when ‘おなまえ’
result[:nickname] = value
when ‘メールアドレス’
result[:email] = value
when ‘参加可能日時’
result[:candidate_dates] = value
when ‘利用頻度’
result[:frequency] = “’” + value # ‘ はエクセル対策
when ‘きっかけ’
result[:kikkake] = value
when ‘要望’
result[:youbou] = value
end
end
}
return result
end

def save(enquete, dbh) dbh.do(«EOF, enquete[:postdate],
enquete[:nickname], enquete[:email], enquete[:candidate_dates],
enquete[:frequency], enquete[:kikkake], enquete[:youbou])
insert into
test.enquetes(
postdate,
nickname,
email,
candidate_dates,
frequency,
kikkake,
youbou
)
values(?, ?, ?, ?, ?, ?, ?)
EOF
end

files = ARGVdbh =
DBI.connect(‘dbi:Mysql:database=test;host=localhost;mysql_read_default_file=/etc/my.cnf’,
‘test’, ‘passwd’)
process_files(files, dbh)
</pre>

CentOS5 に mechanize をインストールした

# gem install mechanize
Building native extensions. This could take a while...
Successfully installed nokogiri-1.2.1
Successfully installed mechanize-0.9.2
2 gems installed
Installing ri documentation for nokogiri-1.2.1...
Installing ri documentation for mechanize-0.9.2...
Installing RDoc documentation for nokogiri-1.2.1...
Installing RDoc documentation for mechanize-0.9.2...



<ul><li>libxml2 が無いといわれる場合、libxml2, libxml2-devel をインストールする。

<pre class="prettyprint">checking for #include <libxml/parser.h>
… no
libxml2 is missing. try ‘port install libxml2’ or ‘yum install libxml2’
(略)

# yum install libxml2 libxml2-devel
</pre></li>

<li>libxslt が無いといわれる場合、libxslt、libxslt-devel をインストールする。

<pre class="prettyprint">checking for #include <libxslt/xslt.h>
… no
libxslt is missing. try ‘port install libxslt’ or ‘yum install libxslt’
(略)

# yum install libxslt libxslt-devel
</pre></li>
</ul>

yum update で yum が落ちる - TypeError: unsubscriptable object

yum update で yum が落ちるときは yum clean metadata で。



0003481: yum install

openmotif22 dies with ‘TypeError: unsubscriptable object’






<pre class="prettyprint">$ sudo yum update
Password:
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirror.nus.edu.sg
* updates: centos.mirror.cdnetworks.com
* addons: mirror.nus.edu.sg
* extras: mirror.averse.net
Setting up Update Process
Resolving Dependencies
–> Running transaction check
—> Package file.i386 0:4.17-15.el5_3.1 set to be updated
—> Package audit-libs-python.i386 0:1.7.7-6.el5_3.3 set to be updated
—> Package audit.i386 0:1.7.7-6.el5_3.3 set to be updated
—> Package sos.noarch 0:1.7-9.16.el5_3.5 set to be updated
—> Package pango.i386 0:1.14.9-5.el5.centos set to be updated
—> Package audit-libs.i386 0:1.7.7-6.el5_3.3 set to be updated
Traceback (most recent call last):
File “/usr/bin/yum”, line 29, in ?
yummain.user_main(sys.argv[1:], exit_code=True)
File “/usr/share/yum-cli/yummain.py”, line 229, in user_main
errcode = main(args)
File “/usr/share/yum-cli/yummain.py”, line 145, in main
(result, resultmsgs) = base.buildTransaction()
File “/usr/lib/python2.4/site-packages/yum/init.py”, line 647,
in buildTransaction
(rescode, restring) = self.resolveDeps()
File “/usr/lib/python2.4/site-packages/yum/depsolve.py”, line 704,
in resolveDeps
for po, dep in self._checkFileRequires():
File “/usr/lib/python2.4/site-packages/yum/depsolve.py”, line 939,
in _checkFileRequires
if not self.tsInfo.getOldProvides(filename) and not
self.tsInfo.getNewProvides(filename):
File “/usr/lib/python2.4/site-packages/yum/transactioninfo.py”, line
414, in getNewProvides
for pkg, hits in self.pkgSack.getProvides(name, flag, version).iteritems():
File “/usr/lib/python2.4/site-packages/yum/packageSack.py”, line
300, in getProvides
return self._computeAggregateDictResult(“getProvides”, name, flags, version)
File “/usr/lib/python2.4/site-packages/yum/packageSack.py”, line
470, in _computeAggregateDictResult
sackResult = apply(method, args)
File “/usr/lib/python2.4/site-packages/yum/sqlitesack.py”, line 861,
in getProvides
return self._search(“provides”, name, flags, version)
File “/usr/lib/python2.4/site-packages/yum/sqlitesack.py”, line 43, in newFunc
return func(args, **kwargs)
File “/usr/lib/python2.4/site-packages/yum/sqlitesack.py”, line 837,
in _search
for pkg in self.searchFiles(name, strict=True):
File “/usr/lib/python2.4/site-packages/yum/sqlitesack.py”, line 43, in newFunc
return func(
args, **kwargs)
File “/usr/lib/python2.4/site-packages/yum/sqlitesack.py”, line 586,
in searchFiles
self._sql_pkgKey2po(rep, cur, pkgs)
File “/usr/lib/python2.4/site-packages/yum/sqlitesack.py”, line 470,
in _sql_pkgKey2po
pkg = self._packageByKey(repo, ob[‘pkgKey’])
File “/usr/lib/python2.4/site-packages/yum/sqlitesack.py”, line 413,
in _packageByKey
po = self.pc(repo, cur.fetchone())
File “/usr/lib/python2.4/site-packages/yum/sqlitesack.py”, line 68,
in init
self._read_db_obj(db_obj)
File “/usr/lib/python2.4/site-packages/yum/sqlitesack.py”, line 94,
in _read_db_obj
setattr(self, item, _share_data(db_obj[item]))
TypeError: unsubscriptable object
</pre>

MODx の eForm から DB に保存する

MODx の eForm
を使うと、メールフォームが簡単につくれる。しかし、メールではなくてDB保存して、あとでまとめてデータを取得したいということもある。



<p>そういう用途にぴったりな eForm2db というのを見かけた。MODx が備える DBAPI と、eForm
のイベントハンドリングを使った、シンプルな snippet だ。こんなに簡単にできるのか、と喜んだのもつかの間、この snippet
を呼ぶと画面は真っ白、Apache のログにはエラー、DB には何も記録されない、という状態になった。</p>

<p>Apache のエラーログはこのような感じ。</p>

<pre class="prettyprint">
[Fri May 08 04:26:59 2009] [error] [client 10.1.1.231] PHP Fatal error: Call to
undefined function eForm2db() in /home/xxx/public_html/modx-0.9.6.3/assets
/snippets/eform/eform.inc.php on line 377, referer: http://test1.xxx.xxx/~xxx/modx/
</pre>

<p>試行錯誤の結果、snippet の呼び出しを [[snippet]] から [!snippet!]
に変えることで解決した。前者はキャッシュされた結果を用いるが、後者は snippet
をキャッシュせずに毎回実行する。たとえばログインsnippet
があって、未ログインの場合はログインフォームを、ログイン後はユーザー名を表示する場合には、キャッシュしてはいけないので後者を使う。</p>

ページに貼り付けるフォームはこんな感じ。フォーム chunk の直前に eForm2db の snippet
を置く。eFormOnBeforeMailSent で、メール送信前にイベント処理をする。

<pre class="prettyprint">
[!eForm2db!]

[!eForm? &formid=form1 &tpl=form1_tpl
&report=form1_report &thankyou=form1_thankyou
&to=xxx@xxx.xxx &from=xxx@xxx.xxx
&fromname=form1 &subject=form1
&eFormOnBeforeMailSent=eForm2db !]
</pre>

eForm2db snippet はこんな感じ。複数選択のチェックボックスは join で一つの文字列にまとめてみた。RDB
のテーブルは、MODx と同じ DB にあらかじめ作っておく。

<pre class="prettyprint">
<?php
function eForm2db( &$fields ) {
global $modx;

$dbTable = array();

$dbTable[email] = $fields[email];
$dbTable[checkbox1] = join(‘, ‘, $fields[checkbox1]);
$dbTable[hitokoto] = $fields[hitokoto];
$dbTable[postdate] = date( ‘YmdHis’, strtotime( $fields[postdate] ) );

$dbQuery = $modx->db->insert( $dbTable, ‘form1’ );

return true;
}
return ‘’;
?>
</pre>