A.2 PL/SQL Server Pages (PSP) Webアプリケーション

PSP Webアプリケーションは、PL/SQL Server Pagesに基づいています。図A-3は、ブラウザからWebサーバーを通じてOracle Database上のPSPストアド・プロシージャをコールする方法を示しています。

この項では、次の項目について説明します。

図A-3 PSP Webアプリケーション

図A-3の説明が続きます
「図A-3 PSP Webアプリケーション」の説明

A.2.1 PSP Webアプリケーションの前提条件

PSP Webアプリケーションには、次の要件があります。

  • Oracle Databaseが起動され、実行中である必要があります。

    接続の例については、『Oracle Database JDBC開発者ガイド』を参照してください。

  • SCOTTアカウントがそのパスワードでロック解除されており、このアカウントにはCREATERESOURCECTXAPPの各権限がありること。

  • Oracle PL/SQLゲートウェイが実行中であること。

    PL/SQLゲートウェイの設定およびPL/SQL Webアプリケーションの開発の詳細は、『Oracle Database開発ガイド』を参照してください。

  • ApacheなどのWebサーバーが稼働し、Oracle Databaseに要求を送信するように適切に構成されていること。

    Apache HTTPサーバーのインストールの詳細は、『Oracle Database 2日でPHP開発者ガイド』を参照してください。

A.2.2 PSP Webアプリケーションの作成

PSP Webアプリケーションを作成するには:

  1. テキスト表を作成します。

    CREATE TABLEコマンドを使用して、HTMLファイルを格納するためのテキスト表を作成する必要があります。各例では、output_tablegist_tableおよびtheme_table表を作成しています。

    CREATE TABLE output_table  (query_id NUMBER, document CLOB);
    CREATE TABLE gist_table  (query_id NUMBER, pov VARCHAR2(80), gist CLOB);
    CREATE TABLE theme_table  (query_id NUMBER, theme VARCHAR2(2000), weight NUMBER);
    
  2. SQL*Loaderを使用して、表にHTMLドキュメントをロードします。

    テキスト表は、HTMLファイルを使用してロードする必要があります。この例では、loader.ctl制御ファイルを使用して、loader.datで指定したファイルをロードします。SQL*Loader文は次のとおりです。

    % sqlldr userid=scott/password control=loader.ctl 
    
  3. CONTEXT索引の作成

    HTMLファイルを索引付けするには、次のようにCONTEXT索引をテキスト列に作成します。HTMLの索引付けであるため、この例では、次のようにフィルタ処理が不要なNULL_FILTERプリファレンス型とHTML_SECTION_GROUP型を使用します。

    create index idx_search_table on search_table(text)
      indextype is ctxsys.context parameters
      ('filter ctxsys.null_filter section group CTXSYS.HTML_SECTION_GROUP');
    
  4. Oracle Databaseのsearch_htmlservicesパッケージをコンパイルします。

    アプリケーションには、選択したドキュメントが表示される必要があります。そのためには、Oracle Databaseがsearch_table内のキャラクタ・ラージ・オブジェクト(CLOB)からドキュメントを読み取り、その結果を出力して表示する必要があります。そのためには、search_htmlservicesパッケージ内のプロシージャをコールします。次のように、SQL*Plusプロンプトでsearch_htmlservices.sqlファイルをコンパイルします。

    SQL> @search_htmlservices.sql
    
    Package created.
    
  5. search_htmlのPSPページのコンパイル(loadpsp.を使用)

    検索ページを呼び出すには、ブラウザからsearch_html.pspをコールします。search_htmlは、Oracle Databaseのloadpspコマンドライン・プログラムを使用して、次のようにコンパイルします。

    % loadpsp -replace -user scott/password search_html.psp
    

    出力は次のようになります。

    "search_html.psp": procedure "search_html" created.

    関連項目:

    PSPの使用方法の詳細は、Oracle Database 11gリリース2 (11.2)の『Oracle Database開発者ガイド』を参照してください。

  6. Webサーバーを構成します。

    クライアントのPSP要求をURLとして受け入れるように、Webサーバーを構成する必要があります。Webサーバーは、クライアントの要求をOracle Databaseに転送し、サーバー出力をブラウザに戻します。図A-3を参照してください。

    Oracle WebDB Webリスナー、またはApache Webサーバーが組み込まれているOracle Application Serverを使用できます。

  7. ブラウザから問合せを入力します。

    URLを使用して、ブラウザから問合せアプリケーションにアクセスできます。URLをWebサーバーで構成します。URLの例は、次のようになります。

    http://server.example.com:7777/mypath/search_html
    

    図A-1および図A-2で示すように、アプリケーションでは、ブラウザに問合せのエントリ・ボックスを表示し、問合せ結果をHTMLリンクのリストとして戻します。

A.2.3 PSP Webアプリケーションのサンプル・コード

この項では、Webアプリケーションのサンプルの作成に使用するコードを示します。次のファイルを記載しています。

A.2.3.1 loader.ctl

この例では、loader.ctlファイルのサンプルを示します。sqlldrでは、このファイルを使用してloader.datデータファイルがロードされます。

LOAD DATA 
        INFILE 'loader.dat'
        INTO TABLE search_table 
        REPLACE 
        FIELDS TERMINATED BY ';'
        (tk             INTEGER,
         title          CHAR,
         text_file      FILLER CHAR,
         text           LOBFILE(text_file) TERMINATED BY EOF)

A.2.3.2 loader.dat

この例では、loader.datファイルのサンプルを示します。各行は、3つのフィールド(ドキュメントの参照番号、ラベル(すなわちタイトル)、およびsearch_table.のテキスト列にロードされるHTMLドキュメント名)で構成されますこの例では、ファイルは切り捨てられています。

1;   Pizza Shredder;Pizza.html
2;   Refrigerator w/ Front-Door Auto Cantaloupe Dispenser;Cantaloupe.html
3;   Self-Tipping Couch;Couch.html
4;   Home Air Dirtier;Mess.html
5;   Set of Pet Magnets;Pet.html
6;   Esteem-Building Talking Pillow;Snooze.html

A.2.3.3 loader.datのHTMLファイルの例

名前が付けられloader.datにロードされるHTMLファイルを参照用に次に示します。

Pizza.html

<html>
<header>
<title>The Pizza Shredder</title>
</header>
<body>
 
<h2>The Pizza Shredder</h2>
<h4>Keeping your pizza preferences secure</h4>
 
So it's the end of a long evening. Beer has been drunk, pizza has been eaten.
<p>
But there's leftover pizza - what are you going to do with it?
 
<p>
You could save it for the morning, or you could feed it to your pet.  But if neither of those appeal (maybe you don't have a pet?) then 
you'll be throwing it in the trash.
 
<p>
But wait a minute - anybody could look through your trash, and figure out what kind of pizza you've been eating! "No big deal," I hear you 
say. But it is! After they've figured out that your favorite pizza is pepperoni, then it's only a short step to figuring out that 
your top-secret online banking password is "pepperoni_pizza."
 
<p>
Get one over the dumpster-divers with our new patent-pending "Mk III Pizza Shredder." Cross-cut blades ensure that your pizza will be rendered 
unreadable, and nobody will be able to identify the original toppings. Also doubles as a lettuce-shredder and may also be used for removing 
unwanted fingertips.
 
<h2>Model Comparison</h2>
 
<table border="1">
  <tr><th>Model</th><th>Blades0</th><th>Pizza Thickness</th><th>Price</th></tr>
  <tr><td>Mk I</td><td>Plastic</td><td>1/2 inch (Thin Crust)</td><td>$69.99</td></tr>
  <tr><td>Mk II</td><td>Brass</td><td>1 inch (Deep Pan)</td><td>$99.99</td></tr>
  <tr><td>Mk III</td><td>Carbon Steel</td><td>2 inch (Calzoni)</td><td>$129.99</td></tr>
</table>
 
</body>
</html>

Cantaloupe.html

<html>
<header>
<title>The Fridge with a Cantaloupe Dispenser</title>
</header>
<body>
<h2>The Fridge with a Cantaloupe Dispenser</h2>
<h4>A nice cold melon at the touch of a button</h4>
 
Does your refrigerator only have a boring water dispenser in the door?
 
<p>
When you're hungry for a cantaloupe, do you have to expend valuable energy opening the fridge door and fishing around amongst the half-used
 packets of pet food?
 
<p>
Do your friends complain that they wish there was an effortless way to get cantaloupes from your fridge? Do you overhear them saying they're 
tired of always having to rummage through your moldy leftovers and seal-a-meals to get to the cold melons?
 
<p>
What you need is the convenience of a built-in cantaloupe dispenser.
 
<p>
Impress your friends. Win praise from your neighbors. Become a legendary host!
 
<p>
<b>Try our new <i>Melonic 2000</i> model!</b>
 
<p>
Works with honeydews and small crenshaws too.
 
<p>
Let the <i>Melonic 2000</i> go to work for you. Order one now at your local store.
 
</body>
</html>

Couch.html

<html>
<header>
<title>The Self-Tipping Couch</title>
</header>
<body>
<h2>The Self-Tipping Couch</h2>
 
<h4>Sometimes it's hard work to get off the couch</h4>
 
<p>
Sometimes it's hard work to get your partner, or your pet, off the couch.
 
<p>
The <b>Self-Tipping Couch</b> solves these problems for you. At the touch of a button it will deposit the contents of the couch onto the
 floor in front of it. 
 
<p>
The <b>Self-Tipping Couch</b> has been proven to boost communication with stubborn spouses, children, and relatives. 
 
<p>
You will never again need to yell, "Get off the couch!" Simply press a button and all those couch hoggers are gently 
dumped onto your carpet.
 
<p>
Get your own <b>Self-Tipping Couch</b> TODAY!
 
</body>
</html>

Mess.html

<html>
<header>
<title>Home Air Dirtier</title>
</header>
<body>
<h2>Home Air Dirtier</h2>
<h4>Missing your home in the middle of the city?</h4>
 
<p>
Like many ex-city-dwellers, you might be finding that the air in the countryside is just too clean.
 
<p>
You can remedy this right now with the <i>UltraAppliance</i> <b>Home Air Dirtier</b>. 
 
<p>
Simply insert our patented <i>CityFilth</i> cartridge, 
and soon you'll be enjoying the aromas of vehicle fumes and decaying garbage that you're used to from home.
 
<p>
<b>Please note:</b> Decaying garbage smells may confuse your pet. 
We recommend adding genuine garbage to your environment if this is a concern.
 
</body>
</html>

Pet.html

<html>
<header>
<title>The Pet Magnet</title>
</header>
<body>
<h2>The Pet Magnet</h2>
 
<h4>Every pet owner loves to let the pet run free, but that's not always possible</h4>
 
<p>
Sometimes local laws require pets to be on leashes. Sometimes a free-roaming pet will ruin a flower bed, leave a "calling card" on the 
sidewalk, or chew through another pet. In the case of extremely smart pets, like chimpanzees or dolphins, the unattended pet may get 
away and run up hundreds of dollars of long-distance charges on your phone.
 
<p>
But leashes aren't always a practical answer. They can be too confining, or too big, or can tug uncomfortably at the pet's neck. They 
may get tangled, or wrapped around poles or passersby. Pets may chew through the leash, or, again, in the case of extremely smart pets, 
burn through it with an acetylene torch. In the case of cats, leashes simply look ridiculous, as though the pet owner really wanted to 
own a dog but got confused at the pet store.
 
<p> 
The <b>Hold 'Em 2000 Pet Magnet</b> from <i>UltraAppliance</i> is the answer. Instead of old-fashioned leashes, the 
<b>Hold 'Em 2000 Pet Magnet</b> keeps your pet under control in a simple way.
 
<p>
Here's how it works. Dozens of small magnets are placed underneath the coat of your pet, where they remain painlessly invisible. Any time 
you need to recall your animal, you merely activate the handy, massive Hold 'Em 2000 Pet Magnet electromagnet (fits inside any extremely 
oversized purse) and your pet is gently and painlessly dragged to you from up to 100 yards. It's a must-have for any pet owner!
 
<p>
 
<blockquote>
<i>
"The <b>Hold 'Em 2000 Pet Magnet</b> not only keeps my dog from running away, but the electromagnet also comes in very handy if I need to 
find a needle in a haystack"</i>
-- Anonymous Celebrity
</blockquote>
</body>
</html>

Snooze.html

<html>
<header>
<title>Esteem-building Talking Pillow</title>
</header>
<body>
<h2>Esteem-building Talking Pillow</h2>
<h4>Do you feel less than your true potential when you wake up in the morning?</h4>
 
<p>
We searched for a way to capture the wasted time spent sleeping and to use this precious time to build motivation, character, and self-esteem.
 
<p>
We are proud to announce the <b>Esteem-building Talking Pillow</b>. Our pride in this wonderful invention glows even more because: 
<i>We use our own invention every night!</i>
 
<p>
Only you will know that you are sleeping with the <b>Esteem-building Talking Pillow</b> because only you can hear the soothing 
affirmations that gently enter your brain through the discreet speaker.
 
<p>
You will wake up refreshed and raring to go with a new sense of pride and enthusiasm for any task the day may bring. 
 
<p>
Be the first to own the <b>Esteem-building Talking Pillow</b>! Your friends and fellow workers will be amazed when you no longer 
cower in the corner. Now you will join in every conversation.
 
<p>
<b>Disclaimer:</b> Not responsible for narcissism and hyberbolic statements. May cause extreme behavior with overuse.
 
</body>
</html>

A.2.3.4 search_htmlservices.sql

set define off
 
create or replace package search_htmlServices as
  procedure showHTMLDoc (p_id in numeric);
  procedure showDoc  (p_id in varchar2, p_query in varchar2);
end search_htmlServices;
/
show errors;
 
create or replace package body search_htmlServices as
 
  procedure showHTMLDoc (p_id in numeric) is
    v_clob_selected   CLOB;
    v_read_amount     integer;
    v_read_offset     integer;
    v_buffer          varchar2(32767);
   begin
 
     select text into v_clob_selected from search_table where tk = p_id;
     v_read_amount := 32767;
     v_read_offset := 1;
   begin
    loop
      dbms_lob.read(v_clob_selected,v_read_amount,v_read_offset,v_buffer);
      htp.print(v_buffer);
      v_read_offset := v_read_offset + v_read_amount;
      v_read_amount := 32767;
    end loop;
   exception
   when no_data_found then
     null;
   end;
 end showHTMLDoc;
 
procedure showDoc (p_id in varchar2, p_query in varchar2) is
 
 v_clob_selected   CLOB;
 v_read_amount     integer;
 v_read_offset     integer;
 v_buffer          varchar2(32767);
 v_query           varchar(2000);
 v_cursor          integer;
 
 begin
   htp.p('<html><title>HTML version with highlighted terms</title>');
   htp.p('<body bgcolor="#ffffff">');
   htp.p('<b>HTML version with highlighted terms</b>');
 
   begin
     ctx_doc.markup (index_name => 'idx_search_table',
                     textkey    => p_id,
                     text_query => p_query,
                     restab     => v_clob_selected,
                     starttag   => '<i><font color=red>',
                     endtag     => '</font></i>');
 
     v_read_amount := 32767;
     v_read_offset := 1;
     begin
      loop
        dbms_lob.read(v_clob_selected,v_read_amount,v_read_offset,v_buffer);
        htp.print(v_buffer);
        v_read_offset := v_read_offset + v_read_amount;
        v_read_amount := 32767;
      end loop;
     exception
      when no_data_found then
         null;
     end;
 
     exception
      when others then
        null; --showHTMLdoc(p_id);
   end;
end showDoc;
end search_htmlServices; 
/
show errors
 
set define on

A.2.3.5 search_html.psp

<%@ plsql procedure="search_html" %>
<%@ plsql parameter="query" default="null" %>
<%! v_results number := 0; %>
 
<html>
<head>
  <title>search_html Search </title>
</head>
<body>
 
<%
 
IF query IS NULL THEN
%>
 
  <center>
    <form method="post" action="search_html">
     <b>Search for: </b>
     <input type="text" name="query" size="30">&nbsp;
     <input type="submit" value="Search">
  </center>
<hr>
 
<% 
  ELSE
%>
 
   <p>
   <%!
      color varchar2(6) := 'ffffff';
   %>
 
   <center>
     <form method="post" action="search_html">
      <b>Search for:</b>
      <input type="text" name="query" size="30" value="<%= query %>">
      <input type="submit" value="Search">
     </form>
   </center>
   <hr>
   <p>
 
   <%
     -- select statement 
    FOR DOC IN (
                SELECT /*+ DOMAIN_INDEX_SORT */ rowid, tk, title, score(1) scr
                FROM search_table
                WHERE CONTAINS(text, query,1) >0
                ORDER BY score(1) DESC
               ) 
         LOOP
           v_results := v_results + 1;
           IF v_results = 1 THEN
 
   %>
 
             <center>
              <table border="0">
                <tr bgcolor="#6699CC">
                  <th>Score</th>
                  <th>Title</th>
                </tr>
 
  <%      END IF; %>
          <tr bgcolor="#<%= color %>">
           <td> <%= doc.scr %>% </td>
           <td> <%= doc.title %>
           [<a href="search_htmlServices.showHTMLDoc?p_id=
                  <%= doc.tk %>">HTML</a>]
           [<a href="search_htmlServices.showDoc?p_id=
                  <%= doc.tk %>&p_query=<%= query %>">Highlight</a>]
           </td>
         </tr>
 
   <%
          IF (color = 'ffffff') THEN
               color := 'eeeeee';
             ELSE
               color := 'ffffff';
          END IF;
 
     END LOOP; 
   %>
 
    </table>
   </center>
 
<% 
  END IF;
%>
</body>
</html>