ヘッダーをスキップ
Pro*COBOL®プログラマーズ・ガイド
11gリリース2(11.2)
E50141-01
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次
索引へ移動
索引

前
 
次
 

12 マルチスレッド・アプリケーション

開発プラットフォームがスレッドをサポートしていない場合、この章は無視してもかまいません。

この章の内容は、次のとおりです。

スレッドの概要

マルチスレッド・アプリケーションでは、共有のアドレス空間で複数のスレッドが実行されます。スレッドはプロセス内で実行される軽量のサブプロセスです。コードとデータ・セグメントは共有しますが、独自のプログラム・カウンタ、マシン・レジスタおよびスタックがあります。スレッド・ローカル属性なしで作業記憶域で宣言された変数は(ローカル記憶域あるいはスレッド・ローカル記憶域とは異なり)、すべてのスレッドに共通のものになります。アプリケーション内部の複数のスレッドから変数へのアクセスを管理するため、相互排他的なメカニズムが多くの場面で必要になります。Mutexは、データの整合性が保たれることを保証する同期化メカニズムです。

mutexの詳細は、マルチスレッドの説明を参照してください。マルチスレッド・アプリケーションの詳細は、スレッド・ファンクションのマニュアルを参照してください。

Pro*COBOLは、マルチスレッド・アプリケーション対応のプラットフォームで、次のものを使用したマルチスレッドOracleサーバー・アプリケーションの開発に対応しています。


注意:

プラットフォームによりサポートするスレッド・パッケージが異なるため、使用しているプラットフォーム固有のOracleマニュアルを参照して、Oracleがスレッド・パッケージをサポートしているかを調べてください。

この章では、前述の機能を使用してマルチスレッドPro*COBOLアプリケーションを開発する方法を説明します。

Pro*COBOLのランタイム・コンテキスト

Pro*COBOLには、スレッドと接続を疎結合するためのランタイム・コンテキストの概念が導入されています。ランタイム・コンテキストには、次のリソースおよびその現在の状態が含まれます。

スレッドと接続の間の疎結合をサポートしているのみでなく、Pro*COBOLではスレッドとランタイム・コンテキストを疎結合できます。Pro*COBOLを使用すると、アプリケーションでランタイム・コンテキストを処理するハンドルを定義し、そのハンドルをスレッド間で渡すことができます。

たとえば、対話形式のアプリケーションで、スレッドT1を作成し、問合せを実行して先頭の10行をアプリケーションに戻します。その後、T1は終了します。必要なユーザー入力が取得されると、別のスレッドT2が作成され(または既存のスレッドが使用され)、T1のランタイム・コンテキストがT2に渡されます。T2は同じカーソルを処理して次の10行をフェッチできます。図12-1はこの処理を示します。

図12-1 疎結合接続およびスレッド

疎結合
「図12-1 疎結合接続およびスレッド」の説明

ランタイム・コンテキストの使用モデル

マルチスレッド・アプリケーションでランタイム・コンテキストを使用する際に考えられる2つのモデルは次のとおりです。

いずれのモデルを使用した場合も、複数のスレッドで同時に1つのランタイム・コンテキストを共有することはできません。2つ以上のスレッドで同じランタイム・コンテキストを同時に使用すると、ランタイム・エラーが発生します。

複数のスレッドで1つのランタイム・コンテキストを共有

図12-2は、マルチスレッド環境で実行するアプリケーションを示します。1つ以上のSQL文を処理するために、様々なスレッドが1つのランタイム・コンテキストを共有します。この場合も、同時に複数のスレッドでランタイム・コンテキストを共有することはできません。図12-2のmutexは、同時使用を回避する方法を示します。

図12-2 スレッド間でのコンテキストの共有

コンテキストの共有
「図12-2 スレッド間でのコンテキストの共有」の説明

複数のスレッドで複数のランタイム・コンテキストを共有

図12-3は、複数のランタイム・コンテキストを使用して複数のスレッドを実行するアプリケーションを示します。この場合、各スレッドは専用のランタイム・コンテキストを使用するため、アプリケーションにはmutexは必要ありません。

図12-3 スレッド間でのコンテキストの非共有

コンテキストの非共有
「図12-3 スレッド間でのコンテキストの非共有」の説明

マルチスレッド・アプリケーションのユーザー・インタフェース機能

Pro*COBOLには、マルチスレッド・アプリケーションに対応した次のユーザー・インタフェース機能があります。

THREADSオプション

Pro*COBOLでは、「マルチスレッド・プログラミングに関する注意事項」に説明されたガイドラインに従ってコマンドラインにTHREADS=YESを指定すると、スレッド・セーフのコードが生成されます。Pro*COBOLでは、THREADS=YESを指定すると、すべてのSQL文がユーザー定義のランタイム・コンテキストのスコープ内で実行されます。プログラムがこの要件を満たしていないと、プリコンパイラ・エラーが戻されます。

ランタイム・コンテキストの埋込みSQL文およびディレクティブ

ランタイム・コンテキストおよびスレッドの定義と使用に対応した埋込みSQLおよびディレクティブは、次のとおりです。

  • EXEC SQL ENABLE THREADS END-EXEC.

  • EXEC SQL CONTEXT ALLOCATE :context_var END-EXEC.

  • EXEC SQL CONTEXT USE { :context_var | DEFAULT} END-EXEC.

  • EXEC SQL CONTEXT FREE :context_var END-EXEC.

前述のEXEC SQL文では、context_varはランタイム・コンテキストに対するハンドルで、次のようにSQL-CONTEXT型として宣言する必要があります。

 01  SQL-CONTEXT context_var END-EXEC.

DEFAULTを使用すると、別のCONTEXT USE文でオーバーライドされるまで、以降のすべての埋込みSQL文にデフォルト(グローバル)ランタイム・コンテキストが使用されます。

様々なコンテキスト文の使用例は、後述の例を参照してください。

SQL-CONTEXTのホスト表の使用禁止

SQL-CONTEXTのホスト表は宣言できません。かわりに、S9(9) COMP変数のホスト表を宣言し、SQL-CONTEXTとしてサブプログラムに宣言した後に、1つずつサブプログラムに渡してください。

EXEC SQL ENABLE THREADS

この実行SQL文は、複数のスレッドをサポートするプロセスを初期化します。このSQL文は、マルチスレッド・アプリケーションを含むプログラム内の最初の実行SQL文にしてください。アプリケーションのすべてのファイルにおいて、ENABLE THREADS文は1回しか使用できません。それ以上使用した場合はエラーとなります。詳細は、「ENABLE THREADS(実行可能埋込みSQL拡張機能)」を参照してください。

EXEC SQL CONTEXT ALLOCATE

この実行SQL文は指定されたランタイム・コンテキストにメモリーを割り当てて初期化します。ランタイム・コンテキスト変数はSQL_CONTEXT型として宣言する必要があります。詳細は、「CONTEXT ALLOCATE(実行可能埋込みSQL拡張機能)」を参照してください。

EXEC SQL CONTEXT USE

EXEC SQL CONTEXT USEディレクティブは、以降の実行SQL文に指定されたランタイム・コンテキストを使用するようにプリコンパイラに指示します。ランタイム・コンテキストを指定するには、EXEC SQL CONTEXT ALLOCATE文で事前に割り当てる必要があります。

EXEC SQL CONTEXT USEディレクティブは、EXEC SQL WHENEVERディレクティブと同様に動作します。つまり、COBOLの標準スコープ・ルールに関係なく、指定されたソース・ファイルでこの文とともに動作するすべての実行SQL文に対して有効です。

詳細は、「CONTEXT USE (Oracle埋込みSQLディレクティブ)」および「CONTEXT ALLOCATE (実行可能埋込みSQL拡張機能)」を参照してください。

EXEC SQL CONTEXT FREE

EXEC SQL CONTEXT FREE実行SQL文は、指定されたランタイム・コンテキストに対応付けられたメモリーを解放し、ホスト・プログラム変数にNULLポインタを挿入します。詳細は、「CONTEXT FREE (実行可能埋込みSQL拡張機能)」を参照してください。

Pro*C/C++プログラムとの対話

ランタイム・コンテキストは、連絡節で定義した引数を使用して渡すことができます。マルチスレッドPro*C/C++プログラムはPro*COBOLサブプログラムを、またPro*COBOLプログラムはPro*C/C++で記述されたサブプログラムをコールできます。

マルチスレッド・プログラミングに関する注意事項

Oracleでは、必ずスレッド・セーフのSQLLIBコードが生成されますが、スレッドと正常に動作するようにソース・コードを設計するのはプログラマの責任です。たとえば、使用する変数のスコープは慎重に決定してください。

また、マルチスレッドでは次のような設計上の要件を考慮してください。

  • 各ランタイム・コンテキストにSQLCAを1つ含めます。

  • 通常は自動変数であるSQLCAのように、スレッド・セーフ・グループ項目としてランタイム・コンテキストごとにSQLDAを宣言します。

  • スレッド・セーフ方式でホスト変数を宣言するときは、静的ホスト変数およびグローバル・ホスト変数の使用に注意してください。

  • 複数のスレッドで1つのランタイム・コンテキストを同時に使用しないでください。

  • デフォルトのデータベース接続を使用するか、AT句でデータベース接続を明示的に定義します。

ランタイム・コンテキストでは、EXEC SQL UPDATEなどの実行可能埋込みSQL文は1つのみにしてください。

プリコンパイル済アプリケーションの既存の要件も適用されます。たとえば、特定のカーソルへの参照はすべて同じソース・ファイルに含まれている必要があります。

マルチスレッドの制限

スレッドを使用する場合は、次の制限事項が適用されます。

  • SQL-CONTEXTデータ型の配列は使用できません。

  • 同時スレッドにはそれぞれSQLCAを指定します。

  • 同時スレッドにはそれぞれ専用のコンテキスト領域を割り当てます。

複数のコンテキストの例

次のコードは、複数のコンテキストを使用する方法と、コンテキスト使用文のスコープを示します。

例1

この例では、スレッドが生成されないため、プリコンパイル・オプションをTHREADS=YESに設定する必要はありません。

 IDENTIFICATION DIVISION.
 PROGRAM-ID. MAIN.
 ...
* declare a context area
 01  CTX1  SQL-CONTEXT.
 01  UID1  PIC X(11) VALUE "SCOTT/TIGER".
 01  UID2  PIC X(10) VALUE "MARY/LION"

 PROCEDURE DIVISION.
...
* allocate context area
     EXEC SQL CONTEXT ALLOCATE :CTX1 END-EXEC.
     EXEC SQL CONTEXT USE :CTX1 END-EXEC.
* all statements until the next context use will use CTX1
     EXEC SQL CONNECT :UID1 END-EXEC.
     EXEC SQL SELECT ....
     EXEC SQL CONTEXT USE DEFAULT END-EXEC.
* all statements physically after the preceding lines will use the default context
     EXEC SQL CONNECT :UID2 END-EXEC.
     EXEC SQL INSERT ...
 ...

例2

次の例は、複数のコンテキストを示します。コンテキストの1つは生成されたスレッドに使用され、もう1つはメイン・プログラムに使用されます。開始したスレッド、SUBPRGM1はコンテキストCTX1を使用し、CTX1はLINKAGE SECTIONを介して渡されます。この例から、CONTEXT USE文のスコープもわかります。


注意:

この例のプログラム・ファイルに加え、この項では以降のすべての例のメイン・プログラムを、THREADS=YESオプションを設定してプリコンパイルする必要があります。

 IDENTIFICATION DIVISION.
 PROGRAM-ID. MAIN.
 ...
* declare two context areas
 01  CTX1  SQL-CONTEXT.
 01  CTX2  SQL-CONTEXT.

 PROCEDURE DIVISION.

* enable threading
     EXEC SQL ENABLE THREADS END-EXEC.

* allocate context areas
     EXEC SQL CONTEXT ALLOCATE :CTX1 END-EXEC.
     EXEC SQL CONTEXT ALLOCATE :CTX2 END-EXEC.

* include your code to start thread "SUBPGM1" using CTX1 here.

     EXEC SQL CONTEXT USE :CTX2 END-EXEC.
* all statement physically after the preceding lines will use CTX2

     EXEC SQL CONNECT :USERID END-EXEC.
     EXEC SQL INSERT .....
 ...

スレッドSUBPRGM1は別のファイルに入ります。

 PROGRAM-ID. SUBPRGM1.
 ...
 01  USERID PIC X(11) VALUE "SCOTT/TIGER".
 LINKAGE SECTION.
 01  CTX1 SQL-CONTEXT.
 PROCEDURE DIVISION USING CTX1.

     EXEC SQL CONTEXT USE :CTX1 END-EXEC.
     EXEC SQL CONNECT :USERID END-EXEC.
     EXEC SQL SELECT ...
 ...

例3

次の例では複数のスレッドが使用されます。各スレッドには、それぞれ別のコンテキストを使用します。スレッドを同時実行する場合は、各スレッドに専用のコンテキストが必要になります。コンテキストは、START文のUSING CLAUSEを使用してスレッドに渡され、スレッド・サブプログラムのLINKAGE SECTIONに宣言されます。

 IDENTIFICATION DIVISION.
 PROGRAM-ID. MAIN.
 ...
 DATA DIVISION.

 01  CTX1 SQL-CONTEXT.
 01  CTX2 SQL-CONTEXT.

 PROCEDURE DIVISION.
 ...
     EXEC SQL ENABLE THREADS END-EXEC.
     EXEC SQL CONTEXT ALLOCATE :CTX1 END-EXEC.
     EXEC SQL CONTEXT ALLOCATE :CTX2 END-EXEC.

* include your code to start thread "SUBPGM" using CTX1 here.
* include your code to start thread "SUBPGM" using CTX2 here.
 ...

スレッドSUBPGMは別のファイルに入ります。

PROGRAM-ID. SUBPGM.
 ...
 DATA DIVISION.
 ...
 01  USERID PIC X(11) VALUE "SCOTT/TIGER".
 ...
 LINKAGE SECTION.
 01  CTX SQL-CONTEXT.
 PROCEDURE DIVISION USING CTX.
     EXEC SQL CONTEXT USE :CTX END-EXEC.
     EXEC SQL CONNECT :USERID END-EXEC.
     EXEC SQL SELECT ....
 ...

例4

次の例では、前の例を基にしていますが、トップレベルのプログラムで接続し、コンテキストとともにその接続がスレッド・サブプログラムに渡されます。

 IDENTIFICATION DIVISION.
 PROGRAM-ID. MAIN.
 ...
 DATA DIVISION.

 01  CTX1 SQL-CONTEXT.
 01  CTX2 SQL-CONTEXT.
 01  USERID PIC X(11) VALUE "SCOTT/TIGER".

 ROCEDURE DIVISION.

     EXEC SQL ENABLE THREADS END-EXEC.
     EXEC SQL CONTEXT ALLOCATE :CTX1 END-EXEC.
     EXEC SQL CONTEXT ALLOCATE :CTX2 END-EXEC.
     EXEC SQL CONTEXT USE :CTX1 END-EXEC.
     EXEC SQL CONNECT :USERID END-EXEC.
     EXEC SQL CONTEXT USE :CTX2 END-EXEC.
     EXEC SQL CONNECT :USERID END-EXEC.

* include your code to start thread "SUBPGM" using CTX1 here.
* include your code to start thread "SUBPGM" using CTX2 here.
 ...

スレッドSUBPRGMは別のファイルに入ります。

 PROGRAM-ID. SUBPGM.
 ...
 LINKAGE SECTION.
 01  CTX SQL-CONTEXT.
 PROCEDURE DIVISION USING CTX.
     EXEC SQL CONTEXT USE :CTX END-EXEC.
     EXEC SQL SELECT ....
 ...

例5

次の例は、1つのコンテキストを共有する複数のスレッドを示します。この場合、スレッドをシリアライズする必要があります

 IDENTIFICATION DIVISION.
 PROGRAM-ID. MAIN.
 ...
 DATA DIVISION.

 01  CTX1 SQL-CONTEXT.

 PROCEDURE DIVISION.

     EXEC SQL ENABLE THREADS END-EXEC.
     EXEC SQL CONTEXT ALLOCATE :CTX1 END-EXEC.

* include your code to start thread1 "SUBPGM1" using CTX1 here.
* include your code to wait for thread1 here.
* include your code to start thread2 "SUBPGM2" using CTX1 here.
 ...

2つのスレッドは別々に2つのファイルに入れられます。最初のファイルの内容は次のとおりです。

 PROGRAM-ID. SUBPGM1.
 ...
 DATA DIVISION.
 ..
 01  USERID PIC X(11) VALUE "SCOTT/TIGER".
 ...
 LINKAGE SECTION.
 01  CTX SQL-CONTEXT.
 PROCEDURE DIVISION USING CTX.
     EXEC SQL CONTEXT USE :CTX END-EXEC.
 ...
     EXEC SQL CONNECT :USERID END-EXEC.

もう1つのファイルにはSUBPGM2が入ります。

 PROGRAM-ID. SUBPGM2.
 ...
 DATA DIVISION.
 ...
 LINKAGE SECTION.
 01  CTX SQL-CONTEXT.
 PROCEDURE DIVISION USING CTX.
     EXEC SQL CONTEXT USE :CTX END-EXEC.
     EXEC SELECT ....
 ...

マルチスレッドの例

この複数ファイルで構成されるアプリケーションは、SQLLIBランタイム・コンテキスト領域(SQL-CONTEXT)を使用して複数のスレッドに対応する1つの方法を示します。THREADS=YESを設定して再コンパイルします。

メイン・プログラム、orathrd2は、sqllibコンテキストを格納するS9(9) COMP変数の配列を宣言します。orathrd2は、次の文を通じてスレッドを使用可能にします。

EXEC SQL ENABLE THREADS END-EXEC. 

次に、(oracon.pcoファイル内の)サブプログラムoraconをコールして、スレッドを割り当てます。さらに、oraconは割り当てられたコンテキストごとに接続を確立します。

ORTHRD2は、THREAD-1またはTHREAD-2のいずれかのスレッド・エントリ・ポイントにコンテキストを渡します。THREAD-1は、1人の従業員の給与を選択して表示するのみです。THREAD-2は、その従業員の給与を選択して更新します。THREAD-2はCOMMITを発行するので、コミット後にSELECTを実行するスレッドから更新を参照できます。(ただし、更新と同時実行するスレッドでは参照できません。)更新とコミットのタイミングは不確定であるため、実行ごとに出力が異なる点に注意してください。

同時スレッドにはそれぞれ別のコンテキストが必要であることに注意してください。コンテキストは後続のスレッドに渡して使用することができますが、スレッドは同一のコンテキストを同時に使用することができません。このモデルは接続プーリングに使用することができます。接続プーリングでは、最初に最大数の接続が作成され、ユーザーの要求を実行するため、使用可能な接続がスレッドに渡されます。

現時点ではSQL-CONTEXTの配列を宣言できないため、S9(9) COMP変数の配列が使用されます。

注意: このプログラムは、SolarisおよびMicroFocus ServerExpressコンパイラを実行するSunワークステーション用に開発されていて、ベンダー固有のディレクティブおよび機能を使用します。

マルチスレッドに対応するCOBOL文の詳細は、使用するプラットフォームのマニュアルを参照してください。

メイン・プログラムは、ファイルorathrd2.pcoにあります。

      $SET REENTRANT MF
       IDENTIFICATION DIVISION.
       PROGRAM-ID. ORATHRD2.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       78 MAX-LOOPS            VALUE 10.
       01 THREAD-ID            USAGE POINTER.
       01 TP-1                 USAGE THREAD-POINTER OCCURS MAX-LOOPS.
       01 IDEN-4               PIC 9(4).
       01 LOOP-COUNTER         PIC 9(2)  COMP-X EXTERNAL.
       01 PEMPNO               PIC S9(4) COMP EXTERNAL.
       01 ISAL                 PIC S9(4) COMP   VALUE ZERO.
           EXEC SQL
                INCLUDE SQLCA
           END-EXEC.
       THREAD-LOCAL-STORAGE SECTION.
       01  CONTEXT-AREA          PIC S9(9) COMP OCCURS MAX-LOOPS.
       PROCEDURE DIVISION.
       MAIN SECTION.
                
           PERFORM INITIALISATION
           PERFORM ORACLE-CONNECTIONS VARYING LOOP-COUNTER
                   FROM 1 BY 1 UNTIL LOOP-COUNTER > MAX-LOOPS
           PERFORM  VARYING LOOP-COUNTER FROM 1 BY 1
              UNTIL LOOP-COUNTER > MAX-LOOPS
               PERFORM START-THREAD
           END-PERFORM
           STOP RUN.

      *---------------------------------------------------------------
      * CHECK THAT WE ARE RUNNING UNDER A MULTI THREADED RTS.
      *---------------------------------------------------------------
       INITIALISATION SECTION.

           CALL "CBL_THREAD_SELF" USING THREAD-ID ON EXCEPTION
                DISPLAY "NO THREAD SUPPORT IN THIS RTS"
                STOP RUN
           END-CALL
           IF RETURN-CODE = 1008
                DISPLAY "CANNOT RUN THIS TEST ON SINGLE THREADED RTS"
                STOP RUN
           END-IF
           DISPLAY "MULTI-THREAD RTS"

      * ENABLING THREADS MUST BE DONE ONCE BEFORE ANY CONTEXT USEAGE
           EXEC SQL ENABLE THREADS END-EXEC.
           IF SQLCODE NOT = ZERO
              DISPLAY 'ERROR ENABLING ORACLE THREAD SUPPORT '
                      ' - ABORTING : ' SQLERRMC
              STOP RUN
           END-IF

      *  SET A VALUE FOR THE EMPLOYEE NUMBER.  BECAUSE THIS IS AN
      *  EXTERNAL VARIABLE, A COPY OF ITS VALUE IS VISIBLE TO THE 
      *  OTHER MODULES IN THIS APPLICATION
           MOVE 7566 TO PEMPNO
           EXIT SECTION.

      *-----------------------------------------------------------------
      * CREATE THREADS AND START WITH EITHER THREAD-1 OR THREAD-2
      *-----------------------------------------------------------------
       START-THREAD SECTION.

           IF LOOP-COUNTER = 2 OR LOOP-COUNTER = 5
              START "THREAD-2 "
                 USING CONTEXT-AREA(LOOP-COUNTER)
                 IDENTIFIED BY TP-1(LOOP-COUNTER)
                 STATUS IS IDEN-4
                 ON EXCEPTION DISPLAY "THREAD CREATE FAILED"
              END-START
              IF IDEN-4 NOT = ZERO
                DISPLAY "THREAD CREATE FAILED RETURNED " IDEN-4
              END-IF
           ELSE
              START "THREAD-1 "
                 USING CONTEXT-AREA(LOOP-COUNTER)
                 IDENTIFIED BY TP-1(LOOP-COUNTER)
                 STATUS IS IDEN-4
                 ON EXCEPTION DISPLAY "THREAD CREATE FAILED"
              END-START
              IF IDEN-4 NOT = ZERO
                DISPLAY "THREAD CREATE FAILED RETURNED " IDEN-4
              END-IF
           END-IF.

       START-THREAD-END.
           EXIT SECTION.


      *-----------------------------------------------------------------
      * ALLOCATE CONTEXT AREAS ESTABLISH CONNECTION WITH EACH AREA.
      *-----------------------------------------------------------------
       ORACLE-CONNECTIONS SECTION.

           CALL "ORACON" USING CONTEXT-AREA(LOOP-COUNTER).
       ORACLE-CONNECTIONS-END.
           EXIT SECTION.

ファイルthread-1.pcoの内容は次のとおりです。

      * This is Thread 1.  It selects and displays the data for 
      * the employee. The context area upon which a connection
      * has been established is passed to the thread through the 
      * linkage section. In a multi-file application, you
      * can pass the context through the linkage section.  
      * Precompile with THREADS=YES.
      * 
      $SET REENTRANT MF
       IDENTIFICATION DIVISION.
       PROGRAM-ID. THREAD-1.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 PEMPNO               PIC S9(4) COMP EXTERNAL.

       LOCAL-STORAGE SECTION.
       01 DEMPNO               PIC Z(4) VALUE ZERO.
       01 PEMP-NAME1           PIC X(15) VARYING  VALUE SPACES.
       01 PSAL-VALUE1          PIC S9(7)V99 COMP-3 VALUE ZERO.
       01 ISAL1                PIC S9(4)   COMP   VALUE ZERO.
       01 DSAL-VALUE           PIC +(7).99 VALUE ZERO.
           EXEC SQL
                INCLUDE SQLCA
           END-EXEC.

       LINKAGE SECTION.
       01 CONTEXT-AREA1         SQL-CONTEXT.

      *---------------------------------------------------------------
      * USING THE PASSED IN CONTEXT, SELECT AND DISPLAY THE
      * DATA FOR EMPLOYEE.  
      *---------------------------------------------------------------
       PROCEDURE DIVISION USING CONTEXT-AREA1.
       MAIN SECTION.

           EXEC SQL WHENEVER SQLERROR GOTO SELECT-ERROR END-EXEC
           EXEC SQL CONTEXT USE :CONTEXT-AREA1 END-EXEC
           EXEC SQL
                SELECT  ENAME, SAL
                  INTO  :PEMP-NAME1, :PSAL-VALUE1:ISAL1
                  FROM  EMP
                 WHERE  EMPNO = :PEMPNO
           END-EXEC
           IF ISAL1 < ZERO
              MOVE ZERO     TO PSAL-VALUE1
           END-IF
           MOVE PEMPNO      TO DEMPNO
           MOVE PSAL-VALUE1 TO DSAL-VALUE
           DISPLAY "FOR EMP ", DEMPNO, " NAME ",
                   PEMP-NAME1-ARR(1:PEMP-NAME1-LEN),
                   " THE CURRENT SALARY IS ", DSAL-VALUE
           EXIT PROGRAM.


      *---------------------------------------------------------------
      * THERE HAS BEEN AN ERROR WHEN SELECTING FROM THE EMP TABLE
      *---------------------------------------------------------------
       SELECT-ERROR SECTION.

           EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC
           DISPLAY "HIT AN ORACLE ERROR SELECTING EMPNO 7566"
           DISPLAY "SQLCODE = ", SQLCODE
           DISPLAY "ERROR TEXT ", SQLERRMC(1:SQLERRML)
           GOBACK
           EXIT SECTION.

ファイルthread-2.pcoの内容は次のとおりです。

      * This is Thread 2.  The program will select, then update,
      * increment, and then commit the salary.  It uses the passed-in 
      * context upon which a connection has previously been established.
      * Precompile with THREADS=YES.
      *
      $SET REENTRANT MF
       IDENTIFICATION DIVISION.
       PROGRAM-ID. THREAD-2.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 PEMPNO               PIC S9(4)   COMP EXTERNAL.

       LOCAL-STORAGE SECTION.
       01 DEMPNO               PIC Z(4) VALUE ZERO.
       01 PEMP-NAME2           PIC X(15) VARYING  VALUE SPACES.
       01 PSAL-VALUE2          PIC S9(7)V99 COMP-3 VALUE 100.
       01 ISAL2                PIC S9(4)   COMP   VALUE ZERO.
       01 DSAL-VALUE           PIC +(7).99 VALUE ZERO.
           EXEC SQL
                INCLUDE SQLCA
           END-EXEC.

       LINKAGE SECTION.
       01 CONTEXT-AREA2         SQL-CONTEXT.

      *---------------------------------------------------------------
      * USING THE PASSED IN CONTEXT AREA, FIRST SELECT TO GET INITIAL
      * VALUES, INCREMENT THE SALARY, UPDATE AND COMMIT.
      *---------------------------------------------------------------
       PROCEDURE DIVISION USING CONTEXT-AREA2.
       MAIN SECTION.

           EXEC SQL WHENEVER SQLERROR GOTO UPDATE-ERROR END-EXEC
           EXEC SQL CONTEXT USE     :CONTEXT-AREA2 END-EXEC
           EXEC SQL
                SELECT  ENAME, SAL
                  INTO  :PEMP-NAME2, :PSAL-VALUE2:ISAL2
                  FROM  EMP
                 WHERE  EMPNO = :PEMPNO
           END-EXEC
           ADD  10  TO PSAL-VALUE2
           EXEC SQL
                   UPDATE  EMP
                      SET  SAL   = :PSAL-VALUE2
                    WHERE  EMPNO = :PEMPNO
           END-EXEC
           MOVE PEMPNO      TO DEMPNO
           MOVE PSAL-VALUE2 TO DSAL-VALUE
           DISPLAY "FOR EMP ", DEMPNO, " NAME ",
                   PEMP-NAME2-ARR(1:PEMP-NAME2-LEN),
                   " THE UPDATED SALARY IS ", DSAL-VALUE
      *    THIS COMMIT IS REQUIRED, OTHERWISE THE DATABASE
      *    WILL BLOCK SINCE THE UPDATES ARE TO THE SAME ROW
           EXEC SQL COMMIT WORK END-EXEC
           EXIT PROGRAM.

      *---------------------------------------------------------------
      * THERE HAS BEEN AN ERROR WHEN UPDATING THE SAL IN THE EMP TABLE
      *---------------------------------------------------------------
       UPDATE-ERROR SECTION.

           EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC
           DISPLAY "HIT AN ORACLE ERROR UPDATING EMPNO 7566"
           DISPLAY "SQLCODE = ", SQLCODE
           DISPLAY "ERROR TEXT ", SQLERRMC(1:SQLERRML)
           GOBACK
           EXIT SECTION.

ファイルoracon.pcoの内容は次のとおりです。

      * This program allocates SQLLIB runtime contexts, stores
      * a pointer to the context in the variable which was
      * passed in from the main program through the linkage section,
      * and establishes a connection on the allocated context.
      *
      * This program is written for Merant MicroFocus COBOL and uses
      * vendor-specific directives and functionality. Precompile
      * with THREADS=YES.
      *
      $SET REENTRANT MF
       IDENTIFICATION DIVISION.
       PROGRAM-ID. ORACON.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 LOGON-STRING         PIC X(40)          VALUE SPACES.
           EXEC SQL
                INCLUDE SQLCA
           END-EXEC.
       LINKAGE SECTION.
       01  CONTEXT          SQL-CONTEXT.

       PROCEDURE DIVISION USING CONTEXT.
       MAIN SECTION.
                
      *-----------------------------------------------------------------
      * ALLOCATE CONTEXT AREAS ESTABLISH CONNECTION WITH EACH AREA.
      *-----------------------------------------------------------------
       ORACLE-CONNECTION SECTION.

           MOVE "SCOTT/TIGER"  TO LOGON-STRING
           EXEC SQL CONTEXT ALLOCATE :CONTEXT END-EXEC
           IF SQLCODE NOT = ZERO
              DISPLAY 'ERROR ALLOCATING CONTEXT '
                      '- ABORTING : ' SQLERRMC
              GOBACK
           ELSE
              DISPLAY 'CONTEXT ALLOCATED'
           END-IF

           EXEC SQL CONTEXT USE :CONTEXT END-EXEC
           EXEC SQL  CONNECT    :LOGON-STRING  END-EXEC
           IF SQLCODE NOT = ZERO
              DISPLAY 'ERROR CONNECTING SECOND THREAD TO THE DATABASE '
                      '- ABORT TEST : ' SQLERRMC
              GOBACK
           ELSE
              DISPLAY 'CONNECTION ESTABLISHED'
           END-IF
           EXIT SECTION.