Hitachi

ノンストップデータベース HiRDB Version 10 UAP開発ガイド


付録H.1 表分割ハッシュ関数

表分割ハッシュ関数とは,分割キーの値から,表分割に指定した分割条件指定順序を取得するものです。この表分割ハッシュ関数を使用したUAPを実行すると,ハッシュ分割した表であっても,表にデータを格納する前に格納先RDエリアが分かります。格納先RDエリアが分かるので,次のような場合に使用すると有効です。

〈この項の構成〉

(1) 表分割ハッシュ関数を使用する場合の前提条件

表分割ハッシュ関数を使用する場合の前提条件を次に示します。

(a) プログラム言語

表分割ハッシュ関数を使用してUAPを作成する場合,次の高級言語で記述できます。

  • C,又はC++言語

(b) 実行できる環境

HiRDBサーバ,又はHiRDBクライアントをインストールしたサーバマシンで実行できます。

ただし,HiRDBクライアントで実行する場合,HiRDBサーバとHiRDBクライアントのOSの組み合わせによって,正しい結果が得られない場合があります。

HiRDBクライアントでの実行可否を次の表に示します。

表H‒1 HiRDBクライアントでの実行可否

HiRDBサーバのOS

HiRDBクライアントのOS

HP-UX,AIX

Linux,Windows

HP-UX,AIX

×

Linux,Windows

×

(凡例)

○:実行できます。

×:バイトオーダが異なるため,分割条件指定順序又は分割キー内通番が不正となります。

(2) 表分割ハッシュ関数を使用したUAPの作成,実行

次の手順でUAPを作成し,実行します。

  1. ソースプログラムの作成

  2. コンパイル,リンケージ

  3. ロードモジュールの実行

(a) プログラムの作成

C,又はC++言語で記述したソースプログラム中に,表分割ハッシュ関数の関数呼出しを記述します。表分割ハッシュ関数は共用ライブラリの形で提供されるので,共用ライブラリをリンクすると使用できます。

表分割ハッシュ関数を使用するときには,提供されるヘッダファイルをソースプログラム作成時にインクルードする必要があります。表分割ハッシュ関数が必要とするすべてのヘッダファイルをインクルードします。表分割ハッシュ関数が必要とするヘッダファイルについては,「表分割ハッシュ関数の詳細」を参照してください。

(b) コンパイル,リンケージ

HiRDBサーバがインストールされているサーバマシン,又はHiRDBクライアントがインストールされているクライアントマシンでコンパイル,リンケージします。

なお,ソースプログラム中にSQL文を埋め込む場合は,コンパイル,リンケージする前に,プリプロセスする必要があります。

コンパイル,リンケージ,及びプリプロセスについては,「UAP実行前の準備」を参照してください。

UNIX版のHiRDBサーバ側でのコンパイル,リンケージ

HiRDBサーバでコンパイル,リンケージする場合の指定例について説明します。

<例>(C言語の場合)
  • ソースファイルの名称がsample.cで,実行形式ファイルの名称を指定しない場合

<32bitモードで動作するUAPを作成する場合>
 
  cc -I $PDDIR/include sample.c -L$PDDIR/client/lib -l sqlauxf
 
<64bitモードで動作するUAPを作成する場合>
 
  cc +DD64 -I $PDDIR/include sample.c -L$PDDIR/client/lib -l sqlauxf64
<例>(C++言語の場合)
  • ソースファイルの名称がsample.Cで,実行形式ファイルの名称を指定しない場合

<32bitモードで動作するUAPを作成する場合>
 
  CC -I $PDDIR/include sample.C -L$PDDIR/client/lib -l sqlauxf
 
<64bitモードで動作するUAPを作成する場合>
 
  CC +DD64 -I $PDDIR/include sample.C -L$PDDIR/client/lib -l sqlauxf64
UNIX版のHiRDBクライアント側でのコンパイル,リンケージ

HiRDBクライアントでコンパイル,リンケージする場合の指定例について説明します。

<例>(C言語の場合)
  • ソースファイルの名称がsample.cで,実行形式ファイルの名称を指定しない場合

<32bitモードで動作するUAPを作成する場合>
 
  cc -I /HiRDB/include sample.c -L/HiRDB/client/lib -l sqlauxf
 
<64bitモードで動作するUAPを作成する場合>
 
  cc +DD64 -I /HiRDB/include sample.c -L/HiRDB/client/lib -l sqlauxf64

下線で示す部分は,HiRDBのインストールディレクトリを指定します。

<例>(C++言語の場合)
  • ソースファイルの名称がsample.Cで,実行形式ファイルの名称を指定しない場合

<32bitモードで動作するUAPを作成する場合>
 
  CC -I /HiRDB/include sample.C -L/HiRDB/client/lib -l sqlauxf
 
<64bitモードで動作するUAPを作成する場合>
 
  CC +DD64 -I /HiRDB/include sample.C -L/HiRDB/client/lib -l sqlauxf64

下線で示す部分は,HiRDBのインストールディレクトリを指定します。

Windows版のHiRDBサーバ側でのコンパイル,リンケージ

C言語のソースプログラムは,ANSI-Cに従ったコンパイラでコンパイルをします。また,C++言語のソースプログラムは,C++に従ったコンパイラでコンパイルをします。

Microsoft Visual C++ Version 1.0を使用してコンパイル,リンケージをする場合のオプションの設定は,オプションメニューから「プロジェクトの設定」を選択します。

Microsoft Visual C++ Version 2.0を使用してコンパイル,リンケージをする場合のオプションの設定は,プロジェクトメニューから「設定」を選択します。

「プロジェクトの設定」,又は「設定」で設定する項目(HiRDBサーバ側)を次の表に示します。

表H‒2 「プロジェクトの設定」,又は「設定」で設定する項目(HiRDBサーバ側)

項目

カテゴリ

カテゴリの設定

設定値

コンパイラ

コード生成

構造体メンバのアライメント

8バイト

使用するランタイムライブラリ

マルチスレッド

プリプロセサ

インクルードのファイルパス

\HiRDB\client\include

リンカ

インプット

ライブラリ

\HiRDB\client\lib

\pdsqlauxf.lib

注 下線で示す部分は,HiRDBのインストールディレクトリを指定してください。

Windows版のHiRDBクライアント側でのコンパイル,リンケージ

C言語のソースプログラムは,ANSI-Cに従ったコンパイラでコンパイルをします。また,C++言語のソースプログラムは,C++に従ったコンパイラでコンパイルをします。

Microsoft Visual C++ Version 1.0を使用してコンパイル,リンケージをする場合のオプションの設定は,オプションメニューから「プロジェクトの設定」を選択します。

Microsoft Visual C++ Version 2.0を使用してコンパイル,リンケージをする場合のオプションの設定は,プロジェクトメニューから「設定」を選択します。

「プロジェクトの設定」,又は「設定」で設定する項目(HiRDBクライアント側)を次の表に示します。

表H‒3 「プロジェクトの設定」,又は「設定」で設定する項目(HiRDBクライアント側)

項目

カテゴリ

カテゴリの設定

設定値

コンパイラ

コード生成

構造体メンバのアライメント

8バイト

使用するランタイムライブラリ

マルチスレッド

プリプロセサ

インクルードのファイルパス

\HiRDB\include

リンカ

インプット

ライブラリ

\HiRDB\lib

\pdsqlauxf.lib

注 下線で示す部分は,HiRDBのインストールディレクトリを指定してください。

(3) 表分割ハッシュ関数の詳細

(a) 入力に必要な情報

表分割ハッシュ関数を呼び出すには,次の1〜8の情報を取得して,引数に設定する必要があります。

  1. 分割に指定したハッシュ関数名

  2. 分割キーに指定した列数

  3. 分割キーの指定順序とデータ型コード,データ長コード

  4. 表の分割数

  5. 分割キーに格納するデータ値

  6. HiRDBサーバで使用する各国文字の全角空白文字

  7. 空白変換レベルの値

  8. DECIMAL型の符号正規化機能の使用有無

この中の1〜4は,CREATE TABLEの次の部分に対応します。

[図データ]

なお,既に表を定義している場合,1〜4はディクショナリ表を検索すれば情報を取得できます。ディクショナリ表の検索例については,「ディクショナリ表からの検索(ハッシュ分割の場合)」を参照してください。

また,空白変換レベル(空白変換機能),及びDECIMAL型の符号正規化機能については,マニュアル「HiRDB システム運用ガイド」を参照してください。

(b) 記述構成

表分割ハッシュ関数の詳細を次のように説明します。

機能

概要について説明します。

ヘッダファイル

表分割ハッシュ関数を使用するために必要な,ヘッダについて説明します。

形式

実際に指定する形式について説明します。

引数

形式で記述している引数とその意味について説明します。

戻り値

表分割ハッシュ関数の戻り値の型(データ型として記述)について説明します。

(c) 表分割ハッシュ関数(p_rdb_dbhash)

機能

分割キーの値が格納される分割条件指定順序(1〜表の分割数),又は分割キー内通番を取得できます。ただし,正常終了しなかった場合,分割条件指定順序の値は不正になります。

分割条件指定順序を取得する行が複数ある場合には,行ごとに分割キーのデータを変更して,表分割ハッシュ関数を呼ぶ必要があります。この場合,分割キーのデータ値以外の引数は変更する必要はありません。

分割キー内通番から分割条件指定順序を求める方法については,「ディクショナリ表からの検索(マトリクス分割の場合)」を参照してください。

ヘッダファイル
#include<pddbhash.h>

表分割ハッシュ関数を使用する場合に必ず指定します。

#include<pdbsqlda.h>

分割キーのデータ型コードを設定する場合,マクロ(PDSQL_で始まるマクロ)を使用して設定するときに指定します。なお,ディクショナリ表からデータ型コードを検索して設定する場合には,指定する必要はありません。

形式1(分割キーに文字集合の指定がない場合)
  int p_rdb_dbhash(short           hashcode,
                   short           ncol,
                   p_rdb_collst_t  *collst,
                   p_rdb_dadlst_t  *dadlst,
                   unsigned int    ndiv,
                   unsigned char   ncspace[2],
                   int             flags,
                   int             *rdno);
形式2(分割キーに文字集合の指定がある場合)
  int p_rdb_dbhash_cs(short           hashcode,
                    short             ncol,
                    p_rdb_collst_t    *collst,
                    p_rdb_csidlst_t   *csidlst,
                    p_rdb_dadlst_t    *dadlst,
                    unsigned int      ndiv,
                    unsigned char     ncspace[2],
                    int               flags,
                    int               *rdno);
引数
hashcode(入力)

ハッシュ関数名に対応するハッシュ関数コードを指定します。ハッシュ関数コードについては,「ハッシュ関数コード」を参照してください。

ncol(入力)

表定義時に,分割キーとして指定した列数を指定します。

collst(入力)

分割キーリストへのポインタを指定します。分割キーリストは,分割キーのデータ型コード,データ長コードから成る構造体で,分割キー数分連続する領域です。分割キーリストについては,「分割キーリスト」を参照してください。

分割キーのデータ型コード,データ長コードについては,ディクショナリ表を検索すれば情報を取得できます。ディクショナリ表の検索例については,「ディクショナリ表からの検索(ハッシュ分割の場合)」を参照してください。

csidlst(入力)

形式2(分割キーに文字集合の指定がある場合)の場合にだけ指定します。分割キーの文字集合IDリストへのポインタを指定します。

文字集合IDリストは,文字集合IDから成る構造体が分割キー数分連続する領域です。文字集合IDリストについては,「文字集合IDリスト」を参照してください。

分割キーの文字集合IDは,ディクショナリ表を検索することで取得できます。ディクショナリ表の検索については,「ディクショナリ表からの検索(ハッシュ分割の場合)」を参照してください。

dadlst(入力)

データアドレスリストへのポインタを指定します。データアドレスリストは,分割キーのデータを格納する領域へのアドレスから成る構造体で,分割キー数分連続する領域です。詳細については,「データアドレスリスト」を参照してください。

ndiv(入力)

ハッシュ分割の分割数を指定します。

ncspace(入力)

HiRDBサーバで使用する各国文字コードの全角空白文字を,2バイトの領域で指定します。分割キーのデータ型がNVARCHARの場合,文字列に続く空白を取り除いてハッシングするために使用します。また,flagsに空白変換レベル1,又は3を指定した場合の分割キー値(NCHAR,NVARCHAR,MCHAR,又はMVARCHAR)の空白変換のときにも使用します。

次の場合に,ncspaceの領域が未設定のときはエラーとなります。

  • 分割キーがNVARCHARの場合

  • flagsに空白変換レベル1,又は3を指定していて,かつ分割キーがNCHAR,NVARCHAR,MCHAR,又はMVARCHARの場合

ncspaceに指定する全角空白文字を次の表に示します。

表H‒4 ncspaceに指定する全角空白文字

pdsetupで指定した文字コード種別※2

ncspace

ncspace[0]

ncspace[1]

sjis(シフトJIS漢字コード)

0x81

0x40

chinese(EUC中国語漢字コード)

0xA1

0xA1

ujis(EUC日本語漢字コード)

0xA1

0xA1

lang-c(単一バイト文字コード)※1

0x00

0x00

utf-8(Unicode(UTF-8))※3

0x00

0x00

utf-8_ivs(Unicode(IVS対応UTF-8))※3

0x00

0x00

chinese-gb18030(中国語漢字コードGB18030)※3

0xA1

0xA1

省略時(HP-UXの場合はsjis)

0x81

0x40

省略時(AIXの場合はsjis)

0x81

0x40

省略時(Linuxの場合はujis)

0xA1

0xA1

省略時(Windowsの場合はsjis)

0x81

0x40

注※1

lang-cの場合,列のデータ型にNCHAR,NVARCHAR,MCHAR,及びMVARCHARは使用できません。

注※2

Windows環境の場合は,pdntenvコマンドで指定した文字コード種別の空白文字コードを指定してください。

注※3

列のデータ型には,NCHAR及びNVARCHARは使用できません。

flags(入力)

空白変換レベル,及びDECIMAL型の符号正規化機能の指定に従って指定します(これらの機能を使用しない場合でも指定する必要があります)。空白変換レベル,及びDECIMAL型の符号正規化機能については,マニュアル「HiRDB システム運用ガイド」を参照してください。

flagsに指定する値を次に示します。

HiRDBの動作環境

flags指定値

空白変換レベル

省略

p_rdb_FLG_SPLVL_0

0

1

p_rdb_FLG_SPLVL_1

3

p_rdb_FLG_SPLVL_3

DECIMAL型の符号正規化機能

省略

p_rdb_FLG_DECNRM_N

N

Y

p_rdb_FLG_DECNRM_Y

注※

HiRDBサーバの文字コードがUnicode(UTF-8)の場合,あらかじめ空白変換をしてからこの関数を実行する必要があるため,flagsの指定値にはp_rdb_FLG_SPLVL_0以外は指定しないでください。

rdno(出力)

分割条件指定順序(1〜表の分割数),又は分割キー内通番が設定されます。

戻り値

データ型:int

p_rdb_RC_RTRN(0)

正常終了

p_rdb_RC_ERRHASH(-1)

ハッシュ関数コード不正(p_rdb_HASH1〜p_rdb_HASH6,p_rdb_HASHZ,p_rdb_HASH0,p_rdb_HASHA〜p_rdb_HASHF)

p_rdb_RC_ERRNCOL(-2)

分割キー数不正(1〜p_rdb_MXDCL)

p_rdb_RC_ERRCLST(-3)

分割キーのデータ型,データ長の領域不正

p_rdb_RC_ERRCTYP(-31)

分割キーのデータ型が不正

p_rdb_RC_ERRCLEN(-32)

分割キーのデータ長が不正

p_rdb_RC_ERRCSID(-33)

分割キーの文字集合IDが不正

p_rdb_RC_ERRDLST(-4)

データアドレスの領域不正

p_rdb_RC_ERRDADR(-41)

データアドレスが未設定

p_rdb_RC_ERRDLEN(-42)

ハッシュ関数がHASH3,HASHC,HASH4,HASHD,HASH5,又はHASHEの場合:データの実長が指定されたハッシュ関数でハッシング可能な最小長より短い

ハッシュ関数がHASH0又はHASHZで,分割キーのデータ型がCHAR型の場合:日付データの文字列表現形式が不正

p_rdb_RC_ERRNDIV(-5)

表の分割数不正(1〜p_rdb_MNCND)

p_rdb_RC_ERRRADR(-6)

分割条件指定順序,又は分割キー内通番の格納領域が未設定

p_rdb_RC_ERRNCSC(-7)

全角空白文字の領域が未設定

注意事項

注意事項を次に示します。

  1. 分割キーがNCHAR,NVARCHAR,MCHAR,又はMVARCHARの場合,flagsに空白変換レベルに対応した値を指定しないと,rdnoの値が不正になることがあります。

  2. 分割キーがNCHAR,NVARCHAR,MCHAR,又はMVARCHARで,かつ空白変換レベルに1,又は3を指定した場合,次に示すどちらかのことをしてください。

    ・setlocale関数でLC_CTYPEカテゴリ,又はLC_ALLカテゴリに適切なロケールを設定する

    ・p_rdb_set_lang関数を呼び出す

    キー値の文字コード種別とsetlocale関数又はp_rdb_set_lang関数で指定したロケールが矛盾する場合,動作は保証されません。WindowsのUAP,文字コード種別がSJISのLinuxのUAP,又は文字コード種別がCHINESEのUAPからこの関数が呼び出される場合は,setlocale関数ではなくp_rdb_set_lang関数を使用します。p_rdb_set_lang関数については,「文字コード種別設定関数」を参照してください。

  3. 分割キー値がDECIMAL,INTERVAL YEAR TO DAY,又はINTERVAL HOUR TO SECONDの場合,flagsにDECIMAL型の符号正規化機能に対応した値を指定しないと,rdnoの値が不正になることがあります。

  4. バージョン05-05より前のHiRDBクライアントで表分割ハッシュ関数を使用する場合,flagsの空白変換レベル,及びDECIMAL型の符号正規化機能は使用できません。したがって,flagsの指定は無効となり,空白変換レベル,及びDECIMAL型の符号正規化機能が省略時の場合と同じ動作になります。flagsの指定を有効にしたい場合,HiRDBサーバ側で実行するか,又はバージョン05-05以降のHiRDBクライアントで実行してください。

  5. HiRDBサーバの文字コードがUnicode(UTF-8)の場合,この関数では空白変換をしません。dadlstに指定する分割キーの値は,事前に空白変換関数p_rdb_conv_space_utf8を使用して変換しておく必要があります。

  6. 文字集合にUTF16の指定がある場合,分割キーのデータはビッグエンディアン形式にする必要があります。ビッグエンディアンにしないと,rdnoの値が不正になるおそれがあります。

(4) データ型とマクロ

(a) ハッシュ関数コード

CREATE TABLE,又はALTER TABLEで指定するハッシュ関数に対応するハッシュ関数コードを次の表に示します。

表H‒5 ハッシュ関数に対応するハッシュ関数コード

ハッシュ関数名

ハッシュ関数コード(値)

HASH1(ハッシュ関数名省略時)

p_rdb_HASH1 (1)

HASH2

p_rdb_HASH2 (2)

HASH3

p_rdb_HASH3 (3)

HASH4

p_rdb_HASH4 (4)

HASH5

p_rdb_HASH5 (5)

HASH6

p_rdb_HASH6 (6)

HASHZ

p_rdb_HASHZ (99)

HASH0

p_rdb_HASH0 (100)

HASHA

p_rdb_HASHA(101)

HASHB

p_rdb_HASHB(102)

HASHC

p_rdb_HASHC(103)

HASHD

p_rdb_HASHD(104)

HASHE

p_rdb_HASHE(105)

HASHF

p_rdb_HASHF(106)

(b) 分割キーリスト

分割キーリストは,分割キーのデータ型コード,データ長コードから成る構造体で,分割キー数分連続する領域です。分割キーを設定する領域を次の表に示します。分割キーが複数ある場合,分割キーとして指定した列数分の配列にする必要があります。

表H‒6 分割キーを設定する領域

データ型

データ型の詳細

説明

p_rdb_collst_t

struct p_rdb_TG_collst {

unsigned short datatype ;

short datalen ;

} p_rdb_collst_t ;

データ型コード

データ長コード

データ型コード,データ長コードを次の表に示します。

表H‒7 データ型コード,データ長コード

データ型

データ型コード

データ長コード

INTERVAL YEAR TO DAY

PDSQL_YEARTODAY

8×256

INTERVAL HOUR TO SECOND

PDSQL_HOURTOSEC

6×256

DATE

PDSQL_DATE

4

TIME

PDSQL_TIME

3

TIMESTAMP[(p)]

PDSQL_TIMESTAMP

7+↑p/2↑(pを省略した場合は0を仮定)

MVARCHAR(n)

PDSQL_MVARCHAR

n

MCHAR[(n)]

PDSQL_MCHAR

n(nを省略した場合は1を仮定)

NVARCHAR(n)

PDSQL_NVARCHAR

n

NCHAR[(n)]

PDSQL_NCHAR

n(nを省略した場合は1を仮定)

VARCHAR(n)

PDSQL_VARCHAR

n

CHAR[(n)]

PDSQL_CHAR

n(nを省略した場合は1を仮定)

FLOAT

PDSQL_FLOAT

8

SMALLFLT

PDSQL_SMALLFLT

4

DECIMAL[(p[,q])]

PDSQL_DECIMAL

p×256+q(pを省略した場合は15を仮定,qを省略した場合は0を仮定)

INTEGER

PDSQL_INTEGER

4

SMALLINT

PDSQL_SMALLINT

2

(c) 文字集合IDリスト

分割キーに文字集合の指定がある場合にだけ指定します。文字集合IDを設定する領域を次の表に示します。分割キーが複数ある場合,分割キーとして指定した列数分の配列にする必要があります。

表H‒8 文字集合IDを設定する領域

データ型

データ型の詳細

説明

p_rdb_csidlst_t

struct p_rdb_TG_csidlst {

int charset_id ;

} p_rdb_csidlst_t ;

文字集合IDコード

文字集合IDコードを次の表に示します。

表H‒9 文字集合IDコード

文字集合

文字集合IDコード(値)

文字集合の指定なし

p_rdb_CSDEF

(0x00000000)

EBCDIK

p_rdb_CSEBK

(0x01000004)

UTF16

p_rdb_CSU16

(0x11030004)

(d) データアドレスリスト

データアドレスリストは,分割キーのデータを格納する領域へのアドレスから成る構造体で,分割キー数分連続する領域です。分割キーのデータアドレスを設定する領域を次の表に示します。分割キーが複数ある場合,分割キーとして指定した列数分の配列にする必要があります。

データ領域は,バイナリ形式で記述してください。バイナリ形式については,マニュアル「HiRDB コマンドリファレンス」を参照してください。

表H‒10 分割キーのデータアドレスを設定する領域

データ型

データ型の詳細

説明

p_rdb_dadlst_t

struct p_rdb_TG_dadlst {

unsigned char * dataaddr ;

} p_rdb_dadlst_t ;

データ領域へのアドレス

注意事項

すべてのデータ型共通の注意事項
  • データアドレスリストの実データは,列で定義したデータ型の形式に変換してください。

  • データアドレスリストの実データ領域は,特に境界調整をする必要はありません。

DECIMAL,INTERVAL YEAR TO DAY,又はINTERVAL HOUR TO SECONDの場合の注意事項
  • 正の値の場合,データアドレスリストの実データの符号部は'C',又は'F'を使用してください。なお,DECIMAL型の符号正規化機能にYを指定している場合は,'A',及び'E'も使用できます。

  • 負の値の場合,データアドレスリストの実データの符号部は'D'を使用してください。なお,DECIMAL型の符号正規化機能にYを指定している場合は,'B'も使用できます。

CHAR,NCHAR,又はMCHARの場合の注意事項
  • CHAR,MCHARの場合,データアドレスリストのデータ領域には,定義長まで1バイトの空白を埋めてください。

  • NCHARの場合,データアドレスリストのデータ領域には,定義長まで2バイトの空白を埋めてください。2バイトの空白は,HiRDBサーバのセットアップ時に指定した文字コードの空白を指定する必要があります。

  • データアドレスリストのデータ領域は,HiRDBサーバで使用する文字コードで指定する必要があります。

VARCHAR,NVARCHAR,又はMVARCHARの場合の注意事項
  • データアドレスリストのデータ領域の実長部分は,文字列長ではなくバイトで表してください。

  • データアドレスリストのデータ領域の実長が,分割キーリストの定義長に満たない場合,後続する文字列に空白を埋めないでください。

  • データアドレスリストのデータ領域は,HiRDBサーバで使用する文字コードで指定してください。

(e) 最大値に関するマクロ

最大値に関するマクロを次の表に示します。

表H‒11 最大値に関するマクロ

マクロ名

意味(値)

p_rdb_MXDCL

分割キーの列数の最大値(16)

p_rdb_MNCND

表の分割数の最大値(4096)

p_rdb_MNCND_0902

表の分割数の最大値(1024)

(バージョン07-02から09-02のHiRDBを使用する場合)

p_rdb_MNCND_0701

表の分割数の最大値(512)

(バージョン07-01までのHiRDBを使用する場合)

(5) コーディング例

ハッシュ分割の場合の,C言語で記述した部分的なコーディング例を次に示します。このコーディング例を,ユーザの用途に合うようにカスタマイズして使用してください。ただし,SQL文実行時のエラー処理については記述していないので,必要に応じて記述するようにしてください。エラー処理については,「SQLのエラーの判定と処置」を参照してください。

(a) 宣言部

/*********************************************************************/
/* ALL RIGHTS RESERVED, COPYRIGHT (C) 1999,2000, HITACHI, LTD.       */
/* LICENSED MATERIAL OF HITACHI,LTD.                                 */
/* 表分割ハッシュ関数を使用したサンプルプログラム                    */
/*********************************************************************/
#include <stdio.h>
#include <string.h>
#include <pdbsqlda.h>
#include <pddbhash.h>
 
union data_area {                             /* データ格納領域      */
    short data_smallint ;
    int data_int ;
    unsigned char data_dec[15] ;
    float data_smallflt ;
    double data_float ;
    unsigned char data_char[255] ;
    struct {
        short length ;
        unsigned char data[255] ;
    } data_varchar ;
    unsigned char data_date[4] ;
    unsigned char data_time[3] ;
    unsigned char data_timestamp[10] ;
    unsigned char data_iytd[5] ;
    unsigned char data_ihts[4] ;
} ;
 
void print_data(short , p_rdb_collst_t * , union data_area *) ;
 
 
/*********************************************************************/
/* メイン関数                                                        */
/*********************************************************************/
int main(int argc , char *argv[])
{
 
  short           hashcode ;              /* ハッシュ関数コード   */
  short           ncol ;                  /* 分割キーの列数       */
  p_rdb_collst_t  collst[p_rdb_MXDCL] ;   /* 分割キーリスト       */
  p_rdb_csidlst_t csidlst[p_rdb_MXDCL] ;  /* 文字集合IDリスト   */
  p_rdb_dadlst_t  dadlst[p_rdb_MXDCL] ;   /* データアドレスリスト */
  union data_area data[p_rdb_MXDCL] ;     /* データ格納領域       */
  unsigned int    ndiv ;                  /* 格納先RDエリア数    */
  unsigned char   ncspace[2] ;            /*各国文字スペースコード*/
  int             flags ;                 /* エンハンス用フラグ   */
  int             rdno ;                  /* 分割条件指定順序     */
  int             rc ;                    /* リターン値           */
  short           i, j, k ;               /* カウンタ用変数       */
 
  struct rdarea {                         /* RDエリアリスト       */
  int             rdareaid ;
  char            rdareaname[31] ;
  } rdarealst [p_rdb_MNCND] ;
 
  EXEC SQL BEGIN DECLARE SECTION ;
    struct {                       /* ハッシュ関数名の埋込み変数    */
      short length ;
      char data[9] ;
    } xhashname ;
    short xncol ;                 /* 分割キーの列数の埋込み変数     */
    short xndiv ;                 /* 表の分割数の埋込み変数         */
    short xdatatype ;             /* データ型コードの埋込み変数     */
    short xdatalen ;              /* データ長コードの埋込み変数     */
    int   xcharset_id ;           /* 文字集合IDコードの埋込み変数*/
    struct {                      /* 格納先RDエリア名の埋込み変数  */
      short length ;
      char data[31] ;
    } xrdname ;
  EXEC SQL END DECLARE SECTION ;
 
  EXEC SQL CONNECT ;

注※ 分割キーに文字集合の指定がある場合にだけ指定します。

(b) データ格納領域,各国文字コードのスペースの設定

  for  (k = 0 ; k < p_rdb_MXDCL ; k ++) {
  dadlst[k].dataaddr = (unsigned char *)&data[k] ;
  }
  ncspace[0] = 0x81 ;                     /* スペースコード          */
  ncspace[1] = 0x40 ;                     /* シフトJIS漢字コードの例*/
  flags = 0 ;

(c) flagsの設定

  /*******************************************************************/
  /* (a) 明示的に指定する場合                                        */
  /*     空白変換レベル1・DECIMAL型の符号正規化機能Yの場合        */
  /*******************************************************************/
  flags=p_rdb_FLG_SPLVL_1+p_rdb_FLG_DECNRM_Y;

(d) ハッシュ関数名,分割キーの列数,格納先RDエリア数の設定

  /*******************************************************************/
  /* (a) コードで設定する場合                                        */
  /*******************************************************************/
  hashcode = p_rdb_HASH6 ;            /* HASH6を指定する場合       */
  ncol = 4 ;                          /* 4列で分割する場合         */
  ndiv = 6 ;                          /* 6分割する場合             */
 
  /*******************************************************************/
  /* (b) ディクショナリ表から検索する場合                            */
  /*******************************************************************/
  EXEC SQL 
      select  HASH_NAME,
            value(N_DIV_COLUMN,1) ,
            N_RDAREA
          into  :xhashname , :xncol, :xndiv
          from MASTER.SQL_TABLES
          where TABLE_SCHEMA=USER
            and TABLE_NAME='TABLE1' ;
 
  xhashname.data[xhashname.length] = '\0' ;
  if (strcmp(xhashname.data,"HASH1") == 0) {
      hashcode=p_rdb_HASH1 ;                         /* HASH1設定  */
  } else if (strcmp(xhashname.data,"HASH2") == 0) {
      hashcode=p_rdb_HASH2 ;                         /* HASH2設定  */
  } else if (strcmp(xhashname.data,"HASH3") == 0) {
      hashcode=p_rdb_HASH3 ;                         /* HASH3設定  */
  } else if (strcmp(xhashname.data,"HASH4") == 0) {
      hashcode=p_rdb_HASH4 ;                         /* HASH4設定  */
  } else if (strcmp(xhashname.data,"HASH5") == 0) {
      hashcode=p_rdb_HASH5 ;                         /* HASH5設定  */
  } else if (strcmp(xhashname.data,"HASH6") == 0) {
      hashcode=p_rdb_HASH6 ;                         /* HASH6設定  */
  } else if (strcmp(xhashname.data,"HASHZ") == 0) {
      hashcode=p_rdb_HASHZ ;                         /* HASHZ設定  */
  } else if (strcmp(xhashname.data,"HASH0") == 0) {
      hashcode=p_rdb_HASH0 ;                         /* HASH0設定  */
  } else if (strcmp(xhashname.data,"HASHA") == 0) {
      hashcode=p_rdb_HASHA ;                         /* HASHA設定  */
  } else if (strcmp(xhashname.data,"HASHB") == 0) {
      hashcode=p_rdb_HASHB ;                         /* HASHB設定  */
  } else if (strcmp(xhashname.data,"HASHC") == 0) {
      hashcode=p_rdb_HASHC ;                         /* HASHC設定  */
  } else if (strcmp(xhashname.data,"HASHD") == 0) {
      hashcode=p_rdb_HASHD ;                         /* HASHD設定  */
  } else if (strcmp(xhashname.data,"HASHE") == 0) {
      hashcode=p_rdb_HASHE ;                         /* HASHE設定  */
  } else if (strcmp(xhashname.data,"HASHF") == 0) {
      hashcode=p_rdb_HASHF ;                         /* HASHF設定  */
  } else {
      /* 将来,ハッシュ関数が追加になった時に追加する。             */
  }
  ncol = xncol ;
  ndiv = xndiv ;
 
  /* =========================================================== */
  /* 表定義情報表示                                              */
  /* =========================================================== */
  printf("ハッシュ関数コード:%d\n",hashcode) ;
  printf("分割キーの列数    :%d\n",ncol) ;
  printf("表の分割数        :%d\n",ndiv) ;
  printf("\n") ;

(e) 分割キーの指定順序,データ型コード,データ長コードの設定(分割キーに文字集合の指定がない場合)

  /******************************************************************/
  /* (a) コードで設定する場合                                       */
  /******************************************************************/
  collst[0].datatype=PDSQL_CHAR ;             /* CHAR(10)        */
  collst[0].datalen=10 ;
  collst[1].datatype=PDSQL_DECIMAL ;          /* DEC(5,2)        */
  collst[1].datalen=5*256+2 ;
  collst[2].datatype=PDSQL_SMALLINT ;         /* SMALLINT        */
  collst[2].datalen=2 ;
  collst[3].datatype=PDSQL_NVARCHAR ;         /* NVARCHAR(4)     */
  collst[3].datalen=4 ;
 
  /*******************************************************************/
  /* (b) ディクショナリ表から検索する場合                            */
  /*******************************************************************/
  EXEC SQL
      declare cr1 cursor for
          select  value(DIVCOL_ORDER,1) ,
                  DATA_TYPE_CODE,
                  DATA_LENGTH_CODE
          from MASTER.SQL_COLUMNS
          where TABLE_SCHEMA=USER
            and TABLE_NAME='TABLE1'
            and DIVIDED_KEY='Y'
          order by 1 asc ;
 
  EXEC SQL open cr1 ;
  EXEC SQL whenever not found goto fetch_end1 ;
 
  for  (i = 0 ; ; i++) {
      EXEC SQL fetch cr1 into :xncol , : xdatatype , : xdatalen ;
      collst[i].datatype = xdatatype ;
      collst[i].datalen = xdatalen ;
  }
 
  fetch_end1 :
  EXEC SQL close cr1 ;

(f) 分割キーの指定順序,データ型コード,データ長コード,文字集合IDの設定(分割キーに文字集合の指定がある場合)

  /*******************************************************************/
  /* (a) コードで設定する場合                                        */
  /*******************************************************************/
  collst[0].datatype=PDSQL_CHAR ;         /* CHAR(10)              */
  collst[0].datalen=10 ;
  csidlst[0].charset_id=p_rdb_CSEBK ;     /* CHARACTER SET EBCDIK  */
  collst[1].datatype=PDSQL_DECIMAL ;      /* DEC(5,2)              */
  collst[1].datalen=5*256+2 ;
  csidlst[1].charset_id=p_rdb_CSDEF ;
  collst[2].datatype=PDSQL_SMALLINT ;     /* SMALLINT              */
  collst[2].datalen=2 ;
  csidlst[2].charset_id=p_rdb_CSDEF ;
  collst[3].datatype=PDSQL_NVARCHAR ;     /* NVARCHAR(4)           */
  collst[3].datalen=4 ;
  csidlst[3].charset_id=p_rdb_CSDEF ;
 
  /*******************************************************************/
  /* (b) ディクショナリ表から検索する場合                            */
  /*******************************************************************/
  EXEC SQL
      declare cr1_cs cursor for
          select  value(DIVCOL_ORDER,1),
                  DATA_TYPE_CODE,
                  DATA_LENGTH_CODE,
                  value(CHARSET_ID,0)
             from MASTER.SQL_COLUMNS
            where TABLE_SCHEMA=USER
              and TABLE_NAME='TABLE1'
              and DIVIDED_KEY='Y'
            order by 1 asc ;
  
  EXEC SQL open cr1_cs ;
  EXEC SQL whenever not found goto fetch_end1_cs ;
  
  for  (i = 0 ; ; i++) {
       EXEC SQL fetch cr1_cs into :xncol , : xdatatype , : xdatalen, :xcharset_id ;
       collst[i].datatype = xdatatype ;
       collst[i].datalen = xdatalen ;
       csidlst[i].charset_id = xcharset_id ;
  }
  
  fetch_end1_cs :
  EXEC SQL close cr1_cs ;

(g) 格納先RDエリア名の設定

  /*******************************************************************/
  /* ディクショナリ表から検索する場合                                */
  /*******************************************************************/
  EXEC SQL
      declare cr2 cursor for
          select RDAREA_NAME
              from MASTER.SQL_DIV_TABLE 
              where TABLE_SCHEMA=USER
                and TABLE_NAME='TABLE1'
              order by DIV_NO asc ;
  
  EXEC SQL open cr2 ;
  EXEC SQL whenever not found goto fetch_end2 ;
 
  for (j = 0 ; ; j++) {
      EXEC SQL fetch cr2 into :xrdname ;
      strncpy(rdarealst[j].rdareaname,
              xrdname.data,
              xrdname.length) ;
      rdarealst[j].rdareaname[xrdname.length] = '\0' ;
  }
 
  fetch_end2 :
  EXEC SQL close cr2 ;
 
  EXEC SQL DISCONNECT ;
 
  /* =========================================================== */
  /* RDエリア情報表示                                          */
  /* =========================================================== */
  printf("RDエリア名:[")  ;
  for (j = 0 ; j<ndiv ; j++) {
      printf("%s",rdarealst[j].rdareaname) ;
      if (j != ndiv-1) {
               printf(",") ;
      } else ;
  }
  printf("]\n") ;
  printf("\n") ;

(h) 分割キーに格納するデータ設定

  /*******************************************************************/
  /* バイナリ形式で代入する。                                        */
  /*  行ごとにデータを設定してハッシュ関数を呼ぶ                     */
  /*******************************************************************/
  memcpy((char *)data[0].data_char,"abcdefg   ",10); /* "abcdefg   " */
 
  data[1].data_dec[0] = 0x04 ;
  data[1].data_dec[1] = 0x32 ; 
  data[1].data_dec[2] = 0x1D ;                   /* -43.21       */
 
  data[2].data_smallint = 12345 ;                /* 12345        */
 
  /* NCHAR,NVARCHARは,HiRDBサーバの文字コードで指定する。   */
  data[3].data_varchar.length = 6 ;
  data[3].data_varchar.data[0] = 0x82 ;    /* あ                      */
  data[3].data_varchar.data[1] = 0xa0 ;    /* シフトJIS漢字コードの例*/
  data[3].data_varchar.data[2] = 0x82 ;    /* い                      */
  data[3].data_varchar.data[3] = 0xa2 ;    /* シフトJIS漢字コードの例*/
  data[3].data_varchar.data[4] = 0x82 ;    /* う                      */
  data[3].data_varchar.data[5] = 0xa4 ;    /* シフトJIS漢字コードの例*/
 
  /* =========================================================== */
  /* データ型コード,データ長コード,データ領域表示              */
  /* =========================================================== */
  print_data(ncol , collst , data) ;
 
  /* =========================================================== */
  /* ハッシュ関数コール                                          */
  /* =========================================================== */
  rc = p_rdb_dbhash(hashcode,ncol,collst,dadlst,ndiv,ncspace,flags,&rdno);
 
  switch (rc) {
  case p_rdb_RC_RTRN :
    /*****************************************************************/
    /* 正常処理                                                      */
    /*****************************************************************/
    printf("分割条件指定順序 : %d -> %s\n",
           rdno,rdarealst[rdno-1].rdareaname) ;
    break ;
  default :
    /*****************************************************************/
    /* エラー処理を追加する                                          */
    /*****************************************************************/
    printf("RETURN CODE=%d\n",rc) ;
    break ;
  }
 
  return ;
}
 
/*********************************************************************/
/* データ型コード,データ長コード,データ領域表示関数                */
/*********************************************************************/
void print_data( short           ncol ,
                 p_rdb_collst_t  *pcollst ,
                 union data_area *pdata )
{
  int i , j ;                                   /*  カウンタ用変数  */
  int len;
  p_rdb_collst_t   *ccollst ;
  union data_area  *cdata ;
 
  printf("分割キー指定順序 データ型コード データ長コード バイナリ形式のデータ値\n") ;
  for  (i = 0 , ccollst = pcollst , cdata = pdata ;
        i<ncol ;
        i++ , ccollst++ , cdata++) {
      printf("             %2d         %#.4x         %#.4x  ",
              i+1,ccollst->datatype, ccollst->datalen) ;
 
    switch (ccollst->datatype) {
      case PDSQL_CHAR :
      case PDSQL_MCHAR :
      case PDSQL_INTEGER :
      case PDSQL_SMALLFLT :
      case PDSQL_FLOAT :
      case PDSQL_SMALLINT :
      case PDSQL_DATE :
      case PDSQL_TIME :
      case PDSQL_TIMESTAMP :
          len=ccollst->datalen ;
          break ;
      case PDSQL_VARCHAR :
      case PDSQL_MVARCHAR :
      case PDSQL_NVARCHAR :
          len=cdata->data_varchar.length+2 ;
          break ;
      case PDSQL_NCHAR :
          len=ccollst->datalen*2 ;
          break ;
      case PDSQL_DECIMAL :
      case PDSQL_YEARTODAY :
      case PDSQL_HOURTOSEC :
          len=ccollst->datalen/256/2+1 ;
          break ;
      default :
          break ;
      }
      for (j=0 ; j<len ;j++){
          printf("%.2X",cdata->data_char[j]) ;
      }
      printf("\n") ;
  }
  printf("\n") ;
return ;
}

(i) HP-UX,シフトJIS漢字コードの場合の実行結果

ハッシュ関数コード:6
分割キーの列数    :4
表の分割数        :6
 
RDエリア名:[RU01,RU02,RU03,RU04,RU05,RU06]
 
分割キー指定順序 データ型コード データ長コード バイナリ形式のデータ値
              1         0x00c4         0x000a  61626364656667202020
              2         0x00e4         0x0502  04321D
              3         0x00f4         0x0002  3039
              4         0x00b0         0x0004  000682A082A282A4
 
分割条件指定順序 : 1 -> RU01

(6) ディクショナリ表からの検索(ハッシュ分割の場合)

ハッシュ分割の場合の,ディクショナリ表からの検索例を次に示します。

(a) ハッシュ分割表のハッシュ関数名,分割キーの列数,表の分割数の取得

SELECT HASH_NAME,                        /*ハッシュ関数名   */
       VALUE(N_DIV_COLUMN,1),            /*分割キーの列数   */
       N_RDAREA                          /*表の分割数       */
    FROM MASTER.SQL_TABLES 
      WHERE TABLE_SCHEMA=認可識別子      /*認可識別子が一致するもの */
        AND TABLE_NAME=表識別子          /*表識別子が一致するもの   */

(b) 分割キー指定順序とデータ型コード,データ長コードの取得(分割キーに文字集合の指定がない場合)

SELECT VALUE(DIVCOL_ORDER,1),           /*分割キー指定順序  */
       DATA_TYPE_CODE,                  /*データ型コード    */
       DATA_LENGTH_CODE                 /*データ長コード    */
    FROM MASTER.SQL_COLUMNS
      WHERE TABLE_SCHEMA=認可識別子     /*認可識別子が一致するもの */
        AND TABLE_NAME=表識別子         /*表識別子が一致するもの   */
        AND DIVIDED_KEY='Y'             /*分割キーのもの           */
    ORDER BY 1 ASC

(c) 分割キー指定順序とデータ型コード,データ長コード,文字集合IDコードの取得(分割キーに文字集合の指定がある場合)

SELECT VALUE(DIVCOL_ORDER,1),            /*分割キー指定順序   */
     DATA_TYPE_CODE,                     /*データ型コード     */
     DATA_LENGTH_CODE,                   /*データ長コード     */
     VALUE(CHARSET_ID,0)                 /*文字集合IDコード  */
   FROM MASTER.SQL_COLUMNS 
     WHERE TABLE_SCHEMA=認可識別子       /*認可識別子が一致するもの */
       AND TABLE_NAME=表識別子           /*表識別子が一致するもの   */
       AND DIVIDED_KEY='Y'               /*分割キーのもの           */
   ORDER BY 1 ASC

(d) 格納先RDエリア名の取得

SELECT  DIV_NO,                       /*分割条件指定順序    */
        RDAREA_NAME                   /*格納先RDエリア名   */ 
    FROM MASTER.SQL_DIV_TABLE
      WHERE TABLE_SCHEMA=認可識別子   /*認可識別子が一致するもの */
        AND TABLE_NAME=表識別子       /*表識別子が一致するもの   */
    ORDER BY 1 ASC

(7) ディクショナリ表からの検索(マトリクス分割の場合)

マトリクス分割の場合の,ディクショナリ表からの検索例を次に示します。

(a) ハッシュ分割表のハッシュ関数名,分割キーの列数,分割キー番号,表の分割数の取得

  • ハッシュ関数名と分割キーの列数の取得

select HASH_NAME,                    /*ハッシュ関数名          */
      value(N_DIV_COLUMN,1),         /*分割キーの列数          */
      KEY_NO                         /*分割キー番号            */
 from MASTER.SQL_DIV_TYPE
     where TABLE_SCHEMA=認可識別子   /*認可識別子が一致するもの*/
       and TABLE_NAME=表識別子       /*表識別子が一致するもの  */
  • キー内分割数の取得

select distinct N_DIVISION           /*キー内分割数            */
from MASTER.SQL_PARTKEY
     where TABLE_SCHEMA=認可識別子   /*認可識別子が一致するもの*/
       and TABLE_NAME=表識別子       /*表識別子が一致するもの  */
       and KEY_NO=分割キー番号       /*ハッシュ分割の          */
                                     /*分割キー番号を設定する  */

(b) 分割キー指定順序とデータ型コード,データ長コードの取得(分割キーに文字集合の指定がない場合)

select DIVCOL_ORDER,                      /*キー内分割数            */
       DATA_TYPE_CODE,                    /*データ型コード          */
       DATA_LENGTH_CODE                   /*データ長コード          */
 from MASTER.SQL_COLUMNS X,
      MASTER.SQL_PARTKEY Y
     where X.TABLE_SCHEMA=Y.TABLE_SCHEMA
       and X.TABLE_NAME=Y.TABLE_NAME
       and X.COLUMN_ID=Y.COLUMN_ID
       and Y.TABLE_SCHEMA=認可識別子      /*認可識別子が一致するもの*/
       and Y.TABLE_NAME=表識別子          /*表識別子が一致するもの  */
       and Y.KEY_NO=分割キー番号          /*ハッシュ分割の          */
                                          /*分割キー番号を設定する  */
  order by DIVCOL_ORDER asc

(c) 分割キー指定順序とデータ型コード,データ長コード,文字集合IDの取得(分割キーに文字集合の指定がある場合)

select DIVCOL_ORDER,                      /*キー内分割数            */
      DATA_TYPE_CODE,                     /*データ型コード          */
      DATA_LENGTH_CODE,                   /*データ長コード          */
      value(CHARSET_ID,0)                 /*文字集合IDコード       */
 from MASTER.SQL_COLUMNS X,
      MASTER.SQL_PARTKEY Y
     where X.TABLE_SCHEMA=Y.TABLE_SCHEMA
       and X.TABLE_NAME=Y.TABLE_NAME
       and X.COLUMN_ID=Y.COLUMN_ID
       and Y.TABLE_SCHEMA=認可識別子     /*認可識別子が一致するもの */
       and Y.TABLE_NAME=表識別子         /*表識別子が一致するもの   */
       and Y.KEY_NO=分割キー番号         /*ハッシュ分割の           */
                                         /*分割キー番号を設定する   */
  order by DIVCOL_ORDER asc

(d) 格納先RDエリア名の取得

select DIV_NO,                       /*分割条件指定順序        */
      RDAREA_NAME                    /*格納先RDエリア名       */
 from MASTER.SQL_DIV_TABLE
     where TABLE_SCHEMA=認可識別子   /*認可識別子が一致するもの*/
       and TABLE_NAME=表識別子       /*表識別子が一致するもの  */
       order by 1 asc

分割条件指定順序は,分割キー内通番から求められます。式を次に示します。

N×m−(N−n)
 N:第2次元の分割数
 m:第1分割キーの分割キー内通番
 n:第2分割キーの分割キー内通番