Oracle8
ConText Cartridge Workbench User's Guide
Release 2.4 A63822-01 |
|
This chapter presents the CTXQUERY sample application, developed
with Oracle Forms 4.5, and illustrates one method for developing applications
using ConText.
The following topics are covered in this chapter:
The CTXQUERY sample application (ctcquery.fmb) is
a basic Oracle Forms 4.5 application which provides a graphical interface
for performing text queries and DML operations with ConText. The application
exists to show one way of developing Forms applications using ConText.
It supports all the query expression operators and can provide query term
highlighting using asterisks in the specified documents.
Note: An icon is not created for CTXQUERY during installation of the ConText Workbench because the sample application requires some setup tasks to be performed on the server before the application can be used. For more information, see "Setting Up the Sample" in this chapter. |
See
Also:
For more information about developing ConText applications, see Oracle8 ConText Cartridge Application Developer's Guide |
The ConText query concepts demonstrated in this example are:
The form is laid out in four blocks on three canvases. There
is a block and a canvas for each step of the query, hitlist, and view with
one extra block for all the buttons. All canvases are displayed in a single
window, CTXQUERY.
This section provides information about the setup tasks that must be performed before using CTXQUERY:
Before the sample Forms application can be used, the demonstration
data must be imported into the required table and demonstration installation
must be performed. The demonstration data is provided in a dump file (demo.dmp).
Installation is performed by a set of SQL scripts (demoinst.sql
and genling.sql).
Importing the demo.dmp file performs the following tasks:
Running the SQL scripts performs the following tasks:
See
Also:
For more information about setting up CTXQUERY, see Oracle8 ConText Cartridge Application Developer's Guide |
The sample application requires Oracle Forms (32-bit), version
4.5.7.4.0 or higher, to be installed.
Oracle Forms is not installed automatically during ConText
Workbench installation and must be installed separately before using the
sample application.
Note: If a version higher than 4.5.7.4.0 is installed on your machine, to use the sample application, the ctxquery.fmb file may have to be regenerated after installation. |
The CTXQUERY form is divided into eight distinct sections:
On startup, the When-New-Form-Instance trigger initializes the form.
When-New-Form-Instance set_window_property (FORMS_MDI_WINDOW, WINDOW_STATE, MAXIMIZE); set_window_property('CTXQUERY', WINDOW_STATE, MAXIMIZE); select query_id.nextval into :global.query_id from dual;
This maximizes the windows for display, then selects a query
ID from a sequence.
This form is designed so that it can be used by multiple
concurrent users, which means that the results tables are shared. When
result tables are shared, a unique query ID separates each user's results
from other users. In this form the unique ID is created as an increasing
sequence of numbers with the last value stored in a global variable.
The query screen is the first screen of the form displayed.
Each widget is part of the query block, which is a
non-base-table block. There is one hidden field in this screen, query_string.
When the Query button is pressed, the When-Button-Pressed trigger goes to the hitlist block and executes a query:
When-Button-Pressed on BUTTONS.QUERY go_block('hitlist'); clear_block(no_validate); execute_query(all_records);
The hitlist block is based on the article_hitlist
view. This view joins the query result table query_temp and the
base table articles into a hitlist which has both score and article
information. Although this block contains items for all the fields in this
view, most are hidden. The visible page displays score, author, section,
and title.
Before the query on the hitlist block is executed, the pre-query trigger fires. This trigger executes the first step of a two-step query, then limits the relational fields to the query criteria:
Pre-Query on HITLIST build_query_string; ctx_query.contains('DEMO_POLICY', :query.query_string, 'QUERY_TEMP', 1, :global.query_id, 0,1,null); -- --limit the relational fields to the query criteria -- :hitlist.conid := :global.query_id; :hitlist.author := :query.author; :hitlist.section := :query.section; copy(:query.pub_date,'hitlist.pub_date');
The build_query_string procedure constructs the query
expression by concatenating the term, weight, and operator fields from
the form and putting them into the query.query_string hidden field.
build_query_string is divided into sections A through
E.
Section A of the code clears the query string of any previous
contents.
Section B takes each term from the user input form and builds the query expression as follows:
Query arguments are enclosed in curly brackets so that any special characters within the argument (e.g., the "&" in Q&A) will not be misinterpreted as ConText operators
If the user has filled in a weighting factor in the appropriate field of the input screen, this value is appended to the search argument.
When the concatenation is finished, a sample term looks
like this:
Expansion | Search Criteria | Weight | Boolean |
---|---|---|---|
! |
{cat} |
*2 |
& |
Note: In CTXQUERY, the user can enter up to three separate query expression. These four steps are repeated to for each query expression. |
Section C of the code strips off extraneous operators at
the end of the final query string since the last term has no boolean operator.
Section D adds the score threshold value to the query expression.
Section E appends the result limit.
PROCEDURE build_query_string IS BEGIN -- --Section A -- :query.query_string := null; -- --Section B -- if (:query.qterm1 is not null) then :query.query_string := :query.query_string || :query.qexp1 || '{' || :query.qterm1 || '}' || '*' || to_char(nvl(:query.qwt1, 1)) || substr(:query.qop1,2,1); end if; if (:query.qterm2 is not null) then :query.query_string := :query.query_string || :query.qexp2 || '{' || :query.qterm2 || '}' || '*' || to_char(nvl(:query.qwt2, 1)) || substr(:query.qop2,2,1); end if; if (:query.qterm3 is not null) then :query.query_string := :query.query_string || :query.qexp3 || '{' || :query.qterm3 || '}' || '*' || to_char(nvl(:query.qwt3, 1)); end if; -- --Section C -- :query.query_string := rtrim(:query.query_string, '&|,;-'); -- --Section D -- if (:query.qthresh is not null) then :query.query_string := '(' || :query.query_string || ')>' || to_char(:query.qthresh); end if; -- --Section E -- if (:query.qlimit is not null) then :query.query_string := '(' || :query.query_string || '):' || to_char(:query.qlimit); end if; END;
When an article in the hitlist is double-clicked, the When-Mouse-Double-Click trigger on hitlist.title displays the article in the VIEW block:
When-Mouse-Double-Click on HITLIST.TITLE GO_BLOCK('VIEW'); EXECUTE_QUERY;
In order to display the correct article, the Pre-Query trigger limits the view block to display the article highlighted in the hitlist block:
Pre-Query on VIEW: :view.article_id := :hitlist.article_id;
The view block is based on articles, and displays
the full text of the article.
When the highlight button on the view block is pressed,
the When-Button-Pressed trigger on buttons.highlight invokes the
CTX_QUERY.HIGHLIGHT procedure.
The highlight procedure is divided into sections A
and B.
Section A call the HIGHLIGHT procedure and performs the following tasks:
The highlight result table (highlight_temp) has the
following structure:
Columns | TYPE |
---|---|
ID |
NUMBER |
OFFSET |
NUMBER |
LENGTH |
NUMBER |
STRENGTH |
NUMBER |
This procedure highlights matching query terms in the text
window by surrounding them with <<< and >>>.
It is not possible to do an INSTR for the search terms because
of the expansion operators; for example, go=going=gone in a stem
expansion. Instead, use the highlight procedure in Section A to generate
the highlights table.
This table holds the offset and the length of each word to
be highlighted.
With the highlights generated, the cursor loop in Section
B works through each offset, length pair backwards from last offset to
first.
The asterisks insert won't change the other offsets. For
each offset, length pair, the asterisks are inserted by reassigning the
full text to: everything before the term (line 1), then the asterisks,
then the term and some more asterisks (line 2) then everything after the
term (line 3). Doing this repeatedly highlights all the terms in the document.
PROCEDURE highlight IS cursor highcur is select offset, length from highlight_temp where id = :global.query_id order by offset desc; -- -- Section A -- BEGIN ctx_query.highlight( 'DEMO_POLICY', -- policy name to_char(:view.article_id), -- textkey :query.query_string, -- query string :global.query_id, -- query_id null, null, 'HIGHLIGHT_TEMP', -- highlight table null, null, null, null); -- -- Section B -- for hc in highcur loop 1. :view.text := substr(:view.text,1,hc.offset - 1) || 2. '***'||substr(:view.text,hc.offset,hc.length)||'***'|| 3. substr(:view.text,hc.offset+hc.length); end loop; END;
When a document is changed it needs to be re-indexed and
new linguistic information needs to be extracted. This can be performed
in a table trigger or in the application.
The view block contains pre-update and pre-index triggers
that perform the necessary re-indexing when there is a change to article
data. Both triggers invoke the reindex_article procedure.
The reindex_article procedure performs the following tasks:
Note: There is no COMMIT; it is performed by the COMMIT of the change to the VIEW block. In SUBMIT, you must explicitly ask for it not to COMMIT (the FALSE second parameter). |
See
Also:
For more information about DML and re-indexing, see Oracle8 ConText Cartridge Administrator's Guide. |
PROCEDURE reindex_article IS handle number; begin # # Section A # ctx_dml.reindex('demo_policy', TO_CHAR(:view.article_id)); # # Section B # delete from article_themes where pk = :view.article_id; delete from article_gists where pk = :view.article_id; # # Section C # ctx_ling.REQUEST_themes('demo_policy', TO_CHAR(:view.article_id), 'article_themes'); ctx_ling.REQUEST_gist('demo_policy', TO_CHAR(:view.article_id), 'article_gists'); # Section D # handle := ctx_ling.submit(0,FALSE,0); end;
Before the session is ended, clean up any leftover rows in the hitlist result table (query_temp) and the highlight result table (highlight_temp) tables for the query ID:
Post-Form delete from query_temp where conid = to_number(:global.query_id); delete from highlight_temp where id = to_number(:global.query_id); standard.commit;
The standard.commit statement executes an Oracle COMMIT
without doing a Forms commit_form.