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%はパスする様になっただけなのだが

Failed 3/13 test scripts, 76.92% okay. 5/241 subtests failed, 97.93% okay.

 

まあ、これだけ動けばなんとかなるでしょ。ということで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]$

 

参考

DBI/DBDについて

DBD::Sybase – search.cpan.org

DBD::Sybase – DBIモジュールのためのSybaseデータベース・ドライバ 【perldoc.jp】

Sybase SQL & Functions

■その他

#ちょっと調べた感じではSybase ASE 11.0.3.3では@@FETCH_STATUSとかROWID()などはサポートされていないみたい。最新バージョンではサポートされているっぽい(?)。

##ASE 15.7の評価版などもSybaseのサイトからダウンロード出来るみたいだけどLinuxは64ビット版だけみたいなのと、インストール方法がよくわからなかったのでダウンロードはしたけどとりあえず保留。

#サイベース情報少ないね。

(Visited 189 times, 1 visits today)

タグ : , , ,