CentOS5.6にSybase ASE 11.0.3.3とDBD::Sybase 1.14をインストールしてみた
下記の記事を参考に、自宅VMware Player 3.1.5上のCentOS 5.6上に Sybase ASE 11.3.3をインストールしてみた。以下の記事を参考にすればちょっと古いけど無料のSybaseをインストールすることが出来る。
CentOS5.6にSybase ASE 11.0.3.3 ESD#6をインストールしてみた – roshi.tv::blog
で、Perlから使いたのでDBD::Sybase 1.14をインストールしてみようとしたが、単純にCPANからinstall DBD::Sybaseではインストール出来なかったのでメモ。
make test時に日本語設定だと以下のような感じで
t/base……….install_driver(Sybase) failed: Can’t load ‘/root/.cpan/build/DBD-Sybase-1.14/blib/arch/auto/DBD/Sybase/Sybase.so’ for module DBD::Sybase: /opt/sybase/lib/libcomn.so: 再配置後にセグメントprotをリストアできません: 許可がありません at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/DynaLoader.pm line 230.
英語環境だと下のような感じでエラーになる。
# Failed test ‘use DBD::Sybase;’
# in t/autocommit.t at line 18.
# Tried to use ‘DBD::Sybase’.
# Error: Can’t load ‘blib/arch/auto/DBD/Sybase/Sybase.so’ for module DBD::Sybase: /opt/sybase/lib/libcomn.so: cannot restore segment prot after reloc: Permission denied at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/DynaLoader.pm line 230.
調べてみるとSELinuxが動いているとコンパイル時に色々問題が出るらしいのでSELinuxを一時的又は永久に無効にするとコンパイル出来る。
SELinuxを無効化する | Smart -Web Magazine
簡単にメモっておくと
SELinuxの動作状況をチェックするにはgetenforceコマンドを利用する。Enforcingと表示されれば有効な状態。PermissiveまたはDisabledと表示されれば無効な状態。
[root@localhost ~]# getenforce
Enforcing
[root@localhost ~]#
SELinuxの有効無効を切り替えるにはsetenforceコマンドを利用する。引数に1を渡して実行すれば有効。0を渡して実行すれば無効になる。
[root@localhost ~]# setenforce 1
[root@localhost ~]# getenforce
Enforcing
[root@localhost ~]# setenforce 0
[root@localhost ~]# getenforce
Permissive
[root@localhost ~]#
あと、まだ以下の様なエラーでコンパイルやtestで通らない場合がある。
our sybase home directory is /opt/sybase. Check the environment variable SYBASE if it is not the one you want!
Using locale name "ja_JP.UTF-8" defined in environment variable LANG
Locale name "ja_JP.UTF-8" doesn’t exist in your /opt/sybase/locales/locales.dat file
t/autocommit….NOK 2
# Failed test ‘use DBD::Sybase;’
# in t/autocommit.t at line 18.
# Tried to use ‘DBD::Sybase’.
# Error: DBD::Sybase initialize: cs_ctx_alloc(112) failed at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/DynaLoader.pm line 253.
言語設定がちゃんとあってないと動かないみたいなのでとりあえず面倒なのでCにした。
export LANG=Cでとりあえずテストもそれなりに動くようになった。
[root@localhost ~]# export LANG=C
[root@localhost ~]# env
(中略)
LANG=C
(中略)
[root@localhost ~]#
と言ってもすべてのテスト(13/13)にパスしなかったのが
Failed 13/13 test scripts, 0.00% okay. 218/231 subtests failed, 5.63% okay.
以下の様に(3/13)に減って76.92%はパスする様になっただけなのだが
まあ、これだけ動けばなんとかなるでしょ。ということでcpanのシェルから
force install DBD::Sybase
して強制インストールした。
perlからDBI経由でSybaseを使う場合も言語の設定が一致していないと以下の様なエラーんなる。なのでとりあえず面倒なのでというかちょっと色々やってみたけどうまくいかなかったのでとりあえず、export LANG=Cで日本語は使わないようにして利用。とりあえず勉強用なのでこれで妥協。余裕があればちゃんとしたけど古いものなのでutf-8に対応してないっぽいのと、逆にlinux側がデフォではShift_JISに対応していないのでめんどくさい。とりあえず下記のサイトが参考になるかも知れない。
SJISを使えるようにする。 – 明日=今日×(反省+前向き)+努力
[root@localhost sybase]# perl test05.pl
The context allocation routine failed when it tried to load localization files!!
One or more following problems may caused the failure
Your sybase home directory is /opt/sybase. Check the environment variable SYBASE if it is not the one you want!
Using locale name "ja_JP.UTF-8" defined in environment variable LANG
Locale name "ja_JP.UTF-8" doesn’t exist in your /opt/sybase/locales/locales.dat file
DBD::Sybase initialize: cs_ctx_alloc(112) failed at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/DynaLoader.pm line 253.
Compilation failed in require at test05.pl line 2.
BEGIN failed–compilation aborted at test05.pl line 2.
[root@localhost sybase]#
sshでサーバにログインして
/opt/sybase/bin/isql -U<ユーザ名> -P<パスワード> -S<サーバ名>
と言った感じでSybaseにログイン
/opt/sybase/bin/isql -Uzipuser2 -Pxxxxxxxx -SSYBASE -Jsjis
テストでこんなテーブルを作ってみた。
CREATE TABLE test2 (
name char(10),
zip7 char(10),
tel char(15),
flag1 tinyint,
flag2 tinyint,
date smalldatetime,
)
ちなみにSybaseではgoコマンドを入力すると実際にSQLが実行される。下のような感じ
1> select * from test2
2> go
name zip7 tel flag1 flag2 date
———- ———- ————— —– —– ————————–
tanaka yamato@yam 1112222333 1 1 Nov 13 2011 6:58PM
tanaka2 yamato2@ya 22222 2 3 Nov 13 2011 6:58PM
tanaka3 yamato3@ya 3333 3 4 Nov 13 2011 6:58PM
tanaka3 yamato4 3333 3 4 Nov 13 2011 6:59PM
tanaka5 tanaka5@aa 3333 3 4 Nov 13 2011 7:02PM
tanaka6 tanaka6 3333 3 4 Nov 13 2011 7:02PM
(6 rows affected)
1>
とりあえず本当に簡単なストアドを勉強がてらに作成してみる。
CREATE PROCEDURE CursorSelect8 @IN_FLAG TINYINT,@RESULT TINYINT OUTPUT,@R2 TINYINT OUTPUT
AS
BEGIN
begin
SELECT
name,
flag1
FROM
test2
WHERE flag1 = @IN_FLAG
end
begin
select @RESULT = 22
select @R2 = 33
end
return 77
END
単純にTera Term上から貼り付けてた。(最近までずっとPuTTYばかり使ってましたがまた最近Tera Termを触り始めました。いつのまにやらずいぶん進化してた。)
goするとエラーがあれば表示される。
1> CREATE PROCEDURE CursorSelect8 @IN_FLAG TINYINT,@RESULT TINYINT OUTPUT,@R2 TINYINT OUTPUT
2> AS
3> BEGIN
4> begin
5> SELECT
6> name,
7> flag1
8> FROM
9> test2
10> WHERE flag1 = @IN_FLAG
11> end
12> begin
13> select @RESULT = 22
14> select @R2 = 33
15> end
16> return 77
17> END
18> go
1>
実際にストアドを実行すると以下の様になる。
1> declare @result tinyint,@r2 tinyint
2> exec CursorSelect8 1,@result output,@r2 output
3> go
name flag1
———- —–
tanaka 1
(1 row affected, return status = 77)
Return parameters:
— —
22 33
1>
これをDBIを使ってPerlで取得するには下の様なサンプルを書いてみた。(突っ込みどころ満載なのでほんとにサンプルとしてみてね。)
●ソース:test05.pl
use DBI;
use DBD::Sybase;
print "DBD::Sybase = $DBD::Sybase::VERSION\n";
my $user = ‘zipuser2’;
my $passwd= ‘hogehoge’;
my $dbh = DBI->connect("dbi:Sybase:", $user, $passwd);
#my $hst = $dbh->prepare(‘SELECT COUNT(*) FROM test1’);
#my $hst = $dbh->prepare(‘declare @result int exec CursorSelect1 3,@result output’);
my $hst = $dbh->prepare(q/
declare @result tinyint,@r2 tinyint
exec CursorSelect8 3,@result output,@r2 output
/);
my $ret = $hst->execute();
print "ret = $ret\n";
unless($ret){
my $errstr = $dbh->errstr;
$hst->finish;
undef $hst;
$dbh->disconnect;
die "err=".$errstr;
}
while(my $ref = $hst->fetchrow_arrayref){
print "line: type=$hst->{syb_result_type} ".$ref->[0],’ ‘,$ref->[1], ‘ ‘,$ref->[2],"\n";
}
my @results = $hst->syb_output_params();
foreach my $str(@results){
print "result:$str\n";
}
$hst->finish;
$dbh->disconnect;
●実行結果
[kumacchi@localhost sybase]$ perl test05.pl
DBD::Sybase = 1.14
ret = -1
line: type=4040 tanaka3 3
line: type=4040 tanaka3 3
line: type=4040 tanaka5 3
line: type=4040 tanaka6 3
result:22
result:33
[kumacchi@localhost sybase]$
ちゃんとmakeできていないからなのか、古いSybaseとDBDが噛み合ってないのか、そういうものなのかわからないが、syb_output_params()メソッドを使うとストアドのreturnの値77が取得出来なかった。22と23は取得できる。(※output_paramsなのだからやっぱりそういうものなのかな?)
そういうわけで修正してみたのが下。
●ソース:test06.pl
use DBI;
use DBD::Sybase;
print "DBD::Sybase = $DBD::Sybase::VERSION\n";
my $user = ‘zipuser2’;
my $passwd= ‘hogehoge’;
my $dbh = DBI->connect("dbi:Sybase:", $user, $passwd);
#my $hst = $dbh->prepare(‘SELECT COUNT(*) FROM test1’);
#my $hst = $dbh->prepare(‘declare @result int exec CursorSelect1 3,@result output’);
my $hst = $dbh->prepare(q/
declare @result tinyint,@r2 tinyint
exec CursorSelect8 3,@result output,@r2 output
/);
my $ret = $hst->execute();
print "ret = $ret\n";
unless($ret){
my $errstr = $dbh->errstr;
$hst->finish;
undef $hst;
$dbh->disconnect;
die "err=".$errstr;
}
{
while(my $ref = $hst->fetchrow_arrayref){
print "line: type=$hst->{syb_result_type} ".$ref->[0],’ ‘,$ref->[1], ‘ ‘,$ref->[2],"\n";
}
redo if $hst->{syb_more_results};
}
#my @results = $hst->syb_output_params();
#foreach my $str(@results){
# print "result:$str\n";
#}
$hst->finish;
$dbh->disconnect;
肝は
redo if $hst->{syb_more_results};
の部分、これでちゃんとreturn 77の値も取得できた。
[kumacchi@localhost sybase]$ perl test05.pl
DBD::Sybase = 1.14
ret = -1
line: type=4040 tanaka3 3
line: type=4040 tanaka3 3
line: type=4040 tanaka5 3
line: type=4040 tanaka6 3
line: type=4043 77
line: type=4042 22 33
[kumacchi@localhost sybase]$
■参考
DBD::Sybase – DBIモジュールのためのSybaseデータベース・ドライバ 【perldoc.jp】
■その他
#ちょっと調べた感じではSybase ASE 11.0.3.3では@@FETCH_STATUSとかROWID()などはサポートされていないみたい。最新バージョンではサポートされているっぽい(?)。
##ASE 15.7の評価版などもSybaseのサイトからダウンロード出来るみたいだけどLinuxは64ビット版だけみたいなのと、インストール方法がよくわからなかったのでダウンロードはしたけどとりあえず保留。
#サイベース情報少ないね。