-- This file defines:
--
-- Tables:
--    Elements          -- Table of elements types/names
--    Groups            -- Table of group names
--    GroupData         -- Group data relation
--    Attributes        -- Table of attribute names
--    AttrData          -- Attribute data relation
--
-- Functions:
--    element_type('name')  -- Returns type id for element type name or
--                             exception if not found.
--    group_id('name')      -- Returns group ID for group name
--                             (creates one if not found)
--    attribute_id('name')  -- Returns ID for attribute name
--                             (creates one if not found)
--    set_attrib('typeName', element, 'attributeName', 'data')
--                          -- Insert data into attributes table(s)
--    get_attrib('typeName', element, 'attributeName')
--                          -- Returns attribute for element or empty string
--
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

-- Table over defined (allowed) Element types
-- This table is predefined and static

drop   table Elements;
create table Elements (
    eltType  int2,      -- Element ID in GroupData(type)
    name     char(10)   -- Type name
);

insert into Elements (eltType, name) values (100, 'group');
insert into Elements (eltType, name) values (101, 'agent');
insert into Elements (eltType, name) values (102, 'cust');
insert into Elements (eltType, name) values (102, 'customer');
insert into Elements (eltType, name) values (103, 'item');
insert into Elements (eltType, name) values (104, 'chan');
insert into Elements (eltType, name) values (104, 'channel');
insert into Elements (eltType, name) values (105, 'pack');
insert into Elements (eltType, name) values (105, 'package');

drop   function element_type (text);
create function element_type (text) returns int2 as '
  declare
    p_name  char(10);
    p_type  int2;

  begin
    p_name = trim(lower($1));
    select eltType into p_type from Elements where (name = p_name);
    if not found then
        raise exception ''Element type % not found'', p_name;
    end if;
    return p_type;
  end;
' language 'PLpgSQL';

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

-- Table over defined groups
-- The only interface sould be via group_id('name') function!

drop sequence Groups_grpID_seq;
drop index    Groups_grpID_key;
drop index    Groups_uix;

create table Groups (
    grpID    serial,    -- Group name ID in GroupData
    name     char(20)   -- Group name 
);
create unique index Groups_uix on Group(name);

drop   function group_id (text);
create function group_id (text) returns int4 as '
  declare
    p_name alias for $1;
    p_id   int4;

  begin
    select grpID into p_id from Groups where (name = p_name);
    if not found then
        insert into Groups (name) values (p_name);
        select last_value into p_id from Groups_grpID_seq;
    end if;
    return p_id;
  end;
' language 'PLpgSQL';

drop   function group_name (int4);
create function group_name (int4) returns text as '
  declare
    p_id    alias for $1;
    p_name  text;
  begin
    select name into p_name from Groups where (grpID = p_id);
    if not found then
        p_name := '''';
    end if;
    return p_name;
  end;
' language 'PLpgSQL';


-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

drop index GroupData_idx;
drop table GroupData;

create table GroupData (
    grpID    int4  REFERENCES Groups(grpID),
    eltType  int2  REFERENCES Elements(eltType),
    element  int4  -- Generic element ID
);
create index GroupData_idx on GroupData (grpID, eltType);

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

drop sequence Attributes_attrID_seq;
drop index    Attributes_attrID_key;
drop index    Attributes_name_uix;;
drop table    Attributes;

create table Attributes (
    attrID   serial,    -- Attribute ID in AttrData
    name     char(10)   -- Attribute name
);
create unique index Attributes_uix on Attributes (name);

drop   function attribute_id (text);
create function attribute_id (text) returns int4 as '
  declare
    p_name alias for $1;
    p_id   int4;

  begin
    select attrID into p_id from Attributes where (name = p_name);
    if not found then
        insert into Attributes (name) values (p_name);
        select last_value into p_id from Attributes_attrID_seq;
    end if;
    return p_id;
  end;
' language 'PLpgSQL';

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

drop   table AttrData;
create table AttrData (
    eltType  int2    REFERENCES Elements(eltType),
    element  int4,   -- Reference ID of type eltType
    attrID   int4    REFERENCES Attributes(attrID),
    data     text    -- Attribute data
);
create unique index AttrData_idx on AttrData (eltType, element, attrID);

drop   function set_attrib (text, int4, text, text);
create function set_attrib (text, int4, text, text) returns bool as'
  declare
    p_typeName  alias for $1;
    p_element   alias for $2;
    p_attrName  alias for $3;
    p_data      alias for $4;

    p_eltType int4;
    p_attrID  int4;
    dummy     int4;

  begin
    p_eltType := element_type(p_typeName);
    p_attrID  := attribute_id(p_attrName);

    select eltType into dummy from AttrData
        where (eltType = p_eltType)
          and (element = p_element)
          and (attrID  = p_attrID);
    if not found then
        insert into AttrData (eltType, element, attrID, data)
            values (p_eltType, p_element, p_attrID, p_data);
    else
        update AttrData set data = p_data
            where (eltType = p_eltType)
              and (element = p_element)
              and (attrID  = p_attrID);
    end if;
    return true;
  end;
' language 'PLpgSQL';


drop   function get_attrib (text, int4, text);
create function get_attrib (text, int4, text) returns text as'
  declare
    p_typeName  alias for $1;
    p_element   alias for $2;
    p_attrName  alias for $3;
    p_data      text;

    p_eltType int4;
    p_attrID  int4;

  begin
    p_eltType := element_type(p_typeName);
    p_attrID  := attribute_id(p_attrName);

    select data into p_data from AttrData
        where (eltType = p_eltType)
          and (element = p_element)
          and (attrID  = p_attrID);
    if not found then
        p_data := '''';
    end if;
    return p_data;
  end;
' language 'PLpgSQL';

select syslog_info('INSTALL', 'groups.sql');
--EOF
