プログラマメモ2 - programmer no memo2

おらくる VSIZE は内部でのサイズを返します。 2011/01/30

oracleです。VSIZEはデータベース内部でのサイズを返してくれるそうです。
で、実験です。
下記のようなテーブルを作成します。

create table bbb
(
a1 NCHAR(1),
a2 NVARCHAR2(1),
a3 CHAR(1 BYTE),
a4 CHAR(1 CHAR),
a5 VARCHAR2(1 BYTE),
a6 VARCHAR2(1 CHAR)
)


ちなみにキャラクターセットの確認
select * from nls_database_parameters where parameter ='NLS_CHARACTERSET'


結果は
AL32UTF8


適当にINSERTします。これってどうなると思います?
INSERT INTO bbb VALUES('あ', 'あ', 'あ', 'あ', 'あ', 'あ')


そうですエラーになります。
SQL実行中に以下のエラーが発生しました。
ORA-12899: 列"SYSTEM"."BBB"."A3"の値が大きすぎます(実際: 3、最大: 1)


では、次ぎにどうなるでしょうか。
INSERT INTO bbb VALUES('あ', 'あ', '1', 'あ', '1', 'あ')


微妙にわかりづらいですが、5つめのカラムに全角の"1"を入れようとしてます。

最後にこれで入ります。
INSERT INTO bbb VALUES('あ', 'あ', '1', 'あ', '1', 'あ')

列長セマンティックを指定しているのでBYTEは1バイトしか入らないです。

サイズをみてみます。
select VSIZE(a1), VSIZE(a2), VSIZE(a3), VSIZE(a4), VSIZE(a5), VSIZE(a6) from bbb


わかりずらいけど、下記のようになります。
VSIZE(A1) VSIZE(A2) VSIZE(A3) VSIZE(A4) VSIZE(A5) VSIZE(A6)
2 2 1 3 1 3


NCHARとCHARで何故サイズが違うのか?

おらくる。基本レプリケーションにチャレンジです。その3 キャラクタセットが違う編 2011/01/30
2011/02/05

オラクルです。基本レプリケーションです。DBのキャラクターセットが違う場合編です。
ゆくゆくはLocaleBuilderで設定した外字マップがどうはたらくのかみてみたいと思います。



手順
(1)マスターサイトにテーブルを作成
(2)レプリカサイトからマスターサイトにDBLink
(3)レプリカサイトでマテリアライズドVIEWを作成

(1)マスターサイトにテーブルを作成


create table EMP
(
  EMP_ID char(3) ,
  EMP_NAME varchar2(10),
  primary key( EMP_ID )
)


(2)レプリカサイトからマスターサイトにDBLink

create database link test2
connect to system identified by oracle
using 'test2'


(3)レプリカサイトでマテリアライズドVIEWを作成

create materialized view MV_EMP
as
select * from emp@test2


で、ここでふとした疑問、このレプリケーションテーブルはどこのキャラクターセットの影響を受けるでしょうか。
そのまえに、マスターサイトとレプリカサイトで、同じテーブルを作成した場合格納されるデータのサイズはキャラクターセットによってどう影響されるかチェック。


insert into EMP values('3', '仲若')

varchar2のサイズはどうなるでしょうか。

VSIZEを使ってみてみますと

select VSIZE(emp_name) from emp


AL32UTF8では、6バイト
JA16SJISTILDEでは、4バイト
という結果になりました。
UTF8だと漢字一文字3バイト
SJISですと漢字一文字2バイト
って感じでしょうか。

基本レプリケーションのテーブルはどうなるでしょうか?
マスターサイトと同じ6バイト?それともレプリカサイトの4バイト?

select VSIZE(emp_name) from MV_EMP


4バイトとなりました。
このことから、キャラクターセットはレプリカサイト自身のもので決定されているようにみえます。

Oracle Databaseグローバリゼーション・サポート・ガイド

おらくる。基本レプリケーションにチャレンジです。その2 2011/01/29
2011/01/29

オラクルです。基本レプリケーションです。前回は、マテリアライズドViewで、手動リフレッシュだったので、今回は、自動でリフレッシュです。



まず、作成済みのマテビューの削除はこのSQLで。

DROP MATERIALIZED VIEW


作業の手順は、
(1)マスターサイトの対象となるテーブルにCREATE MATERIALIZED VIEW LOGします。
(2)レプリカサイトでCREATE MATERIALIZED VIEWします。
自動で更新されるか試し
(3)マスターサイトを更新
(4)レプリカサイトに反映されてるか調べます。

参考


(1)マスターサイト
CREATE MATERIALIZED VIEW LOG ON emp


(2)レプリカサイト
create materialized view MV_EMP
REFRESH FAST NEXT SYSDATE
as
select * from emp@orcl



(3)マスターサイト
insert into EMP values('3', 'softbank')


(4)レプリカサイト
select * from MV_EMP

おらくる。基本レプリケーションにチャレンジです。その1 2011/01/29

オラクルです。基本レプリケーションにチャレンジです。



基本レプリケーションは、マスターサイトのテーブルの複製(レプリカ(Replica))をリモートサイト上に作る機能だそうです。
オラクルは、このリモートサイト上の複製(レプリカ(Replica))をMaterializedView(マテリアライズドビュー)で実現します。

オレオレ開発環境で試してみようと思います。
オレオレ環境なので、マスターとレプリカサイトが同じマシン内にあるという感じです...
(ちゃんと試してみたいな...)

で、まずはじめにDBLink(データベースリンク)なるものを作成します。
ちなみにデータベースリンクの説明

データベース・リンクは、あるデータベースから別のデータベースへの1方向通信パスを定義するポインタです。


参考

データベースリンクを作成するためには、DBNAMEを知ってないといけないらしい。
マスターサイトで確認
select DBID, NAME, DB_UNIQUE_NAME from V$DATABASE


グローバルネームの確認
select * from global_name



DB_NAMEがorclなDBにsystemユーザーで、パスワードがorclで、リンク名前がorclで作成
create database link orcl
connect to system identified by oracle
using 'orcl'


DBLinkができたかをレプリカサイトで確認
select * from user_db_links



つぎにマスターサイトでテーブルを作成
create table EMP
(
  EMP_ID char(3) ,
  EMP_NAME varchar2(10),
  primary key( EMP_ID )
)


で、DBLink経由でEMP表に接続してみる。
表@DBLink名前
でアクセス
select * from emp@orcl


アクセスできた。

つぎにレプリカサイトでマテリアライズドビューを作成する。
こんな感じ
create materialized view MV_EMP
as
select * from emp@orcl;


でこの表をselectすると値がとれることを確認。

つぎに、マスターサイトで表に値を入れてるみて、マテリアライズドビューにすぐに反映されないことを確認したのちに
手動でリフレッシュしてあげる。

exec dbms_mview.refresh('MV_EMP')


参考

[oracle]varcharのデータ型にバイナリを入れることができるか。 2011/01/22

Oracleです。テーブルのデータ型で悩み中です。どういう悩みかというと、char,varchar2のデータ型にバイナリのデータ(ようするに生のデータ)を入るのか、というものです。本来は、そういう用途だと、BLOBとかRAWの型だというのは承知のうえで。

で、入れてそれを使えるのかという実験です。
もしかして、他に方法があるかもしれませんが、結論からいうとできないです。
>_<!

ちなみに環境は、プログラマメモ2: oracleオレオレ開発環境、まずは接続で使ったものと同じです。

NLS_CHARACTERSETは、


select * from nls_database_parameters where parameter ='NLS_CHARACTERSET';
NLS_CHARACTERSET
JA16SJISTILDE

です。

下記ようなテーブルを用意します。

create table aaa
(
code varchar(30),
moji1 varchar(10 BYTE),
moji2 varchar(10 BYTE),
moji3 raw(10),
moji4 blob
);

最初の列に文字コードを指定して、データとしてその文字コードで表現された文字を入れたいというような発想です。
列長セマンティックをよく知らず設定したりしてますが...

検証用コードです。

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


public class TestDB_moji {

public static void main(String[] args) throws SQLException,
ClassNotFoundException, IOException {
String s = "仲";
aaa("utf8", s);
aaa("sjis", s);
// aaa("jis", s);
}

/*
* 目的 VARCHARの項目にバイナリなデータを保存できるのかな検証
*
* シナリオ 文字コードを指定して,setBytesを使って登録し、とりだして復元できるか調べる
*/
static void aaa(String code, String s) throws SQLException,
IOException {
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:@192.168.24.135:1521:test", "system",
"oracle");
// DatabaseMetaData meta = connection.getMetaData();

try {
if(true){
PreparedStatement statement = null;
String q = "INSERT INTO aaa(code, moji1, moji2, moji3, moji4) VALUES(?, ? , ?, ?, ?)";

statement = connection.prepareStatement(q);
// 文字コードで指定したバイト配列
byte[] bs = s.getBytes(code);
// まず普通に入れると
statement.setString(1, code);
statement.setString(2, new String(bs));// varchar2
statement.setBytes(3, bs);// varchar2
statement.setBytes(4, bs);// raw
statement.setBytes(5, bs);// blob
// statement.setBlob(5, new ByteArrayInputStream(bs));// blob
statement.executeUpdate();
connection.commit();
}
// バイトで値入れたら復元できるかな
{
ResultSet resultSet = null;

Statement statement = connection.createStatement();

resultSet = statement.executeQuery("select * from aaa");

int i = 0;
StringBuilder builder = new StringBuilder();
while (resultSet.next()) {
String c = resultSet.getString(1);
builder.append(
String.format(
"%d code:[%s] moi1:[%s] moi2:[%s] moi3:[%s] moi4:[%s]%n",
++i,
resultSet.getString(1), resultSet
.getString(2), new String(resultSet
.getBytes(3), c), new String(
resultSet.getBytes(4), c),
new String(resultSet.getBytes(5), c)));

}
resultSet.close();
statement.close();
System.out.println(builder);
Utils.write(new File("/z/a.txt"), new String(builder).getBytes());
}

} finally {
connection.close();
}

}
}

で、実行します。

こんな感じで登録されてます。


検証のプログラムの実行結果は、

1 code:[utf8] moi1:[莉イ] moi2:[E4BBB2] moi3:[仲] moi4:[仲]
2 code:[sjis] moi1:[仲] moi2:[9287] moi3:[仲] moi4:[仲]


raw,blobはjava側のgetBytesで復元できます。がvarcharでは復元できませんし、文字列になってしまってる...

!!1000件!! 2011/01/22
2011/01/23

プログラマメモ2の記事数が1000件いきました。
blogger上の下書きも含めてだと思うから、実際に公開されている記事は少ないけど。
いろいろ書き散らしてきたけど、これからまた、書き散らしていくことになるのでしょう。

ああビットビットビット 2011/01/21

Javaです。Integer.toBinaryStringはちょっとかなり自分のニーズとかけはなれた仕様だなーと思う今日この頃です。
ビットとバイトの関係いまだに頭が混乱します。
ビットのたちぐあいを8ビット、えーと1バイト限定で。

public class aBitBitBit {

public static void main(String[] args) {
System.out.println(binstr(0));
System.out.println(binstr(1));
System.out.println(binstr(2));
System.out.println(binstr(3));
System.out.println(binstr(4));
System.out.println(binstr(8));
System.out.println(binstr(16));
System.out.println(binstr(32));
System.out.println(binstr(64));
System.out.println(binstr(128));
System.out.println(binstr(255));
System.out.println(binstr(256));
System.out.println(binstr(-1));
System.out.println(binstr(0x1));
System.out.println(binstr(0xfe));
System.out.println(binstr(0xff));
}

static String binstr(int b) {
StringBuilder builder = new StringBuilder();

int[] is = { 128, 64, 32, 16, 8, 4, 2, 1 };
for (int i : is) {
if (0 < (b & i)) {
builder.append("1");
} else {
builder.append("0");
}
}

return new String(builder);
}

}


実行結果はこんな感じ
00000000
00000001
00000010
00000011
00000100
00001000
00010000
00100000
01000000
10000000
11111111
00000000
11111111
00000001
11111110
11111111

フォント名前とサイズと測りたい文字列を指定して、表示サイズ(高さ、幅)を出力します。 2011/01/16

フォント名前とサイズと測りたい文字列を指定して、表示サイズ(高さ、幅)を出力します。
関数で定義してます。

void print(NSString *fontName, int fontSize, NSString *str) {

NSFont *font;
font = [NSFont fontWithName:fontName size:fontSize];
NSSize size = [str sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
font, NSFontAttributeName,
nil]];
double w = size.width;
double h = size.height;
NSLog(@"fontname:[%@] fontsize:[%d] string:[%@] w:[%f] h:[%f]", fontName, fontSize, str, w, h);
}


まあまあうまくいってると思うけどどうだろう...

参考

NSRectからCGRectにします。 2011/01/16

NSRectからCGRectにします。


上記のサイトにあったマクロのほうが簡単かな。

#define NSRectToCGRect(r) CGRectMake(r.origin.x, r.origin.y, r.size.width, r.size.height)

NSWindowが閉じるイベントをひろう 2011/01/16

NSWindowが閉じるさいのイベントをひろいます。
ためしてみたのだけど、これはNSWindowを継承して、作成したクラスにwindowWillCloseを実装するのではなく、デリゲートを設定して使用するみたい。デリゲートのオブジェクトのほうで、イベントの通知を受けるみたい。

windowWillCloseにいくまえにwindowShouldCloseがよばれて、そこでほんとに閉じるのか問いあわせるのかな。


- (void)windowWillClose:(NSNotification *)notification {
NSLog(@"%s", __PRETTY_FUNCTION__);
}


参考

Tells the delegate that the window is about to close.



アプリケーション終了はこんな感じ

[NSApp terminate:self];

NSStringFromRectとNSRectFromString 2011/01/15

cocoaです。
NSStringFromRectとNSRectFromStringです。
NSWindowの位置情報保存に、NSRectをユーザデフォルトに保存したいなと思いました。で、NSStringFromRectとNSRectFromStringは、NSRectから文字列にするのと、文字列からNSRectを復元するのに使えます。
ちなみにNSStringFromRectの形式はこれはJSONなのかな。

参考


ユーザデフォルトに保存してみるコード
NSUserDefaults *userDefaults;
userDefaults = [NSUserDefaults standardUserDefaults];
NSRect rect = [window frame];
// NSStringFromRect([val rectValue]), @"frame"

// NSRectから文字列をつくる
NSString *s = NSStringFromRect(rect);
[userDefaults setValue:s forKey:@"frame"];
[userDefaults synchronize];

NSWindowでマウスイベントを受け取る 2011/01/13
2011/01/15

NSWindowでマウスイベントを受け取ります。
NSWindowを継承して、NSResponderに定義してあるのを適当に実装。
とれないイベントがあるんだよね...
どうとるんだろう。

追記:mouseMovedは、setAcceptsMouseMovedEventsにYESを設定でOK。


#import "MyWindow.h"


@implementation MyWindow

- (void) mouseDown:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void) mouseDragged:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void) mouseUp:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}


/**
このイベントはNSWindowではどうとるのだろう?
mouseEntered,mouseExited
*/
- (void) mouseMoved:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void) mouseEntered:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void) mouseExited:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}


- (void) rightMouseDown:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void) rightMouseDragged:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void) rightMouseUp:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void) otherMouseDown:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void) otherMouseDragged:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void) otherMouseUp:(NSEvent *)event {
NSLog(@"%s", __PRETTY_FUNCTION__);
}

@end


参考
マウスイベントを処理するCocoaアプリケーションにしてみる - ザリガニが見ていた...。

NSWindowでキーイベントを受け取る 2011/01/13

NSWindowでキーの受付はNSWindowをサブクラスして行うようですね。

参考




#import "MyWindow.h"


@implementation MyWindow

/**
これ必要
*/
- (BOOL) canBecomeKeyWindow
{
return YES;
}

/**
これ必要
*/
- (BOOL) canBecomeMainWindow
{
return YES;
}

/**
キーイベントを受け取るよ
*/
- (void) keyDown: (NSEvent *) event
{
NSLog(@"KeyDown pressed[%d]", [event keyCode]);
}
@end

NSWindowをフルスクリーンで表示 2011/01/12

osxです。「NSWindowをフルスクリーンで表示したい」です。xibを使わないで試してます。

参考


画面のサイズは、NSScreenのmainScreenで取得できます。

参考

試したコード。
アプリケーションを終了するコードは含んでないので、
実行すると画面がまっくろくろすけになるので、command+tabでファインダーを選んでアプリケーションを終了させてください。



#import <Cocoa/Cocoa.h>
#import "mac_app_test_01AppDelegate.h"

int main(int argc, char *argv[])
{
NSLog(@"** a1[%d]", argc);
NSLog(@"** a1[%d]", sizeof(argv));
for (int i=0; i < sizeof(argv); i++) {
NSLog(@"** a1[%s]", argv[i]);
}

id app = [NSApplication sharedApplication];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
mac_app_test_01AppDelegate *a = [mac_app_test_01AppDelegate alloc];
[a autorelease];
[app setDelegate:a];
[app run];
return 0;

// return NSApplicationMain(argc, (const char **) argv);
}

#import

@interface mac_app_test_01AppDelegate : NSObject {
NSWindow *window;
}

@property (assign) IBOutlet NSWindow *window;

@end



#import "mac_app_test_01AppDelegate.h"

@implementation mac_app_test_01AppDelegate

@synthesize window;

- (void)go{
/*
* このコードは、
* http://storklab.cyber-ninja.jp/lab/tips/programming/cocoa_fullscreen.html
* を参考にしています。
*/


NSRect mainScreen = [[NSScreen mainScreen] frame];


window = [[NSWindow alloc] initWithContentRect:mainScreen
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:YES];


// 背景を黒に
[window setBackgroundColor:[NSColor blackColor]];

// デアクティブのときは画面を表示しない
[window setHidesOnDeactivate:YES];

// アプリケーションがアクティブでなくてもウインドウを前面に持ってくるらしい
[window orderFrontRegardless];

// メニューバーを消す
[NSMenu setMenuBarVisible:NO];


}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSLog(@"OK\n");
[self go];
}

@end

2011年は 2011/01/10
2011/01/15

2011年の目標をとりあえず。

昨年は、ようやくiphoneアプリをひとつリリースできたのだけど、いろいろ作りたかったものを作れず(なまけていたため)、少しばかり残念だったのだ。

今年(2011年)は、macアプリが流通するための仕組みをappleさんが公開してたのを契機に、macアプリにチャレンジな年にしようと思う。大きなアプリでなく、僕の《等身大》のアプリを目指すのである。僕が使いやすい僕のためのTWITTERのクライアントをつくったら、つかってくれる人いるかなと、夢想したり。

まあ今年(2011年)は、苦手なRDBとか、LL言語(もうこの言い方しない?)チャレンジしつつ、いろいろつくってリリースしていこう。Javaがoracleさんのものになるとは思ってなかったし、ここまでスマートフォンがはやるとも思ってなかったし、母親がMacユーザになるとも思ってなかったのだけど、いろいろ変化していくのだなと。Javaにこだわらず、ひろくひろくね。あと、100記事書いたら1記事ぐらい、「おお」といわれる記事書けたらいいな..

というわけで、今年もよろしくです。