Listing #1:
I created a table as follows:
CREATE TABLE LU_XML_MAPPING
(
TABLE_FIELD_NAME VARCHAR2(60 BYTE),
XML_MAPPING VARCHAR2(30 BYTE)
);
ALTER TABLE LU_XML_MAPPING ADD (
UNIQUE (XML_MAPPING));
Listing #2:
CREATE TABLE SEARCH_TABLE
(
DEP_ID NUMBER(12) NOT NULL,
XML_CLOB CLOB NOT NULL,
UPDATE_DATE DATE DEFAULT SYSDATE
);
CREATE UNIQUE INDEX SEARCH_TABLE_PK ON SEARCH_TABLE
(DEP_ID);
ALTER TABLE SEARCH_TABLE ADD (
CONSTRAINT SEARCH_TABLE_PK
PRIMARY KEY
(DEP_ID));
ALTER TABLE SEARCH_TABLE ADD (
CONSTRAINT SEARCH_TABLE_FK
FOREIGN KEY (DEP_ID)
REFERENCES DEPOSITS_BASE (DEP_ID)
ON DELETE CASCADE);
Listing #3:
CREATE OR REPLACE PACKAGE Create_Search_Field AS
PROCEDURE deposit_info(dep_id_in NUMBER, mode_in VARCHAR2);
PROCEDURE land_st_info(dep_id_in IN NUMBER);
PROCEDURE print_doc(dep_id_in NUMBER, mode_in VARCHAR2);
END Create_Search_Field;
The associated package body for the above procedure is:
CREATE OR REPLACE PACKAGE BODY Create_Search_Field
AS
-----------------------------------------------------------------------
PROCEDURE deposit_info (dep_id_in NUMBER, mode_in VARCHAR2)
IS
TYPE depc IS REF CURSOR;
v_cursor depc;
v_rec deposits%ROWTYPE;
v_sql VARCHAR2 (1000);
v_count NUMBER := 0;
v_clob CLOB := NULL;
v_mode VARCHAR2 (6) := mode_in;
v_errorcode VARCHAR2(90) := NULL;
v_errortext VARCHAR2(4000) := NULL;
BEGIN
SELECT COUNT (*)
INTO v_count
FROM deposits
WHERE dep_id = dep_id_in;
IF v_count > 0
THEN
v_sql := 'SELECT * ' || 'FROM deposits WHERE 1=1';
IF dep_id_in IS NOT NULL
THEN
DBMS_SESSION.set_context ('SEARCH_CTX', 'DEP_ID', dep_id_in);
v_sql :=
v_sql
|| ' and dep_id = sys_context(''SEARCH_CTX'', ''DEP_ID'')';
END IF;
OPEN v_cursor FOR v_sql;
v_clob := v_clob || ' ' || CHR (13);
LOOP
FETCH v_cursor
INTO v_rec;
EXIT WHEN v_cursor%NOTFOUND;
v_clob :=
v_clob
|| ' '
|| v_rec.dep_id
|| ' '
|| CHR (13);
v_clob :=
v_clob
|| ' '
|| v_rec.rec_tp
|| ' '
|| CHR (13);
v_clob :=
v_clob
|| ' '
|| v_rec.dev_st
|| ' '
|| CHR (13);
v_clob :=
v_clob
|| ' '
|| v_rec.oper_tp
|| ' '
|| CHR (13);
v_clob :=
v_clob
|| ' '
|| v_rec.site_commod_type
|| ' '
|| CHR (13);
v_clob :=
v_clob
|| ' '
|| v_rec.sig
|| ' '
|| CHR (13);
v_clob :=
v_clob
|| ' '
|| v_rec.min_area_name
|| ' '
|| CHR (13);
END LOOP;
v_clob := v_clob || ' ' || CHR (13);
END IF;
IF UPPER (v_mode) = 'INSERT'
THEN
INSERT INTO SEARCH_TABLE
VALUES (dep_id_in, v_clob, SYSDATE);
ELSIF UPPER (v_mode) = 'UPDATE'
THEN
UPDATE SEARCH_TABLE
SET xml_clob = v_clob,
update_date = SYSDATE
WHERE dep_id = dep_id_in;
END IF;
EXCEPTION
WHEN OTHERS
THEN
-- enter a call to your logging routine, optional
NULL;
END deposit_info;
-----------------------------------------------------------------------
PROCEDURE land_st_info (dep_id_in IN NUMBER)
IS
TYPE land_stc IS REF CURSOR;
v_cursor land_stc;
v_rec land_status%ROWTYPE;
v_sql VARCHAR2 (1000);
v_count NUMBER := NULL;
v_clob CLOB := NULL;
BEGIN
SELECT COUNT (*)
INTO v_count
FROM LAND_ST_BASE
WHERE dep_id = dep_id_in;
IF v_count > 0
THEN
v_sql := 'SELECT * ' || 'FROM land_status WHERE 1=1';
IF dep_id_in IS NOT NULL
THEN
v_sql :=
v_sql
|| ' and dep_id = sys_context(''SEARCH_CTX'', ''DEP_ID'')';
END IF;
v_sql := v_sql || ' ORDER BY LINE';
OPEN v_cursor FOR v_sql;
v_clob := v_clob || ' ' || CHR (13);
LOOP
FETCH v_cursor
INTO v_rec;
EXIT WHEN v_cursor%NOTFOUND;
v_clob :=
v_clob
|| ' '
|| v_rec.land_st
|| ' '
|| CHR (13);
v_clob :=
v_clob
|| ' '
|| v_rec.admin_area
|| ' '
|| CHR (13);
END LOOP;
v_clob := v_clob || ' ' || CHR (13);
END IF;
UPDATE SEARCH_TABLE
SET xml_clob = xml_clob || v_clob
WHERE dep_id = dep_id_in;
END land_st_info;
-----------------------------------------------------------------------
PROCEDURE print_doc (dep_id_in NUMBER, mode_in VARCHAR2)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
v_mode VARCHAR2 (6) := mode_in;
BEGIN
deposit_info (dep_id_in, v_mode);
land_st_info (dep_id_in);
-- add in calls to execute other procedures for additional tables here...
COMMIT;
END print_doc;
END Create_Search_Field;
/
Listing #4:
CREATE OR REPLACE PROCEDURE Fill_Clobs IS
v_errorcode VARCHAR2(90) := NULL;
v_errortext VARCHAR2(4000) := NULL;
CURSOR dep_cur IS
SELECT dep_id
FROM DEPOSITS_BASE
WHERE dep_id IN
(SELECT dep_id FROM SEARCH_TABLE WHERE dbms_lob.getlength(xml_clob) < 1)
ORDER BY dep_id;
dep_rec dep_cur%ROWTYPE;
v_id NUMBER := NULL;
BEGIN
FOR dep_rec IN dep_cur
LOOP
v_id := dep_rec.dep_id;
Create_Search_Field.print_doc(v_id,'INSERT');
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
-- enter a call to your logging routine, optional
NULL;
END;
Listing #5:
DROP INDEX search_index; -- search_index is the index name, again same caveats as above.
ctx_ddl.create_preference('clob_idx_storage', 'BASIC_STORAGE');
ctx_ddl.set_attribute('clob_idx_storage', 'I_TABLE_CLAUSE', 'tablespace usgs_lob_idx storage (initial 10M next 10M)');
ctx_ddl.set_attribute('clob_idx_storage', 'R_TABLE_CLAUSE', 'tablespace usgs_lob_idx storage (initial 1M) lob (data) store as (cache)');
ctx_ddl.set_attribute('clob_idx_storage', 'N_TABLE_CLAUSE', 'tablespace usgs_lob_idx storage (initial 1M)');
ctx_ddl.set_attribute('clob_idx_storage', 'I_INDEX_CLAUSE', 'tablespace usgs_lob_idx storage (initial 1M) compress 2');
ctx_ddl.set_attribute('clob_idx_storage', 'P_TABLE_CLAUSE', 'tablespace usgs_lob_idx storage (initial 1M)');
CREATE INDEX search_index ON search_table(xml_clob)
indextype IS ctxsys.context
parameters('datastore ctxsys.direct_datastore
storage clob_idx_storage
filter ctxsys.null_filter
section group ctxsys.auto_section_group
sync (ON COMMIT)');
Modify the above accordingly, if you need/want a different tablespace or will have multiple text indexes, hence different “preferences” and/or index names.
Listing #6:
SELECT dep_id, dev_st, oper_tp, sig, NAME,
MIN (commod) KEEP (DENSE_RANK FIRST ORDER BY c_line ASC) commod,
MIN (commod_group) KEEP (DENSE_RANK FIRST ORDER BY c_line ASC) commod_group,
MIN (import) KEEP (DENSE_RANK FIRST ORDER BY c_line ASC) import,
MIN (usgs_num) KEEP (DENSE_RANK FIRST ORDER BY mt_rec ASC) usgs_num,
MIN (model_name) KEEP (DENSE_RANK FIRST ORDER BY mt_rec ASC) model_name,
MIN (country) KEEP (DENSE_RANK FIRST ORDER BY l_line ASC) country,
MIN (state_prov) KEEP (DENSE_RANK FIRST ORDER BY l_line ASC) state_prov,
MIN (county) KEEP (DENSE_RANK FIRST ORDER BY l_line ASC) county
FROM NEW_MASTER_QUERY
WHERE dep_id IN
(SELECT dep_id
FROM search_table where CONTAINS( xml_clob, '&F130_WHERE_CLAUSE.') > 0 )
GROUP BY dep_id, dev_st, oper_tp, sig, NAME
Listing #7:
Listing #8:
declare
v_sql varchar2(4000);
v_count PLS_INTEGER;
begin
IF apex_collection.collection_exists( p_collection_name => 'SEARCH_COLLECTION' ) THEN
v_count := APEX_COLLECTION.COLLECTION_MEMBER_COUNT (p_collection_name => 'SEARCH_COLLECTION' );
IF v_count > 0 THEN
v_sql := 'select apex_item.select_list_from_lov_xl(1,c001,''LOV_TABLE_NAMES'',null,''NO'') table_field_name,
apex_item.select_list_from_lov(3,c002,''LOV_COMPARISON'',null,''NO'') comp_oper,
apex_item.text(4,c003,45) search_text,
apex_item.select_list_from_lov(5,c004,''LOV_AND_OR'',''onChange="javascript:va_AddTableRow(this,''''table_grab'''',1);"'',''NO'') and_or
FROM apex_collections
WHERE collection_name = ''SEARCH_COLLECTION''
ORDER BY seq_id
';
ELSE
v_sql:= 'select apex_item.select_list_from_lov_xl(1,table_field_name,''LOV_TABLE_NAMES'',null,''NO'') table_field_name,
apex_item.select_list_from_lov(3,comp_oper,''LOV_COMPARISON'',null,''NO'') comp_oper,
apex_item.text(4,search_text,45) search_text,
apex_item.select_list_from_lov(5,and_or,''LOV_AND_OR'',''onChange="javascript:va_AddTableRow(this,''''table_grab'''',1);"'',''NO'') and_or
from lu_xml_search;';
END IF;
ELSE
v_sql:= 'select apex_item.select_list_from_lov_xl(1,table_field_name,''LOV_TABLE_NAMES'',null,''NO'') table_field_name,
apex_item.select_list_from_lov(3,comp_oper,''LOV_COMPARISON'',null,''NO'') comp_oper,
apex_item.text(4,search_text,45) search_text,
apex_item.select_list_from_lov(5,and_or,''LOV_AND_OR'',''onChange="javascript:va_AddTableRow(this,''''table_grab'''',1);"'',''NO'') and_or
from lu_xml_search;';
END IF;
return v_sql;
end;
Listing #9:
DECLARE
clause VARCHAR2(900);
v_tag VARCHAR2(60) := NULL;
v_tab VARCHAR2(60) := NULL;
v_search VARCHAR2(60) := NULL;
v_cond VARCHAR2(5) := NULL;
i pls_integer := 1;
v_errorcode VARCHAR2(90) := NULL;
v_errortext VARCHAR2(4000) := NULL;
BEGIN
clause := ' AND 1=1';
FOR i IN 1 .. apex_application.g_f01.COUNT
LOOP
IF apex_application.g_f01(i) IS
NOT NULL THEN
IF apex_application.g_f01(i) LIKE '%ENTIRE TABLE%' THEN
IF apex_application.g_f03(i) = 'EQUALS' THEN
SELECT xml_table_mapping
INTO v_tag
FROM lu_xml_mapping
WHERE TABLE_NAME = apex_application.g_f01(i);
ELSE -- g_fo3(i) = 'NOT EQUALS'
IF apex_application.g_f03(i) = 'NOT EQUALS' THEN
SELECT xml_table_mapping
INTO v_tag
FROM lu_xml_mapping
WHERE TABLE_NAME = apex_application.g_f01(i);
END IF;
END IF;
ELSE
IF apex_application.g_f03(i) = 'EQUALS' THEN
SELECT xml_field_mapping
INTO v_tag
FROM lu_xml_mapping
WHERE TABLE_NAME = apex_application.g_f01(i);
ELSE -- g_fo3(i) = 'NOT EQUALS'
IF apex_application.g_f03(i) = 'NOT EQUALS' THEN
SELECT xml_field_mapping
INTO v_tag
FROM lu_xml_mapping
WHERE TABLE_NAME = apex_application.g_f01(i);
END IF;
END IF;
END IF;
END IF;
v_search := apex_application.g_f04(i);
clause := clause || v_cond || ' contains(xml_clob, ''' || v_search || ' within ' || v_tag || ''') > 0';
v_cond := ' ' || apex_application.g_f05(i);
END LOOP;
IF clause = ' AND 1=1' THEN
:P3_WHERE_CLAUSE := '1=1';
ELSE
:P3_WHERE_CLAUSE := SUBSTR(clause,9);
END IF;
EXCEPTION
WHEN no_data_found THEN
-- enter a call to your logging routine, optional
NULL;
WHEN others THEN
-- enter a call to your logging routine, optional
NULL;
END;
Listing #10:
SELECT dep_id, dev_st, oper_tp, sig, NAME,
MIN (commod) KEEP (DENSE_RANK FIRST ORDER BY c_line ASC) commod,
MIN (commod_group) KEEP (DENSE_RANK FIRST ORDER BY c_line ASC) commod_group,
MIN (import) KEEP (DENSE_RANK FIRST ORDER BY c_line ASC) import,
MIN (usgs_num) KEEP (DENSE_RANK FIRST ORDER BY mt_rec ASC) usgs_num,
MIN (model_name) KEEP (DENSE_RANK FIRST ORDER BY mt_rec ASC) model_name,
MIN (country) KEEP (DENSE_RANK FIRST ORDER BY l_line ASC) country,
MIN (state_prov) KEEP (DENSE_RANK FIRST ORDER BY l_line ASC) state_prov,
MIN (county) KEEP (DENSE_RANK FIRST ORDER BY l_line ASC) county
FROM NEW_MASTER_QUERY
WHERE dep_id IN
(SELECT dep_id
FROM search_table where &P3_WHERE_CLAUSE. )
GROUP BY dep_id, dev_st, oper_tp, sig, NAME
Listing #11:
DECLARE
search_clause VARCHAR2 (1900) := NULL;
v_tag VARCHAR2 (60) := NULL;
v_tab VARCHAR2 (60) := NULL;
v_not VARCHAR2 (4) := NULL;
v_search VARCHAR2 (60) := NULL;
v_cond VARCHAR2 (5) := NULL;
i PLS_INTEGER := 1;
BEGIN
search_clause := ' AND 1=1';
apex_collection.create_or_truncate_collection
(p_collection_name => 'SEARCH_COLLECTION');
IF apex_application.g_f01 (i) IS NOT NULL
THEN
FOR i IN 1 .. apex_application.g_f01.COUNT
LOOP
IF apex_application.g_f03 (i) = 'EQUALS'
THEN
v_not := NULL;
ELSE
-- g_fo3(i) = 'NOT EQUALS'
v_not := ' NOT';
END IF;
SELECT xml_mapping
INTO v_tag
FROM LU_XML_MAPPING
WHERE table_field_name = apex_application.g_f01 (i);
apex_collection.add_member (p_collection_name => 'SEARCH_COLLECTION',
p_c001 => apex_application.g_f01(i),
p_c002 => apex_application.g_f03(i),
p_c003 => apex_application.g_f04(i),
p_c004 => apex_application.g_f05(i)
);
v_search := apex_application.g_f04 (i);
search_clause :=
search_clause
|| v_cond
|| v_not
|| ' contains(xml_clob, '''
|| v_search
|| ' within '
|| v_tag
|| ''') > 0';
v_cond := ' ' || apex_application.g_f05 (i);
v_not := NULL;
END LOOP;
END IF;
IF search_clause = ' AND 1=1'
THEN
:p3_where_clause := '1=1';
ELSE
:p3_where_clause := SUBSTR (search_clause, 9);
END IF;
-- Now need to clear the last and/or condition in the collection
i := apex_application.g_f01.COUNT;
IF apex_application.g_f01 (i) IS NOT NULL
THEN
apex_collection.update_member_attribute
(p_collection_name => 'SEARCH_COLLECTION',
p_seq => i,
p_attr_number => 4,
p_attr_value => NULL
);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
-- enter a call to your logging routine, optional
NULL;
WHEN OTHERS
THEN
-- enter a call to your logging routine, optional
NULL;
:p3_where_clause := '1=1';
END;