-- ToughLog
\set HOSTNAME `echo "'$HOSTNAME'"`
select syslog('I', :HOSTNAME, 'path.sql', 'ID',
'$Id$'
);
select syslog('I', :HOSTNAME, 'path.sql', 'INSTALL',
'Install table Path and function cg_PathID().'
);

drop function	cg_PathID(Path.Path%type);
drop function CountSlash(Path.Path%type);
drop function cg_PathLevel(Path.Path%type);
drop table	Path;
drop table	PathLevel;

create table Path(
	PathID		serial NOT NULL primary key,
	paCreated	timestamp with time zone DEFAULT now(),
	Path		text unique NOT NULL,
	SlashCount	int4,
	IsADir		bool NOT NULL DEFAULT 't'
);
create unique index Path_PathID_uix on Path(PathID);
create unique index Path_Path_uix on Path(Path);

comment on table Path is 'Map between Path and PathID.
Shortname: pa.';
comment on column Path.PathID is 'Unique ID for Path.';
comment on column Path.Path is 'Full path to file or sub directory, like /arch/index.html.';
comment on column Path.SlashCount is 'Number of slashes in a path.
/arch/sport/tennis/ is equal 4.
/arch/sport/tennis/index.html is equal 4.
A double slash (//) count as one slash.';
comment on column Path.IsADir is 'Either it is a file or a sub directory. If the last character in path is a / (slash) it is sub directory, if it is not a / it is a file.';

create table PathLevel(
	plCreated	timestamp with time zone DEFAULT now(),
	LevelID	int4,-- REFRENCES Path(PathID),
	PathID	int4-- REFRENCES Path, -- ON DELETE CASCADE,
	--LevelCount int4
	--CONSTRAIN UNIQUE (LevelID,PathID)
);

comment on table PathLevel is '
select substring($P FROM ''^(.*/)[^/]+/?$'')

Example:
ID Path
 1 /
20 /arch/sport/tennis/
21 /arch/sport/golf/
22 /arch/sport/
23 /arch/

/+ root
 |
 + arch/
   |
   + sport/
     |
     + tennis/
     + golf/

Parent		Child
/arch/sport/	/arch/sport/tennis/
/arch/sport/	/arch/sport/golf/
/arch/		/arch/sport/tennis/
/arch/		/arch/sport/golf/
/arch/		/arch/sport/
/		/arch/sport/tennis/
/		/arch/sport/golf/
/		/arch/sport/
/		/arch/

LevelID	PathID 
22	20
22	21
22	22
23	20
23	21
23	22
23	23

SELECT * FROM httplog WHERE PathID IN(
 SELECT PathID FROM PathLevel WHERE LevelID=(
  SELECT PathID FROM Path WHERE Path=''/arch/sport''
 )
)

INSERT INTO PathLevel(PathID,LevelID) VALUES(cg_Path(''/arch/sport/tennis''),cg_Path(''/arch/sport/tennis''));
INSERT INTO PathLevel(PathID,LevelID) VALUES(cg_Path(''/arch/sport/tennis''),cg_Path(''/arch/sport''));
INSERT INTO PathLevel(PathID,LevelID) VALUES(cg_Path(''/arch/sport/tennis''),cg_Path(''/arch''));
';

comment on column Path.PathID is 'Unique ID for Path i.e. /arch/sport/tennis/';
comment on column PathLevel.LevelID is 'References to a shorter PathID, i.e. /arch/sport/ when Level==2.';

create or replace function CountSlash(Path.Path%type) returns Int4 as '
declare
	cnt	int4;
	idx	int4;
	p_name  alias for $1;
begin
	cnt := 0;
	idx := 1;
	-- Count all slashes
	while idx <= char_length(p_name) loop
		if substr(p_name, idx, 1) = ''/'' then
			cnt := cnt + 1;
			-- Skip trough double // slashes
			while idx <= char_length(p_name) and substr(p_name, idx, 1) = ''/'' loop
				idx := idx + 1;
			end loop;
		else
			idx := idx + 1;
		end if;
	end loop;
	return cnt;
end;
' language 'PLpgSQL';

-- Test CountSlash()
select
	1 = CountSlash('/') AND
	1 = CountSlash('/test') AND
	2 = CountSlash('/test/') AND
	2 = CountSlash('/test/car') AND
	3 = CountSlash('/test/car/') AND
	3 = CountSlash('/test//car/')
AS "All CountSlash() OK?"; 

create or replace function cg_PathID(Path.Path%type) returns Path.PathID%type as '
declare
	p_name		alias for $1;
	v_PathID	Path.PathID%type;
	v_LevelID	PathLevel.LevelID%type;
	sname		Path.Path%type;
	idx		int4;
	cnt		int4;
begin
	sname := trim(p_name);
	select PathID into v_PathID from Path where (Path = sname);
	if not found then
		insert into Path (Path, SlashCount, IsADir) values(sname, CountSlash(sname), substr(sname,length(sname),1)=''/'' );
		select last_value into v_PathID from Path_PathID_seq;
		if substr(sname, 1, 1) = ''/'' then
			idx := length(sname);
			while idx > 0 loop
				if idx <> 1 and substr(sname, idx, 1) = ''/'' then
					sname := substr(sname, 1, idx);
					select PathID into v_LevelID from Path where Path=sname;
					if not found then
						insert into Path (Path, SlashCount, IsADir) values(sname, CountSlash(sname), substr(sname,length(sname),1)=''/'' );
						select last_value into v_LevelID from Path_PathID_seq;
						insert into PathLevel(PathID, LevelID) values(v_LevelID, v_LevelID);
					end if;
					insert into PathLevel(PathID, LevelID) values(v_PathID, v_LevelID);
				end if;
				idx := idx - 1;
			end loop;
		end if;
	end if;
	return v_PathID;
end;
' language 'PLpgSQL';
		-- --select substring(sname FROM '^(.*/)[^/]+/?$') into shortpath;
		--shortpath := substring(sname FROM '^(.*/)[^/]+/?$');
		--insert into PathLevel(PathID,LevelID) values(cg_PathID(shortpath), id);

create or replace function cg_PathLevel(Path.Path%type) returns Path.Path%type as '
' language 'PLpgSQL';

comment on function cg_PathID(Path.Path%type) is 'Create PathID and get Path.';

select cg_PathID('');
select cg_PathID('/');
select cg_PathID('/test/car/audi/index.html');
select cg_PathID('/test/car/vw/index.html');
--select LevelCount, LevelID, P.Path, PP.Path from PathLevel PL, Path P, Path PP where PL.LevelID=P.PathID AND PL.PathID=PP.PathID;
--select PL.PathID, P.Path, PP.Path from PathLevel PL, Path P, Path PP where PL.LevelID=P.PathID AND PL.PathID=PP.PathID and LevelCount=2;

select
	count(h.httplogid) as "hitcount",
	pa.path
from
	httplog h,
	path pa,
	pathlevel pl
where
	pa.slashcount = 3
	and h.pathid = pl.pathid 
	and pl.levelid=pa.pathid
	and hitdatetime>'2005-01-03 00:00:01+01'
	and hitdatetime<'2005-01-04 06:00:01+01'
group by
	pa.path
order by
	hitcount desc
limit	20
;

select
	count(ses) as "count",
	path
from (
	select
		h.sessionid as "ses",
		pa.path
	from
		httplog h,
		path pa,
		pathlevel pl
	where
		pa.slashcount = 3
		--and h.pathid in (select pathid from pathlevel where levelid=pa.pathid)
		and h.pathid = pl.pathid 
		and pl.levelid=pa.pathid
		and hitdatetime>'2005-01-03 00:00:01+01'
		and hitdatetime<'2005-01-04 06:00:01+01'
	group by
		h.sessionid,
		pa.path
) as "foo"
group by
	path
order by
	count desc
limit	20
;

--EOF
