-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- 
-- $Id: WFS_locks.sql.in,v 1.1 2005/04/15 15:09:20 strk Exp $
--
-- PostGIS - Spatial Types for PostgreSQL
-- http://postgis.refractions.net
-- Copyright 2001-2003 Refractions Research Inc.
--
-- This is free software; you can redistribute and/or modify it under
-- the terms of the GNU General Public Licence. See the COPYING file.
--  
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#define CREATEFUNCTION CREATE OR REPLACE FUNCTION

#if USE_VERSION > 72
# define _IMMUTABLE_STRICT IMMUTABLE STRICT
# define _IMMUTABLE IMMUTABLE
# define _STABLE_STRICT STABLE STRICT
# define _STABLE STABLE
# define _VOLATILE_STRICT VOLATILE STRICT
# define _VOLATILE VOLATILE
# define _STRICT STRICT
#else 
# define _IMMUTABLE_STRICT  with(iscachable,isstrict)
# define _IMMUTABLE with(iscachable)
# define _STABLE_STRICT with(isstrict)
# define _STABLE 
# define _VOLATILE_STRICT with(isstrict)
# define _VOLATILE 
# define _STRICT with(isstrict)
#endif 


-----------------------------------------------------------------------
-- LONG TERM LOCKING
-----------------------------------------------------------------------

-- UnlockRows(authid)
-- removes all locks held by the given auth
-- returns the number of locks released
CREATEFUNCTION UnlockRows(text)
	RETURNS int
	AS '
DECLARE
	ret int;
BEGIN
	EXECUTE ''DELETE FROM authorization_table where authid = '' ||
		quote_literal($1);

	GET DIAGNOSTICS ret = ROW_COUNT;

	RETURN ret;
END;
'
LANGUAGE 'plpgsql' _VOLATILE_STRICT;

-- LockRow([schema], table, rowid, auth, [expires]) 
-- Returns 1 if successfully obtained the lock, 0 otherwise
CREATEFUNCTION LockRow(text, text, text, text, timestamp)
	RETURNS int
	AS '
DECLARE
	myschema alias for $1;
	mytable alias for $2;
	myrid   alias for $3;
	authid alias for $4;
	expires alias for $5;
	ret int;
	mytoid oid;
	myrec RECORD;
	
BEGIN
	EXECUTE ''DELETE FROM authorization_table WHERE expires < now()''; 

	SELECT c.oid INTO mytoid FROM pg_class c, pg_namespace n
		WHERE c.relname = mytable
		AND c.relnamespace = n.oid
		AND n.nspname = myschema;

	-- RAISE NOTICE ''toid: %'', mytoid;

	FOR myrec IN SELECT * FROM authorization_table WHERE 
		toid = mytoid AND rid = myrid
	LOOP
		IF myrec.authid != authid THEN
			RETURN 0;
		ELSE
			RETURN 1;
		END IF;
	END LOOP;

	EXECUTE ''INSERT INTO authorization_table VALUES (''||
		quote_literal(mytoid)||'',''||quote_literal(myrid)||
		'',''||quote_literal(expires)||
		'',''||quote_literal(authid) ||'')'';

	GET DIAGNOSTICS ret = ROW_COUNT;

	RETURN ret;
END;'
LANGUAGE 'plpgsql' _VOLATILE_STRICT;

-- LockRow(schema, table, rid, authid);
CREATEFUNCTION LockRow(text, text, text, text)
	RETURNS int
	AS
'SELECT LockRow($1, $2, $3, $4, now()::timestamp+''1:00'');'
	LANGUAGE 'sql' _VOLATILE_STRICT;

-- LockRow(table, rid, authid);
CREATEFUNCTION LockRow(text, text, text)
	RETURNS int
	AS
#if USE_VERSION >= 73
'SELECT LockRow(current_schema(), $1, $2, $3, now()::timestamp+''1:00'');'
#else
'SELECT LockRow('''', $1, $2, $3, now()::timestamp+''1:00'');'
#endif
	LANGUAGE 'sql' _VOLATILE_STRICT;

-- LockRow(schema, table, rid, expires);
CREATEFUNCTION LockRow(text, text, text, timestamp)
	RETURNS int
	AS
#if USE_VERSION >= 73
'SELECT LockRow(current_schema(), $1, $2, $3, $4);'
#else
'SELECT LockRow('''', $1, $2, $3, $4);'
#endif
	LANGUAGE 'sql' _VOLATILE_STRICT;


CREATEFUNCTION AddAuth(text)
	RETURNS BOOLEAN
	AS '
DECLARE
	lockid alias for $1;
	okay boolean;
	myrec record;
BEGIN
	-- check to see if table exists
	--  if not, CREATE TEMP TABLE mylock (transid xid, lockcode text)
	okay := ''f'';
	FOR myrec IN SELECT * FROM pg_class WHERE relname = ''temp_lock_have_table'' LOOP
		okay := ''t'';
	END LOOP; 
	IF (okay <> ''t'') THEN 
		CREATE TEMP TABLE temp_lock_have_table (lockcode text)
			ON COMMIT DELETE ROWS;
	END IF;

	--  INSERT INTO mylock VALUES ( $1)
	EXECUTE ''INSERT INTO temp_lock_have_table VALUES ( ''||
		quote_literal(lockid) ||'')'';

	RETURN true::boolean;
END;
'
LANGUAGE PLPGSQL;
 

-- CheckAuth( <schema>, <table>, <ridcolumn> )
CREATEFUNCTION CheckAuth(text, text, text)
	RETURNS INT
	AS '
DECLARE
	schema text;
BEGIN

#if USE_VERSION >= 73
	if ( $1 != '''' ) THEN
		schema = $1;
	ELSE
		SELECT current_schema() into schema;
	END IF;
#endif

	EXECUTE ''CREATE TRIGGER check_auth BEFORE UPDATE OR DELETE ON '' 
#if USE_VERSION >= 73
		|| quote_ident(schema) || ''.'' || quote_ident($2)
#else
		|| quote_ident($2)
#endif
		||'' FOR EACH ROW EXECUTE PROCEDURE CheckAuthTrigger(''
		|| quote_literal($3) || '')'';
	RETURN 0;
END;
'
LANGUAGE 'plpgsql';

-- CheckAuth(<table>, <ridcolumn>)
CREATEFUNCTION CheckAuth(text, text)
	RETURNS INT
	AS
	'SELECT CheckAuth('''', $1, $2)'
	LANGUAGE 'SQL';

CREATEFUNCTION CheckAuthTrigger()
	RETURNS trigger AS 
	'@MODULE_FILENAME@', 'check_authorization'
	LANGUAGE C;


---------------------------------------------------------------
-- END
---------------------------------------------------------------

