Ditch our own viz tests and just use query_parser_fts()
authorLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Tue, 30 Apr 2013 22:06:33 +0000 (18:06 -0400)
committerLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Fri, 3 May 2013 13:57:49 +0000 (09:57 -0400)
After a talk with Mike yesterday we realized this was even possible.  Or
maybe that was already clear to him but not yet to me.  This has taken a
while to get almost right.

Signed-off-by: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Open-ILS/src/sql/Pg/upgrade/YYYY.schema.bib-auth-browse.sql

index daaed50..d795e88 100644 (file)
@@ -6885,96 +6885,6 @@ Revision 1.2 - Added Log Comment  2003/03/24 19:37:42  ckeith
 -- ----------------------------------------------------
 -- XXX TODO From here down, add this to stock SQL files
 
--- The following view supports checking for visibility for OPAC browse.
-CREATE OR REPLACE VIEW asset.visible_holdings AS
-SELECT 
-    bre.id AS record,
-    COALESCE(
-        aovc.circ_lib, acn_for_uri_map.owning_lib, acp_for_peer_bibs.circ_lib
-    ) AS ou,
-    COALESCE(aovc_acp.location, acp_for_peer_bibs.location) AS copy_location
-FROM biblio.record_entry bre
-LEFT JOIN asset.opac_visible_copies aovc
-    ON (aovc.record = bre.id)
-LEFT JOIN asset.copy aovc_acp
-    ON (aovc.copy_id = aovc_acp.id)
-LEFT JOIN asset.call_number acn_for_uri_map
-    ON (acn_for_uri_map.record = aovc.record)
-LEFT JOIN asset.uri_call_number_map aucnm
-    ON (aucnm.call_number = acn_for_uri_map.id)
-LEFT JOIN asset.uri auri
-    ON (aucnm.uri = auri.id)
-LEFT JOIN biblio.peer_bib_copy_map bpbcm
-    ON (bpbcm.peer_record = bre.id)
-LEFT JOIN asset.copy acp_for_peer_bibs
-    ON (bpbcm.target_copy = acp_for_peer_bibs.id )
-LEFT JOIN asset.copy_location peer_copy_loc
-    ON (peer_copy_loc.id = acp_for_peer_bibs.location )
-LEFT JOIN config.copy_status peer_copy_status
-    ON (peer_copy_status.id = acp_for_peer_bibs.status)
-WHERE
-    NOT bre.deleted AND
-    COALESCE(auri.active, TRUE) AND
-    NOT COALESCE(acp_for_peer_bibs.deleted, FALSE) AND
-    COALESCE(
-        acp_for_peer_bibs.opac_visible,
-        peer_copy_loc.opac_visible,
-        peer_copy_status.opac_visible,
-        TRUE     -- URIs and things on aovc are already known to be visible
-    )
-UNION
-SELECT
-    bre.id AS record,
-    aou.id AS ou,
-    NULL AS copy_location
-FROM biblio.record_entry bre
-INNER JOIN config.bib_source cbs
-    ON (cbs.id = bre.source AND cbs.transcendant)
-INNER JOIN actor.org_unit aou ON (true)
-WHERE NOT bre.deleted ;
-
--- This view supports checking for holdings in scope for staff browse.
-
-CREATE OR REPLACE VIEW asset.staff_holdings AS
-SELECT 
-    bre.id AS record,
-    COALESCE(
-        acp.circ_lib, acn_for_uri_map.owning_lib, acp_for_peer_bibs.circ_lib
-    ) AS ou,
-    COALESCE(acp.location, acp_for_peer_bibs.location) AS copy_location
-FROM biblio.record_entry bre
-LEFT JOIN asset.call_number acn
-    ON (acn.record = bre.id)
-LEFT JOIN asset.copy acp
-    ON (acp.call_number = acn.id)
-LEFT JOIN asset.call_number acn_for_uri_map
-    ON (acn_for_uri_map.record = bre.id)
-LEFT JOIN asset.uri_call_number_map aucnm
-    ON (aucnm.call_number = acn_for_uri_map.id)
-LEFT JOIN asset.uri auri
-    ON (aucnm.uri = auri.id)
-LEFT JOIN biblio.peer_bib_copy_map bpbcm
-    ON (bpbcm.peer_record = bre.id)
-LEFT JOIN asset.copy acp_for_peer_bibs
-    ON (bpbcm.target_copy = acp_for_peer_bibs.id )
-LEFT JOIN asset.copy_location peer_copy_loc
-    ON (peer_copy_loc.id = acp_for_peer_bibs.location )
-LEFT JOIN config.copy_status peer_copy_status
-    ON (peer_copy_status.id = acp_for_peer_bibs.status)
-WHERE
-    NOT bre.deleted AND
-    COALESCE(auri.active, TRUE) AND
-    NOT COALESCE(acp_for_peer_bibs.deleted, FALSE)
-UNION
-SELECT
-    bre.id AS record,
-    aou.id AS ou,
-    NULL AS copy_location
-FROM biblio.record_entry bre
-INNER JOIN config.bib_source cbs
-    ON (cbs.id = bre.source AND cbs.transcendant)
-INNER JOIN actor.org_unit aou ON (true)
-WHERE NOT bre.deleted ;
 ALTER TABLE metabib.browse_entry ADD COLUMN sort_value TEXT;
 
 CREATE OR REPLACE FUNCTION metabib.browse_entry_sort_value()
@@ -7003,7 +6913,7 @@ CREATE INDEX CONCURRENTLY browse_entry_sort_value_idx
 -- indices.
 
 -- CREATE INDEX CONCURRENTLY browse_entry_sort_value_idx_desc
---    ON metabib.browse_entry USING BTREE (sort_value DESC);
+--     ON metabib.browse_entry USING BTREE (sort_value DESC);
 
 CREATE TYPE metabib.flat_browse_entry_appearance AS (
     browse_entry BIGINT,
@@ -7014,82 +6924,19 @@ CREATE TYPE metabib.flat_browse_entry_appearance AS (
 );
 
 
-CREATE OR REPLACE FUNCTION metabib._browse_joins_and_where(
+CREATE OR REPLACE FUNCTION metabib.browse_pivot(
     search_field        INT[],
-    browse_term         TEXT,
-    context_org         INT DEFAULT NULL,
-    context_loc_group   INT DEFAULT NULL,
-    staff               BOOL DEFAULT FALSE
-) RETURNS TEXT[] AS $p$
-DECLARE
-    joins               TEXT;
-    where_clause        TEXT;
-    scope_test_view     TEXT;
+    browse_term         TEXT
+) RETURNS SETOF TEXT AS $p$
 BEGIN
-    joins := '
+    RETURN QUERY EXECUTE 'SELECT mbe.sort_value FROM metabib.browse_entry mbe
         JOIN metabib.browse_entry_def_map mbedm ON (
             mbedm.entry = mbe.id AND
             mbedm.def = ANY(' || quote_literal(search_field) || ')
-        ) ';
-    where_clause := '';
-
-    IF staff THEN
-        scope_test_view := 'asset.staff_holdings';
-    ELSE
-        scope_test_view := 'asset.visible_holdings';
-    END IF;
-
-    IF context_org IS NOT NULL OR context_loc_group IS NOT NULL THEN
-
-        joins := joins || ' JOIN ' || scope_test_view ||
-            ' scope_test ON (scope_test.record = mbedm.source) ';
-
-        IF context_org IS NOT NULL THEN
-            where_clause := where_clause ||
-                'scope_test.ou IN (
-                    SELECT id FROM actor.org_unit_descendants(' ||
-                context_org || ')) AND ';
-        END IF;
-
-        IF context_loc_group IS NOT NULL THEN
-            where_clause := where_clause ||
-                '(scope_test.copy_location IS NULL OR
-                    scope_test.copy_location IN (SELECT location FROM asset.copy_location_group_map WHERE lgroup = ' ||
-                context_loc_group || ')) AND ';
-        END IF;
-    END IF;
-
-    RETURN ARRAY[joins, where_clause];
-END;
-
-$p$ LANGUAGE PLPGSQL;
-
-CREATE OR REPLACE FUNCTION metabib.browse_pivot(
-    search_field        INT[],
-    browse_term         TEXT,
-    context_org         INT DEFAULT NULL,
-    context_loc_group   INT DEFAULT NULL
-) RETURNS TEXT AS $p$
-DECLARE
-    joins               TEXT;
-    where_clause        TEXT;
-    joins_and_where     TEXT[];
-    result              TEXT;
-BEGIN
-    joins_and_where := metabib._browse_joins_and_where(
-        search_field, browse_term, context_org, context_loc_group
-    );
-
-    joins := joins_and_where[1];
-    where_clause := joins_and_where[2];
-
-    EXECUTE 'SELECT mbe.sort_value FROM metabib.browse_entry mbe ' ||
-        joins || 'WHERE ' || where_clause ||
-        ' mbe.sort_value >= public.search_normalize(' ||
+        )
+        WHERE mbe.sort_value >= public.search_normalize(' ||
             quote_literal(browse_term) ||
-        ') ORDER BY mbe.sort_value LIMIT 1 ' INTO result;
-
-    RETURN result;  -- note, can be NULL
+        ') ORDER BY mbe.sort_value LIMIT 1 ';
 END;
 $p$ LANGUAGE PLPGSQL;
 
@@ -7103,57 +6950,45 @@ CREATE OR REPLACE FUNCTION metabib.browse(
     result_offset       INT DEFAULT 0   -- Can be negative!
 ) RETURNS SETOF metabib.flat_browse_entry_appearance AS $p$
 DECLARE
-    joins               TEXT;
-    where_clause        TEXT;
-    joins_and_where     TEXT[];
-    result_query        TEXT;
+    inner_query         TEXT;
+    whole_query         TEXT;
+    loc_query_part      TEXT;
     pivot_sort_value    TEXT;
     f                   RECORD;
     r                   metabib.flat_browse_entry_appearance%ROWTYPE;
     use_offset          INT;
 BEGIN
-    pivot_sort_value := metabib.browse_pivot(
-        search_field, browse_term, context_org, context_loc_group
-    );
+    SELECT INTO pivot_sort_value * FROM metabib.browse_pivot(search_field, browse_term);
 
     IF pivot_sort_value IS NULL THEN
         RETURN;
     END IF;
 
-    joins_and_where := metabib._browse_joins_and_where(
-        search_field, browse_term, context_org, context_loc_group
-    );
-
-    joins := joins_and_where[1];
-    where_clause := joins_and_where[2];
-
-    result_query :=
-        'SELECT mbe.id, mbe.value, mbe.sort_value,
-            ARRAY_TO_STRING(
-                (SELECT ARRAY_AGG(field) FROM (
-                    SELECT DISTINCT UNNEST(ARRAY_AGG(mbedm.def)) AS field
-                ) y),
-                $$,$$
-            ) AS fields,
-            ARRAY_TO_STRING(ARRAY_AGG(mbedm.authority), $$,$$) AS authorities,
-            (SELECT COUNT(source) FROM (
-                SELECT DISTINCT UNNEST(ARRAY_AGG(mbedm.source)) AS source
-            ) x) sources
-        FROM metabib.browse_entry mbe ' ||
-        joins ||
-        'WHERE ' || where_clause;
+    inner_query := '
+    SELECT
+        mbe.id AS id,
+        (SELECT ARRAY_AGG(src) FROM (
+            SELECT DISTINCT UNNEST(ARRAY_AGG(mbedm.source)) AS src
+        ) ss) AS records,
+        1 AS rel
+    FROM metabib.browse_entry mbe
+    JOIN metabib.browse_entry_def_map mbedm ON (
+        mbedm.entry = mbe.id AND
+        mbedm.def = ANY(' || quote_literal(search_field) || ')
+    )
+    WHERE ';
 
     -- PostgreSQL is not magic. We can't actually pass a negative offset.
     IF result_offset >= 0 THEN
         use_offset := result_offset;
-        result_query := result_query ||
+        inner_query := inner_query ||
             ' mbe.sort_value >= ' || quote_literal(pivot_sort_value) ||
-        ' GROUP BY 1,2,3 ORDER BY mbe.sort_value ';
+        ' GROUP BY 1,3,mbe.sort_value ORDER BY mbe.sort_value ';
     ELSE
         -- Step 1 of 2 to deliver what the user wants with a negative offset:
-        result_query := result_query ||
+        inner_query := inner_query ||
             ' mbe.sort_value < ' || quote_literal(pivot_sort_value) ||
-        ' GROUP BY 1,2,3 ORDER BY mbe.sort_value DESC ';
+        ' GROUP BY 1,3,mbe.sort_value ORDER BY mbe.sort_value DESC ';
 
         use_offset := ABS(result_offset) - result_limit;
         IF use_offset < 0 THEN
@@ -7167,22 +7002,46 @@ BEGIN
         END IF;
     END IF;
 
-    result_query := result_query ||
-        ' LIMIT ' || result_limit || ' OFFSET ' || use_offset;
-
-    IF result_offset < 0 THEN
-        -- Step 2 of 2 to deliver what the user wants with a negative offset:
-        result_query := 'SELECT * FROM (' || result_query ||
-            ') x ORDER BY sort_value ASC';  -- Un-reverse the result set.
+-- XXX    result_query := result_query ||
+-- XXX        ' LIMIT ' || result_limit || ' OFFSET ' || use_offset;
+-- XXX
+-- XXX    IF result_offset < 0 THEN
+-- XXX        -- Step 2 of 2 to deliver what the user wants with a negative offset:
+-- XXX        result_query := 'SELECT * FROM (' || result_query ||
+-- XXX            ') x ORDER BY sort_value ASC';  -- Un-reverse the result set.
+-- XXX    END IF;
+
+    IF context_loc_group IS NULL THEN
+        loc_query_part := 'NULL, ';
+    ELSE
+        loc_query_part :=
+            '(SELECT location FROM asset.copy_location_group_map WHERE
+            lgroup = ' || quote_literal(context_loc_group) || '), ';
     END IF;
 
---    RAISE NOTICE 'query is { % }', result_query;
-    FOR f IN EXECUTE result_query LOOP
+    whole_query := 'SELECT * FROM search.query_parser_fts(' ||
+        quote_literal(context_org) ||
+        ', NULL, ' ||
+        quote_literal(inner_query) ||
+        ', NULL, ' || 
+        loc_query_part ||
+        use_offset || ',' ||
+        result_limit ||
+        ', 10000,
+        NULL, ' ||
+        staff ||
+        ', FALSE)';
+    RAISE NOTICE 'query is { % }', whole_query;
+
+    FOR f IN EXECUTE whole_query LOOP
+        IF f.id IS NULL THEN
+            CONTINUE;   -- We don't need the summary row
+        END IF;
         r.browse_entry := f.id;
-        r.value := f.value;
-        r.fields := f.fields;
-        r.authorities := f.authorities;
-        r.sources := f.sources;
+        r.value := NULL;    -- XXX rest of these are TODO
+        r.fields := NULL;
+        r.authorities := NULL;
+        r.sources := NULL;
 
         RETURN NEXT r;
     END LOOP;