2008年10月23日 (木)

Mac de Caché というか MUMPS というか Objectscript か

Cachéはむか〜〜し、むか〜し日本DEC時代に関わっていたDSM-11やVAX/DSMようするにMUMPSを祖先に持つ。今ではSQL/トランザクション制御/ODBCもサポートしているというからOracle11gと他のデータベース間でOracle Generic Connectivityで遊ぶのも面白いかな・・・ということで試しにインストール。
そういえばCodezineで記事を書いている佐藤さんって日本DEC時代に担当していたディストリクトは違うけどDSM-11やVAX/DSMを担当されていた方だよな〜多分、随分前なので多分としか書けないけど。近いうちに確認できるだろうけど。(^^)


Cachéのéをタイプするためにフランス語タイプできるようにしちゃったし。 w

Cache_001

Cache_002

Cache_003

Cache_004

Cache_005

Cache_006

Cache_007

Cache_008

Cache_009

Cache_010

サポートされているプラットフォームの一覧をみるとPowerPC版MacOSXはTigerまでということになっている。
ちなみに、x86版MacOSXであれば最新版がダウンロードできるようだが、PowerPC版はダウンロードできないようだ。今回インストールしたのは一昨年にダウンロードしていたものなので1年半ぐらい前のバージョン。いつかは試そうと思いつついままで塩漬けだったわけです。
http://www.intersystems.com/cache/technology/product-tables/prodversion.html

無償版ダウンロードページは以下「但し、このシングルユーザライセンスは、評価・テストを目的としたもので商用アプリケーションの開発、販売、運用には使用できません。」とのこと。
http://www.intersystems.co.jp/cache/downloads/index.html

昔のMUMPS(M言語)の言語仕様しか覚えていないので暫しCaché Objectscriptのリファレンスを斜め読み。。イメージはそんなに変ってないか。。。ということでHello World!では面白くないのでMUMPS言語というか、M言語というか Caché ObjectscriptでFizz Buzzしてみた。
(新しいObjectscriptの文法でコーディングするならコマンドや慣習として省略形でコーディングすることが多かったMUMPSだけど、今は省略形は利用しないほうが読み易いよね、きっと。
MUMPSは習慣的に省略形のコマンドや関数でコーディングされているものが多かったから(現在でも省略形でコーディングする事が多いのかは知らない・・・・)、私が初めてMUMPSのコードを見たときは何じゃこれ! なんの記号? プログラムなのかこれ? と感じたことを思い出した。今回のコードも省略形使ってますが。www

MacOSXのTerminalを起動して。。。。(インストール後にはCachéが自動起動してる。。)
う〜〜〜〜ん、MUMPSの子孫だけどサンプルコード見るとJavaとかC的な文法もあるのね今のMUMPSじゃなくてObjectscriptは・・・今回は昔のMUMPSっぽく書いたけど。。

G5Server:˜ discus$ 
G5Server:˜ discus$ csession cache -U user

USER>

USER>f i=1:1:100 w $case(i#15,0:"FizzBuzz",:$case(i#3,0:"Fizz",:$case(i#5,0:"Buzz",:i))),!
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz

・・・・中略・・・・

89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz

USER>
USER>halt
G5Server:~ discus$

ついでにシャットダウンしてみるか。。。

G5Server:~ discus$ 
G5Server:˜ discus$ sudo ccontrol stop cache
Password:

Cache Shutdown Status: 3:51 pm 19 Oct 2008

0 interactive jobs (Telnet/Lat)
0 background jobs (from job command)
0 Cache Direct server jobs
0 Cache Objects server jobs
0 CSP server jobs
0 ODBC server jobs
26 system jobs

Do you want to broadcast a message to anyone? No => No
Do you want to see the Cache status report? No => Yes

Cache System Status: 3:51 pm 19 Oct 2008
Process Device Namespace Routine CPU,Glob Pr User/Location
355 CONTROL 0,0 0
379 WRTDMN 227,23 0
380 GARCOL 0,0 0
381 JRNDMN 13830,141 0
389 EXPDMN 0,0 0
382 SLAVWD 7,126 0
385 SLAVWD 0,0 0
383 SLAVWD 0,0 0
388 SLAVWD 0,0 0
384 SLAVWD 0,0 0
387 SLAVWD 0,0 0
386 SLAVWD 0,0 0
419 /dev/null %SYS %SYS.Task 124096,23819 0 TASKMGR
398 /dev/null %SYS MONITOR 46080,3557 0
1838 /dev/ttyp1 %SYS SYS.Process 8256,1067 0 %System
400 /dev/null %SYS CLNDMN 704,47 0
401 /dev/null %SYS RECEIVE 90752,10111 0
402 /dev/null %SYS ECPWork 192,65 0
403 /dev/null %SYS ECPWork 192,64 0
404 /dev/null %SYS ECPWork 192,63 0
405 /dev/null %SYS ECPWork 192,63 0
406 /dev/null %SYS ECPWork 192,63 0
407 /dev/null %SYS ECPWork 192,63 0
408 /dev/null %SYS ECPWork 192,63 0
409 /dev/null %SYS ECPWork 192,63 0
1170 /dev/null %SYS %CSP.Daemon 12224,1290 0
411 |TCP|1972 %SYS %SYS.SERVER 192,65 0
416 /dev/null %SYS %MONAPP 61760,11240 0

2 user, 26 system, 32 mb global/1 mb routine cache

Do you want to broadcast a message to anyone? No => No
Do you want to see the Cache status report? No => No
Do you want to run the user defined shutdown routine? Yes => No
Are you ready for the system to halt? Yes => Yes

15:52:19 Shutting down Cache
15:52:20 Notifying Clients
15:52:20 No user shutdown routines to execute
15:52:20 Stopping User Jobs
15:52:20 Stopping Network Servers
15:52:21 Withdrawing from License Domain
15:52:21 Waiting for users to stop
15:52:21 Stopping Client Networking
15:52:21 Removing database locks
15:52:21 Updating Journal File
15:52:22 Waiting for database updates to complete
15:52:23 Database updates complete
15:52:23 Stopping System Jobs
15:52:27 Shutdown complete
G5Server:˜ discus$


ということで、あとはOracle Generic ConnectivityをOracle11gで試すときまでのお楽しみ・・・?!

| | コメント (0) | トラックバック (0)

2007年10月22日 (月)

Oracle de XMLDB #4

データベースマガジンでもXQuery1.0は"習うより慣れろ"なんて書いてあったので、使って覚えるのが一番いいだろうなということで前々回に環境を構築したのだが、予想外の展開で、なかなか思うように試す時間がとれない・・・、それでも何とか時間を作らなきゃね。ということでやっとその続き。  

バックナンバー:
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?


最初はFizzBuzzからやってみた。(笑) さずがに、Hello Worldじゃつまらなかったので・・・・。

いつものように、Oracle Database 11g for Linux x86へMacOSXのTerminalからssh接続!

Last login: Sat Oct 20 02:18:51 on console
Welcome to Darwin!
G5Server:˜ discus$ su - oracle
Password:
G5Server:˜ oracle$
G5Server:˜ oracle$ ssh oracle@glasscatfish
oracle@glasscatfish's password:
Last login: Sat Oct 20 02:19:12 2007 from 192.168.1.19
[oracle@glasscatfish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 月 10月 20 14:13:23 2007

Copyright (c) 1982, 2007, Oracle. All rights reserved.

> conn scott/tiger@lampeye
接続されました。

SCOTT> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
PL/SQL Release 11.1.0.6.0 - Production
CORE 11.1.0.6.0 Production
TNS for Linux: Version 11.1.0.6.0 - Production
NLSRTL Version 11.1.0.6.0 - Production

SCOTT> set timi on
SCOTT> l
1 xquery
2 for $n in 1 to 100
3 return
4 if ($n mod 15 eq 0) then 'fizzbuzz'
5 else if ($n mod 3 eq 0) then 'fizz'
6 else if ($n mod 5 eq 0) then 'buzz'
7* else $n
SCOTT> /
1
2
fizz
4
buzz
fizz
7
8
fizz
・・・・中略・・・・
fizz
97
98
fizz
buzz

100アイテムが選択されました。

経過: 00:00:00.06
SCOTT>


ついでなので、以前SQLでFizzBuzzしたものと処理時間を比較してみた。
お〜!、SQLでFizzBuzzしたほうが早いな〜!

SCOTT> with
2 t as (
3 select 1 from dual group by cube(1,1,1,1)
4 )
5 select
6 case 0
7 when mod(rownum,15) then 'fizzbuzz'
8 when mod(rownum,3) then 'fizz'
9 when mod(rownum,5) then 'buzz'
10 else to_char(rownum)
11 end as results
12 from
13 t a cross join t b
14 where
15 rownum <= 100;
1
2
fizz
4
buzz
fizz
7
8
・・・・中略・・・・
fizz
97
98
fizz
buzz

100行が選択されました。

経過: 00:00:00.03
SCOTT>


多分、どなたかXQueryでやっているんじゃないかな〜!? ということでググってみたら、ありました、User's Forum For DB2 Japanに。。(^^;;;

いや〜〜〜、目から鱗ですね。User's Forum For DB2 Japanのスレッドにある下記コードは、面白い。(私のコードは読みやすいかもしれないが、ストレート過ぎるかもね。ちょいと捻ったほうが、XQueryのトリッキーな動きも見えてくるというもの。)
以下のコードは、XPath2.0/XQuery1.0では、xs:booleanじゃなくても真理値として扱われる値やシーケンスにフィルタ式を用いているなどなど参考になります。m(_ _)m
(ただ、xs:booleanじゃなくても真理値として扱われるという性質を多用しるぎると難読化傾向はあるかもしれないですね。)

SCOTT> l
1 xquery
2 for $n in 1 to 100
3 return
4 fn:concat(
5 $n[($n mod 3 and $n mod 5)],
6 'fizz'[fn:not($n mod 3)],
7 'buzz'[fn:not($n mod 5)]
8* )
SCOTT> /
1
2
fizz
4
buzz
fizz
7
8
・・・・中略・・・・
97
98
fizz
buzz

100アイテムが選択されました。

経過: 00:00:00.06
SCOTT>


XQueryの条件式を少々書き換えてみた。私が最初に書いたXQueryより条件式の部分が読みにくくなりますよね、やはり。(実行速度に影響がなければ、読みやすい方がいいな。。)

SCOTT> l
1 xquery
2 for $n in 1 to 100
3 return
4 if (fn:not($n mod 15)) then 'fizzbuzz'
5 else if (fn:not($n mod 3)) then 'fizz'
6 else if (fn:not($n mod 5)) then 'buzz'
7* else $n
SCOTT> /
1
2
fizz
4
buzz
fizz
7
8
・・・・中略・・・・
97
98
fizz
buzz

100アイテムが選択されました。

経過: 00:00:00.06
SCOTT>

やはりxs:booleanじゃなくても真理値として扱われるという性質は、間違いやすいところなのでもうちょっと突っ込んで理解しておく必要があるなぁ。いい加減に覚えているとハマりそうな予感。

2007/10/23 追記
Oracle10g R2でもできますよ。

| | コメント (0) | トラックバック (0)

2007年8月30日 (木)

Oracle de Fizzbuzz #2

前回はOracle上にFizzbuzz用基本的な環境を作成したところまでだった。
今回は、幾つかの前提を設け、なるべくこちらの意図した解答を引き出す工夫も含めて..

事前にnullを設定した10行を登録した表を用意しておき、SQL文だけでFizzbuzzを解かせるなんてのもおもしろそう。

SYS> create table fizzbuzz.x (x number(1));

表が作成されました。

SYS> l
1 begin
2 for i in 1..10 loop
3 insert into fizzbuzz.x values(null);
4 end loop;
5* end;
SYS> /

PL/SQLプロシージャが正常に完了しました。

SYS> commit;

コミットが完了しました。

SYS> set null NULLだ!
SYS> select * from fizzbuzz.x;

X
----------
NULLだ!
NULLだ!
NULLだ!
NULLだ!
NULLだ!
NULLだ!
NULLだ!
NULLだ!
NULLだ!
NULLだ!

10行が選択されました。

上記のような前提なら、以下のような答えを期待しちゃう。ポイントは直積するか、という点と、rownum疑似列を使っうかどうか、ってところ。。

FIZZBUZZ> l
1 select
2 case 0
3 when mod(rownum,15) then 'fizzbuzz'
4 when mod(rownum,3) then 'fizz'
5 when mod(rownum,5) then 'buzz'
6 else to_char(rownum)
7 end as results
8 from
9* x a cross join x b
FIZZBUZZ>

事前にデータを準備せず、100行の生成もSQLで行うことを期待するのであれば、オラクルだと Oracle9i以降であれば、cube又はrollup、Oracle10g以降であれば階層問合せのいずれかというところか。
case式の変わりに、decodeを利用したり、with句を利用しないで単純に副問い合せにしたりといういくつかのバリエーションはあるとおもうが・・・・・。
(いまさら、Oracle8iを利用することもないだろうから。。。まだ、利用している方、すみません。。。)

部分的cubeがいくつの小計を計算するかさえ知っていれば。。。以下のようなクエリで実現できる。以下の方法であれば、cubeがサポートされたOracle9i以降で実行できるクエリ版、fizzbuzzが作れる。

日本語のマニュアルはこちら
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19217-02/aggreg.htm#sthref1627

英語版のマニュアルはこちら
http://download.oracle.com/docs/cd/B19306_01/server.102/b14223/aggreg.htm#sthref1627

FIZZBUZZ> edit
file afiedt.bufが書き込まれました。

1 with
2 t as (
3 select 1 from dual group by cube(1,1,1,1)
4 )
5 select
6 case 0
7 when mod(rownum,15) then 'fizzbuzz'
8 when mod(rownum,3) then 'fizz'
9 when mod(rownum,5) then 'buzz'
10 else to_char(rownum)
11 end as results
12 from
13 t a cross join t b
14 where
15* rownum <= 100
尚、cubeがサポートされてないリリースだと、、ちと面倒だが、、、Oracle9i以降であれば使える方法ですよん。

階層問い合せで行う方法もあるが、個人的にはcubeを使ったクエリのほうが好き。以下の例で利用している階層問合せは、Oracle9iでは1行しか返してこないので将来的にもそのような挙動をするのか多少不安だし。。

FIZZBUZZ> l
1 with
2 t as
3 (
4 select level
5 from dual
6 connect by level <= 10
7 )
8 select
9 case 0
10 when mod(rownum,15) then 'fizzbuzz'
11 when mod(rownum,3) then 'fizz'
12 when mod(rownum,5) then 'buzz'
13 else to_char(rownum)
14 end as results
15 from
16* t a cross join t b
FIZZBUZZ>


といったところだろうか。

| | コメント (0) | トラックバック (0)