Buna TGH ,

e mai jos o solutie folosita
de mine intr-un project
cu  PostgresSQL.

Daca e prea complicat poti
intreba pe <pers>.

E destul de <offtopic>

fie tree

a - b - c - d
    |
    e _ g 
    |
    f

parents(id, parent)
a NULL
b a
c b
d c
e b
g e
f e

hierarchy(id, hit)
// Adica
Daca Parents(b,a) si Parents(c,b) atunci hierarchy(c,a)
Un fel de inchidere trazitiva rezolvata cu un triger.
---
b a
c b, c a
d a, d b, d c


Uite si scriptul cu
triger cu tot.


--
-- The Postgres specific
hacks                                                               
--
--create function plpgsql_call_handler() RETURNS opaque
--as '/usr/lib/pgsql/plpgsql.so' language
'c';                                               

create function plpgsql_call_handler() RETURNS opaque
as '/usr/local/pgsql/lib/plpgsql.so' language 'c';
 
create trusted procedural language 'plpgsql'
HANDLER plpgsql_call_handler
LANCOMPILER 'PL/pgSQL';

-- Data model

CREATE TABLE projects (
    id          integer      PRIMARY KEY,
    name        varchar(100)  NOT NULL,
    info        varchar(255) DEFAULT '',
    url_desc    varchar(255) DEFAULT '',
    url_info    varchar(255) DEFAULT '',
    parent      integer      DEFAULT 0,
    begin_date  integer      NOT NULL,
    end_date    integer      NOT NULL
);

CREATE SEQUENCE seq_projects_id;
CREATE INDEX idx_projects_parent ON projects(parent);

CREATE TABLE work_item (
    email       varchar(100) NOT NULL,
    proj_id     integer      NOT NULL,
    begin_date  integer      NOT NULL,
    end_date    integer      NOT NULL,
    status      varchar(12)  NOT NULL,
    comment     text         DEFAULT '',
    PRIMARY KEY (email, proj_id),
    CHECK ( status in ('active','close','wait') )   
);

CREATE INDEX idx_work_item_email    ON work_item(email);
CREATE INDEX idx_work_item_proj_id  ON work_item(proj_id);

CREATE TABLE pontaj (
    id          integer      PRIMARY KEY,
    email       varchar(100) NOT NULL,
    proj_id     integer      NOT NULL,
    begin_date  integer      NOT NULL,
    end_date    integer      NOT NULL,
    comment     text         DEFAULT ''
);

CREATE SEQUENCE seq_pontaj_id;
CREATE INDEX idx_pontaj_email       ON pontaj(email);
CREATE INDEX idx_pontaj_proj_id     ON pontaj(proj_id);
CREATE INDEX idx_pontaj_begin_date  ON pontaj(begin_date);
CREATE INDEX idx_pontaj_end_date    ON pontaj(end_date);
CREATE INDEX idx_pontaj_e_date      ON pontaj(email,begin_date);


CREATE VIEW view_work_item AS
  SELECT work_item.email      AS email, 
         work_item.proj_id    AS proj_id, 
         work_item.begin_date AS begin_date, 
         work_item.end_date   AS end_date,
         work_item.status     AS status,
         work_item.comment    AS comment,
         projects.name        AS name,
         projects.info        AS info,
         projects.url_desc    AS url_desc
  FROM work_item, projects
  WHERE proj_id = id;  



CREATE TABLE hierarchy (
    id          integer      PRIMARY KEY,
    proj_id     integer      NOT NULL,
    child_id    integer      NOT NULL,
    level       integer      DEFAULT 1,
    child_hier  integer      DEFAULT 1
);

CREATE SEQUENCE seq_hierarchy;
CREATE INDEX idx_hierarchy_proj_id   ON hierarchy(proj_id);
CREATE INDEX idx_hierarchy_child_id  ON hierarchy(child_id);


CREATE FUNCTION get_parent_project_id(integer)
   RETURNS integer
   AS '
      DECLARE 
        p_proj_id alias for $1;
      BEGIN
        RETURN parent from projects WHERE id = p_proj_id;
      END;
   '
   LANGUAGE 'plpgsql';

CREATE FUNCTION hierarchy_new_project(integer)
   RETURNS integer
   AS '
      DECLARE 
        p_proj_id alias for $1;
        v_parent_id integer;
        v_hier_new_id integer;
        v_count integer;
      BEGIN
        v_count := 0;
        IF p_proj_id = NULL THEN
           RETURN 0;
        ELSE
           v_parent_id := p_proj_id;
           LOOP
              IF v_parent_id = NULL THEN
                 RETURN v_count;
              ELSE
                 IF (SELECT count(*) FROM hierarchy
                         WHERE proj_id = v_parent_id AND child_id =
p_proj_id) = 0 THEN
                   SELECT nextval(''seq_hierarchy'') INTO v_hier_new_id;
                   INSERT INTO hierarchy (id, proj_id, child_id)
                      VALUES (v_hier_new_id, v_parent_id, p_proj_id);
                   v_count := v_count + 1;
                 END IF; 
              END IF;
              v_parent_id := get_parent_project_id(v_parent_id);
           END LOOP;
        END IF;   
      END;
   '
   LANGUAGE 'plpgsql';

CREATE FUNCTION on_new_project()
   RETURNS opaque
   AS '
      DECLARE
        v_parent_id integer;
        v_hier_new_id integer;
      BEGIN
        IF NEW.id = NULL THEN
           RETURN NEW;
        ELSE
           v_parent_id := NEW.id;
           LOOP
              IF v_parent_id = NULL THEN
                 RETURN NEW;
              ELSE
                 IF (SELECT count(*) FROM hierarchy
                         WHERE proj_id = v_parent_id AND child_id =
NEW.id) = 0 THEN
                   SELECT nextval(''seq_hierarchy'') INTO v_hier_new_id;
                   INSERT INTO hierarchy (id, proj_id, child_id)
                      VALUES (v_hier_new_id, v_parent_id, NEW.id);
                 END IF;
              END IF;
              v_parent_id := get_parent_project_id(v_parent_id);
           END LOOP;
        END IF;
      END;
   '
   LANGUAGE 'plpgsql';      

CREATE TRIGGER trig_new_project 
   AFTER INSERT 
   ON projects 
   FOR EACH ROW 
   EXECUTE PROCEDURE on_new_project();


CREATE VIEW view_total_pontaj AS
  SELECT projects.id          AS proj_id,
         projects.name        AS name,
         projects.parent      AS parent,
         hierarchy.child_id   AS child_id,
         pontaj.email         AS email,
         pontaj.begin_date    AS begin_date,
         pontaj.end_date      AS end_date
  FROM   projects, hierarchy, pontaj
  WHERE  projects.id         = hierarchy.proj_id AND
         hierarchy.child_id  = pontaj.proj_id;

CREATE VIEW view_nod_pontaj AS
  SELECT projects.id          AS proj_id,
         projects.name        AS name,
         projects.parent      AS parent,
         pontaj.email         AS email,
         pontaj.begin_date    AS begin_date,
         pontaj.end_date      AS end_date
  FROM   projects, pontaj
  WHERE  projects.id = pontaj.proj_id;

 
Petrica.

---
Pentru dezabonare, trimiteti mail la 
[EMAIL PROTECTED] cu subiectul 'unsubscribe rlug'.
REGULI, arhive si alte informatii: http://www.lug.ro/mlist/


Raspunde prin e-mail lui