Emmanuel BENOîT
3a0f5bbb78
Added the necessary database code to convert the contents of event queues into actual event records. The changes include: * a new table, events.pending_events, which is automatically filled by a trigger when events are inserted into queue tables, * the game.events.batchSize constant which defines the maximal amount of events to process in a single transaction, * the events.eq_process() stored procedure, which processes the events. In addition, the "hstore" extension was added as it is the easiest way to convert events from the queues' table model to the store's meta-model.
183 lines
No EOL
4.5 KiB
PL/PgSQL
183 lines
No EOL
4.5 KiB
PL/PgSQL
-- LegacyWorlds Beta 6
|
|
-- PostgreSQL database scripts
|
|
--
|
|
-- Functions that extract event data from the queue tables
|
|
-- and store them in the long term storage tables.
|
|
--
|
|
-- Copyright(C) 2004-2012, DeepClone Development
|
|
-- --------------------------------------------------------
|
|
|
|
|
|
/*
|
|
* Entity fields table
|
|
* -------------------
|
|
*
|
|
* This table, which is filled when the database is created, associates entity
|
|
* types with fields in the events.field_values table.
|
|
*/
|
|
DROP TABLE IF EXISTS events._entity_fields;
|
|
CREATE TABLE events._entity_fields(
|
|
efdef_entity events.entity_field_type NOT NULL PRIMARY KEY ,
|
|
field_name NAME NOT NULL ,
|
|
field_type NAME NOT NULL
|
|
);
|
|
INSERT INTO events._entity_fields VALUES
|
|
( 'EMP' , 'empire_id' , 'INT' ) ,
|
|
( 'PLN' , 'planet_id' , 'INT' ) ,
|
|
( 'FLT' , 'fleet_id' , 'BIGINT' ) ,
|
|
( 'ALL' , 'alliance_id' , 'INT' ) ,
|
|
( 'BAT' , 'battle_id' , 'BIGINT' ) ,
|
|
( 'ADM' , 'admin_id' , 'INT' ) ,
|
|
( 'BUG' , 'bug_report_id' , 'BIGINT' );
|
|
|
|
|
|
|
|
/*
|
|
* Process a pending event
|
|
* -----------------------
|
|
*
|
|
* /!\ INTERNAL FUNCTION /!\
|
|
*
|
|
* This procedure processes a single row from an event queue.
|
|
*
|
|
* If the specified event identifier actually exists in the queue, it is
|
|
* converted and stored in the main events tables, then the queue entry is
|
|
* removed.
|
|
*
|
|
* In all cases, the entry is deleted from events.pending_events.
|
|
*
|
|
* Parameters:
|
|
* _event_id The event's identifier
|
|
* _evdef_id The event's type
|
|
*
|
|
* Returns:
|
|
* ??? TRUE
|
|
*/
|
|
DROP FUNCTION IF EXISTS events.eq_process_event( BIGINT , TEXT );
|
|
CREATE FUNCTION events.eq_process_event(
|
|
_event_id BIGINT ,
|
|
_evdef_id TEXT )
|
|
RETURNS BOOLEAN
|
|
LANGUAGE PLPGSQL
|
|
STRICT VOLATILE SECURITY INVOKER
|
|
AS $eq_process_event$
|
|
|
|
DECLARE
|
|
_tbl TEXT;
|
|
_qstr TEXT;
|
|
_qentry RECORD;
|
|
_nfound INT;
|
|
_efdef RECORD;
|
|
|
|
BEGIN
|
|
|
|
_tbl := 'events.eq_' || replace( _evdef_id , '-' , '_' );
|
|
_qstr := 'SELECT event_rtime , event_gtime , empire_id FROM '
|
|
|| _tbl || ' WHERE event_id = $1';
|
|
EXECUTE _qstr INTO _qentry USING _event_id;
|
|
GET DIAGNOSTICS _nfound = ROW_COUNT;
|
|
|
|
IF _nfound > 0
|
|
THEN
|
|
|
|
INSERT INTO events.events_v2 (
|
|
event_id , evdef_id , event_rtime , event_gtime , empire_id
|
|
) VALUES (
|
|
_event_id , _evdef_id , _qentry.event_rtime ,
|
|
_qentry.event_gtime , _qentry.empire_id
|
|
);
|
|
|
|
_qstr := format( $field_acquisition$
|
|
SELECT efdef_id , field_name , field_type ,
|
|
( efdef_type = 'I18N') AS i18n , _sq1.value
|
|
FROM events.field_definitions
|
|
INNER JOIN (
|
|
SELECT (each(hstore(_tbl))).*
|
|
FROM %s _tbl
|
|
WHERE _tbl.event_id = $1
|
|
) _sq1 ON _sq1.key = 'ef_' || replace(efdef_id , '-','_')
|
|
LEFT OUTER JOIN events._entity_fields
|
|
USING ( efdef_entity )
|
|
WHERE evdef_id = $2
|
|
$field_acquisition$ , _tbl );
|
|
|
|
FOR _efdef IN EXECUTE _qstr USING _event_id , _evdef_id
|
|
LOOP
|
|
_qstr := 'INSERT INTO events.field_values(event_id,evdef_id,efdef_id,efval_litteral'
|
|
|| ( CASE
|
|
WHEN _efdef.field_name IS NOT NULL
|
|
THEN ',' || _efdef.field_name
|
|
WHEN _efdef.i18n
|
|
THEN ',string_id'
|
|
ELSE
|
|
''
|
|
END ) || ') ';
|
|
|
|
IF _efdef.i18n
|
|
THEN
|
|
_qstr := _qstr || $i18n_query$
|
|
SELECT $1,$2,$3,_str.id::TEXT||' '||_str.name,_str.id
|
|
FROM defs.strings _str
|
|
WHERE _str.name = $4
|
|
$i18n_query$;
|
|
ELSIF _efdef.field_name IS NOT NULL
|
|
THEN
|
|
_qstr := _qstr || format( 'VALUES($1,$2,$3,$4,$4::%s)' , _efdef.field_type );
|
|
ELSE
|
|
_qstr := _qstr || 'VALUES($1,$2,$3,$4)';
|
|
END IF;
|
|
|
|
EXECUTE _qstr USING _event_id , _evdef_id , _efdef.efdef_id , _efdef.value;
|
|
END LOOP;
|
|
|
|
END IF;
|
|
|
|
DELETE FROM events.pending_events
|
|
WHERE event_id = _event_id;
|
|
RETURN TRUE;
|
|
|
|
END;
|
|
$eq_process_event$;
|
|
|
|
REVOKE EXECUTE
|
|
ON FUNCTION events.eq_process_event( BIGINT , TEXT )
|
|
FROM PUBLIC;
|
|
|
|
|
|
|
|
/*
|
|
* Process pending events
|
|
* ----------------------
|
|
*
|
|
* This procedure processes events from the queues. Each time the procedure is
|
|
* called, it will process at most "game.events.batchSize" events.
|
|
*
|
|
* Returns:
|
|
* ??? TRUE if events were processed, FALSE if the queues are
|
|
* empty
|
|
*/
|
|
DROP FUNCTION IF EXISTS events.eq_process( );
|
|
CREATE FUNCTION events.eq_process( )
|
|
RETURNS BOOLEAN
|
|
LANGUAGE PLPGSQL
|
|
STRICT VOLATILE SECURITY DEFINER
|
|
AS $eq_process$
|
|
|
|
DECLARE
|
|
_limit INT;
|
|
|
|
BEGIN
|
|
_limit := sys.get_constant( 'game.events.batchSize' );
|
|
PERFORM events.eq_process_event( event_id , evdef_id )
|
|
FROM events.pending_events
|
|
LIMIT _limit;
|
|
RETURN FOUND;
|
|
END;
|
|
$eq_process$;
|
|
|
|
REVOKE EXECUTE
|
|
ON FUNCTION events.eq_process( )
|
|
FROM PUBLIC;
|
|
GRANT EXECUTE
|
|
ON FUNCTION events.eq_process( )
|
|
TO :dbuser; |