一般的に、mrルーチンによって、テーブルのオープン、レコードの追加、削除、検索、更新が行なえます。すべての操作は 一つのレコードに対して実行可能です。以下に示す、6つのデータポインタがあります。
最初の5つのデータポインタは、"addr"として宣言され、6番目の文字列は、"char *"として宣言しなくてはなりません。 テーブル、レコード、フィールド、条件の各記述子は、Emppress内部構造体へのポインタです。"addr"データタイプは、 "char *"として定義されていますが、これらのポインタは、文字列ではないので、そのように使用してはなりません。 addrデータタイプは、この連想子として使用されています。
ヘッダーファイル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 */
Empress mrルーチンを使用した、プログラムの作成には、2つの方法があります。
通常のmainプロシージャを、msmainとします。これは必要な初期化を行い、mainプロシージャをインクルード します。また、通常通り、パラメータargcとargvを使用できます。 同様に、通常のexitプロシージャをmsexitにします。
mainプロシージャを書くことも可能です。そのためには、msinitを呼び出して初期化し、msexitを呼び出して クリーンアップします。
msclean関数は、プログラム終了前に、呼び出され実行されるプロシージャを、スタックに配置します。
mrルーチンを使用したプログラムは、ccではなくempccまたはempc++で、コンパイルされる必要があります。この結果、 コンパイルで、Empress関数のライブラリが、確実にリンクされます。この他はccと同様に機能します。
mscall文も、empccまたはempc++によって、コンパイルされるプログラムで使用できます。例えば、アプリケーション プログラム内で、新しいテーブルを作成する、最も簡単な方法は、mscall文を使用することです。
ここでは、フィールド値の内部、外部、ファイルフォーマットについて解説します。外部フォーマットは、クエリーの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の使用方法を解説して います。
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* |
テーブルに、レコードレベルのロックが設定されていて、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 */
プログラム内で、ファイルをオープンする必要がある場合、Empressがすべての使用可能なファイルをオープンしていて 実行できないのであれば、Empressによって、オープンされるファイルの数を制限する必要があります。 これは、オペレーティングシステムに、Empressのシステム変数MSFILESOPENを、設定することで実行できます。 例えば、Empressがオープンできるファイル数を、10に設定する場合を以下に示します。
setenv MSFILESOPEN 10
MSFILESOPEN = 10 export MSFILESOPEN
set MSFILESOPEN = 10
これによって、Empressが10ファイルを越えたアクセスが、できないというわけではありません。 制限の10に到達した場合、Empressは、新しいファイルをオープンする前に、アクセスされていない、古いファイルをクローズ します。Empressによってクローズされたファイルは、必要に応じてアクセス時にオープンされます。Empressはファイルの 内容を内部に保存します。よって、クローズされたり、再オープンされたかはユーザには、わかりません
詳細は、Empress SQL: User's GuideのSetting Variables を参照してください。
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 | 最終のエラーメッセージを取得します。 |
アプリケーションプログラムの作成時に、ユーザ関数名が、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*
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関数は、表現式タイプを指定のデータタイプに変換します。
mrルーチンの多くの引数は、データベース名、テーブル名、フィールド名を指定するか、データ値を指定します。一般的に 、これらの引数は文字列です。
複数のデータベースに、同一のテーブル名が存在する場合、以下に示すようにデータベース名とコロンが、テーブル名の 前に指定されます。
database:table
同様にフィールド名は、テーブル名とピリオドを指定することで特定されます。さらにデータベース名を指定しても特定する ことができます。
attribute table.attribute database:table.attribute
テーブルのフィールド名を間違えたために発生するエラーは、デバッグは難しいので、テーブル名でフィールド名を特定 するようにしてください。
mrルーチンを使用した場合の、5つのエラータイプを示します。
すべてのエラーは、以下のフォーマットで表示されます。
*** エラータイプ *** エラーの詳細
プログラムバグ
プログラムバグのエラーメッセージは、アプリケーションプログラム内に、プログラミングミスがあることを表示します。 通常は、不正なパラメータを関数に受け渡すことにより発生します。例えば、readモードでオープンされた テーブルに、データを挿入しようとしたり、更新処理において、違うテーブルから、新旧のレコードを指定した 場合などに発生します。
スペース障害
このエラーは、プログラムがスペース不足で実行できない場合に表示されます。レコード記述子らフィールド記述子 などに、割当てたスペースは、必要がなくなった時点で解放するようにプログラムしてください。非常に多くの フィールドを持つテーブルを処理する場合にも、スペース障害が発生する場合があります。
ユーザエラー
このエラーは、アプリケーションの実行中に、入力されたデータによって発生する場合があります。例えば、 不正なテーブル名や、フィールド名を関数に受け渡した結果発生します。プログラムに書き込まれた、フィールド名 であれば、発見、修正は簡単ですが、実行中に入力されたものであれば、mrngeta関数などにより チェックする必要があります。
データベース障害
このエラーは、重大なエラーであり、データベースが破壊されている場合に発生します。
ファイル障害
mrルーチンが、アクセスできるはずのファイルにアクセスできない場合に発生します。一般的に重大なエラーで あり、データベースが破壊されている恐れがあります。
データベースのデータディクショナリーに、テーブルに対してロックが指定されている場合、テーブルまたはレコードは readモードまたはupdateモードでロックされます。データディクショナリーに適切なロックレベルが指定されていない場合 には、テーブルまたはロックを行なう関数を呼び出しても効果はありません。
テーブルまたはレコードを、readモードでロックする場合は、他のユーザもreadモードであればアクセスできます。従って 、このテーブルまたはレコードを更新したいユーザは、他のユーザが対象テーブルの処理を中止するまで、アクセスでき なくなります
テーブルまたはレコードを、updateモードでロックする場合は、他のユーザは誰も、読込みあるいは書込みのために、 そのテーブルまたはレコードをアクセスできなくなります。もし、一人のユーザが、テーブルまたはレコードを長時間に 渡ってロックしている場合、あるいはロックされたままで解除されない場合には、障害が発生する可能せいがあります。
テーブルは、read、update、deferredモードでオープンできます。テーブルをreadモードでオープンすると、テーブルに 対し、readロックを行ない、updateモードでオープンすると、updateロックを行います。また、deferredモードでオープン すると、普段はreadロックが行なわれ、更新処理の時だけupdateロックに変更されます。
テーブルレベルロックは、テーブルのオープン時に効力が発生し、グループレベルロックは、mrgetbegin関数の実行時 に効力が発生し、レコードレベルロックは、mrget関数実行時に効力が発生します。
msclrlkユーティリティ、empadmユーティリティは、ロックを解除することができます。またデバッグでは、MSDEBUG変数に abortを指定することにより、コアダンプを取得することができます。
mx/mrルーチンを呼び出す、実行モジュールは、以下の条件内で機種間での移動が可能です。