Event-related functions split

Because the events management functions are definitely going to be quite
big, I thought it would be better to split them into multiple SQL files.
For now, there's a file for event definition functions and one for
functions that manipulate priority overrides. The old file containing
the old code stays around for now.
This commit is contained in:
Emmanuel BENOîT 2012-07-01 01:04:26 +02:00
parent 9e84f333e7
commit dc9ef2292d
3 changed files with 1008 additions and 998 deletions

View file

@ -0,0 +1,865 @@
-- LegacyWorlds Beta 6
-- PostgreSQL database scripts
--
-- Functions allowing event definitions to be added to the
-- database
--
-- Copyright(C) 2004-2012, DeepClone Development
-- --------------------------------------------------------
/*
* Return values for event definition functions
* ---------------------------------------------
*/
DROP TYPE IF EXISTS events.evdef_create_result CASCADE;
CREATE TYPE events.evdef_create_result AS ENUM(
/* The event type definition function succeeded. If it was the initial
* creation function or a field creation function, this means the creation
* can continue. If it was the finalisation function, this means the event
* definition has been added.
*/
'OK' ,
/* A bad identifier was specified. This value is returned by both the
* initial creation function and event field definition functions.
*/
'BAD_ID' ,
/* An internationalised string (either an event type's name or template)
* could not be found.
*/
'BAD_STRINGS' ,
/* Duplicate event or field identifier found. This value is returned by
* the finalisation function, with its "_fld" set to NULL if the duplicate
* identifier is the event's.
*/
'DUPLICATE' ,
/* Bad event or field specification found. This value is returned by the
* finalisation function when an event or field cannot be inserted due to
* check failures.
*/
'BAD_SPEC' ,
/* This error code is returned when trying to finalise an event after one
* of the definition calls failed.
*/
'NO_DATA'
);
/*
* Start defining a new event type
* -------------------------------
*
* This function creates a temporary table used to defgine a new type of
* event. No checks beyond the length and contents of the event type's
* identifier are made at this point.
*
* Note: the temporary table will be created in all cases, even when the
* identifier is invalid.
*
* Parameters:
* _id The identifier of the event type
* _prio The event type's default priority
* _adj Whether the player may adjust the priority for this type
* of events.
* _i18n The "base" of the I18N strings identifiers; the function
* will attempt to use "<_i18n>Name" as the name's
* identifier and "<_i18n>Template" as the template's.
*
* Returns:
* ??? An error code: OK or BAD_ID
* (see events.evdef_create_result)
*/
DROP FUNCTION IF EXISTS events.evdef_start( TEXT , INT , BOOLEAN , TEXT );
CREATE FUNCTION events.evdef_start(
_id TEXT ,
_prio INT ,
_adj BOOLEAN ,
_i18n TEXT )
RETURNS events.evdef_create_result
LANGUAGE PLPGSQL
STRICT VOLATILE SECURITY DEFINER
AS $evdef_start$
DECLARE
_name_id INT;
_template_id INT;
BEGIN
CREATE TEMPORARY TABLE evdef_temp(
evdef_id TEXT ,
evfld_id TEXT ,
evfld_typespec TEXT
) ON COMMIT DROP;
IF LENGTH( _id ) < 2 OR LENGTH( _id ) > 48
OR NOT _id ~ '^[a-z\-]+$'
THEN
RETURN 'BAD_ID';
END IF;
SELECT INTO _name_id id FROM defs.strings
WHERE name = _i18n || 'Name';
SELECT INTO _template_id id FROM defs.strings
WHERE name = _i18n || 'Template';
IF _name_id IS NULL OR _template_id IS NULL THEN
RETURN 'BAD_STRINGS';
END IF;
INSERT INTO evdef_temp( evdef_id , evfld_typespec )
VALUES( _id , _prio::TEXT || ',' || _adj::TEXT
|| ',' || _name_id || ',' || _template_id );
RETURN 'OK';
END;
$evdef_start$;
REVOKE EXECUTE
ON FUNCTION events.evdef_start( TEXT , INT , BOOLEAN , TEXT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_start( TEXT , INT , BOOLEAN , TEXT )
TO :dbuser;
/*
* Create a new field
* ------------------
*
* /!\ INTERNAL FUNCTION /!\
*
* This function adds data about a new field to the temporary event
* definition table.
*
* Parameters:
* _id The field's identifier
* _opt Whether the field is optional
* _type The field's type
* _etype The field's entity type (may be NULL)
* _is_int Whether the field is an integer (may be NULL)
* _min_val Minimal value/length (may be NULL)
* _max_val Maximal value/length (may be NULL)
*
* Returns:
* ??? An error code: OK or BAD_ID
* (see events.evdef_create_result)
*/
DROP FUNCTION IF EXISTS events.evdef_addfld_internal(
TEXT , BOOLEAN , events.field_type , events.entity_field_type ,
BOOLEAN , NUMERIC , NUMERIC ) CASCADE;
CREATE FUNCTION events.evdef_addfld_internal(
_id TEXT ,
_opt BOOLEAN ,
_type events.field_type ,
_etype events.entity_field_type ,
_is_int BOOLEAN ,
_min_val NUMERIC ,
_max_val NUMERIC
) RETURNS events.evdef_create_result
LANGUAGE PLPGSQL
CALLED ON NULL INPUT
VOLATILE SECURITY INVOKER
AS $evdef_addfld_internal$
DECLARE
_iq_string TEXT;
BEGIN
IF LENGTH( _id ) < 2 OR LENGTH( _id ) > 48
OR NOT _id ~ '^[a-z\-]+$'
THEN
DELETE FROM evdef_temp;
RETURN 'BAD_ID'::events.evdef_create_result;
END IF;
_iq_string := _opt::TEXT || ' , ''' || _type::TEXT || ''' , ';
IF _etype IS NULL
THEN
_iq_string := _iq_string || 'NULL';
ELSE
_iq_string := _iq_string || '''' || _etype::TEXT || '''';
END IF;
_iq_string := _iq_string || ' , ';
IF _is_int IS NULL
THEN
_iq_string := _iq_string || 'NULL';
ELSE
_iq_string := _iq_string || _is_int::TEXT;
END IF;
_iq_string := _iq_string || ' , ';
IF _min_val IS NULL
THEN
_iq_string := _iq_string || 'NULL';
ELSE
_iq_string := _iq_string || _min_val::TEXT;
END IF;
_iq_string := _iq_string || ' , ';
IF _max_val IS NULL
THEN
_iq_string := _iq_string || 'NULL';
ELSE
_iq_string := _iq_string || _max_val::TEXT;
END IF;
INSERT INTO evdef_temp( evdef_id , evfld_id , evfld_typespec )
SELECT evdef_id , _id , _iq_string
FROM evdef_temp
WHERE evfld_id IS NULL;
RETURN 'OK'::events.evdef_create_result;
END;
$evdef_addfld_internal$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_internal(
TEXT , BOOLEAN , events.field_type , events.entity_field_type ,
BOOLEAN , NUMERIC , NUMERIC )
FROM PUBLIC;
/*
* Actual field creation functions
* --------------------------------
*
* Bunch of functions that create the field records in the temporary table
* through events.evdef_addfld_internal().
*
* Note:
* These functions are not dropped manually here, as it is assumed that
* dropping events.evdef_addfld_internal() will have cascaded.
*/
-- INTEGER FIELD, NO BOUNDS
CREATE FUNCTION events.evdef_addfld_int( _id TEXT , _opt BOOLEAN )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'NUMERIC'::events.field_type,NULL,TRUE,NULL,NULL); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_int( TEXT , BOOLEAN )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_int( TEXT , BOOLEAN )
TO :dbuser;
-- INTEGER FIELD W/ LOWER BOUND
CREATE FUNCTION events.evdef_addfld_int_min( _id TEXT , _opt BOOLEAN , _min INT )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'NUMERIC'::events.field_type,NULL,TRUE,$3::NUMERIC,NULL); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_int_min( TEXT , BOOLEAN , INT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_int_min( TEXT , BOOLEAN , INT )
TO :dbuser;
-- INTEGER FIELD W/ HIGHER BOUND
CREATE FUNCTION events.evdef_addfld_int_max( _id TEXT , _opt BOOLEAN , _max INT )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'NUMERIC'::events.field_type,NULL,TRUE,NULL,$3::NUMERIC); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_int_max( TEXT , BOOLEAN , INT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_int_max( TEXT , BOOLEAN , INT )
TO :dbuser;
-- INTEGER FIELD W/ LIMITED RANGE
CREATE FUNCTION events.evdef_addfld_int_range( _id TEXT , _opt BOOLEAN , _min INT , _max INT )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'NUMERIC'::events.field_type,NULL,TRUE,$3::NUMERIC,$4::NUMERIC); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_int_range( TEXT , BOOLEAN , INT , INT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_int_range( TEXT , BOOLEAN , INT , INT )
TO :dbuser;
-- REAL FIELD, NO BOUNDS
CREATE FUNCTION events.evdef_addfld_real( _id TEXT , _opt BOOLEAN )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'NUMERIC'::events.field_type,NULL,FALSE,NULL,NULL); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_real( TEXT , BOOLEAN )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_real( TEXT , BOOLEAN )
TO :dbuser;
-- REAL FIELD W/ LOWER BOUND
CREATE FUNCTION events.evdef_addfld_real_min( _id TEXT , _opt BOOLEAN , _min DOUBLE PRECISION )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'NUMERIC'::events.field_type,NULL,FALSE,$3::NUMERIC,NULL); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_real_min( TEXT , BOOLEAN , DOUBLE PRECISION )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_real_min( TEXT , BOOLEAN , DOUBLE PRECISION )
TO :dbuser;
-- REAL FIELD W/ HIGHER BOUND
CREATE FUNCTION events.evdef_addfld_real_max( _id TEXT , _opt BOOLEAN , _max DOUBLE PRECISION )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'NUMERIC'::events.field_type,NULL,FALSE,NULL,$3::NUMERIC); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_real_max( TEXT , BOOLEAN , DOUBLE PRECISION )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_real_max( TEXT , BOOLEAN , DOUBLE PRECISION )
TO :dbuser;
-- REAL FIELD W/ LIMITED RANGE
CREATE FUNCTION events.evdef_addfld_real_range( _id TEXT , _opt BOOLEAN , _min DOUBLE PRECISION , _max DOUBLE PRECISION )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'NUMERIC'::events.field_type,NULL,FALSE,$3::NUMERIC,$4::NUMERIC); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_real_range( TEXT , BOOLEAN , DOUBLE PRECISION , DOUBLE PRECISION )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_real_range( TEXT , BOOLEAN , DOUBLE PRECISION , DOUBLE PRECISION )
TO :dbuser;
-- TEXT FIELD, NO BOUNDS
CREATE FUNCTION events.evdef_addfld_text( _id TEXT , _opt BOOLEAN )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'TEXT'::events.field_type,NULL,NULL,NULL,NULL); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_text( TEXT , BOOLEAN )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_text( TEXT , BOOLEAN )
TO :dbuser;
-- TEXT FIELD W/ LOWER BOUND
CREATE FUNCTION events.evdef_addfld_text_min( _id TEXT , _opt BOOLEAN , _min INT )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'TEXT'::events.field_type,NULL,NULL,$3::NUMERIC,NULL); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_text_min( TEXT , BOOLEAN , INT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_text_min( TEXT , BOOLEAN , INT )
TO :dbuser;
-- TEXT FIELD W/ HIGHER BOUND
CREATE FUNCTION events.evdef_addfld_text_max( _id TEXT , _opt BOOLEAN , _max INT )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'TEXT'::events.field_type,NULL,NULL,NULL,$3::NUMERIC); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_text_max( TEXT , BOOLEAN , INT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_text_max( TEXT , BOOLEAN , INT )
TO :dbuser;
-- TEXT FIELD W/ LIMITED RANGE
CREATE FUNCTION events.evdef_addfld_text_range( _id TEXT , _opt BOOLEAN , _min INT , _max INT )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'TEXT'::events.field_type,NULL,NULL,$3::NUMERIC,$4::NUMERIC); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_text_range( TEXT , BOOLEAN , INT , INT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_text_range( TEXT , BOOLEAN , INT , INT )
TO :dbuser;
-- BOOLEAN FIELD
CREATE FUNCTION events.evdef_addfld_bool( _id TEXT , _opt BOOLEAN )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'BOOL'::events.field_type,NULL,NULL,NULL,NULL); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_bool( TEXT , BOOLEAN )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_bool( TEXT , BOOLEAN )
TO :dbuser;
-- I18N TEXT FIELD
CREATE FUNCTION events.evdef_addfld_i18n( _id TEXT , _opt BOOLEAN )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'I18N'::events.field_type,NULL,NULL,NULL,NULL); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_i18n( TEXT , BOOLEAN )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_i18n( TEXT , BOOLEAN )
TO :dbuser;
-- ENTITY LINK FIELD
CREATE FUNCTION events.evdef_addfld_entity( _id TEXT , _opt BOOLEAN , _etype events.entity_field_type )
RETURNS events.evdef_create_result
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $$ SELECT events.evdef_addfld_internal(
$1,$2,'ENTITY'::events.field_type,$3,NULL,NULL,NULL); $$;
REVOKE EXECUTE
ON FUNCTION events.evdef_addfld_entity( TEXT , BOOLEAN , events.entity_field_type )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_addfld_entity( TEXT , BOOLEAN , events.entity_field_type )
TO :dbuser;
/*
* Create an event definition record
* ---------------------------------
*
* /!\ INTERNAL FUNCTION /!\
*
* This function inserts the record for an event definition into the
* appropriate table.
*
* Returns:
* ??? An error code
*/
DROP FUNCTION IF EXISTS events.evdef_create_record( );
CREATE FUNCTION events.evdef_create_record( )
RETURNS events.evdef_create_result
LANGUAGE PLPGSQL
STRICT VOLATILE SECURITY INVOKER
AS $evdef_create_record$
DECLARE
_rec RECORD;
_qstr TEXT;
BEGIN
SELECT INTO _rec *
FROM evdef_temp
WHERE evfld_id IS NULL;
IF NOT FOUND
THEN
RETURN 'NO_DATA';
END IF;
_qstr := 'INSERT INTO events.event_definitions (' ||
'evdef_id , evdef_priority , evdef_adjustable , ' ||
'evdef_name_id , evdef_template_id' ||
') VALUES ( $1 , ' || _rec.evfld_typespec || ');';
BEGIN
EXECUTE _qstr USING _rec.evdef_id;
EXCEPTION
WHEN unique_violation THEN
RETURN 'DUPLICATE';
WHEN check_violation THEN
RETURN 'BAD_SPEC';
END;
RETURN 'OK';
END;
$evdef_create_record$;
REVOKE EXECUTE
ON FUNCTION events.evdef_create_record( )
FROM PUBLIC;
/*
* Create an event field definition record
* ---------------------------------------
*
* /!\ INTERNAL FUNCTION /!\
*
* This function inserts a new event field definition record into the
* appropriate table.
*
* Parameters:
* _evdef_id The event definition's identifier
* _efdef_id The field's identifier
* _typespec The type specification from the temporary table
*
* Returns:
* ??? An error code
*/
DROP FUNCTION IF EXISTS events.evdef_create_field_record(
TEXT , TEXT , TEXT );
CREATE FUNCTION events.evdef_create_field_record(
_evdef_id TEXT ,
_efdef_id TEXT ,
_typespec TEXT )
RETURNS events.evdef_create_result
LANGUAGE PLPGSQL
STRICT VOLATILE SECURITY INVOKER
AS $evdef_create_field_record$
DECLARE
_qstr TEXT;
BEGIN
_qstr := 'INSERT INTO events.field_definitions (' ||
'evdef_id , efdef_id , efdef_optional , efdef_type , ' ||
'efdef_entity , efdef_integer , efdef_min , efdef_max ' ||
') VALUES ( $1 , $2 , ' || _typespec || ');';
BEGIN
EXECUTE _qstr USING _evdef_id , _efdef_id;
EXCEPTION
WHEN unique_violation THEN
RETURN 'DUPLICATE';
WHEN check_violation THEN
RETURN 'BAD_SPEC';
END;
RETURN 'OK';
END;
$evdef_create_field_record$;
REVOKE EXECUTE
ON FUNCTION events.evdef_create_field_record( TEXT , TEXT , TEXT )
FROM PUBLIC;
/*
* Generate the DDL for a numeric field
* ------------------------------------
*
* /!\ INTERNAL FUNCTION /!\
*
* This function generates the DDL for a numeric event field in an event queue
* table.
*
* Parameters:
* _fname The field's table name
* _opt Whether the field is optional
* _is_int Whether the field is an integer
* _min Minimal value of the field (may be NULL)
* _max Maximal value of the field (may be NULL)
*
* Returns:
* ??? The field's DDL
*/
DROP FUNCTION IF EXISTS events.efdef_ddl_numeric(
TEXT , BOOLEAN , BOOLEAN , NUMERIC , NUMERIC );
CREATE FUNCTION events.efdef_ddl_numeric(
_fname TEXT ,
_opt BOOLEAN ,
_is_int BOOLEAN ,
_min NUMERIC ,
_max NUMERIC )
RETURNS TEXT
LANGUAGE SQL
IMMUTABLE SECURITY INVOKER
CALLED ON NULL INPUT
AS $efdef_ddl_numeric$
SELECT ',' || $1 || ' '
|| ( CASE WHEN $3 THEN 'BIGINT' ELSE 'DOUBLE PRECISION' END )
|| ( CASE WHEN $2 THEN '' ELSE ' NOT NULL' END )
|| ( CASE
WHEN $4 IS NULL AND $5 IS NULL
THEN ''
ELSE
' CHECK(' || $1 || ( CASE
WHEN $5 IS NULL
THEN '>=' || $4::TEXT
WHEN $4 IS NULL
THEN '<=' || $5::TEXT
ELSE
' BETWEEN ' || $4::TEXT || ' AND ' || $5::TEXT
END ) || ')'
END );
$efdef_ddl_numeric$;
REVOKE EXECUTE
ON FUNCTION events.efdef_ddl_numeric(
TEXT , BOOLEAN , BOOLEAN , NUMERIC , NUMERIC )
FROM PUBLIC;
/*
* Generate the DDL for a text field
* ---------------------------------
*
* /!\ INTERNAL FUNCTION /!\
*
* This function generates the DDL for a text event field in an event queue
* table.
*
* Parameters:
* _fname The field's table name
* _opt Whether the field is optional
* _min Minimal length of the field (may be NULL)
* _max Maximal length of the field (may be NULL)
*
* Returns:
* ??? The field's DDL
*/
DROP FUNCTION IF EXISTS events.efdef_ddl_text(
TEXT , BOOLEAN , NUMERIC , NUMERIC );
CREATE FUNCTION events.efdef_ddl_text(
_fname TEXT ,
_opt BOOLEAN ,
_min NUMERIC ,
_max NUMERIC )
RETURNS TEXT
LANGUAGE SQL
IMMUTABLE SECURITY INVOKER
CALLED ON NULL INPUT
AS $efdef_ddl_text$
SELECT ',' || $1 || ' '
|| ( CASE WHEN $4 IS NULL THEN 'TEXT' ELSE 'VARCHAR(' || $4::TEXT || ')' END )
|| ( CASE WHEN $2 THEN '' ELSE ' NOT NULL' END )
|| ( CASE
WHEN $3 IS NULL
THEN ''
ELSE
' CHECK(LENGTH(' || $1 || ')>=' || $3::TEXT || ')'
END );
$efdef_ddl_text$;
REVOKE EXECUTE
ON FUNCTION events.efdef_ddl_text(
TEXT , BOOLEAN , NUMERIC , NUMERIC )
FROM PUBLIC;
/*
* Generate the DDL for an entity field
* ------------------------------------
*
* /!\ INTERNAL FUNCTION /!\
*
* This function generates the DDL for an entity event field in an event queue
* table.
*
* Parameters:
* _fname The field's table name
* _opt Whether the field is optional
* _etype Type of entity to reference
*
* Returns:
* ??? The field's DDL
*/
DROP FUNCTION IF EXISTS events.efdef_ddl_entity(
TEXT , BOOLEAN , events.entity_field_type );
CREATE FUNCTION events.efdef_ddl_entity(
_fname TEXT ,
_opt BOOLEAN ,
_etype events.entity_field_type )
RETURNS TEXT
LANGUAGE SQL
STRICT IMMUTABLE SECURITY INVOKER
AS $efdef_ddl_entity$
SELECT ',' || $1 || ' '
|| ( CASE
WHEN $3 IN ( 'EMP' , 'PLN', 'ALL' , 'ADM' ) THEN 'INT'
ELSE 'BIGINT'
END ) || ( CASE WHEN $2 THEN ' NOT NULL' ELSE '' END )
|| ' REFERENCES ' || ( CASE $3
WHEN 'EMP' THEN 'emp.empires(name_id)'
WHEN 'PLN' THEN 'verse.planets(name_id)'
WHEN 'FLT' THEN 'fleets.fleets(id)'
WHEN 'ALL' THEN 'emp.alliances(id)'
WHEN 'BAT' THEN 'battles.battles(id)'
WHEN 'ADM' THEN 'admin.administrators(id)'
WHEN 'BUG' THEN 'bugs.initial_report_events(event_id)'
END ) || ' ON DELETE CASCADE';
$efdef_ddl_entity$;
REVOKE EXECUTE
ON FUNCTION events.efdef_ddl_entity(
TEXT , BOOLEAN , events.entity_field_type )
FROM PUBLIC;
/*
* Create the event queuing table for a new definition
* ---------------------------------------------------
*
* /!\ INTERNAL FUNCTION /!\
*
* This function generates the event queuing table from the list of fields
* that compose an event definition. The queuing table's name will always be
* "events.evq_<type identifier>"; it will contain an event identifier
* generated from the event ID sequence (events.event_id_sequence), an empire
* identifier, a timestamp, the tick identifier, and rows corresponding to the
* event definition's fields.
*
* Parameters:
* _evdef_id The event definition's identifier
*/
DROP FUNCTION IF EXISTS events.evdef_create_queue_table( TEXT );
CREATE FUNCTION _temp_init_func(_user TEXT) RETURNS VOID LANGUAGE PLPGSQL AS $init_func$
BEGIN EXECUTE $init_code$
CREATE FUNCTION events.evdef_create_queue_table( _evdef_id TEXT )
RETURNS VOID
LANGUAGE PLPGSQL
STRICT VOLATILE SECURITY INVOKER
AS $evdef_create_queue_table$
DECLARE
_rec RECORD;
_qstr TEXT;
_fname TEXT;
BEGIN
_qstr := 'CREATE TABLE events.eq_' || replace( _evdef_id , '-' , '_' )
|| $tbl_def$ (
event_id BIGINT NOT NULL PRIMARY KEY
DEFAULT nextval('events.event_id_sequence'::regclass) ,
event_rtime TIMESTAMP WITHOUT TIME ZONE NOT NULL
DEFAULT now( ) ,
event_gtime BIGINT NOT NULL ,
empire_id INT NOT NULL REFERENCES emp.empires ( name_id )
ON DELETE CASCADE
$tbl_def$;
FOR _rec IN SELECT *
FROM events.field_definitions
WHERE evdef_id = _evdef_id
LOOP
_fname := 'ef_' || replace( _rec.efdef_id , '-' , '_' );
_qstr := _qstr || ( CASE _rec.efdef_type
WHEN 'NUMERIC' THEN
events.efdef_ddl_numeric( _fname , _rec.efdef_optional ,
_rec.efdef_integer , _rec.efdef_min , _rec.efdef_max )
WHEN 'TEXT' THEN
events.efdef_ddl_text( _fname , _rec.efdef_optional ,
_rec.efdef_min , _rec.efdef_max )
WHEN 'BOOL' THEN
',' || _fname || ' BOOLEAN' || ( CASE
WHEN NOT _rec.efdef_optional THEN ' NOT NULL'
ELSE ''
END )
WHEN 'I18N' THEN
',' || _fname || ' VARCHAR(64)' || ( CASE
WHEN NOT _rec.efdef_optional THEN ' NOT NULL'
ELSE ''
END ) || ' REFERENCES defs.strings(name)'
WHEN 'ENTITY' THEN
events.efdef_ddl_entity( _fname , _rec.efdef_optional ,
_rec.efdef_entity )
END );
END LOOP;
_qstr := _qstr || ');';
EXECUTE _qstr;
_qstr := 'GRANT INSERT ON TABLE events.eq_' || replace( _evdef_id , '-' , '_' )
|| ' TO $init_code$ || $1 || $init_code$;';
EXECUTE _qstr;
END;
$evdef_create_queue_table$; $init_code$ USING $1; END; $init_func$;
SELECT _temp_init_func(:dbuser_string);
DROP FUNCTION _temp_init_func(TEXT);
REVOKE EXECUTE
ON FUNCTION events.evdef_create_queue_table( TEXT )
FROM PUBLIC;
/*
* Validate and finalise an event definition
* -----------------------------------------
*
* This function inserts the contents of the temporary event definition table
* into the main table. If everything goes well, the event queuing table is
* created and the temporary table is destroyed.
*
* Returns:
* _error An error code (see events.evdef_create_result)
* _fld The name of the field which caused the error, or NULL
* if the error was table-related or if there was no
* error.
*/
DROP FUNCTION IF EXISTS events.evdef_finalise( );
CREATE FUNCTION events.evdef_finalise(
OUT _error events.evdef_create_result ,
OUT _fld TEXT )
LANGUAGE PLPGSQL
STRICT VOLATILE SECURITY DEFINER
AS $evdef_finalise$
DECLARE
_eid TEXT;
_rec RECORD;
BEGIN
-- First create the event definition record
_fld := NULL;
_error := events.evdef_create_record( );
IF _error = 'OK'
THEN
-- Then create records for all fields
FOR _rec IN SELECT * FROM evdef_temp WHERE evfld_id IS NOT NULL
LOOP
_error := events.evdef_create_field_record(
_rec.evdef_id , _rec.evfld_id , _rec.evfld_typespec );
IF _error <> 'OK'
THEN
-- Destroy the definition record on failure
_fld := _rec.evfld_id;
DELETE FROM events.event_definitions
WHERE evdef_id = _rec.evdef_id;
EXIT;
END IF;
END LOOP;
END IF;
-- If everything went well so far, create the queueing table
IF _error = 'OK'
THEN
SELECT INTO _eid evdef_id FROM evdef_temp LIMIT 1;
PERFORM events.evdef_create_queue_table( _eid );
END IF;
DROP TABLE evdef_temp;
END;
$evdef_finalise$;
REVOKE EXECUTE
ON FUNCTION events.evdef_finalise( )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evdef_finalise( )
TO :dbuser;

View file

@ -0,0 +1,143 @@
-- LegacyWorlds Beta 6
-- PostgreSQL database scripts
--
-- Functions to manipulate player-defined event priority
-- overrides.
--
-- Copyright(C) 2004-2012, DeepClone Development
-- --------------------------------------------------------
/*
* Set an event priority override
* ------------------------------
*
* Adds a new event priority override or modify its value. If the event type
* does not exist, does not allow overrides or if the specified priority is
* invalid, the error will be ignored silently.
*
* Parameters:
* _empire_id The identifier of the player's empire
* _evdef_id The identifier of the event type
* _priority The custom priority value
*/
DROP FUNCTION IF EXISTS events.evcp_set( INT , TEXT , INT );
CREATE FUNCTION events.evcp_set(
_empire_id INT ,
_evdef_id TEXT ,
_priority INT )
RETURNS VOID
LANGUAGE PLPGSQL
STRICT VOLATILE SECURITY DEFINER
AS $evcp_set$
DECLARE
_user_id INT;
BEGIN
BEGIN
INSERT INTO events.custom_priorities(
evdef_id , address_id , evcp_priority )
SELECT _evdef_id , owner_id , _priority
FROM naming.empire_names
WHERE id = _empire_id;
IF NOT FOUND
THEN
RAISE EXCEPTION 'missing empire';
END IF;
EXCEPTION
WHEN unique_violation THEN
UPDATE events.custom_priorities
SET evcp_priority = _priority
WHERE evdef_id = _evdef_id
AND address_id = (
SELECT owner_id
FROM naming.empire_names
WHERE id = _empire_id );
END;
EXCEPTION
WHEN raise_exception THEN
PERFORM sys.write_sql_log( 'Events' , 'WARNING'::log_level ,
'Call to events.evcp_set() from missing empire #' || _empire_id );
WHEN foreign_key_violation OR check_violation THEN
PERFORM sys.write_sql_log( 'Events' , 'WARNING'::log_level ,
'Bad call to events.evcp_set() from empire #' || _empire_id );
END;
$evcp_set$;
REVOKE EXECUTE
ON FUNCTION events.evcp_set( INT , TEXT , INT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evcp_set( INT , TEXT , INT )
TO :dbuser;
/*
* Clear an event priority override
* --------------------------------
*
* Remove an event priority override from the custom priorities table. If
* there was no override for the specified event type and empire, do nothing.
*
* Parameters:
* _empire_id The identifier of the player's empire
* _evdef_id The identifier of the event type
*/
DROP FUNCTION IF EXISTS events.evcp_clear( INT , TEXT );
CREATE FUNCTION events.evcp_clear(
_empire_id INT ,
_evdef_id TEXT )
RETURNS VOID
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $evcp_clear$
DELETE FROM events.custom_priorities
WHERE evdef_id = $2
AND address_id = (
SELECT owner_id
FROM naming.empire_names
WHERE id = $1 )
$evcp_clear$;
REVOKE EXECUTE
ON FUNCTION events.evcp_clear( INT , TEXT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evcp_clear( INT , TEXT )
TO :dbuser;
/*
* Clear all event priority overrides
* ----------------------------------
*
* Remove all event priority overrides set by some player.
*
* Parameters:
* _empire_id The identifier of the player's empire
*/
DROP FUNCTION IF EXISTS events.evcp_clear( INT );
CREATE FUNCTION events.evcp_clear( _empire_id INT )
RETURNS VOID
LANGUAGE SQL
STRICT VOLATILE SECURITY DEFINER
AS $evcp_clear$
DELETE FROM events.custom_priorities
WHERE address_id = (
SELECT owner_id
FROM naming.empire_names
WHERE id = $1 )
$evcp_clear$;
REVOKE EXECUTE
ON FUNCTION events.evcp_clear( INT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION events.evcp_clear( INT )
TO :dbuser;