Chapter 2: mr ルーチン




2.1 はじめに

一般的に、mrルーチンによって、テーブルのオープン、レコードの追加、削除、検索、更新が行なえます。すべての操作は 一つのレコードに対して実行可能です。以下に示す、6つのデータポインタがあります。

  1. オープンされたテーブルを指す、テーブル記述子(teble_descriptors)。

  2. フィールドを指す、フィールド記述子(attribute_descriptors)。

  3. レコードを指す、レコード記述子(record_descriptors)。

  4. フィールドまたはレコードと、条件を関連付ける、条件記述子(qualification_descriptors)。

  5. テーブルと条件を関連付ける、検索記述子(retrieval_descriptors)。

  6. フィールド値の、外部フォーマットに一致する文字列(strings)。いくつかのフィールド値の、フォーマットを以下の 章で解説します。

最初の5つのデータポインタは、"addr"として宣言され、6番目の文字列は、"char *"として宣言しなくてはなりません。 テーブル、レコード、フィールド、条件の各記述子は、Emppress内部構造体へのポインタです。"addr"データタイプは、 "char *"として定義されていますが、これらのポインタは、文字列ではないので、そのように使用してはなりません。 addrデータタイプは、この連想子として使用されています。



2.2 mrルーチンによるアクセス

2.2.1 ヘッダーファイルmscc.h

ヘッダーファイルmscc.hは、mrルーチンを使用するプログラムの先頭で、インクルードしなくてはなりません。ここには すべてのmr関数の定義と、多数のデータタイプ(addr、booleanなど)と定数の定義が含まれています。 mscc.hは、標準I/Oライブラリをインクルードしているので、プログラム中で、このライブラリをインクルードする必要は ありません。mscc.hファイルの内容を、以下に示します。

mscc.hファイルは、バージョンによって内容が違います。正確なファイルの内容は、$EMPRESSPATH/includeディレクトリにあるファイルを参照してください。



   /***********************************************************************
    *      (c) Copyright   Empress Software Inc. 1983, 2002
    ***********************************************************************/

   #ifndef __MSCC_H

   #define __MSCC_H

   #ifdef __cplusplus
   extern "C" {
   #endif

   #include        <stdio.h>
   #include        "c.h"

   #include        <misc/public.h>
   #include        <usrmp/msdsqldt.h>
   #include        <usrfns/dtparvar.hx>
   #include        <api/mrapi.hx>
   #include        <api/msapi.hx>
   #include        <api/mxapi.hx>
   #include        <misc/init.hx>
   #include        <misc/mscc_com.h>
   #include        <misc/mxe.h>
   #include        <misc/mxtrig.h>


   #ifdef __cplusplus
   }
   #endif

   #endif  /* __MSCC_H */


2.2.2 初期化とクリーンアップ

Empress mrルーチンを使用した、プログラムの作成には、2つの方法があります。

  1. 通常のmainプロシージャを、msmainとします。これは必要な初期化を行い、mainプロシージャをインクルード します。また、通常通り、パラメータargcとargvを使用できます。 同様に、通常のexitプロシージャをmsexitにします。

  2. mainプロシージャを書くことも可能です。そのためには、msinitを呼び出して初期化し、msexitを呼び出して クリーンアップします。

msclean関数は、プログラム終了前に、呼び出され実行されるプロシージャを、スタックに配置します。

2.2.3 コンパイルとリンク

mrルーチンを使用したプログラムは、ccではなくempccまたはempc++で、コンパイルされる必要があります。この結果、 コンパイルで、Empress関数のライブラリが、確実にリンクされます。この他はccと同様に機能します。

mscall文も、empccまたはempc++によって、コンパイルされるプログラムで使用できます。例えば、アプリケーション プログラム内で、新しいテーブルを作成する、最も簡単な方法は、mscall文を使用することです。



2.3 内部、外部、ファイルフォーマット

ここでは、フィールド値の内部、外部、ファイルフォーマットについて解説します。外部フォーマットは、クエリーのSELECT コマンドによって、表示されるフォーマットです。外部フォーマットの値は、文字列です。

内部フォーマットは、Empressで処理されるフォーマットです。これは外部フォーマットと、必ずしも一致しません。例えば date(1)タイプの値は、"20 April 2003"として処理されているわけではありません。またDOLLARタイプでは、ドル記号、カンマ、ピリオドを 持った値が、処理されているわけではありません。

ファイルフォーマットは、Empressによりディスク上に、値が保存される場合のフォーマットです。アプリケーションプログラムで 、ファイルフォーマットを、直接検索することはありません。

フィールド値は、通常は外部フォーマットで検索されますが、integer値または内部フォーマット値を、直接検索することも 可能です。フィールドへの、値の割り当ては、通常は外部フォーマットまたはinteger値で行いますが、内部フォーマットで 、直接割り当てることも可能です。

外部フォーマットで、検索された値の算術を行なう場合には、sscanf()やatof()を使用して、文字列から数値に変換する必要 があります。またドル記号、アスタリスクなどは、変換前に、DOLLAR値から削除しなければなりません。これを実行する方法 はdollcvtであり、3章で解説します。

BULKデータ値は、他のタイプとは異なった処理となります。外部フォーマットで、Bulk値を出力するには、バイトを通常 必要としない、16進文字に変換します。Bulkデータは、mrgetiを用いて内部フォーマットで取得できます。この関数は Bulkデータの検索用に、特に意図して作成されたものですが、他の内部フォーマットを取得するためにも、使用することが 可能です。次に章のサンプルプログラム、voice.cで内部フォーマットのBulk値を取得する、mrgetiの使用方法を解説して います。



2.4 データタイプ

Empressデータタイプ(MSデータタイプ)とC言語データタイプは、通常(マシンのアーキテクチャに従って)、以下のように 対応します。 データベースからの検索値を、C変数に格納する場合には、対応した適切なタイプでなければなりません。

Table 2-1 MSデータタイプに対応するC言語データタイプ

MSデータタイプ Cデータタイプ
CHAR
CHARACTER
char[](EOSで終了)
SHORTINTEGER
SMALLINT
char
INTEGER
INT
short
LONGINTEGER long
DATE gen_date
DOLLAR unsigned char[]
REAL float
LONGFLOAT
DOUBLE PRECISION
double
FLOAT float : if decimal places <=6
double : if decimal places > 6
TEXT char[] (EOSで終了)
BULK gen_binary*
DECIMAL
DEC
unsigned char[]
TIME gen_date
NLSCHAR
NLSCHARACTER
char[] (EOSで終了)
NLSTEXT char[] (EOSで終了)
MICROTIMESTAMP gen_date


Table 2-2 汎用データタイプに対応するC言語データタイプ

汎用データタイプ Cデータタイプ
GENERIC CHAR char*
GENERIC INTEGER gen_integer
GENERIC DECIMAL gen_dec
GENERIC FLOAT gen_float
GENERIC DATE gen_date
GENERIC BOOLEAN gen_boolean
GENERIC EXTERNAL char*
GENERIC INTERVAL gen_date
GENERIC BINARY gen_binary*



2.5 エラーハンドリング

テーブルに、レコードレベルのロックが設定されていて、mrルーチンから、アクセスするレコードがロックされている場合、 あるいは、テーブルに格納しようとしているデータが、範囲チェックや重複制限インデックスのために、認められない場合、 あるいは、不適切なデータが受け渡された場合など、mrルーチンが、正しく実行を完了できない場合があります。

mrルーチンが失敗した場合に、呼出しプログラムを終了するか、しないかは関数によって異なります。関数の、成功あるいは 失敗を示す、フラグを返す関数は、他の方法で指定しない限り、失敗した場合には終了しません。フラグを返さない関数は、 失敗した場合に終了します。操作は、失敗時に終了する関数と、しない関数の2つを使用している場合が、あることに注意 してください。

失敗した場合でも、終了しない関数では、mroperr変数に、mrerrno.hファイルで定義されている、エラー変数MERE....の いづれかがセットされます。mroperr変数を参照する事により、失敗した原因や理由を取得することができ、アプリケーションを 制御することが可能となります。

mrerrno.hファイルの内容を、以下に示します。尚、この内容はバージョンにより違います。正確な内容は、 $EMPRESSPATH/include/usrmrディレクトリ配下にある、ファイルを参照してください。



   /***********************************************************************
    *  (c) Copyright Empress Software Inc. 1983, 2002
    ***********************************************************************/
   
   #define MRNOERR             0 /* no error indication*/
   #define MRERNAME            1 /* invalid table name */
   #define MREREXIST           2 /* table already exists */
   #define MRERNEXIST          3 /* table does not exist */
   #define MRERRPERM           4 /* no read permission on table */
   #define MRERWPERM           5 /* no read/write permission on tab */
   #define MRERBUSY            6 /* database/table lock busy */
   #define MRERVWOP            7 /* operation invalid on view */
   #define MRERVWDEF           8 /* invalid definition for view */
   #define MRERVWRECUR         9 /* recursive definition for view */
   #define MRERDBEXIST        10 /* not a database */
   #define MRERANAME          11 /* invalid attribute name */
   #define MRERAEXIST         12 /* attribute already exists */
   #define MRERANEXIST        13 /* attribute does not exist */
   #define MRERDTPAR          14 /* invalid data type/parameters */
   #define MRERINAME          15 /* invalid index name */
   #define MRERNULL           16 /* null value for attribute */
   #define MRERUDUP           17 /* duplicate value for attribute */
   #define MRERDUP            18 /* too many duplicate values */
   #define MRERCVT            19 /* bad value conversion for attr */
   #define MRERPRIV           20 /* no privilege for table */
   #define MRERAPRIV          21 /* no update privilege on attribute */
   #define MRERCRPRIV         22 /* no create table privilege */
   #define MRERQOP            23 /* invalid operator/function */
   #define MRERQATTR          24 /* incompatible attributes */
   #define MRERQPAT           25 /* invalid pattern */
   #define MRERQRNG           26 /* invalid range */
   #define MRERXCONS          27 /* invalid constant */
   #define MRERXCVT           28 /* invalid conversion */
   #define MRERXFUNC          29 /* invalid operator/function */
   #define MRERIEXIST         30 /* index already exists */
   #define MRERINEXIST        31 /* index does not exist */
   #define MRERICOMP          32 /* index name/definition mismatch */
   #define MRERCREATOR        33 /* invalid creator name */
   #define MRERCRPERMS        34 /* invalid create permissions */
   #define MRERDDEXIST        35 /* data dictionary already exists */
   #define MRERDBA            36 /* not the dba */
   #define MRERINPRIV         37 /* insufficient privileges */
   #define MRERDBACR          38 /* not the dba or creator */
   #define MRERRCNAME         39 /* invalid constraint name */
   #define MRERRCEXIST        40 /* constraint already exists */
   #define MRERRCNEXIST       41 /* constraint does not exist */
   #define MRERRCINSERT       42 /* insert constraint violation */
   #define MRERRCDELETE       43 /* delete constraint violation */
   #define MRERRCLKBUSY       44 /* cannot check constraint */
   #define MRERRCINCDTS       45 /* incompatible types in constraint */
   #define MRERRCOTABLE       46 /* cannot open table for constraint */
   #define MRERRCNATTR        47 /* invalid attribute in constraint */
   #define MRERNLOC           48 /* invalid location */
   #define MRERVWTWICE        49 /* table selected twice in view */
   #define MRERVWNONEQ        50 /* join condition without '=' */
   #define MRERVWOROP         51 /* OR conjunction in view */
   #define MRERVWNOTOP        52 /* NOT operator in view */
   #define MRERVWJOIN         53 /* insufficient join conditions */
   #define MRERVWKEY          54 /* insufficient keys in view */
   #define MRERVWREATTR       55 /* view attributes repeated/equated */
   #define MRERVWNONULL       56 /* cannot obtain 'not null' value */
   #define MRERVWUNIND        57 /* unique value unobtainable in view */
   #define MREREXPR           58 /* expression failure */
   #define MRERTRPROGRESS     59 /* transaction already in progress */
   #define MRERTRSTARTNOT     60 /* unable to start transaction */
   #define MRERTROFF          61 /* no transaction in progress */
   #define MRERTRINVSVP       62 /* invalid save point name */
   #define MRERTRSVPEXISTS    63 /* save point name already exists */
   #define MRERTRNOSVP        64 /* save point does not exist */
   #define MRERNUPDMODE       65 /* table opened in non-updatable mode */
   #define MRERSERVER         66 /* server not available */
   #define MRERANOTDTF        67 /* not a variable length attribute */
   #define MRERINOVRFL        68 /* index has no overflow file */
   #define MRERCRFL           69 /* cannot create data files */
   #define MRERCRFLACCESS     70 /* no access to create data files */
   #define MRERVWATTREX       71 /* too many attribute names specified */
   #define MRERGENDT          72 /* unknown generic type */
   #define MRERRECNO          73 /* invalid record number */
   #define MRERDT             74 /* invalid data type */
   #define MREREXDTPAR        75 /* too many parameters for the data type */
   #define MRERBADDTPAR       76 /* bad data type parameter */
   #define MRERATTRSPEC       77 /* attribute specification not allowed */
   #define MRERHAVBADA        78 /* disallowed attribute in having clause */
   #define MRERVWGRPGRP       79 /* no group by allowed on grouped view */
   #define MRERVWGRPHAV       80 /* no having allowed on grouped view */
   #define MRERVWGRPJOIN      81 /* no join allowed on a grouped view */
   #define MRERVWGRPQUAL      82 /* no qual allowed on grouped view */
   #define MRERVWORDERINT     83 /* invalid order by specification (integer) */
   #define MRERVWINSELHAV     84 /* invalid select list with having clause */
   #define MRERQNESTATTR      85 /* too many attributes in nested select */
   #define MRERVWAGGATTRX     86 /* no derived aggr attribute in expression */
   #define MRERVWAGGRHAV      87 /* no having allowed on aggregate view */
   #define MRERVWAGGRJOIN     88 /* no join allowed on a aggregate view */
   #define MRERVWAGGRQUAL     89 /* no qual allowed on aggregate view */
   #define MRERVWGRPAGGR      90 /* no aggr function allowed on grouped view */
   #define MRERVWINSELDIST    91 /* invalid select list with select distinct */
   #define MRERVWAGGATTRG     92 /* no derived aggr attribute in group by */
   #define MRERNOHASHREC      93 /* record not found in table */
   #define MREROPMODE         94 /* invalid table open mode */
   #define MRERVWORDERSEL     95 /* invalid order by specification (select) */
   #define MRERINVTXT         96 /* invalid char in the value for attribute */
   #define MRERDRIOATTR       97 /* direct I/O not supported for attribute */
   #define MRERDRIOSET        98 /* file redirection error */
   #define MRERCRSIZE         99 /* record size too large */
   #define MRERNLCOMP        100 /* null compile entry for the table */
   #define MRERNOCOMP        101 /* no compile entry for the table */
   #define MRERNVEW          102 /* expecting a view, got a table */
   #define MR_DB_ALREADY_LOCKED 103 /* the database has been already locked */
   #define MR_IN_ADM         104 /* the dba put the database down*/
   #define MRERDTER          105 /* Refer to error at DT level */
   #define MRERINVUREC       106 /* invalid record for update */
   #define MRERURECDEL       107 /* record for update has been deleted */
   #define MRERAGGRNORECS    108 /* no records to do aggregate */
   #define MRERNOCRSHM       109 /* cannot create shared memory */
   #define MRERNORMSHM       110 /* cannot remove shared memory */
   #define MREROUTERILL      111 /* Illegal outer join */
   #define MRERNOSHM         112 /* No shared memory available */
   #define MRERDRECDEL       113 /* deleted record for delete */
   #define MRERNONEXIST      114 /* no data file for '%s' */
   #define MRERNET           115 /* network error in file operation */
   #define MREROPEN          116 /* bad data file for '%s' */
   #define MRERFLOPMODE      117 /* invalid open mode '%c' */
   #define MRERSVPORT_BADID  118 /* invalid server port id */
   #define MRERSVPORT_INCOMPAT 119 /* incompatible server port id */
   #define MRERSVPORT_UNDEF  120 /* server port not defined */
   #define MREROPDICTMODE    121 /* invalid data dictionary open mode */
   #define MRERFULLBUSY      122 /* lock resource is full */
   #define MRERNOLKRESOURCE  123 /* cannot access lock resource */
   #define MRERBADRECORD     124     /* bad record retrieved */
   #define MRERBADDATARETR   125     /* from DT: bad var.len.val.retrieved*/
   #define MRERSORTLOCK      126 /* sort by error(locked) **WARNING */
   
   #define MRERMNAME         127 /* invalid module name */
   #define MRERMEXIST        128 /* module already exist */
   #define MRERMNEXIST       129 /* module does not exist */
   #define MRERLANGOPTION    130 /* invalid language option */
   #define MRERFNAME         131 /* invalid SQL-invoked routine name */
   #define MRERFMCLASS       132 /* there are multiple function
                                    classes for same routine */
   #define MRERFEXIST        133 /* SQL-invoked routine already exist */
   #define MRERFNEXIST       134 /* SQL-invoked routine not exist */ 
   #define MRERPARAMNAME     135 /* invalid parameter name */
   #define MRERPARAMEXIST    136 /* parameter already exist */
   #define MRERPARAMNEXIST   137 /* parameter does not exist */
   #define MRERPARAMNO       138 /* invalid parameter number */ 
   #define MRERQPARAM        139 /* incompatible parameter */
   #define MRERPARAMNUM      140 /* too many parameters */
   #define MRERPARAMNUM1     141 /* expecting one parameter */
   #define MRERPARAMNUM2     142 /* expecting two parameters */
   #define MRERPARAMB        143 /* parameter data type should 
                                    be generic boolean */  
   #define MRERPARAMNB       144 /* parameter data type should 
                                    be parametric data type */
   #define MRERRETB          145 /* return data type should be 
                                    generic boolean */
   #define MRERRETNB         146 /* return data type should be 
                                    parametric data type */
   #define MRERARETNB        147 /* aggregate function's return data type 
                                    should be parametric data type */
   #define MREREXTNAME       148 /* invalid external function name */
   #define MREREXTEXIST      149 /* external name already exist */
   #define MRERFILENEXIST    150   /* file doesn't exist */
   
   #define MRERTRNAME        151  /* invalid trigger name */
   #define MRERTREXIST       152 /* trigger already exist */
   #define MRERTRNEXIST      153 /* trigger does not exist */
   #define MRERMODWRAPCOMPFAIL 154 /* failed to compile wrapper for module */
   #define MRERDDCACHEFAIL   155 /* failed to modify DD_CACHE for module */
   #define MRERXSVFUNC       156 /* SQL-invoked routine '%s' is not 
                                    available on the client */
   #define MRERTRIGABORT     157 /* operation aborted by trigger */
   #define MRERXTRIGPROC     158 /* trigger procedure should have
                                    no parameter */
   #define MRERNOTRIGPROC    159 /* trigger procedure '%s' unavailable */
   #define MRERTRIG_OLD_NEW  160 /* attribute '%s' must be qualified 
                                    by OLD or NEW */
   #define MRERTRIGNESTED    161 /* nested queries are not allowed
                                    for triggers */
   #define MRERPARAMSTYLE    162 /* parameter style of SQL-invoked
                                    routine '%s' inconsistent */ 
   #define MRERMODWRAPGENFAIL 163 /* failed to generate wrapper for system */
   #define MRERNOATTR        164 /* no attributes left in table '%s */
   #define MRERRNGCONVT      165 /* cannot convert range check for 
                                    attribute '%s' */
   #define MRERCANTADDATTR   166 /* cannot add non-null attribute 
                                    to non-empty table */
   #define MRERDUPATTR       167 /* duplicate attribute '%s' */
   #define MRERFEWCONS       168 /* too few constants */
   #define MRERMANYCONS      169 /* too many constants */
   #define MRERWRONGCONS     170 /* wrong number of constants */
   #define MRERAINVEXPR      171 /* invalid expression for attribute '%s' */
   #define MRERSAMETAB       172 /* same table involved in select 
                                    and insert */
   #define MRERFEWSETATTR    173 /* too few SET attributes */
   #define MRERMANYSETATTR   174 /* too many SET attributes */
   #define MRERFEWATTRS      175 /* too few attributes in '%s' */
   #define MRERNOTNULLATTR   176 /* not-null attribute '%s' is not 
                                    included in attribute list */
   #define MRERINVATTR       177 /* invalid attribute '%s' for table '%s' */
   #define MRERINVIDXPARM    178 /* invalid index parameters (%s, %s)" */
   #define MRERNOPRIVCRVW    179 /* insufficient privileges to create view */
   #define MRERUNEQCONSTR    180 /* unequal number of attributes 
                                    in the constraint */
   #define MRERNOCONSTR      181 /* constraint '%s' does not exist */
   #define MRERNOIDX         182 /* index '%s' does not exist */
   #define MRERSYSTABLE      183 /* cannot perform %s operation on %s */
   #define MRERINVOPR        184 /* invalid operator '%s' */
   #define MREREXPRPROB      185 /* expression cannot be evaluated 
                                    or out of range */
   #define MRERUPDMOD        186 /* failed to update module '%s' 
                                    (unable to resolve symbol) */ 
   #define MRERCOPYRL        187 /* failed to copy file from server 
                                    to client */
   #define MRERCOPYLR        188 /* failed to copy file from client 
                                    to server */
   #define MRERINVCALLEXPR   189 /* invalid call expression, output 
                                    is not bound with a variable */
   /* next number is 190 */



2.6 Empressファイル割当て

プログラム内で、ファイルをオープンする必要がある場合、Empressがすべての使用可能なファイルをオープンしていて 実行できないのであれば、Empressによって、オープンされるファイルの数を制限する必要があります。 これは、オペレーティングシステムに、Empressのシステム変数MSFILESOPENを、設定することで実行できます。 例えば、Empressがオープンできるファイル数を、10に設定する場合を以下に示します。

これによって、Empressが10ファイルを越えたアクセスが、できないというわけではありません。 制限の10に到達した場合、Empressは、新しいファイルをオープンする前に、アクセスされていない、古いファイルをクローズ します。Empressによってクローズされたファイルは、必要に応じてアクセス時にオープンされます。Empressはファイルの 内容を内部に保存します。よって、クローズされたり、再オープンされたかはユーザには、わかりません

詳細は、Empress SQL: User's GuideSetting Variables を参照してください。



2.7 名前付け規約

mrルーチンの、それぞれの関数名は規則的な方法で、命名されています。個々の関数名は、"mr"で始まります。 次に、機能を表す1文字が付けられます。例えば、条件を処理する関数であれば、"q"が付けられます。 そして、また次には、処理を表す文字、例えば検索であれば"get"が付けられます。 "mr"の次に、"t"が入る関数は、関数の失敗、成功を通知すつ値を返します。"t"が入らない関数は、失敗したら 呼出しプログラムは、終了します。

すべてのmrルーチンの分類と、概要を以下に示します。個々の関数の詳細な仕様は、このマニュアルの最後に記載 されています。プログラム作成時に参照してください。

以下に、テーブルのオープンとクローズで使用される関数を示します。

Table 2-3: オープン関数

名前 概要
mropen データディクショナリーで指定されたロックを伴い、テーブルをオープンします。 失敗時には、呼出しプログラムを終了します。
mrtopen テーブルをオープンします。失敗時には、呼出しプログラムを終了しません。
mropdict データディクショナリーの、全テーブルをオープンします。失敗時には、呼出しプログラムを終了します。
mrtopdict データディクショナリーの、全テーブルをオープンします。 失敗時には、呼出しプログラムを終了しません。
mrclose テーブルをクローズし、ロックを解除します。
mrcldict データディクショナリーをクローズします。
mrqdb ディレクトリーが、データベースであるかチェックします。

以下に、ロックで使用される関数を示します。

Table 2-4: ロック関数

名前 概要
mrlktab テーブルレベルのロックを設定します。
mrlkrec レコードにロックを設定します。
mrultab テーブルレベルのロックを解除します。
mrulrec レコードのロックを解除します。

以下に、メモリの確保と解放で使用される関数を示します。

Table 2-5: スペース確保関数

名前 概要
mrmkrec 1つのレコードを保存するためのスペースを確保します。
mrfrrec mrmkrecで確保したスペースを開放します。
mrspv 1つのフィールド値を保存するためにスペースを確保します。
mrfree mrspvで確保したスペースを開放します。

以下に、フィールド記述子の操作で使用する関数を示します。

Table 2-6: フィールド記述子関数

名前 概要
mrngeta フィールド名から記述子を取得します。
mrigeta フィールド番号から記述子を取得します。
mrganame 記述子からフィールド名をします。

以下に、レコードに値を割り当てに使用する関数を示します。

Table 2-7: レコード割当て関数

名前 概要
mrputvs レコード内のフィールドに、値(外部フォーマット)を割当てます。失敗しても終了しません。
mrputvi レコード内のフィールドに、integer値を割当てます。失敗しても終了しません。
mrputi レコード内のフィールドに、値(内部フォーマット)を割当てます。失敗しても終了しません。
mrmptvs レコード内のフィールドに、値(外部フォーマット)を割当てます。失敗したら終了します。
mrmptvi レコード内のフィールドに、integer値を割当てます。
mrsetnv レコード内のフィールドに、NULL値を割当てます。
mrsetnr レコード内のすべてのフィールドに、NULL値を割当てます。

以下に、テーブル内にレコードを挿入するために使用する関数を示します。

Table 2-8: 挿入関数

名前 概要
mradd レコードを挿入します。失敗時に終了します。
mrtadd レコードを挿入します。失敗時に終了しません。
mraddend テーブルへの、レコード挿入後のクリーンアップを行います。

以下に、レコードを削除する場合に使用する関数を示します。

Table 2-9: 削除関数

名前 概要
mrdel レコードを削除します。失敗時に終了します。
mrtdel レコードを削除します。失敗時に終了しません。
mrdelend レコードを削除した後の、クリーンアップを行ないます。

以下に、レコードを更新する場合に使用する関数を示します。

Table 2-10: 更新関数

名前 概要
mrcopyr フィールド値を、レコードから別のレコードにコピーします。
mrput レコードを更新します。失敗時に終了します。
mrtput レコードを更新します。失敗時に終了しません。

以下に、検索に初期化を行なう場合に使用する関数を示します。

Table 2-11: 初期化関数

名前 概要
mrgetbegin 検索のために、条件とレコードを関連付けます。失敗時に終了します。
mrtgtbegin 検索のために、条件とレコードを関連付けます。失敗時に終了しません。
mrsrtbegin ソート検索のために、条件とレコードを関連付けます。失敗時に終了します。
mrtsrbegin ソート検索のために、条件とレコードを関連付けます。失敗時に終了しません。

以下に、検索のために使用される関数を示します。

Table 2-12: 検索関数

名前 概要
mrget レコードを検索します。
mrtget レコードを検索します。ロックされていれば通知します。
mrreget レコードを再検索します。
mrprev 前のレコードを検索します。
mrtprev 前のレコードを検索します。ロックされていれば通知します。
mrreprev 前のレコードを再検索します。
mrgetrec 以前に検索されたポインタが、参照するレコードを取得します。
mrgetend 検索後のクリーンアップを行ないます。
mrcontrol Bulk値から、検索されるバイト数を指定します。
mrcopyv フィールド値(外部フォーマット)を、割付けられたスペースに割当てます。
mrcopyi フィールド値(内部フォーマット)を、変数に割当てます。
mrgetvs フィールド値(外部フォーマット)を取得します。
mrgetvi フィールド値(integer値)を取得します。
mrgeti フィールド値(内部フォーマット)を取得します。
mrgetptr 後で使用するために、指定レコードへのポインタを取得します。
mrgfunc フィールドに対し、集計関数(count,max,min,avg,sum)の結果を取得します。失敗時に終了します。
mrtgfunc フィールドに対し、集計関数(count,max,min,avg,sum)の結果を取得します。失敗時に終了しません。

以下に、フィールド値の比較を実行する場合に使用する関数を示します。

Table 2-13: 比較関数

名前 概要
mrcompare 変数が、フィールド値に等しいか、小さいか、大きいか調べます。
mrnullr レコード全体が、NULLであるか調べます。
mrnullv フィールド値が、NULLであるか調べます。

以下に、異なるデータタイプ間で、値の変換に使用する関数を示します。

Table 2-14: 入力変換関数

名前 概要
mrcvt 外部フォーマットから、ファイルフォーマットへ値を変換します。(他の関数との共有バッファ使用)
mrcvtin 内部フォーマットから、ファイルフォーマットへ値を変換します。(他の関数との共有バッファ使用)
mrcvtv 外部フォーマットから、ファイルフォーマットへ値を変換します。(mrcvtiとの共有バッファ使用)
mrcvtv2 外部フォーマットから、ファイルフォーマットへ値を変換します。(mrcvti2との共有バッファ使用)
mrcvti 内部フォーマットから、ファイルフォーマットへ値を変換します。(mrcvtvとの共有バッファ使用)
mrcvti2 内部フォーマットから、ファイルフォーマットへ値を変換します。(mrcvtv2との共有バッファ使用)

以下に、フィールドを比較する場合に使用する関数を示します。

Table 2-15: 条件関数

名前 概要
mrqcon フィールド値を定数と比較します。失敗時には終了します。
mrtqcon フィールド値を定数と比較します。失敗時には終了しません。
mrqrng フィールド値を指定範囲と比較します。失敗時には終了します。
mrtqrng フィールド値を指定範囲と比較します。失敗時には終了しません。
mrqatr 2つのフィールド値を比較します。失敗時には終了します。
mrtqatr 2つのフィールド値を比較します。失敗時には終了しません。
mrqmch フィールド値を定数とマッチングします。失敗時には終了します。
mrtqmch フィールド値を定数とマッチングします。失敗時には終了しません。
mrqnul フィールド値をNULLと比較します。失敗時には終了します。
mrtqnul フィールド値をNULLと比較します。失敗時には終了しません。
mrqseq フィールド値が文字列と等しいか調べます。失敗時には終了します。
mrqieq フィールド値が文字列と等しいか調べます。失敗時には終了しません。
mrqand 2つの条件をAND結合します。
mrqor 2つの条件をOR結合します。
mrqnot 比較条件を否定します。
mrqlst 以前に取得した、レコードへのポインタのリストで、レコードを制限します。

以下に、トランザクションを制御するのに使用する関数を示します。

Table 2-16: トランザクション関数

名前 概要
mrtrstart トランザクションを開始します。
mrtrcancel トランザクションを取り消します。
mrtrcommit トランザクションを確定します。
mrtrsave トランザクション内にセーブポイントを設定します。
mrtrrollback セーブポイントまでロールバックします。

以下に、表現を構築する場合に使用する関数を示します。

Table 2-17: 表現関数

名前 概要
mrebegin 表現式の構築を開始します。
mreend 表現式の構築を完了します。
mreabort 表現式の構築を中止します。
mrqexpr 表現式を制限に配置します。
mrerun 表現式を実行し、結果を取得します。
mrefree 表現式の記述子を解放します。
mrerecattr フィールドオペランドを付加します。
mrecons 定数オペランドを付加します。
mreicvar 最新の変数を、制御変数に関連付けます。
mreivar 変数オペランドを付加します。
mrecvarg タイプ変換演算子を付加します。
mrefunc 関数または演算子を付加します。
mrenull NULL演算子を付加します。
mrgdtpar データタイプ記述子を調べます。

以下に、BULKとTEXTデータタイプ用の、データストリーミング関数を示します。

Table 2-18: データストリーミング関数

名前 概要
mrbuktxtcrt .dtfファイル(BULK、TEXTのオーバーフローファイル)中に、指定されたスペースを作成します。
mrsubbegin データストリーミングの更新操作を開始します。
mrsubend データストリーミングの更新操作を終了します。
mrsubputi BULK、TEXTのデータタイプに対して、データセグメントの更新を実行します。
mrsubgeti BULK、TEXTのデータセグメントを検索します。
mrbuktxtlen BULK、TEXTのデータ長を取得します。

以下に、エラーハンドリングに使用する関数を示します。

Table 2-19: エラーハンドリング関数

名前 概要
mrprterr mr関数が失敗した場合に、適切なエラーメッセージを表示します。呼出しプログラムを終了します。
mrerrmsg 最終のエラーメッセージを取得します。



2.8 Empress内部関数名

アプリケーションプログラムの作成時に、ユーザ関数名が、Empressの内部関数名と 同一の場合、リンク時にエラーが発生します。関数名で障害が発生した場合、接頭辞をチェックして、必要に応じて変更してください。

この障害を防ぐために、Empress内部関数名に使用される、接頭辞の一覧を以下に示します。(この一覧は完璧なものでは ありません。またバージョンにより違います。)


   addr         ap*
   byte
   cpbytes*     cv* 
   date*        day*       dt* 
   er*          ewrite*    exit*     extsrt* 
   fl*          fm*        fork* 
   gdat*        gdec*      gflt*     gint* 
   int
   ll* 
   main         match*     mem*      month*   mp*    mr*     ms*
   msbool       mw*        mx* 
   of* 
   prog* 
   ql* 
   ran* 
   sc*          sep*       sfmt       sig*     sm*    sp*     str* 
   taddr        time*      tty*     
   ufx* 
   varg* 
   wkday*       word        ww* 
   xf* 
   year*



2.9 mrルーチンの一般的な概要

mrルーチンの、一般的な使用法を以下に解説します。以下に記述する関数の多くは、失敗時に呼出しプログラムを終了 しないで、エラーコードを返すものと、呼出しプログラムを終了させるものの、相対する2種類の関数を提供します。 また、検索や条件定義のためにも、多くの関数を提供します。次の章では、関数の使用方法に関する解説と、サンプル プログラムを提供します。

データベースディレクトリ、テーブル名、オープンするモードを指定し、mropen関数を実行すると、テーブルをオープンし 、データディクショナリーに設定されたレベルにより、ロックを行いテーブル記述子のポインタを返します。 一旦テーブルがオープンされると、mrmkrec関数により、テーブル記述子からレコード記述子のポインタを取得します。 その後、数々の操作を行なった後に、mrclose関数によってテーブルをクローズします。

フィールドの操作を行なう場合には、フィールド識別子を取得するために、mrigeta関数、またはmrngeta関数を使用します。 既に記述子がある場合には、mrganame関数を使用して、フィールド名を取得できます。

レコードを検索する場合には、mrgetbegin関数により初期化します。この関数は、検索条件をテーブルのレコードと関連付け します。検索条件がない場合でも、mrgetbegin関数は呼出しが必要となり、ソートされた検索を行なう場合には、代わりに mrsrtbegin関数を使用します。

検索条件は、mrqcon関数、mrqrng関数、mrqatr関数、mrqmch関数、mrqnul関数を使用して設定します。これらの関数は、 フィールド値を定数、範囲、他のフィールド値と比較し定数とのマッチングや、NULLとの比較を行なうために使用されます。 この時使用される値が、外部フォーマットの場合には、mrcvt関数により、ファイルフォーマットへ変換しなくてはなりません。 複雑な検索条件には、ANDやORまたはNOTを指定しなくてはなりません。その場合には、mqrand関数、mrqor関数、 mrqnot関数を使用します。

検索は、mrget関数とmrprev関数を繰り返し使用することによって実行されます。mrget関数(またはmrprev関数)を使用する ごとに、定義されたレコード構造に、内部フォーマットでレコード値が保存されます。他のプロセスによりロックされ、一時的に アクセスできない場合には、再検索するためにmrreget関数(またはmrreprev関数)を使用します。mrspv関数は、フィールド値 の、保存用スペースを割当てるために使用します。mrcopyv関数は、そのスペースに値を保存します。(TEXTデータタイプの 場合には、mrcopyv関数の代わりに、mrgetvs関数を使用しなくてはなりません。)こうして、アプリケーションプログラムによって 、検索と操作が可能な文字列による、外部フォーマットが作成されます。

mrfree関数は、mrspv関数によって、割当てられたスペースを開放します。

フィールドの集計関数(COUNT、MIN、MAX、AVG、SUM)は、mrgfunc関数によって実行されます。

新しいレコードを作成するには、mrputvs関数(フィールド値をNULLにする場合は、mrsetnv関数)を使用して、フィールド値 をレコード構造に付加します。外部フォーマットではなく、内部フォーマットでプログラムする場合には、mrputvs関数の 代わりに、mrputi関数を使用します。mrsetnr関数を使用して、レコード全体を明示的に、NULLに設定できます。 そしてmradd関数を使用して、レコードがテーブルに追加されます。mraddend関数は、追加処理のクリーンアップを行い ます。レコードの追加が行なえない可能性がある場合(ユニークインデックスが設定されているのに、重複値が入力されたり、 レコードレベルのロックがかかっているなど)、処理の結果を通知する、mrtadd関数を使用してください。

レコードを削除するには、mrdel関数またはmrtdel関数を使用します。また削除後には、mrdelend関数を使用して、クリーン アップを行ないます。

更新は、新しいレコードを作成するために、mrmkrec関数を使用し、レコードをコピーして使用するので、mrcopyr関数を 使用します。また、フィールド値を変更するためにmrputvs関数を使用し、更新後のレコードに置き換えるために、mrput関数 を使用します。

レコード構造に割当てたスペースは、mrfrrec関数を使用して解放します。必要なくなったスペースは、必ず開放するように プログラムしてください。

データベースのデータディクショナリーは、mropdict関数によりオープンされ、mrcldict関数によってクローズします。

トランザクションは、mrtrstart関数によって開始し、mrtrcommit関数またはmrtrcancel関数によって、コミットやキャンセルを 行います。また、トランザクション中のセーブポイントは、mrtrsave関数によって設定し、セーブポイントまでのロールバックは mrtrrollback関数を使用します。

表現式を構築する場合には、mrebegin関数を使用して開始し、mreend関数を使用して終了します。式はmrerun関数に よって評価され、mrqexpr関数を使用して制限に変換されます。評価後にmrefree関数を使用して解放します。 エラーが検知された場合には、mreabort関数を使用して、構築を中止します。表現式の構築では、mrecons関数、 mreivar関数、mrerecattr関数が、それぞれ定数、変数、フィールドを次の引数として、付加するのに使用されます。 関数を付加するには、mrefunc関数が使用されます。mrenull関数は、最終の引数がNULLであるかチェックし、 mrgdtpar関数は、データタイプ記述子をチェックし、mrecvarg関数は、表現式タイプを指定のデータタイプに変換します。



2.10 データベース、テーブル、フィールド名

mrルーチンの多くの引数は、データベース名、テーブル名、フィールド名を指定するか、データ値を指定します。一般的に 、これらの引数は文字列です。

複数のデータベースに、同一のテーブル名が存在する場合、以下に示すようにデータベース名とコロンが、テーブル名の 前に指定されます。

   database:table

同様にフィールド名は、テーブル名とピリオドを指定することで特定されます。さらにデータベース名を指定しても特定する ことができます。

   attribute
   table.attribute
   database:table.attribute

テーブルのフィールド名を間違えたために発生するエラーは、デバッグは難しいので、テーブル名でフィールド名を特定 するようにしてください。



2.11 エラーメッセージ

mrルーチンを使用した場合の、5つのエラータイプを示します。

すべてのエラーは、以下のフォーマットで表示されます。

   *** エラータイプ *** エラーの詳細

プログラムバグ

プログラムバグのエラーメッセージは、アプリケーションプログラム内に、プログラミングミスがあることを表示します。 通常は、不正なパラメータを関数に受け渡すことにより発生します。例えば、readモードでオープンされた テーブルに、データを挿入しようとしたり、更新処理において、違うテーブルから、新旧のレコードを指定した 場合などに発生します。

スペース障害

このエラーは、プログラムがスペース不足で実行できない場合に表示されます。レコード記述子らフィールド記述子 などに、割当てたスペースは、必要がなくなった時点で解放するようにプログラムしてください。非常に多くの フィールドを持つテーブルを処理する場合にも、スペース障害が発生する場合があります。

ユーザエラー

このエラーは、アプリケーションの実行中に、入力されたデータによって発生する場合があります。例えば、 不正なテーブル名や、フィールド名を関数に受け渡した結果発生します。プログラムに書き込まれた、フィールド名 であれば、発見、修正は簡単ですが、実行中に入力されたものであれば、mrngeta関数などにより チェックする必要があります。

データベース障害

このエラーは、重大なエラーであり、データベースが破壊されている場合に発生します。

ファイル障害

mrルーチンが、アクセスできるはずのファイルにアクセスできない場合に発生します。一般的に重大なエラーで あり、データベースが破壊されている恐れがあります。



2.12 ロック

データベースのデータディクショナリーに、テーブルに対してロックが指定されている場合、テーブルまたはレコードは readモードまたはupdateモードでロックされます。データディクショナリーに適切なロックレベルが指定されていない場合 には、テーブルまたはロックを行なう関数を呼び出しても効果はありません。

テーブルまたはレコードを、readモードでロックする場合は、他のユーザもreadモードであればアクセスできます。従って 、このテーブルまたはレコードを更新したいユーザは、他のユーザが対象テーブルの処理を中止するまで、アクセスでき なくなります

テーブルまたはレコードを、updateモードでロックする場合は、他のユーザは誰も、読込みあるいは書込みのために、 そのテーブルまたはレコードをアクセスできなくなります。もし、一人のユーザが、テーブルまたはレコードを長時間に 渡ってロックしている場合、あるいはロックされたままで解除されない場合には、障害が発生する可能せいがあります。

テーブルは、read、update、deferredモードでオープンできます。テーブルをreadモードでオープンすると、テーブルに 対し、readロックを行ない、updateモードでオープンすると、updateロックを行います。また、deferredモードでオープン すると、普段はreadロックが行なわれ、更新処理の時だけupdateロックに変更されます。

テーブルレベルロックは、テーブルのオープン時に効力が発生し、グループレベルロックは、mrgetbegin関数の実行時 に効力が発生し、レコードレベルロックは、mrget関数実行時に効力が発生します。

msclrlkユーティリティ、empadmユーティリティは、ロックを解除することができます。またデバッグでは、MSDEBUG変数に abortを指定することにより、コアダンプを取得することができます。



2.13 移植性

mx/mrルーチンを呼び出す、実行モジュールは、以下の条件内で機種間での移動が可能です。

  1. 互換性のあるオペレーティングシステム
  2. Empressのバージョンが同一である
上記の条件を満たさない場合には、ターゲットマシンでの再コンパイルが必要になります。