Skip to content

Commit 1b593d2

Browse files
authored
adding search doc column to at_physical_location (#123)
* adding search doc column to at_physical_location this will allow an Oracle Text index to be used and then allow fast search using CONTAINS within CDA queries for text search
1 parent 600b67d commit 1b593d2

9 files changed

Lines changed: 251 additions & 10 deletions

File tree

docker-compose.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,16 @@ services:
1010
- ORACLE_PASSWORD=password
1111
ports:
1212
- "1521:1521"
13+
healthcheck:
14+
test: [ "CMD-SHELL", "echo 'SELECT 1 FROM dual;' | sqlplus -s sys/${ORACLE_PASSWORD}@localhost/FREEPDB1 as sysdba | grep -q '1'" ]
15+
interval: 10s
16+
timeout: 5s
17+
retries: 30
18+
start_period: 60s
19+
1320
schema:
1421
build:
15-
context: ./schema
22+
context: .
1623
container_name: cwms-dev-schema
1724
environment:
1825
- DB_HOST_PORT=cwms-dev-db:1521
@@ -25,6 +32,6 @@ services:
2532
- OFFICE_EROC=S0
2633
# With installonce set to 0 the schema will be removed (equivalent to ant clean build) each time this runs.
2734
- INSTALLONCE=0
28-
- QUIET=0
35+
- QUIET=0
2936
volumes:
3037
cwms-dev-oracle:

schema/src/buildCWMS_DB.sql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,10 +401,11 @@ begin
401401
dbms_utility.compile_schema('&cwms_schema');
402402
end;
403403
/
404+
404405
prompt Rebuilding all disabled function-based indexes...
405406
begin
406407
for rec in (select index_name from all_indexes where owner = '&cwms_schema' and funcidx_status = 'DISABLED') loop
407-
execute immediate 'alter index &cwms_schema..'||rec.index_name||' rebuild';
408+
execute immediate 'alter index &cwms_schema..'||rec.index_name||' rebuild';
408409
end loop;
409410
end;
410411
/
@@ -421,6 +422,8 @@ exception
421422
end;
422423
/
423424

425+
426+
@@cwms/oracle_text/setup_indexes.sql
424427
--
425428
-- all done
426429
--

schema/src/cwms/at_schema.sql

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ CREATE TABLE AT_PHYSICAL_LOCATION
240240
OFFICE_CODE NUMBER(14),
241241
NATION_CODE VARCHAR2(2),
242242
NEAREST_CITY VARCHAR2(50),
243+
SEARCH_DOC VARCHAR2(1000),
243244
CONSTRAINT AT_PHYSICAL_LOCATION_PK PRIMARY KEY (LOCATION_CODE) USING INDEX
244245
)
245246
TABLESPACE CWMS_20AT_DATA
@@ -283,6 +284,7 @@ COMMENT ON COLUMN AT_PHYSICAL_LOCATION.PUBLISHED_LONGITUDE IS 'Longitude of loca
283284
COMMENT ON COLUMN AT_PHYSICAL_LOCATION.OFFICE_CODE IS 'References the office who''s bounday contains this location.';
284285
COMMENT ON COLUMN AT_PHYSICAL_LOCATION.NATION_CODE IS 'References the nation containing this location.';
285286
COMMENT ON COLUMN AT_PHYSICAL_LOCATION.NEAREST_CITY IS 'Name of city nearest this location.';
287+
COMMENT ON COLUMN AT_PHYSICAL_LOCATION.SEARCH_DOC IS 'Placeholder column for Oracle Text full-text search index. The indexed document text is dynamically generated by the USER_DATASTORE procedure (CWMS_LOC.BUILD_SEARCH_DOC) during indexing and is not stored in this column.';
286288
287289
288290
ALTER TABLE AT_PHYSICAL_LOCATION ADD CONSTRAINT AT_PHYSICAL_LOCATION_CK1 CHECK (TRIM(SUB_LOCATION_ID) = SUB_LOCATION_ID);
@@ -311,11 +313,11 @@ STORAGE (
311313
)
312314
NOPARALLEL
313315
/
314-
316+
SHOW ERRORS;
315317
316318
INSERT INTO at_physical_location
317-
(location_code, base_location_code, active_flag, location_kind)
318-
VALUES (0, 0, 'F', 1);
319+
(location_code, base_location_code, active_flag, location_kind)
320+
VALUES (0, 0, 'F', 1);
319321
320322
COMMIT;
321323

schema/src/cwms/cwms_loc_pkg.sql

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3167,6 +3167,62 @@ AS
31673167
p_datums in varchar2 default null,
31683168
p_office_id in varchar2 default null)
31693169
return clob;
3170+
3171+
3172+
/**
3173+
* Builds the search document for a location specifically for use by Oracle Text.
3174+
*
3175+
* <p>This procedure is used by the Oracle Text <code>USER_DATASTORE</code> defined
3176+
* for the <code>AT_PHYSICAL_LOCATION.SEARCH_DOC</code> column. During text index
3177+
* creation or synchronization, the procedure constructs a denormalized text document
3178+
* containing ids and metadata which are tokenized and stored in the text index.</p>
3179+
*
3180+
* <p>The resulting text is not stored in the <code>SEARCH_DOC</code> column itself.
3181+
* It is used by the Oracle Text indexing engine and stored in the text index tables associated with the
3182+
* <code>AT_PHYSICAL_LOCATION_SEARCH_IDX</code> index.</p>
3183+
*
3184+
* <p>The generated document may include values such as:</p>
3185+
* <ul>
3186+
* <li>Base location id</li>
3187+
* <li>Sub-location id</li>
3188+
* <li>Combined location identifier (<code>BASE-SUB</code>)</li>
3189+
* <li>Public name</li>
3190+
* <li>Long name</li>
3191+
* <li>Description</li>
3192+
* <li>Map label</li>
3193+
* <li>Nearest city</li>
3194+
* <li>Location kind id</li>
3195+
* <li>Location type</li>
3196+
* </ul>
3197+
*
3198+
* <p>This enables full-text search queries such as:</p>
3199+
*
3200+
* <pre>
3201+
* SELECT SCORE(1) AS relevance,
3202+
* location_id,
3203+
* public_name,
3204+
* long_name,
3205+
* nearest_city
3206+
* FROM av_loc
3207+
* WHERE CONTAINS(search_doc, '(FOLSOM AND DAM) OR (AMERICAN AND RIVER)', 1) > 0
3208+
* ORDER BY SCORE(1) DESC;
3209+
* </pre>
3210+
*
3211+
* <p>The procedure is executed automatically during:</p>
3212+
* <ul>
3213+
* <li>Initial creation of the Oracle Text index</li>
3214+
* <li>Index synchronization operations</li>
3215+
* <li>Row updates when the index is configured with <code>SYNC (ON COMMIT)</code></li>
3216+
* </ul>
3217+
*
3218+
* @param p_rowid The <code>ROWID</code> of the <code>AT_PHYSICAL_LOCATION</code> row
3219+
*
3220+
* @param p_doc The generated search document text returned to the Oracle Text engine for tokenization and indexing.
3221+
*/
3222+
procedure build_search_doc(
3223+
p_rowid in rowid,
3224+
p_doc out varchar2
3225+
);
31703226
END cwms_loc;
31713227
/
31723228

schema/src/cwms/cwms_loc_pkg_body.sql

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,6 +2483,10 @@ AS
24832483
UPDATE at_base_location abl
24842484
SET base_location_id = l_base_location_id_new
24852485
WHERE abl.base_location_code = l_base_location_code_old;
2486+
-- innocuous update that will force a reindex on at_physical_location.search_doc
2487+
UPDATE at_physical_location
2488+
SET search_doc = search_doc
2489+
WHERE base_location_code = l_base_location_code_old;
24862490
--
24872491
WHEN l_sub_location_id_new IS NULL
24882492
THEN -- Old Loc renamed to new Base Loc --
@@ -11052,6 +11056,40 @@ end unassign_loc_groups;
1105211056
v_package_log_prop_text := nvl(p_text, sys_context('userenv', 'sid'));
1105311057
end set_package_log_property_text;
1105411058

11059+
procedure build_search_doc(
11060+
p_rowid in rowid,
11061+
p_doc out varchar2
11062+
)
11063+
is
11064+
begin
11065+
select max(
11066+
coalesce(b.base_location_id,'') || ' '
11067+
|| coalesce(pl.sub_location_id,'') || ' '
11068+
|| case
11069+
when pl.sub_location_id is not null
11070+
then b.base_location_id || '-' || pl.sub_location_id || ' '
11071+
else ''
11072+
end
11073+
|| coalesce(pl.public_name,'') || ' '
11074+
|| coalesce(pl.long_name,'') || ' '
11075+
|| coalesce(pl.description,'') || ' '
11076+
|| coalesce(pl.map_label,'') || ' '
11077+
|| coalesce(pl.nearest_city,'') || ' '
11078+
|| coalesce(k.location_kind_id,'') || ' '
11079+
|| coalesce(pl.location_type,'')
11080+
)
11081+
into p_doc
11082+
from at_physical_location pl
11083+
left join at_base_location b
11084+
on b.base_location_code = pl.base_location_code
11085+
left join cwms_location_kind k
11086+
on k.location_kind_code = pl.location_kind
11087+
where pl.rowid = p_rowid;
11088+
11089+
p_doc := coalesce(p_doc, '');
11090+
11091+
end build_search_doc;
11092+
1105511093
begin
1105611094
g_location_code_cache.name := 'cwms_loc.g_location_code_cache';
1105711095
g_location_id_cache.name := 'cwms_loc.g_location_id_cache';
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) 2026
3+
* United States Army Corps of Engineers - Hydrologic Engineering Center (USACE/HEC)
4+
* All Rights Reserved. USACE PROPRIETARY/CONFIDENTIAL.
5+
* Source may not be released without written approval from HEC
6+
*/
7+
prompt Creating Oracle Text preferences and indexes
8+
9+
begin
10+
ctx_ddl.drop_preference('loc_search_ds');
11+
exception when others then null;
12+
end;
13+
/
14+
begin
15+
ctx_ddl.create_preference('loc_search_ds', 'USER_DATASTORE');
16+
ctx_ddl.set_attribute('loc_search_ds', 'PROCEDURE', '&cwms_schema..cwms_loc.build_search_doc');
17+
ctx_ddl.create_preference('loc_search_lexer', 'BASIC_LEXER');
18+
ctx_ddl.create_preference('loc_search_wordlist', 'BASIC_WORDLIST');
19+
end;
20+
/
21+
commit;
22+
23+
begin
24+
execute immediate 'drop index at_physical_location_search_idx';
25+
exception
26+
when others then
27+
if sqlcode != -1418 then raise; end if;
28+
end;
29+
/
30+
create index at_physical_location_search_idx
31+
on at_physical_location (search_doc)
32+
indextype is ctxsys.context
33+
parameters ('datastore loc_search_ds
34+
lexer loc_search_lexer
35+
wordlist loc_search_wordlist
36+
sync (on commit)');
37+
/
38+
39+
alter index CWMS_20.AT_PHYSICAL_LOCATION_SEARCH_IDX rebuild;
40+
41+
begin
42+
ctx_ddl.sync_index('AT_PHYSICAL_LOCATION_SEARCH_IDX');
43+
end;
44+
/

schema/src/cwms/views/av_loc.sql

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ insert into at_clob
5656
* @field nation_id Nation encompassing location (may be inherited from base location)
5757
* @field nearest_city City nearest to location (may be inherited from base location)
5858
* @field active_flag Depricated - loc_active_flag replaces active_flag as of v2.1
59+
* @field search_doc Placeholder column for Oracle Text full-text search index. The indexed document text is dynamically generated by the USER_DATASTORE procedure (CWMS_LOC.BUILD_SEARCH_DOC) during indexing and is not stored in this column.
5960
*/
6061
');
6162

@@ -90,7 +91,8 @@ select LOCATION_CODE,
9091
BOUNDING_OFFICE_ID,
9192
NATION_ID,
9293
NEAREST_CITY,
93-
active_flag
94+
active_flag,
95+
SEARCH_DOC
9496
from
9597
( with phy_loc as
9698
( select loc.location_code,
@@ -119,7 +121,8 @@ from
119121
nvl (loc.nearest_city, bas.nearest_city) as nearest_city,
120122
blo.active_flag as base_loc_active_flag,
121123
loc.active_flag as loc_active_flag,
122-
loc.active_flag as active_flag
124+
loc.active_flag as active_flag,
125+
loc.search_doc
123126
from -- join the base location metadata (bas) with the location (loc)
124127
cwms_20.at_physical_location loc left join
125128
cwms_20.at_physical_location bas on ( bas.location_code = loc.base_location_code ) left join

schema/src/cwms/views/av_loc2.sql

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ insert into at_clob
6464
* @field loc_alias_category The location category that owns the location group to which the alias for the location_id or base_location_id belongs. Null if location_id is not an alias.
6565
* @field loc_alias_group The location group to which the alias for the location_id or base_location_id belongs. Null if location_id is not an alias.
6666
* @field db_office_code Unique number identifying the office that owns the location
67+
* @field search_doc Placeholder column for Oracle Text full-text search index. The indexed document text is dynamically generated by the USER_DATASTORE procedure (CWMS_LOC.BUILD_SEARCH_DOC) during indexing and is not stored in this column.
6768
*/
6869
');
6970

@@ -102,7 +103,8 @@ create or replace force view av_loc2
102103
aliased_item,
103104
loc_alias_category,
104105
loc_alias_group,
105-
db_office_code
106+
db_office_code,
107+
search_doc
106108
)
107109
as
108110
select q1.location_code,
@@ -141,7 +143,8 @@ as
141143
q1.aliased_item,
142144
q1.loc_alias_category,
143145
q1.loc_alias_group,
144-
q1.db_office_code
146+
q1.db_office_code,
147+
pl.search_doc
145148
from (------------------------------------
146149
-- location and alias ids, office --
147150
------------------------------------
@@ -227,6 +230,8 @@ as
227230
and lc.loc_category_code = lg.loc_category_code
228231
)
229232
) q1
233+
join at_physical_location pl
234+
on pl.location_code = q1.location_code
230235
join
231236
(--------------------------------------
232237
-- unit system, unit, and elevation --

0 commit comments

Comments
 (0)