unapi: rank returned volumes and copies by library
authorDan Scott <dan@coffeecode.net>
Sat, 10 Mar 2012 23:28:24 +0000 (18:28 -0500)
committerDan Scott <dan@coffeecode.net>
Thu, 15 Mar 2012 04:34:32 +0000 (00:34 -0400)
Introduce another unapi argument, "pref_lib", to identify the user's
preferred library, and provide a corresponding routine that calculates
the rank of a particular library given "pref_lib" and "search_lib" as
arguments.

Then sort the call numbers and copies that are returned according to the
rank of the corresponding library, rather than strictly alphabetically
by library name.

Signed-off-by: Dan Scott <dan@coffeecode.net>
Open-ILS/src/sql/Pg/990.schema.unapi.sql

index d8f0317..f632eb8 100644 (file)
@@ -5,6 +5,20 @@ CREATE SCHEMA unapi;
 
 CREATE OR REPLACE FUNCTION evergreen.org_top() RETURNS SETOF actor.org_unit AS $$ SELECT * FROM actor.org_unit WHERE parent_ou IS NULL LIMIT 1; $$ LANGUAGE SQL ROWS 1;
 CREATE OR REPLACE FUNCTION evergreen.array_remove_item_by_value(inp ANYARRAY, el ANYELEMENT) RETURNS anyarray AS $$ SELECT ARRAY_ACCUM(x.e) FROM UNNEST( $1 ) x(e) WHERE x.e <> $2; $$ LANGUAGE SQL;
+CREATE OR REPLACE FUNCTION evergreen.rank_ou(lib INT, pref_lib INT, search_lib INT)
+RETURNS INTEGER AS $$
+    WITH pref_libs AS (
+        SELECT id, distance FROM actor.org_unit_descendants_distance($2)
+    ), search_libs AS (
+        SELECT id, distance FROM actor.org_unit_descendants_distance($3)
+    )
+    SELECT COALESCE(
+        (SELECT distance - 10000 FROM pref_libs WHERE id = $1),
+        (SELECT distance FROM search_libs WHERE id = $1),
+        10000
+    );
+
+$$ LANGUAGE SQL;
 
 CREATE TABLE unapi.bre_output_layout (
     name                TEXT    PRIMARY KEY,
@@ -46,12 +60,36 @@ CREATE OR REPLACE FUNCTION unapi.acpn   ( obj_id BIGINT, format TEXT, ename TEXT
 CREATE OR REPLACE FUNCTION unapi.acl    ( obj_id BIGINT, format TEXT, ename TEXT, includes TEXT[], org TEXT, depth INT DEFAULT NULL, slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE ) RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
 CREATE OR REPLACE FUNCTION unapi.ccs    ( obj_id BIGINT, format TEXT, ename TEXT, includes TEXT[], org TEXT, depth INT DEFAULT NULL, slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE ) RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
 CREATE OR REPLACE FUNCTION unapi.ascecm ( obj_id BIGINT, format TEXT, ename TEXT, includes TEXT[], org TEXT, depth INT DEFAULT NULL, slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE ) RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
-CREATE OR REPLACE FUNCTION unapi.bre    ( obj_id BIGINT, format TEXT, ename TEXT, includes TEXT[], org TEXT, depth INT DEFAULT NULL, slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE ) RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
+CREATE OR REPLACE FUNCTION unapi.bre (
+    obj_id BIGINT,
+    format TEXT,
+    ename TEXT,
+    includes TEXT[],
+    org TEXT,
+    depth INT DEFAULT NULL,
+    slimit HSTORE DEFAULT NULL,
+    soffset HSTORE DEFAULT NULL,
+    include_xmlns BOOL DEFAULT TRUE,
+    pref_lib INT DEFAULT NULL
+)
+RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
 CREATE OR REPLACE FUNCTION unapi.bmp    ( obj_id BIGINT, format TEXT, ename TEXT, includes TEXT[], org TEXT, depth INT DEFAULT NULL, slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE ) RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
 CREATE OR REPLACE FUNCTION unapi.mra    ( obj_id BIGINT, format TEXT, ename TEXT, includes TEXT[], org TEXT, depth INT DEFAULT NULL, slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE ) RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
 CREATE OR REPLACE FUNCTION unapi.circ   ( obj_id BIGINT, format TEXT, ename TEXT, includes TEXT[], org TEXT DEFAULT '-', depth INT DEFAULT NULL, slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE ) RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
 
-CREATE OR REPLACE FUNCTION unapi.holdings_xml ( bid BIGINT, ouid INT, org TEXT, depth INT DEFAULT NULL, includes TEXT[] DEFAULT NULL::TEXT[], slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE) RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
+CREATE OR REPLACE FUNCTION unapi.holdings_xml (
+    bid BIGINT,
+    ouid INT,
+    org TEXT,
+    depth INT DEFAULT NULL,
+    includes TEXT[] DEFAULT NULL::TEXT[],
+    slimit HSTORE DEFAULT NULL,
+    soffset HSTORE DEFAULT NULL,
+    include_xmlns BOOL DEFAULT TRUE,
+    pref_lib INT DEFAULT NULL
+)
+RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
+
 CREATE OR REPLACE FUNCTION unapi.biblio_record_entry_feed ( id_list BIGINT[], format TEXT, includes TEXT[], org TEXT, depth INT DEFAULT NULL, slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE, title TEXT DEFAULT NULL, description TEXT DEFAULT NULL, creator TEXT DEFAULT NULL, update_ts TEXT DEFAULT NULL, unapi_url TEXT DEFAULT NULL, header_xml XML DEFAULT NULL ) RETURNS XML AS $F$ SELECT NULL::XML $F$ LANGUAGE SQL;
 
 CREATE OR REPLACE FUNCTION unapi.memoize (classname TEXT, obj_id BIGINT, format TEXT,  ename TEXT, includes TEXT[], org TEXT, depth INT DEFAULT NULL, slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE ) RETURNS XML AS $F$
@@ -140,7 +178,19 @@ BEGIN
 END;
 $F$ LANGUAGE PLPGSQL;
 
-CREATE OR REPLACE FUNCTION unapi.bre ( obj_id BIGINT, format TEXT,  ename TEXT, includes TEXT[], org TEXT, depth INT DEFAULT NULL, slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE ) RETURNS XML AS $F$
+CREATE OR REPLACE FUNCTION unapi.bre (
+    obj_id BIGINT,
+    format TEXT,
+    ename TEXT,
+    includes TEXT[],
+    org TEXT,
+    depth INT DEFAULT NULL,
+    slimit HSTORE DEFAULT NULL,
+    soffset HSTORE DEFAULT NULL,
+    include_xmlns BOOL DEFAULT TRUE,
+    pref_lib INT DEFAULT NULL
+)
+RETURNS XML AS $F$
 DECLARE
     me      biblio.record_entry%ROWTYPE;
     layout  unapi.bre_output_layout%ROWTYPE;
@@ -187,7 +237,7 @@ BEGIN
 
     -- grab hodlings if we need them
     IF ('holdings_xml' = ANY (includes)) THEN 
-        hxml := unapi.holdings_xml(obj_id, ouid, org, depth, evergreen.array_remove_item_by_value(includes,'holdings_xml'), slimit, soffset, include_xmlns);
+        hxml := unapi.holdings_xml(obj_id, ouid, org, depth, evergreen.array_remove_item_by_value(includes,'holdings_xml'), slimit, soffset, include_xmlns, pref_lib);
     ELSE
         hxml := NULL::XML;
     END IF;
@@ -237,7 +287,18 @@ BEGIN
 END;
 $F$ LANGUAGE PLPGSQL;
 
-CREATE OR REPLACE FUNCTION unapi.holdings_xml (bid BIGINT, ouid INT, org TEXT, depth INT DEFAULT NULL, includes TEXT[] DEFAULT NULL::TEXT[], slimit HSTORE DEFAULT NULL, soffset HSTORE DEFAULT NULL, include_xmlns BOOL DEFAULT TRUE) RETURNS XML AS $F$
+CREATE OR REPLACE FUNCTION unapi.holdings_xml (
+    bid BIGINT,
+    ouid INT,
+    org TEXT,
+    depth INT DEFAULT NULL,
+    includes TEXT[] DEFAULT NULL::TEXT[],
+    slimit HSTORE DEFAULT NULL,
+    soffset HSTORE DEFAULT NULL,
+    include_xmlns BOOL DEFAULT TRUE,
+    pref_lib INT DEFAULT NULL
+)
+RETURNS XML AS $F$
      SELECT  XMLELEMENT(
                  name holdings,
                  XMLATTRIBUTES(
@@ -278,7 +339,7 @@ CREATE OR REPLACE FUNCTION unapi.holdings_xml (bid BIGINT, ouid INT, org TEXT, d
                          name volumes,
                          (SELECT XMLAGG(acn) FROM (
                             SELECT  unapi.acn(y.id,'xml','volume',evergreen.array_remove_item_by_value( evergreen.array_remove_item_by_value($5,'holdings_xml'),'bre'), $3, $4, $6, $7, FALSE) FROM (
-                                SELECT  distinct acn.id, aou.name, acn.label_sortkey
+                                SELECT  distinct acn.id, aou.name, acn.label_sortkey, evergreen.rank_ou(aou.id, COALESCE($9, $2), $2) AS pref_ou
                                   FROM  asset.call_number acn
                                         JOIN asset.copy acp ON (acn.id = acp.call_number)
                                         JOIN actor.org_unit_descendants( $2 ) aoud ON (acp.circ_lib = aoud.id)
@@ -286,7 +347,7 @@ CREATE OR REPLACE FUNCTION unapi.holdings_xml (bid BIGINT, ouid INT, org TEXT, d
                                   WHERE acn.record = $1
                                       AND acn.deleted IS FALSE
                                       AND acp.deleted IS FALSE
-                                  ORDER BY aou.name, acn.label_sortkey
+                                  ORDER BY pref_ou, aou.name, acn.label_sortkey
                                   LIMIT ($6 -> 'acn')::INT
                                   OFFSET ($7 -> 'acn')::INT
                             )y
@@ -297,7 +358,7 @@ CREATE OR REPLACE FUNCTION unapi.holdings_xml (bid BIGINT, ouid INT, org TEXT, d
                          name volumes,
                          (SELECT XMLAGG(acn) FROM (
                             SELECT  unapi.acn(y.id,'xml','volume',evergreen.array_remove_item_by_value( evergreen.array_remove_item_by_value($5,'holdings_xml'),'bre'), $3, $4, $6, $7, FALSE) FROM (
-                                SELECT  distinct acn.id, aou.name, acn.label_sortkey
+                                SELECT  distinct acn.id, aou.name, acn.label_sortkey, evergreen.rank_ou(aou.id, COALESCE($9, $2), $2) AS pref_ou
                                   FROM  asset.call_number acn
                                         JOIN asset.copy acp ON (acn.id = acp.call_number)
                                         JOIN actor.org_unit_descendants( $2, $4 ) aoud ON (acp.circ_lib = aoud.id)
@@ -305,7 +366,7 @@ CREATE OR REPLACE FUNCTION unapi.holdings_xml (bid BIGINT, ouid INT, org TEXT, d
                                   WHERE acn.record = $1
                                       AND acn.deleted IS FALSE
                                       AND acp.deleted IS FALSE
-                                  ORDER BY aou.name, acn.label_sortkey
+                                  ORDER BY pref_ou, aou.name, acn.label_sortkey
                                   LIMIT ($6 -> 'acn')::INT
                                   OFFSET ($7 -> 'acn')::INT
                             )y