create language plpgsql;
---
--- remove duplicate elements from array
---
CREATE OR REPLACE FUNCTION array_uniq(anyarray)
RETURNS anyarray as $$
SELECT array(SELECT DISTINCT $1[i] FROM
    generate_series(array_lower($1,1), array_upper($1,1)) g(i));
$$ LANGUAGE SQL STRICT IMMUTABLE;


---
--- remove null elements from array
---
CREATE OR REPLACE FUNCTION array_filter_null(anyarray)
RETURNS anyarray as $$
SELECT array(SELECT $1[i] FROM
    generate_series(array_lower($1,1), array_upper($1,1)) g(i) WHERE $1[i] IS NOT NULL) ;
$$ LANGUAGE SQL STRICT IMMUTABLE;


-- error messages classifier
-- DROP TABLE enum_error  CASCADE;
CREATE TABLE enum_error (
        id SERIAL PRIMARY KEY,
        status varchar(128) UNIQUE NOT NULL,
        status_cs varchar(128) UNIQUE NOT NULL -- czech translation
        );
                        
                        

-- error messages EN and CS


INSERT INTO enum_error VALUES(  1000 , 'Command completed successfully',    'Příkaz úspěšně proveden');
INSERT INTO enum_error VALUES(  1001 , 'Command completed successfully; action pending',  'Příkaz úspěšně proveden; vykonání akce odloženo');

INSERT INTO enum_error VALUES(  1300 , 'Command completed successfully; no messages',    'Příkaz úspěšně proveden; žádné nové zprávy');
INSERT INTO enum_error VALUES(  1301 , 'Command completed successfully; ack to dequeue',    'Příkaz úspěšně proveden; potvrď za účelem vyřazení z fronty');
INSERT INTO enum_error VALUES(  1500 , 'Command completed successfully; ending session',    'Příkaz úspěšně proveden; konec relace');


INSERT INTO enum_error VALUES(  2000 ,    'Unknown command',    'Neznámý příkaz');
INSERT INTO enum_error VALUES(  2001 ,    'Command syntax error',    'Chybná syntaxe příkazu');
INSERT INTO enum_error VALUES(  2002 ,    'Command use error',     'Chybné použití příkazu');
INSERT INTO enum_error VALUES(  2003 ,    'Required parameter missing',    'Požadovaný parametr neuveden');
INSERT INTO enum_error VALUES(  2004 ,    'Parameter value range error',    'Chybný rozsah parametru');
INSERT INTO enum_error VALUES(  2005 ,    'Parameter value syntax error',    'Chybná syntaxe hodnoty parametru');


INSERT INTO enum_error VALUES( 2100 ,   'Unimplemented protocol version',    'Neimplementovaná verze protokolu');
INSERT INTO enum_error VALUES( 2101 ,   'Unimplemented command',     'Neimplementovaný příkaz');
INSERT INTO enum_error VALUES( 2102 ,   'Unimplemented option',    'Neimplementovaná volba');
INSERT INTO enum_error VALUES( 2103 ,   'Unimplemented extension',    'Neimplementované rozšíření');
INSERT INTO enum_error VALUES( 2104 ,   'Billing failure',     'Účetní selhání');
INSERT INTO enum_error VALUES( 2105 ,   'Object is not eligible for renewal',     'Objekt je nezpůsobilý pro obnovení');
INSERT INTO enum_error VALUES( 2106 ,   'Object is not eligible for transfer',    'Objekt je nezpůsobilý pro transfer');


INSERT INTO enum_error VALUES( 2200 ,    'Authentication error',    'Chyba ověření identity');
INSERT INTO enum_error VALUES( 2201 ,    'Authorization error',     'Chyba oprávnění');
INSERT INTO enum_error VALUES( 2202 ,    'Invalid authorization information',    'Chybná autorizační informace');

INSERT INTO enum_error VALUES( 2300 ,    'Object pending transfer',    'Objekt čeká na transfer');
INSERT INTO enum_error VALUES( 2301 ,    'Object not pending transfer',    'Objekt nečeká na transfer');
INSERT INTO enum_error VALUES( 2302 ,    'Object exists',    'Objekt existuje');
INSERT INTO enum_error VALUES( 2303 ,    'Object does not exist',    'Objekt neexistuje');
INSERT INTO enum_error VALUES( 2304 ,    'Object status prohibits operation',    'Status objektu nedovoluje operaci');
INSERT INTO enum_error VALUES( 2305 ,    'Object association prohibits operation',    'Asociace objektu nedovoluje operaci');
INSERT INTO enum_error VALUES( 2306 ,    'Parameter value policy error',    'Chyba zásady pro hodnotu parametru');
INSERT INTO enum_error VALUES( 2307 ,    'Unimplemented object service',    'Neimplementovaná služba objektu');
INSERT INTO enum_error VALUES( 2308 ,    'Data management policy violation',    'Porušení zásady pro správu dat');

INSERT INTO enum_error VALUES( 2400 ,    'Command failed',    'Příkaz selhal');
INSERT INTO enum_error VALUES( 2500 ,    'Command failed; server closing connection',    'Příkaz selhal; server uzavírá spojení');
INSERT INTO enum_error VALUES( 2501 ,    'Authentication error; server closing connection',    'Chyba ověření identity; server uzavírá spojení');
INSERT INTO enum_error VALUES( 2502 ,    'Session limit exceeded; server closing connection',    'Limit na počet relací překročen; server uzavírá spojení');

select setval('enum_error_id_seq', 2502);

comment on table enum_error is
'Table of error messages
id   - message
1000 - command completed successfully
1001 - command completed successfully, action pending
1300 - command completed successfully, no messages
1301 - command completed successfully, act to dequeue
1500 - command completed successfully, ending session
2000 - unknown command
2001 - command syntax error
2002 - command use error
2003 - required parameter missing
2004 - parameter value range error
2005 - parameter value systax error
2100 - unimplemented protocol version
2101 - unimplemented command
2102 - unimplemented option
2103 - unimplemented extension
2104 - billing failure
2105 - object is not eligible for renewal
2106 - object is not eligible for transfer
2200 - authentication error
2201 - authorization error
2202 - invalid authorization information
2300 - object pending transfer
2301 - object not pending transfer
2302 - object exists
2303 - object does not exists
2304 - object status prohibits operation
2305 - object association prohibits operation
2306 - parameter value policy error
2307 - unimplemented object service
2308 - data management policy violation
2400 - command failed
2500 - command failed, server closing connection
2501 - authentication error, server closing connection
2502 - session limit exceeded, server closing connection';
comment on column enum_error.id is 'id of error';
comment on column enum_error.status is 'error message in english language';
comment on column enum_error.status_cs is 'error message in native language';
-- classifier of error messages  reason
CREATE TABLE enum_reason (
        id SERIAL PRIMARY KEY,
        reason varchar(128) UNIQUE NOT NULL,
        reason_cs varchar(128)  UNIQUE  NOT NULL -- czech translation
        );


INSERT INTO enum_reason VALUES(  1 ,  'bad format of contact handle'   , 'neplatný formát ukazatele kontaktu' );
INSERT INTO enum_reason VALUES(  2 ,  'bad format of nsset handle' ,  'neplatný formát ukazatele nssetu' );
INSERT INTO enum_reason VALUES(  3 ,  'bad format of fqdn domain'  , 'neplatný formát názvu domény' );

INSERT INTO enum_reason VALUES(  4 ,  'Domain name not applicable.'  , 'nepoužitelný název domény' );

-- for check
INSERT INTO enum_reason VALUES(  5 , 'invalid format'  , 'neplatný formát' );
INSERT INTO enum_reason VALUES(  6 ,  'already registered.'   , 'již zaregistrováno' );
INSERT INTO enum_reason VALUES(  7 , 'within protection period.' , 'je v ochranné lhůtě' );


INSERT INTO enum_reason VALUES( 8 , 'Invalid IP address.' , 'neplatná IP adresa'  );
INSERT INTO enum_reason VALUES(  9 ,  'Invalid nameserver hostname.'  ,  'neplatný formát názvu jmenného serveru DNS' );
INSERT INTO enum_reason VALUES(  10 ,  'Duplicate nameserver address.' , 'duplicitní adresa jmenného serveru DNS'  );
INSERT INTO enum_reason VALUES(  11 ,  'Glue IP address not allowed here.'  , 'nepovolená  IP adresa glue záznamu' );
INSERT INTO enum_reason VALUES(  12 ,  'At least two nameservers required.'  , 'jsou zapotřebí alespoň dva DNS servery' );


-- badly entered period in domain renew 
INSERT INTO enum_reason VALUES(  13 , 'invalid date of period' ,  'neplatná hodnota periody' );
INSERT INTO enum_reason VALUES( 14 , 'period exceedes maximal allowed validity time.' , 'perioda je nad maximální dovolenou hodnotou' );
INSERT INTO enum_reason VALUES( 15 , 'period is not aligned with allowed step.' , 'perioda neodpovídá dovolenému intervalu' );


-- country code doesn't exist
INSERT INTO enum_reason VALUES(  16 , 'Unknown country code'  , 'neznámý kód země' );

-- unknown msgID doesn't exist
INSERT INTO enum_reason VALUES(  17 , 'Unknown message ID' ,  'neznámé msgID' );


-- for ENUMval	
INSERT INTO enum_reason VALUES(  18 , 'Validation expiration date can not be used here.' ,  'datum vypršení platnosti se nepoužívá'  );
INSERT INTO enum_reason VALUES(  19 , 'Validation expiration date does not match registry data.' , 'datum vypršení platnosti je neplatné' );
INSERT INTO enum_reason VALUES(  20 , 'Validation expiration date is required.' , 'datum vypršení platnosti je požadováno' );

-- Update NSSET it can not be removed or added  DNS host or replaced tech contact 1 tech is minimum 
INSERT INTO enum_reason VALUES(  21 , 'Can not remove nameserver.'  , 'nelze odstranit jmenný server DNS' );
INSERT INTO enum_reason VALUES(  22 , 'Can not add nameserver'  , 'nelze přidat jmenný server DNS' );

INSERT INTO enum_reason VALUES(  23 ,  'Can not remove technical contact'  , 'nelze vymazat technický kontakt'  );

-- when technical/administrative contact not exist or is already assigned to object (domain/keyset/nsset)
INSERT INTO enum_reason VALUES(  24 , 'Technical contact is already assigned to this object.'  , 'Technický kontakt je již přiřazen k tomuto objektu' );
INSERT INTO enum_reason VALUES(  25 , 'Technical contact does not exist' ,  'Technický kontakt neexistuje');

INSERT INTO enum_reason VALUES(  26 , 'Administrative contact is already assigned to this object.'  , 'Administrátorský kontakt je již přiřazen k tomuto objektu' );
INSERT INTO enum_reason VALUES(  27 , 'Administrative contact does not exist' ,  'Administrátorský kontakt neexistuje'   );
 
-- for domain when owner or nsset doesn't exist
INSERT INTO enum_reason VALUES( 28 ,  'nsset handle does not exist.' , 'sada jmenných serverů není vytvořena' );
INSERT INTO enum_reason VALUES( 29 ,  'contact handle of registrant does not exist.' , 'ukazatel kontaktu vlastníka není vytvořen' );

-- if dns host cannot be added or removed
INSERT INTO enum_reason VALUES( 30 , 'Nameserver is already set to this nsset.' , 'jmenný server DNS je již přiřazen sadě jmenných serverů' );
INSERT INTO enum_reason VALUES( 31 , 'Nameserver is not set to this nsset.'  , 'jmenný server DNS není přiřazen sadě jmenných serverů' );

-- for domain renew when entered date of epiration doesn't fit 
INSERT INTO enum_reason VALUES( 32 ,  'Expiration date does not match registry data.' , 'Nesouhlasí datum expirace' );
 
-- error from mod_eppd, if it is missing 'op' attribute in transfer command 
INSERT INTO enum_reason VALUES( 33 ,  'Attribute op in element transfer is missing', 'Chybí atribut op u elementu transfer' );
-- error from mod_eppd, if it is missing a type of ident element
INSERT INTO enum_reason VALUES( 34 ,  'Attribute type in element ident is missing', 'Chybí atribut type u elementu ident' );
-- error from z mod_eppd, if it is missing attribute msgID in element poll
INSERT INTO enum_reason VALUES( 35 ,  'Attribute msgID in element poll is missing', 'Chybí atribut msgID u elementu poll' );

-- blacklist domain
INSERT INTO enum_reason VALUES( 36 ,  'Registration is prohibited'  , 'Registrace je zakázána' );
-- XML validation process failed
INSERT INTO enum_reason VALUES( 37 ,  'Schemas validity error: ' , 'Chyba validace XML schemat: ' );

-- duplicate contact for tech or admin 
INSERT INTO enum_reason VALUES(  38 , 'Duplicity contact' , 'Duplicitní kontakt' );

---
--- moved from keyset.sql
---
INSERT INTO enum_reason VALUES (39, 'Bad format of keyset handle', 'Neplatný formát ukazatele keysetu');
INSERT INTO enum_reason VALUES (40, 'Keyset handle does not exist', 'Ukazatel keysetu není vytvořen');
INSERT INTO enum_reason VALUES (41, 'DSRecord does not exists', 'DSRecord záznam neexistuje');
INSERT INTO enum_reason VALUES (42, 'Can not remove DSRecord', 'Nelze odstranit DSRecord záznam');
INSERT INTO enum_reason VALUES (43, 'Duplicity DSRecord', 'Duplicitní DSRecord záznam');
INSERT INTO enum_reason VALUES (44, 'DSRecord already exists for this keyset', 'DSRecord již pro tento keyset existuje');
INSERT INTO enum_reason VALUES (45, 'DSRecord is not set for this keyset', 'DSRecord pro tento keyset neexistuje');
INSERT INTO enum_reason VALUES (46, 'Field ``digest type'''' must be 1 (SHA-1)', 'Pole ``digest type'''' musí být 1 (SHA-1)');
INSERT INTO enum_reason VALUES (47, 'Digest must be 40 characters long', 'Digest musí být dlouhý 40 znaků');


INSERT INTO enum_reason VALUES (48, 'Object does not belong to the registrar', 'Objekt nepatří registrátorovi');
INSERT INTO enum_reason VALUES (49, 'Too many technical administrators contacts.', 'Příliš mnoho administrátorských kontaktů');
INSERT INTO enum_reason VALUES (50, 'Too many DS records', 'Příliš mnoho DS záznamů');
INSERT INTO enum_reason VALUES (51, 'Too many DNSKEY records', 'Příliš mnoho DNSKEY záznamů');

INSERT INTO enum_reason VALUES (52, 'Too many nameservers in this nsset', 'Příliš mnoho jmenných serverů DNS je přiřazeno sadě jmenných serverů');
INSERT INTO enum_reason VALUES (53, 'No DNSKey record', 'Žádný DNSKey záznam');
INSERT INTO enum_reason VALUES (54, 'Field ``flags'''' must be 0, 256 or 257', 'Pole ``flags'''' musí být 0, 256 nebo 257');
INSERT INTO enum_reason VALUES (55, 'Field ``protocol'''' must be 3', 'Pole ``protocol'''' musí být 3');
INSERT INTO enum_reason VALUES (56, 'Field ``alg'''' must be 1,2,3,4,5,6,7,8,10,12,252,253,254 or 255', 'Pole ``alg'''' musí být 1,2,3,4,5,6,7,8,10,12,252,253,254 nebo 255');
INSERT INTO enum_reason VALUES (57, 'Field ``key'''' has invalid length', 'Pole ``key'''' má špatnou délku');
INSERT INTO enum_reason VALUES (58, 'Field ``key'''' contains invalid character', 'Pole ``key'''' obsahuje neplatný znak');
INSERT INTO enum_reason VALUES (59, 'DNSKey already exists for this keyset', 'DNSKey již pro tento keyset existuje');
INSERT INTO enum_reason VALUES (60, 'DNSKey does not exist for this keyset', 'DNSKey pro tento keyset neexistuje');
INSERT INTO enum_reason VALUES (61, 'Duplicity DNSKey', 'Duplicitní DNSKey');
INSERT INTO enum_reason VALUES (62, 'Keyset must have DNSKey or DSRecord', 'Keyset musí mít DNSKey nebo DSRecord');

SELECT setval('enum_reason_id_seq', 62);

comment on table enum_reason is 'Table of error messages reason';
comment on column enum_reason.reason is 'reason in english language';
comment on column enum_reason.reason_cs is 'reason in native language';
-- function classifier
-- DROP TABLE enum_ssntype CASCADE;
CREATE TABLE enum_ssntype (
        id SERIAL PRIMARY KEY,
        type varchar(8) UNIQUE NOT NULL,
        description varchar(64) UNIQUE NOT NULL
        );

-- login function
INSERT INTO enum_ssntype  VALUES(1 , 'RC' , 'born number');
INSERT INTO enum_ssntype  VALUES(2 , 'OP' , 'identity card number');
INSERT INTO enum_ssntype  VALUES(3 , 'PASS' , 'passwport');
INSERT INTO enum_ssntype  VALUES(4 , 'ICO' , 'organization identification number');
INSERT INTO enum_ssntype  VALUES(5 , 'MPSV' , 'social system identification');
INSERT INTO enum_ssntype  VALUES(6 , 'BIRTHDAY' , 'day of birth');

select setval('enum_ssntype_id_seq', 6);

comment on table enum_ssntype is
'Table of identification number types

types:
id - type   - description
 1 - RC     - born number
 2 - OP     - identity card number
 3 - PASS   - passport number
 4 - ICO    - organization identification number
 5 - MPSV   - social system identification
 6 - BIRTHDAY - day of birth';
comment on column enum_ssntype.type is 'type abbrevation';
comment on column enum_ssntype.description is 'type description';
-- Country codes and names obtained from ISO 3166-1
--   http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm
-- Case updated by wikipedia
--   http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements
-- Valid since 1. 7. 2012
--DROP TABLE enum_country CASCADE;
CREATE TABLE enum_country (
        id char(2) PRIMARY KEY,
        country varchar(1024) UNIQUE NOT NULL,
        country_cs  varchar(1024) UNIQUE -- optional czech title
        );

comment on table enum_country is 'list of country codes and names';
comment on column enum_country.id is 'country code (e.g. CZ for Czech republic)';
comment on column enum_country.country is 'english country name';
comment on column enum_country.country_cs is 'optional country name in native language';

-- delete all records 
DELETE FROM  enum_country ;
-- read all states
INSERT INTO enum_country (id,country) VALUES ( 'AD' , 'Andorra' );
INSERT INTO enum_country (id,country) VALUES ( 'AE' , 'United Arab Emirates' );
INSERT INTO enum_country (id,country) VALUES ( 'AF' , 'Afghanistan' );
INSERT INTO enum_country (id,country) VALUES ( 'AG' , 'Antigua and Barbuda' );
INSERT INTO enum_country (id,country) VALUES ( 'AI' , 'Anguilla' );
INSERT INTO enum_country (id,country) VALUES ( 'AL' , 'Albania' );
INSERT INTO enum_country (id,country) VALUES ( 'AM' , 'Armenia' );
INSERT INTO enum_country (id,country) VALUES ( 'AO' , 'Angola' );
INSERT INTO enum_country (id,country) VALUES ( 'AQ' , 'Antarctica' );
INSERT INTO enum_country (id,country) VALUES ( 'AR' , 'Argentina' );
INSERT INTO enum_country (id,country) VALUES ( 'AS' , 'American Samoa' );
INSERT INTO enum_country (id,country) VALUES ( 'AT' , 'Austria' );
INSERT INTO enum_country (id,country) VALUES ( 'AU' , 'Australia' );
INSERT INTO enum_country (id,country) VALUES ( 'AW' , 'Aruba' );
INSERT INTO enum_country (id,country) VALUES ( 'AX' , 'Åland Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'AZ' , 'Azerbaijan' );
INSERT INTO enum_country (id,country) VALUES ( 'BA' , 'Bosnia and Herzegovina' );
INSERT INTO enum_country (id,country) VALUES ( 'BB' , 'Barbados' );
INSERT INTO enum_country (id,country) VALUES ( 'BD' , 'Bangladesh' );
INSERT INTO enum_country (id,country) VALUES ( 'BE' , 'Belgium' );
INSERT INTO enum_country (id,country) VALUES ( 'BF' , 'Burkina Faso' );
INSERT INTO enum_country (id,country) VALUES ( 'BG' , 'Bulgaria' );
INSERT INTO enum_country (id,country) VALUES ( 'BH' , 'Bahrain' );
INSERT INTO enum_country (id,country) VALUES ( 'BI' , 'Burundi' );
INSERT INTO enum_country (id,country) VALUES ( 'BJ' , 'Benin' );
INSERT INTO enum_country (id,country) VALUES ( 'BL' , 'Saint Barthélemy' );
INSERT INTO enum_country (id,country) VALUES ( 'BM' , 'Bermuda' );
INSERT INTO enum_country (id,country) VALUES ( 'BN' , 'Brunei Darussalam' );
INSERT INTO enum_country (id,country) VALUES ( 'BO' , 'Bolivia, Plurinational State of' );
INSERT INTO enum_country (id,country) VALUES ( 'BQ' , 'Bonaire, Sint Eustatius and Saba' );
INSERT INTO enum_country (id,country) VALUES ( 'BR' , 'Brazil' );
INSERT INTO enum_country (id,country) VALUES ( 'BS' , 'Bahamas' );
INSERT INTO enum_country (id,country) VALUES ( 'BT' , 'Bhutan' );
INSERT INTO enum_country (id,country) VALUES ( 'BV' , 'Bouvet Island' );
INSERT INTO enum_country (id,country) VALUES ( 'BW' , 'Botswana' );
INSERT INTO enum_country (id,country) VALUES ( 'BY' , 'Belarus' );
INSERT INTO enum_country (id,country) VALUES ( 'BZ' , 'Belize' );
INSERT INTO enum_country (id,country) VALUES ( 'CA' , 'Canada' );
INSERT INTO enum_country (id,country) VALUES ( 'CC' , 'Cocos (Keeling) Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'CD' , 'Congo, the Democratic Republic of the' );
INSERT INTO enum_country (id,country) VALUES ( 'CF' , 'Central African Republic' );
INSERT INTO enum_country (id,country) VALUES ( 'CG' , 'Congo' );
INSERT INTO enum_country (id,country) VALUES ( 'CH' , 'Switzerland' );
INSERT INTO enum_country (id,country) VALUES ( 'CI' , E'Côte d\'Ivoire' );
INSERT INTO enum_country (id,country) VALUES ( 'CK' , 'Cook Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'CL' , 'Chile' );
INSERT INTO enum_country (id,country) VALUES ( 'CM' , 'Cameroon' );
INSERT INTO enum_country (id,country) VALUES ( 'CN' , 'China' );
INSERT INTO enum_country (id,country) VALUES ( 'CO' , 'Colombia' );
INSERT INTO enum_country (id,country) VALUES ( 'CR' , 'Costa Rica' );
INSERT INTO enum_country (id,country) VALUES ( 'CU' , 'Cuba' );
INSERT INTO enum_country (id,country) VALUES ( 'CV' , 'Cape Verde' );
INSERT INTO enum_country (id,country) VALUES ( 'CW' , 'Curaçao' );
INSERT INTO enum_country (id,country) VALUES ( 'CX' , 'Christmas Island' );
INSERT INTO enum_country (id,country) VALUES ( 'CY' , 'Cyprus' );
INSERT INTO enum_country (id,country) VALUES ( 'CZ' , 'Czech Republic' );
INSERT INTO enum_country (id,country) VALUES ( 'DE' , 'Germany' );
INSERT INTO enum_country (id,country) VALUES ( 'DJ' , 'Djibouti' );
INSERT INTO enum_country (id,country) VALUES ( 'DK' , 'Denmark' );
INSERT INTO enum_country (id,country) VALUES ( 'DM' , 'Dominica' );
INSERT INTO enum_country (id,country) VALUES ( 'DO' , 'Dominican Republic' );
INSERT INTO enum_country (id,country) VALUES ( 'DZ' , 'Algeria' );
INSERT INTO enum_country (id,country) VALUES ( 'EC' , 'Ecuador' );
INSERT INTO enum_country (id,country) VALUES ( 'EE' , 'Estonia' );
INSERT INTO enum_country (id,country) VALUES ( 'EG' , 'Egypt' );
INSERT INTO enum_country (id,country) VALUES ( 'EH' , 'Western Sahara' );
INSERT INTO enum_country (id,country) VALUES ( 'ER' , 'Eritrea' );
INSERT INTO enum_country (id,country) VALUES ( 'ES' , 'Spain' );
INSERT INTO enum_country (id,country) VALUES ( 'ET' , 'Ethiopia' );
INSERT INTO enum_country (id,country) VALUES ( 'FI' , 'Finland' );
INSERT INTO enum_country (id,country) VALUES ( 'FJ' , 'Fiji' );
INSERT INTO enum_country (id,country) VALUES ( 'FK' , 'Falkland Islands (Malvinas)' );
INSERT INTO enum_country (id,country) VALUES ( 'FM' , 'Micronesia, Federated States of' );
INSERT INTO enum_country (id,country) VALUES ( 'FO' , 'Faroe Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'FR' , 'France' );
INSERT INTO enum_country (id,country) VALUES ( 'GA' , 'Gabon' );
INSERT INTO enum_country (id,country) VALUES ( 'GB' , 'United Kingdom' );
INSERT INTO enum_country (id,country) VALUES ( 'GD' , 'Grenada' );
INSERT INTO enum_country (id,country) VALUES ( 'GE' , 'Georgia' );
INSERT INTO enum_country (id,country) VALUES ( 'GF' , 'French Guiana' );
INSERT INTO enum_country (id,country) VALUES ( 'GG' , 'Guernsey' );
INSERT INTO enum_country (id,country) VALUES ( 'GH' , 'Ghana' );
INSERT INTO enum_country (id,country) VALUES ( 'GI' , 'Gibraltar' );
INSERT INTO enum_country (id,country) VALUES ( 'GL' , 'Greenland' );
INSERT INTO enum_country (id,country) VALUES ( 'GM' , 'Gambia' );
INSERT INTO enum_country (id,country) VALUES ( 'GN' , 'Guinea' );
INSERT INTO enum_country (id,country) VALUES ( 'GP' , 'Guadeloupe' );
INSERT INTO enum_country (id,country) VALUES ( 'GQ' , 'Equatorial Guinea' );
INSERT INTO enum_country (id,country) VALUES ( 'GR' , 'Greece' );
INSERT INTO enum_country (id,country) VALUES ( 'GS' , 'South Georgia and the South Sandwich Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'GT' , 'Guatemala' );
INSERT INTO enum_country (id,country) VALUES ( 'GU' , 'Guam' );
INSERT INTO enum_country (id,country) VALUES ( 'GW' , 'Guinea-Bissau' );
INSERT INTO enum_country (id,country) VALUES ( 'GY' , 'Guyana' );
INSERT INTO enum_country (id,country) VALUES ( 'HK' , 'Hong Kong' );
INSERT INTO enum_country (id,country) VALUES ( 'HM' , 'Heard Island and McDonald Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'HN' , 'Honduras' );
INSERT INTO enum_country (id,country) VALUES ( 'HR' , 'Croatia' );
INSERT INTO enum_country (id,country) VALUES ( 'HT' , 'Haiti' );
INSERT INTO enum_country (id,country) VALUES ( 'HU' , 'Hungary' );
INSERT INTO enum_country (id,country) VALUES ( 'ID' , 'Indonesia' );
INSERT INTO enum_country (id,country) VALUES ( 'IE' , 'Ireland' );
INSERT INTO enum_country (id,country) VALUES ( 'IL' , 'Israel' );
INSERT INTO enum_country (id,country) VALUES ( 'IM' , 'Isle of Man' );
INSERT INTO enum_country (id,country) VALUES ( 'IN' , 'India' );
INSERT INTO enum_country (id,country) VALUES ( 'IO' , 'British Indian Ocean Territory' );
INSERT INTO enum_country (id,country) VALUES ( 'IQ' , 'Iraq' );
INSERT INTO enum_country (id,country) VALUES ( 'IR' , 'Iran, Islamic Republic of' );
INSERT INTO enum_country (id,country) VALUES ( 'IS' , 'Iceland' );
INSERT INTO enum_country (id,country) VALUES ( 'IT' , 'Italy' );
INSERT INTO enum_country (id,country) VALUES ( 'JE' , 'Jersey' );
INSERT INTO enum_country (id,country) VALUES ( 'JM' , 'Jamaica' );
INSERT INTO enum_country (id,country) VALUES ( 'JO' , 'Jordan' );
INSERT INTO enum_country (id,country) VALUES ( 'JP' , 'Japan' );
INSERT INTO enum_country (id,country) VALUES ( 'KE' , 'Kenya' );
INSERT INTO enum_country (id,country) VALUES ( 'KG' , 'Kyrgyzstan' );
INSERT INTO enum_country (id,country) VALUES ( 'KH' , 'Cambodia' );
INSERT INTO enum_country (id,country) VALUES ( 'KI' , 'Kiribati' );
INSERT INTO enum_country (id,country) VALUES ( 'KM' , 'Comoros' );
INSERT INTO enum_country (id,country) VALUES ( 'KN' , 'Saint Kitts and Nevis' );
INSERT INTO enum_country (id,country) VALUES ( 'KP' , E'Korea, Democratic People\'s Republic of' );
INSERT INTO enum_country (id,country) VALUES ( 'KR' , 'Korea, Republic of' );
INSERT INTO enum_country (id,country) VALUES ( 'KW' , 'Kuwait' );
INSERT INTO enum_country (id,country) VALUES ( 'KY' , 'Cayman Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'KZ' , 'Kazakhstan' );
INSERT INTO enum_country (id,country) VALUES ( 'LA' , E'Lao People\'s Democratic Republic' );
INSERT INTO enum_country (id,country) VALUES ( 'LB' , 'Lebanon' );
INSERT INTO enum_country (id,country) VALUES ( 'LC' , 'Saint Lucia' );
INSERT INTO enum_country (id,country) VALUES ( 'LI' , 'Liechtenstein' );
INSERT INTO enum_country (id,country) VALUES ( 'LK' , 'Sri Lanka' );
INSERT INTO enum_country (id,country) VALUES ( 'LR' , 'Liberia' );
INSERT INTO enum_country (id,country) VALUES ( 'LS' , 'Lesotho' );
INSERT INTO enum_country (id,country) VALUES ( 'LT' , 'Lithuania' );
INSERT INTO enum_country (id,country) VALUES ( 'LU' , 'Luxembourg' );
INSERT INTO enum_country (id,country) VALUES ( 'LV' , 'Latvia' );
INSERT INTO enum_country (id,country) VALUES ( 'LY' , 'Libya' );
INSERT INTO enum_country (id,country) VALUES ( 'MA' , 'Morocco' );
INSERT INTO enum_country (id,country) VALUES ( 'MC' , 'Monaco' );
INSERT INTO enum_country (id,country) VALUES ( 'MD' , 'Moldova, Republic of' );
INSERT INTO enum_country (id,country) VALUES ( 'ME' , 'Montenegro' );
INSERT INTO enum_country (id,country) VALUES ( 'MF' , 'Saint Martin (French part)' );
INSERT INTO enum_country (id,country) VALUES ( 'MG' , 'Madagascar' );
INSERT INTO enum_country (id,country) VALUES ( 'MH' , 'Marshall Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'MK' , 'Macedonia, the former Yugoslav Republic of' );
INSERT INTO enum_country (id,country) VALUES ( 'ML' , 'Mali' );
INSERT INTO enum_country (id,country) VALUES ( 'MM' , 'Myanmar' );
INSERT INTO enum_country (id,country) VALUES ( 'MN' , 'Mongolia' );
INSERT INTO enum_country (id,country) VALUES ( 'MO' , 'Macao' );
INSERT INTO enum_country (id,country) VALUES ( 'MP' , 'Northern Mariana Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'MQ' , 'Martinique' );
INSERT INTO enum_country (id,country) VALUES ( 'MR' , 'Mauritania' );
INSERT INTO enum_country (id,country) VALUES ( 'MS' , 'Montserrat' );
INSERT INTO enum_country (id,country) VALUES ( 'MT' , 'Malta' );
INSERT INTO enum_country (id,country) VALUES ( 'MU' , 'Mauritius' );
INSERT INTO enum_country (id,country) VALUES ( 'MV' , 'Maldives' );
INSERT INTO enum_country (id,country) VALUES ( 'MW' , 'Malawi' );
INSERT INTO enum_country (id,country) VALUES ( 'MX' , 'Mexico' );
INSERT INTO enum_country (id,country) VALUES ( 'MY' , 'Malaysia' );
INSERT INTO enum_country (id,country) VALUES ( 'MZ' , 'Mozambique' );
INSERT INTO enum_country (id,country) VALUES ( 'NA' , 'Namibia' );
INSERT INTO enum_country (id,country) VALUES ( 'NC' , 'New Caledonia' );
INSERT INTO enum_country (id,country) VALUES ( 'NE' , 'Niger' );
INSERT INTO enum_country (id,country) VALUES ( 'NF' , 'Norfolk Island' );
INSERT INTO enum_country (id,country) VALUES ( 'NG' , 'Nigeria' );
INSERT INTO enum_country (id,country) VALUES ( 'NI' , 'Nicaragua' );
INSERT INTO enum_country (id,country) VALUES ( 'NL' , 'Netherlands' );
INSERT INTO enum_country (id,country) VALUES ( 'NO' , 'Norway' );
INSERT INTO enum_country (id,country) VALUES ( 'NP' , 'Nepal' );
INSERT INTO enum_country (id,country) VALUES ( 'NR' , 'Nauru' );
INSERT INTO enum_country (id,country) VALUES ( 'NU' , 'Niue' );
INSERT INTO enum_country (id,country) VALUES ( 'NZ' , 'New Zealand' );
INSERT INTO enum_country (id,country) VALUES ( 'OM' , 'Oman' );
INSERT INTO enum_country (id,country) VALUES ( 'PA' , 'Panama' );
INSERT INTO enum_country (id,country) VALUES ( 'PE' , 'Peru' );
INSERT INTO enum_country (id,country) VALUES ( 'PF' , 'French Polynesia' );
INSERT INTO enum_country (id,country) VALUES ( 'PG' , 'Papua New Guinea' );
INSERT INTO enum_country (id,country) VALUES ( 'PH' , 'Philippines' );
INSERT INTO enum_country (id,country) VALUES ( 'PK' , 'Pakistan' );
INSERT INTO enum_country (id,country) VALUES ( 'PL' , 'Poland' );
INSERT INTO enum_country (id,country) VALUES ( 'PM' , 'Saint Pierre and Miquelon' );
INSERT INTO enum_country (id,country) VALUES ( 'PN' , 'Pitcairn' );
INSERT INTO enum_country (id,country) VALUES ( 'PR' , 'Puerto Rico' );
INSERT INTO enum_country (id,country) VALUES ( 'PS' , 'Palestinian Territory, Occupied' );
INSERT INTO enum_country (id,country) VALUES ( 'PT' , 'Portugal' );
INSERT INTO enum_country (id,country) VALUES ( 'PW' , 'Palau' );
INSERT INTO enum_country (id,country) VALUES ( 'PY' , 'Paraguay' );
INSERT INTO enum_country (id,country) VALUES ( 'QA' , 'Qatar' );
INSERT INTO enum_country (id,country) VALUES ( 'RE' , 'Réunion' );
INSERT INTO enum_country (id,country) VALUES ( 'RO' , 'Romania' );
INSERT INTO enum_country (id,country) VALUES ( 'RS' , 'Serbia' );
INSERT INTO enum_country (id,country) VALUES ( 'RU' , 'Russian Federation' );
INSERT INTO enum_country (id,country) VALUES ( 'RW' , 'Rwanda' );
INSERT INTO enum_country (id,country) VALUES ( 'SA' , 'Saudi Arabia' );
INSERT INTO enum_country (id,country) VALUES ( 'SB' , 'Solomon Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'SC' , 'Seychelles' );
INSERT INTO enum_country (id,country) VALUES ( 'SD' , 'Sudan' );
INSERT INTO enum_country (id,country) VALUES ( 'SE' , 'Sweden' );
INSERT INTO enum_country (id,country) VALUES ( 'SG' , 'Singapore' );
INSERT INTO enum_country (id,country) VALUES ( 'SH' , 'Saint Helena, Ascension and Tristan da Cunha' );
INSERT INTO enum_country (id,country) VALUES ( 'SI' , 'Slovenia' );
INSERT INTO enum_country (id,country) VALUES ( 'SJ' , 'Svalbard and Jan Mayen' );
INSERT INTO enum_country (id,country) VALUES ( 'SK' , 'Slovakia' );
INSERT INTO enum_country (id,country) VALUES ( 'SL' , 'Sierra Leone' );
INSERT INTO enum_country (id,country) VALUES ( 'SM' , 'San Marino' );
INSERT INTO enum_country (id,country) VALUES ( 'SN' , 'Senegal' );
INSERT INTO enum_country (id,country) VALUES ( 'SO' , 'Somalia' );
INSERT INTO enum_country (id,country) VALUES ( 'SR' , 'Suriname' );
INSERT INTO enum_country (id,country) VALUES ( 'SS' , 'South Sudan' );
INSERT INTO enum_country (id,country) VALUES ( 'ST' , 'Sao Tome and Principe' );
INSERT INTO enum_country (id,country) VALUES ( 'SV' , 'El Salvador' );
INSERT INTO enum_country (id,country) VALUES ( 'SX' , 'Sint Maarten (Dutch part)' );
INSERT INTO enum_country (id,country) VALUES ( 'SY' , 'Syrian Arab Republic' );
INSERT INTO enum_country (id,country) VALUES ( 'SZ' , 'Swaziland' );
INSERT INTO enum_country (id,country) VALUES ( 'TC' , 'Turks and Caicos Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'TD' , 'Chad' );
INSERT INTO enum_country (id,country) VALUES ( 'TF' , 'French Southern Territories' );
INSERT INTO enum_country (id,country) VALUES ( 'TG' , 'Togo' );
INSERT INTO enum_country (id,country) VALUES ( 'TH' , 'Thailand' );
INSERT INTO enum_country (id,country) VALUES ( 'TJ' , 'Tajikistan' );
INSERT INTO enum_country (id,country) VALUES ( 'TK' , 'Tokelau' );
INSERT INTO enum_country (id,country) VALUES ( 'TL' , 'Timor-Leste' );
INSERT INTO enum_country (id,country) VALUES ( 'TM' , 'Turkmenistan' );
INSERT INTO enum_country (id,country) VALUES ( 'TN' , 'Tunisia' );
INSERT INTO enum_country (id,country) VALUES ( 'TO' , 'Tonga' );
INSERT INTO enum_country (id,country) VALUES ( 'TR' , 'Turkey' );
INSERT INTO enum_country (id,country) VALUES ( 'TT' , 'Trinidad And Tobago' );
INSERT INTO enum_country (id,country) VALUES ( 'TV' , 'Tuvalu' );
INSERT INTO enum_country (id,country) VALUES ( 'TW' , 'Taiwan, Province of China' );
INSERT INTO enum_country (id,country) VALUES ( 'TZ' , 'Tanzania, United Republic of' );
INSERT INTO enum_country (id,country) VALUES ( 'UA' , 'Ukraine' );
INSERT INTO enum_country (id,country) VALUES ( 'UG' , 'Uganda' );
INSERT INTO enum_country (id,country) VALUES ( 'UM' , 'United States Minor Outlying Islands' );
INSERT INTO enum_country (id,country) VALUES ( 'US' , 'United States' );
INSERT INTO enum_country (id,country) VALUES ( 'UY' , 'Uruguay' );
INSERT INTO enum_country (id,country) VALUES ( 'UZ' , 'Uzbekistan' );
INSERT INTO enum_country (id,country) VALUES ( 'VA' , 'Holy See (Vatican City State)' );
INSERT INTO enum_country (id,country) VALUES ( 'VC' , 'Saint Vincent and the Grenadines' );
INSERT INTO enum_country (id,country) VALUES ( 'VE' , 'Venezuela, Bolivarian Republic of' );
INSERT INTO enum_country (id,country) VALUES ( 'VG' , 'Virgin Islands, British' );
INSERT INTO enum_country (id,country) VALUES ( 'VI' , 'Virgin Islands, U.S.' );
INSERT INTO enum_country (id,country) VALUES ( 'VN' , 'Viet Nam' );
INSERT INTO enum_country (id,country) VALUES ( 'VU' , 'Vanuatu' );
INSERT INTO enum_country (id,country) VALUES ( 'WF' , 'Wallis and Futuna' );
INSERT INTO enum_country (id,country) VALUES ( 'WS' , 'Samoa' );
INSERT INTO enum_country (id,country) VALUES ( 'YE' , 'Yemen' );
INSERT INTO enum_country (id,country) VALUES ( 'YT' , 'Mayotte' );
INSERT INTO enum_country (id,country) VALUES ( 'ZA' , 'South Africa' );
INSERT INTO enum_country (id,country) VALUES ( 'ZM' , 'Zambia' );
INSERT INTO enum_country (id,country) VALUES ( 'ZW' , 'Zimbabwe' );
-- Czech country names obtained from enumeration of country names from Czech Statistical Office
--   http://www.czso.cz/csu/klasifik.nsf/i/ciselnik_zemi_%28czem%29
-- Valid since 1. 7. 2012

--- country names in czech language
UPDATE enum_country SET country_cs= 'Andorra' WHERE ID= 'AD' ;
UPDATE enum_country SET country_cs= 'Spojené arabské emiráty' WHERE ID= 'AE' ;
UPDATE enum_country SET country_cs= 'Afghánistán' WHERE ID= 'AF' ;
UPDATE enum_country SET country_cs= 'Antigua a Barbuda' WHERE ID= 'AG' ;
UPDATE enum_country SET country_cs= 'Anguilla' WHERE ID= 'AI' ;
UPDATE enum_country SET country_cs= 'Albánie' WHERE ID= 'AL' ;
UPDATE enum_country SET country_cs= 'Arménie' WHERE ID= 'AM' ;
UPDATE enum_country SET country_cs= 'Angola' WHERE ID= 'AO' ;
UPDATE enum_country SET country_cs= 'Antarktika' WHERE ID= 'AQ' ;
UPDATE enum_country SET country_cs= 'Argentina' WHERE ID= 'AR' ;
UPDATE enum_country SET country_cs= 'Americká Samoa' WHERE ID= 'AS' ;
UPDATE enum_country SET country_cs= 'Rakousko' WHERE ID= 'AT' ;
UPDATE enum_country SET country_cs= 'Austrálie' WHERE ID= 'AU' ;
UPDATE enum_country SET country_cs= 'Aruba' WHERE ID= 'AW' ;
UPDATE enum_country SET country_cs= 'Alandské ostrovy' WHERE ID= 'AX' ;
UPDATE enum_country SET country_cs= 'Ázerbájdžán' WHERE ID= 'AZ' ;
UPDATE enum_country SET country_cs= 'Bosna a Hercegovina' WHERE ID= 'BA' ;
UPDATE enum_country SET country_cs= 'Barbados' WHERE ID= 'BB' ;
UPDATE enum_country SET country_cs= 'Bangladéš' WHERE ID= 'BD' ;
UPDATE enum_country SET country_cs= 'Belgie' WHERE ID= 'BE' ;
UPDATE enum_country SET country_cs= 'Burkina Faso' WHERE ID= 'BF' ;
UPDATE enum_country SET country_cs= 'Bulharsko' WHERE ID= 'BG' ;
UPDATE enum_country SET country_cs= 'Bahrajn' WHERE ID= 'BH' ;
UPDATE enum_country SET country_cs= 'Burundi' WHERE ID= 'BI' ;
UPDATE enum_country SET country_cs= 'Benin' WHERE ID= 'BJ' ;
UPDATE enum_country SET country_cs= 'Svatý Bartoloměj' WHERE ID= 'BL' ;
UPDATE enum_country SET country_cs= 'Bermudy' WHERE ID= 'BM' ;
UPDATE enum_country SET country_cs= 'Brunej Darussalam' WHERE ID= 'BN' ;
UPDATE enum_country SET country_cs= 'Mnohonárodní stát Bolívie' WHERE ID= 'BO' ;
UPDATE enum_country SET country_cs= 'Bonaire, Svatý Eustach a Saba' WHERE ID= 'BQ' ;
UPDATE enum_country SET country_cs= 'Brazílie' WHERE ID= 'BR' ;
UPDATE enum_country SET country_cs= 'Bahamy' WHERE ID= 'BS' ;
UPDATE enum_country SET country_cs= 'Bhútán' WHERE ID= 'BT' ;
UPDATE enum_country SET country_cs= 'Bouvetův ostrov' WHERE ID= 'BV' ;
UPDATE enum_country SET country_cs= 'Botswana' WHERE ID= 'BW' ;
UPDATE enum_country SET country_cs= 'Bělorusko' WHERE ID= 'BY' ;
UPDATE enum_country SET country_cs= 'Belize' WHERE ID= 'BZ' ;
UPDATE enum_country SET country_cs= 'Kanada' WHERE ID= 'CA' ;
UPDATE enum_country SET country_cs= 'Kokosové (Keelingovy) ostrovy' WHERE ID= 'CC' ;
UPDATE enum_country SET country_cs= 'Kongo, demokratická republika' WHERE ID= 'CD' ;
UPDATE enum_country SET country_cs= 'Středoafrická republika' WHERE ID= 'CF' ;
UPDATE enum_country SET country_cs= 'Kongo, republika' WHERE ID= 'CG' ;
UPDATE enum_country SET country_cs= 'Švýcarsko' WHERE ID= 'CH' ;
UPDATE enum_country SET country_cs= 'Pobřeží slonoviny' WHERE ID= 'CI' ;
UPDATE enum_country SET country_cs= 'Cookovy ostrovy' WHERE ID= 'CK' ;
UPDATE enum_country SET country_cs= 'Chile' WHERE ID= 'CL' ;
UPDATE enum_country SET country_cs= 'Kamerun' WHERE ID= 'CM' ;
UPDATE enum_country SET country_cs= 'Čína' WHERE ID= 'CN' ;
UPDATE enum_country SET country_cs= 'Kolumbie' WHERE ID= 'CO' ;
UPDATE enum_country SET country_cs= 'Kostarika' WHERE ID= 'CR' ;
UPDATE enum_country SET country_cs= 'Kuba' WHERE ID= 'CU' ;
UPDATE enum_country SET country_cs= 'Kapverdy' WHERE ID= 'CV' ;
UPDATE enum_country SET country_cs= 'Curaçao' WHERE ID= 'CW' ;
UPDATE enum_country SET country_cs= 'Vánoční ostrov' WHERE ID= 'CX' ;
UPDATE enum_country SET country_cs= 'Kypr' WHERE ID= 'CY' ;
UPDATE enum_country SET country_cs= 'Česká republika' WHERE ID= 'CZ' ;
UPDATE enum_country SET country_cs= 'Německo' WHERE ID= 'DE' ;
UPDATE enum_country SET country_cs= 'Džibutsko' WHERE ID= 'DJ' ;
UPDATE enum_country SET country_cs= 'Dánsko' WHERE ID= 'DK' ;
UPDATE enum_country SET country_cs= 'Dominika' WHERE ID= 'DM' ;
UPDATE enum_country SET country_cs= 'Dominikánská republika' WHERE ID= 'DO' ;
UPDATE enum_country SET country_cs= 'Alžírsko' WHERE ID= 'DZ' ;
UPDATE enum_country SET country_cs= 'Ekvádor' WHERE ID= 'EC' ;
UPDATE enum_country SET country_cs= 'Estonsko' WHERE ID= 'EE' ;
UPDATE enum_country SET country_cs= 'Egypt' WHERE ID= 'EG' ;
UPDATE enum_country SET country_cs= 'Západní Sahara' WHERE ID= 'EH' ;
UPDATE enum_country SET country_cs= 'Eritrea' WHERE ID= 'ER' ;
UPDATE enum_country SET country_cs= 'Španělsko' WHERE ID= 'ES' ;
UPDATE enum_country SET country_cs= 'Etiopie' WHERE ID= 'ET' ;
UPDATE enum_country SET country_cs= 'Finsko' WHERE ID= 'FI' ;
UPDATE enum_country SET country_cs= 'Fidži' WHERE ID= 'FJ' ;
UPDATE enum_country SET country_cs= 'Falklandské ostrovy (Malvíny)' WHERE ID= 'FK' ;
UPDATE enum_country SET country_cs= 'Mikronésie, federativní státy' WHERE ID= 'FM' ;
UPDATE enum_country SET country_cs= 'Faerské ostrovy' WHERE ID= 'FO' ;
UPDATE enum_country SET country_cs= 'Francie' WHERE ID= 'FR' ;
UPDATE enum_country SET country_cs= 'Gabon' WHERE ID= 'GA' ;
UPDATE enum_country SET country_cs= 'Spojené království' WHERE ID= 'GB' ;
UPDATE enum_country SET country_cs= 'Grenada' WHERE ID= 'GD' ;
UPDATE enum_country SET country_cs= 'Gruzie' WHERE ID= 'GE' ;
UPDATE enum_country SET country_cs= 'Francouzská Guyana' WHERE ID= 'GF' ;
UPDATE enum_country SET country_cs= 'Guernsey' WHERE ID= 'GG' ;
UPDATE enum_country SET country_cs= 'Ghana' WHERE ID= 'GH' ;
UPDATE enum_country SET country_cs= 'Gibraltar' WHERE ID= 'GI' ;
UPDATE enum_country SET country_cs= 'Grónsko' WHERE ID= 'GL' ;
UPDATE enum_country SET country_cs= 'Gambie' WHERE ID= 'GM' ;
UPDATE enum_country SET country_cs= 'Guinea' WHERE ID= 'GN' ;
UPDATE enum_country SET country_cs= 'Guadeloupe' WHERE ID= 'GP' ;
UPDATE enum_country SET country_cs= 'Rovníková Guinea' WHERE ID= 'GQ' ;
UPDATE enum_country SET country_cs= 'Řecko' WHERE ID= 'GR' ;
UPDATE enum_country SET country_cs= 'Jižní Georgie a Jižní Sandwichovy ostrovy' WHERE ID= 'GS' ;
UPDATE enum_country SET country_cs= 'Guatemala' WHERE ID= 'GT' ;
UPDATE enum_country SET country_cs= 'Guam' WHERE ID= 'GU' ;
UPDATE enum_country SET country_cs= 'Guinea-Bissau' WHERE ID= 'GW' ;
UPDATE enum_country SET country_cs= 'Guyana' WHERE ID= 'GY' ;
UPDATE enum_country SET country_cs= 'Hongkong' WHERE ID= 'HK' ;
UPDATE enum_country SET country_cs= 'Heardův ostrov a McDonaldovy ostrovy' WHERE ID= 'HM' ;
UPDATE enum_country SET country_cs= 'Honduras' WHERE ID= 'HN' ;
UPDATE enum_country SET country_cs= 'Chorvatsko' WHERE ID= 'HR' ;
UPDATE enum_country SET country_cs= 'Haiti' WHERE ID= 'HT' ;
UPDATE enum_country SET country_cs= 'Maďarsko' WHERE ID= 'HU' ;
UPDATE enum_country SET country_cs= 'Indonésie' WHERE ID= 'ID' ;
UPDATE enum_country SET country_cs= 'Irsko' WHERE ID= 'IE' ;
UPDATE enum_country SET country_cs= 'Izrael' WHERE ID= 'IL' ;
UPDATE enum_country SET country_cs= 'Ostrov Man' WHERE ID= 'IM' ;
UPDATE enum_country SET country_cs= 'Indie' WHERE ID= 'IN' ;
UPDATE enum_country SET country_cs= 'Britské indickooceánské území' WHERE ID= 'IO' ;
UPDATE enum_country SET country_cs= 'Irák' WHERE ID= 'IQ' ;
UPDATE enum_country SET country_cs= 'Írán (islámská republika)' WHERE ID= 'IR' ;
UPDATE enum_country SET country_cs= 'Island' WHERE ID= 'IS' ;
UPDATE enum_country SET country_cs= 'Itálie' WHERE ID= 'IT' ;
UPDATE enum_country SET country_cs= 'Jersey' WHERE ID= 'JE' ;
UPDATE enum_country SET country_cs= 'Jamajka' WHERE ID= 'JM' ;
UPDATE enum_country SET country_cs= 'Jordánsko' WHERE ID= 'JO' ;
UPDATE enum_country SET country_cs= 'Japonsko' WHERE ID= 'JP' ;
UPDATE enum_country SET country_cs= 'Keňa' WHERE ID= 'KE' ;
UPDATE enum_country SET country_cs= 'Kyrgyzstán' WHERE ID= 'KG' ;
UPDATE enum_country SET country_cs= 'Kambodža' WHERE ID= 'KH' ;
UPDATE enum_country SET country_cs= 'Kiribati' WHERE ID= 'KI' ;
UPDATE enum_country SET country_cs= 'Komory' WHERE ID= 'KM' ;
UPDATE enum_country SET country_cs= 'Svatý Kryštof a Nevis' WHERE ID= 'KN' ;
UPDATE enum_country SET country_cs= 'Korea, lidově demokratická republika' WHERE ID= 'KP' ;
UPDATE enum_country SET country_cs= 'Korejská republika' WHERE ID= 'KR' ;
UPDATE enum_country SET country_cs= 'Kuvajt' WHERE ID= 'KW' ;
UPDATE enum_country SET country_cs= 'Kajmanské ostrovy' WHERE ID= 'KY' ;
UPDATE enum_country SET country_cs= 'Kazachstán' WHERE ID= 'KZ' ;
UPDATE enum_country SET country_cs= 'Laoská lidově demokratická republika' WHERE ID= 'LA' ;
UPDATE enum_country SET country_cs= 'Libanon' WHERE ID= 'LB' ;
UPDATE enum_country SET country_cs= 'Svatá Lucie' WHERE ID= 'LC' ;
UPDATE enum_country SET country_cs= 'Lichtenštejnsko' WHERE ID= 'LI' ;
UPDATE enum_country SET country_cs= 'Srí Lanka' WHERE ID= 'LK' ;
UPDATE enum_country SET country_cs= 'Libérie' WHERE ID= 'LR' ;
UPDATE enum_country SET country_cs= 'Lesotho' WHERE ID= 'LS' ;
UPDATE enum_country SET country_cs= 'Litva' WHERE ID= 'LT' ;
UPDATE enum_country SET country_cs= 'Lucembursko' WHERE ID= 'LU' ;
UPDATE enum_country SET country_cs= 'Lotyšsko' WHERE ID= 'LV' ;
UPDATE enum_country SET country_cs= 'Libye' WHERE ID= 'LY' ;
UPDATE enum_country SET country_cs= 'Maroko' WHERE ID= 'MA' ;
UPDATE enum_country SET country_cs= 'Monako' WHERE ID= 'MC' ;
UPDATE enum_country SET country_cs= 'Moldavsko' WHERE ID= 'MD' ;
UPDATE enum_country SET country_cs= 'Černá Hora' WHERE ID= 'ME' ;
UPDATE enum_country SET country_cs= 'Svatý Martin (francouzská část)' WHERE ID= 'MF' ;
UPDATE enum_country SET country_cs= 'Madagaskar' WHERE ID= 'MG' ;
UPDATE enum_country SET country_cs= 'Marshallovy ostrovy' WHERE ID= 'MH' ;
UPDATE enum_country SET country_cs= 'Makedonie, bývalá jugoslávská republika' WHERE ID= 'MK' ;
UPDATE enum_country SET country_cs= 'Mali' WHERE ID= 'ML' ;
UPDATE enum_country SET country_cs= 'Myanmar' WHERE ID= 'MM' ;
UPDATE enum_country SET country_cs= 'Mongolsko' WHERE ID= 'MN' ;
UPDATE enum_country SET country_cs= 'Macao' WHERE ID= 'MO' ;
UPDATE enum_country SET country_cs= 'Ostrovy Severní Mariany' WHERE ID= 'MP' ;
UPDATE enum_country SET country_cs= 'Martinik' WHERE ID= 'MQ' ;
UPDATE enum_country SET country_cs= 'Mauritánie' WHERE ID= 'MR' ;
UPDATE enum_country SET country_cs= 'Montserrat' WHERE ID= 'MS' ;
UPDATE enum_country SET country_cs= 'Malta' WHERE ID= 'MT' ;
UPDATE enum_country SET country_cs= 'Mauricius' WHERE ID= 'MU' ;
UPDATE enum_country SET country_cs= 'Maledivy' WHERE ID= 'MV' ;
UPDATE enum_country SET country_cs= 'Malawi' WHERE ID= 'MW' ;
UPDATE enum_country SET country_cs= 'Mexiko' WHERE ID= 'MX' ;
UPDATE enum_country SET country_cs= 'Malajsie' WHERE ID= 'MY' ;
UPDATE enum_country SET country_cs= 'Mosambik' WHERE ID= 'MZ' ;
UPDATE enum_country SET country_cs= 'Namibie' WHERE ID= 'NA' ;
UPDATE enum_country SET country_cs= 'Nová Kaledonie' WHERE ID= 'NC' ;
UPDATE enum_country SET country_cs= 'Niger' WHERE ID= 'NE' ;
UPDATE enum_country SET country_cs= 'Ostrov Norfolk' WHERE ID= 'NF' ;
UPDATE enum_country SET country_cs= 'Nigérie' WHERE ID= 'NG' ;
UPDATE enum_country SET country_cs= 'Nikaragua' WHERE ID= 'NI' ;
UPDATE enum_country SET country_cs= 'Nizozemsko' WHERE ID= 'NL' ;
UPDATE enum_country SET country_cs= 'Norsko' WHERE ID= 'NO' ;
UPDATE enum_country SET country_cs= 'Nepál' WHERE ID= 'NP' ;
UPDATE enum_country SET country_cs= 'Nauru' WHERE ID= 'NR' ;
UPDATE enum_country SET country_cs= 'Niue' WHERE ID= 'NU' ;
UPDATE enum_country SET country_cs= 'Nový Zéland' WHERE ID= 'NZ' ;
UPDATE enum_country SET country_cs= 'Omán' WHERE ID= 'OM' ;
UPDATE enum_country SET country_cs= 'Panama' WHERE ID= 'PA' ;
UPDATE enum_country SET country_cs= 'Peru' WHERE ID= 'PE' ;
UPDATE enum_country SET country_cs= 'Francouzská Polynésie' WHERE ID= 'PF' ;
UPDATE enum_country SET country_cs= 'Papua Nová Guinea' WHERE ID= 'PG' ;
UPDATE enum_country SET country_cs= 'Filipíny' WHERE ID= 'PH' ;
UPDATE enum_country SET country_cs= 'Pákistán' WHERE ID= 'PK' ;
UPDATE enum_country SET country_cs= 'Polsko' WHERE ID= 'PL' ;
UPDATE enum_country SET country_cs= 'Saint Pierre a Miquelon' WHERE ID= 'PM' ;
UPDATE enum_country SET country_cs= 'Pitcairn' WHERE ID= 'PN' ;
UPDATE enum_country SET country_cs= 'Portoriko' WHERE ID= 'PR' ;
UPDATE enum_country SET country_cs= 'Palestinské území (okupované)' WHERE ID= 'PS' ;
UPDATE enum_country SET country_cs= 'Portugalsko' WHERE ID= 'PT' ;
UPDATE enum_country SET country_cs= 'Palau' WHERE ID= 'PW' ;
UPDATE enum_country SET country_cs= 'Paraguay' WHERE ID= 'PY' ;
UPDATE enum_country SET country_cs= 'Katar' WHERE ID= 'QA' ;
UPDATE enum_country SET country_cs= 'Réunion' WHERE ID= 'RE' ;
UPDATE enum_country SET country_cs= 'Rumunsko' WHERE ID= 'RO' ;
UPDATE enum_country SET country_cs= 'Srbsko' WHERE ID= 'RS' ;
UPDATE enum_country SET country_cs= 'Ruská federace' WHERE ID= 'RU' ;
UPDATE enum_country SET country_cs= 'Rwanda' WHERE ID= 'RW' ;
UPDATE enum_country SET country_cs= 'Saúdská Arábie' WHERE ID= 'SA' ;
UPDATE enum_country SET country_cs= 'Šalomounovy ostrovy' WHERE ID= 'SB' ;
UPDATE enum_country SET country_cs= 'Seychely' WHERE ID= 'SC' ;
UPDATE enum_country SET country_cs= 'Súdán' WHERE ID= 'SD' ;
UPDATE enum_country SET country_cs= 'Švédsko' WHERE ID= 'SE' ;
UPDATE enum_country SET country_cs= 'Singapur' WHERE ID= 'SG' ;
UPDATE enum_country SET country_cs= 'Svatá Helena, Ascension a Tristan da Cunha' WHERE ID= 'SH' ;
UPDATE enum_country SET country_cs= 'Slovinsko' WHERE ID= 'SI' ;
UPDATE enum_country SET country_cs= 'Svalbard a Jan Mayen' WHERE ID= 'SJ' ;
UPDATE enum_country SET country_cs= 'Slovensko' WHERE ID= 'SK' ;
UPDATE enum_country SET country_cs= 'Sierra Leone' WHERE ID= 'SL' ;
UPDATE enum_country SET country_cs= 'San Marino' WHERE ID= 'SM' ;
UPDATE enum_country SET country_cs= 'Senegal' WHERE ID= 'SN' ;
UPDATE enum_country SET country_cs= 'Somálsko' WHERE ID= 'SO' ;
UPDATE enum_country SET country_cs= 'Surinam' WHERE ID= 'SR' ;
UPDATE enum_country SET country_cs= 'Jižní Súdán' WHERE ID= 'SS' ;
UPDATE enum_country SET country_cs= 'Svatý Tomáš a Princův ostrov' WHERE ID= 'ST' ;
UPDATE enum_country SET country_cs= 'Salvador' WHERE ID= 'SV' ;
UPDATE enum_country SET country_cs= 'Svatý Martin (nizozemská část)' WHERE ID= 'SX' ;
UPDATE enum_country SET country_cs= 'Syrská arabská republika' WHERE ID= 'SY' ;
UPDATE enum_country SET country_cs= 'Svazijsko' WHERE ID= 'SZ' ;
UPDATE enum_country SET country_cs= 'Ostrovy Turks a Caicos' WHERE ID= 'TC' ;
UPDATE enum_country SET country_cs= 'Čad' WHERE ID= 'TD' ;
UPDATE enum_country SET country_cs= 'Francouzská jižní území' WHERE ID= 'TF' ;
UPDATE enum_country SET country_cs= 'Togo' WHERE ID= 'TG' ;
UPDATE enum_country SET country_cs= 'Thajsko' WHERE ID= 'TH' ;
UPDATE enum_country SET country_cs= 'Tádžikistán' WHERE ID= 'TJ' ;
UPDATE enum_country SET country_cs= 'Tokelau' WHERE ID= 'TK' ;
UPDATE enum_country SET country_cs= 'Východní Timor' WHERE ID= 'TL' ;
UPDATE enum_country SET country_cs= 'Turkmenistán' WHERE ID= 'TM' ;
UPDATE enum_country SET country_cs= 'Tunisko' WHERE ID= 'TN' ;
UPDATE enum_country SET country_cs= 'Tonga' WHERE ID= 'TO' ;
UPDATE enum_country SET country_cs= 'Turecko' WHERE ID= 'TR' ;
UPDATE enum_country SET country_cs= 'Trinidad a Tobago' WHERE ID= 'TT' ;
UPDATE enum_country SET country_cs= 'Tuvalu' WHERE ID= 'TV' ;
UPDATE enum_country SET country_cs= 'Tchaj-wan' WHERE ID= 'TW' ;
UPDATE enum_country SET country_cs= 'Tanzanská sjednocená republika' WHERE ID= 'TZ' ;
UPDATE enum_country SET country_cs= 'Ukrajina' WHERE ID= 'UA' ;
UPDATE enum_country SET country_cs= 'Uganda' WHERE ID= 'UG' ;
UPDATE enum_country SET country_cs= 'Menší odlehlé ostrovy USA' WHERE ID= 'UM' ;
UPDATE enum_country SET country_cs= 'Spojené státy' WHERE ID= 'US' ;
UPDATE enum_country SET country_cs= 'Uruguay' WHERE ID= 'UY' ;
UPDATE enum_country SET country_cs= 'Uzbekistán' WHERE ID= 'UZ' ;
UPDATE enum_country SET country_cs= 'Svatý stolec (Vatikánský městský stát)' WHERE ID= 'VA' ;
UPDATE enum_country SET country_cs= 'Svatý Vincenc a Grenadiny' WHERE ID= 'VC' ;
UPDATE enum_country SET country_cs= 'Bolívarovská republika Venezuela' WHERE ID= 'VE' ;
UPDATE enum_country SET country_cs= 'Britské Panenské ostrovy' WHERE ID= 'VG' ;
UPDATE enum_country SET country_cs= 'Americké Panenské ostrovy' WHERE ID= 'VI' ;
UPDATE enum_country SET country_cs= 'Vietnam' WHERE ID= 'VN' ;
UPDATE enum_country SET country_cs= 'Vanuatu' WHERE ID= 'VU' ;
UPDATE enum_country SET country_cs= 'Wallis a Futuna' WHERE ID= 'WF' ;
UPDATE enum_country SET country_cs= 'Samoa' WHERE ID= 'WS' ;
UPDATE enum_country SET country_cs= 'Jemen' WHERE ID= 'YE' ;
UPDATE enum_country SET country_cs= 'Mayotte' WHERE ID= 'YT' ;
UPDATE enum_country SET country_cs= 'Jižní Afrika' WHERE ID= 'ZA' ;
UPDATE enum_country SET country_cs= 'Zambie' WHERE ID= 'ZM' ;
UPDATE enum_country SET country_cs= 'Zimbabwe' WHERE ID= 'ZW' ;
-- DROP TABLE zone CASCADE;
CREATE TABLE zone (
        id SERIAL PRIMARY KEY,
        fqdn VARCHAR(255) UNIQUE NOT NULL,  --zone fully qualified name
        ex_period_min int NOT NULL,  --minimal prolongation of the period of domains validity in months
        ex_period_max int NOT NULL,  --maximal prolongation of the period of domains validity in months
        val_period int NOT NULL,  --enum domains revalidation period in months
        dots_max  int NOT NULL DEFAULT 1,  --maximal number of dots in zone name
        enum_zone BOOLEAN DEFAULT 'f',  --flag if zone is for enum
        warning_letter BOOLEAN NOT NULL DEFAULT TRUE
        );

COMMENT ON TABLE zone IS
'This table contains zone parameters';
COMMENT ON COLUMN zone.id IS 'unique automatically generated identifier';
COMMENT ON COLUMN zone.fqdn IS 'zone fully qualified name';
COMMENT ON COLUMN zone.ex_period_min IS 'minimal prolongation of the period of domains validity in months';
COMMENT ON COLUMN zone.ex_period_max IS 'maximal prolongation of the period of domains validity in months';
COMMENT ON COLUMN zone.val_period IS 'enum domains revalidation period in months';
COMMENT ON COLUMN zone.dots_max IS 'maximal number of dots in zone name';
COMMENT ON COLUMN zone.enum_zone IS 'flag if zone is for enum';

-- DROP TABLE Registrar CASCADE;
CREATE TABLE Registrar (
  ID SERIAL PRIMARY KEY,
  ICO  varchar(50), -- ICO of registrar
  DIC  varchar(50), -- DIC of registrar
  varsymb  char(10)  , -- coupling variable symbol ( ico )
  VAT boolean DEFAULT True, -- whether VAT should be count by invoicing 
  Handle varchar(255) UNIQUE NOT NULL,
  Name varchar(1024),
  Organization varchar(1024),
  Street1 varchar(1024),
  Street2 varchar(1024),
  Street3 varchar(1024),
  City varchar(1024),
  StateOrProvince varchar(1024),
  PostalCode varchar(32),
  Country char(2) REFERENCES enum_country,
  Telephone varchar(32),
  Fax varchar(32),
  Email varchar(1024),
  Url varchar(1024),
  System bool default false,
  Regex varchar(30) default NULL
);

comment on table Registrar is 'Evidence of registrars, who can create or change administered object via register';
comment on column Registrar.ID is 'unique automatically generated identifier';
comment on column Registrar.ICO is 'organization identification number';
comment on column Registrar.DIC is 'tax identification number';
comment on column Registrar.varsymb is 'coupling variable symbol (ico)';
comment on column Registrar.VAT is 'whether VAT should be count in invoicing';
comment on column Registrar.Handle is 'unique text string identifying registrar, it is generated by system admin when new registrar is created';
comment on column Registrar.Name is 'registrats name';
comment on column Registrar.Organization is 'Official company name';
comment on column Registrar.Street1 is 'part of address';
comment on column Registrar.Street2 is 'part of address';
comment on column Registrar.Street3 is 'part of address';
comment on column Registrar.City is 'part of address - city';
comment on column Registrar.StateOrProvince is 'part of address - region';
comment on column Registrar.PostalCode is 'part of address - postal code';
comment on column Registrar.Country is 'code for country from enum_country table';
comment on column Registrar.Telephone is 'phone number';
comment on column Registrar.Fax is 'fax number';
comment on column Registrar.Email is 'e-mail address';
comment on column Registrar.Url is 'registrars web address';

-- DROP TABLE RegistrarACL CASCADE;
CREATE TABLE RegistrarACL (
  ID SERIAL PRIMARY KEY,
  RegistrarID INTEGER NOT NULL REFERENCES Registrar,
  Cert varchar(1024) NOT NULL, -- certificate fingerprint
  Password varchar(64) NOT NULL
);

comment on table RegistrarACL is 'Registrars login information';
comment on column RegistrarACL.Cert is 'certificate fingerprint';
comment on column RegistrarACL.Password is 'login password';

CREATE TABLE RegistrarInvoice (
  ID SERIAL PRIMARY KEY,
  RegistrarID INTEGER NOT NULL REFERENCES Registrar, -- registrar id
  Zone integer NOT NULL REFERENCES Zone,  --  zone for which has registrar an access
  FromDate date NOT NULL , -- date when began registrar work in a zone
  toDate date -- after this date registrar is not allowed to register
);

comment on column RegistrarInvoice.Zone is 'zone for which has registrar an access';
comment on column RegistrarInvoice.FromDate is 'date when began registrar work in a zone';
comment on column RegistrarInvoice.toDate is 'after this date, registrar is not allowed to register';

CREATE TABLE History (
        ID SERIAL PRIMARY KEY,
        valid_from TIMESTAMP NOT NULL DEFAULT NOW(),
        valid_to TIMESTAMP,
        next INTEGER,
        request_id BIGINT
);

COMMENT ON TABLE history IS
'Main evidence table with modified data, it join historic tables modified during same operation
create - in case of any change';
COMMENT ON COLUMN history.id IS 'unique automatically generated identifier';
COMMENT ON COLUMN history.valid_from IS 'date from which was this history created';
COMMENT ON COLUMN history.valid_to IS 'date to which was history actual (NULL if it still is)';
COMMENT ON COLUMN history.next IS 'next history id';

CREATE INDEX history_action_valid_from_idx ON history (valid_from);
CREATE UNIQUE INDEX history_next_idx ON history (next);
CREATE INDEX history_request_id_idx ON history (request_id) WHERE request_id IS NOT NULL;

-- DROP TABLE  OBJECT  CASCADE;


CREATE TABLE OBJECT_registry (
       ID SERIAL PRIMARY KEY,
       ROID varchar(255) UNIQUE NOT NULL , -- unique roid
       type smallint , -- object type 1 contact 2 nsset 3 domain
       NAME varchar(255)  NOT NULL , -- handle or FQDN
       CrID INTEGER NOT NULL REFERENCES Registrar,
       CrDate timestamp NOT NULL DEFAULT now(),
       ErDate timestamp DEFAULT NULL, -- erase date 
       CrhistoryID INTEGER  REFERENCES History, -- link into create history
       historyID integer REFERENCES history -- link to last change in history                 
       );

-- index
CREATE INDEX object_registry_upper_name_1_idx 
 ON object_registry (UPPER(name)) WHERE type=1;
CREATE INDEX object_registry_upper_name_2_idx 
 ON object_registry (UPPER(name)) WHERE type=2;
CREATE INDEX object_registry_name_3_idx 
 ON object_registry  (NAME) WHERE type=3;
CREATE INDEX object_registry_historyid_idx ON object_registry (historyid);

comment on column OBJECT_registry.ID is 'unique automatically generated identifier';
comment on column OBJECT_registry.ROID is 'unique roid';
comment on column OBJECT_registry.type is 'object type (1-contact, 2-nsset, 3-domain)';
comment on column OBJECT_registry.name is 'handle of fqdn';
comment on column OBJECT_registry.CrID is 'link to registrar';
comment on column OBJECT_registry.CrDate is 'object creation date and time';
comment on column OBJECT_registry.ErDate is 'object erase date';
comment on column OBJECT_registry.CrhistoryID is 'link into create history';
comment on column OBJECT_registry.historyID is 'link to last change in history';

-- For updating previous history record (or current in case of deletion of object)
CREATE OR REPLACE FUNCTION object_registry_update_history_rec() RETURNS TRIGGER AS $$
BEGIN
    -- when updation object, set valid_to and next of previous history record
    IF OLD.historyid != NEW.historyid THEN
        UPDATE history
            SET valid_to = NOW(), -- NOW() is the same during the transaction, so this will be the same as valid_from of new history record
                next = NEW.historyid
            WHERE id = OLD.historyid;
    END IF; 
    
    -- when deleting object (setting object_registry.erdate), set valid_to of current history record    
    IF OLD.erdate IS NULL and NEW.erdate IS NOT NULL THEN
        UPDATE history
            SET valid_to = NEW.erdate
            WHERE id = OLD.historyid;
    END IF; 
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

--DROP TRIGGER trigger_object_registry_update_history_rec ON object_registry;
CREATE TRIGGER trigger_object_registry_update_history_rec AFTER UPDATE
    ON object_registry FOR EACH ROW
    EXECUTE PROCEDURE object_registry_update_history_rec();


CREATE TABLE OBJECT (
        ID INTEGER PRIMARY KEY  REFERENCES object_registry (id),
        ClID INTEGER NOT NULL REFERENCES Registrar,
        UpID INTEGER REFERENCES Registrar,
        TrDate timestamp DEFAULT NULL,
        UpDate timestamp DEFAULT NULL,
        AuthInfoPw varchar(300) -- in XML schemas
        );

-- index
CREATE INDEX object_upid_idx ON "object" (upid);
CREATE INDEX object_clid_idx ON "object" (clid);


-- DROP TABLE Contact CASCADE;
CREATE TABLE Contact (
        ID INTEGER PRIMARY KEY REFERENCES object (id),
        Name varchar(1024),
        Organization varchar(1024),
        Street1 varchar(1024),
        Street2 varchar(1024),
        Street3 varchar(1024),
        City varchar(1024),
        StateOrProvince varchar(1024),
        PostalCode varchar(32),
        Country char(2) REFERENCES enum_country,
        Telephone varchar(64),
        Fax varchar(64),
        Email varchar(1024),
        DiscloseName boolean NOT NULL DEFAULT False,
        DiscloseOrganization boolean NOT NULL DEFAULT False,
        DiscloseAddress boolean NOT NULL DEFAULT False,
        DiscloseTelephone boolean NOT NULL DEFAULT False,
        DiscloseFax boolean NOT NULL DEFAULT False,
        DiscloseEmail boolean NOT NULL DEFAULT False,
        NotifyEmail varchar(1024),
        VAT varchar(32),
        SSN varchar(64),
	    SSNtype INTEGER REFERENCES enum_ssntype,
        DiscloseVAT boolean NOT NULL DEFAULT False,
        DiscloseIdent boolean NOT NULL DEFAULT False,
        DiscloseNotifyEmail boolean NOT NULL DEFAULT False
        );

comment on table Contact is 'List of contacts which act in registry as domain owners and administrative contacts for nameservers group';
comment on column Contact.ID is 'references into object table';
comment on column Contact.Name is 'name of contact person';
comment on column Contact.Organization is 'full trade name of organization';
comment on column Contact.Street1 is 'part of address';
comment on column Contact.Street2 is 'part of address';
comment on column Contact.Street3 is 'part of address';
comment on column Contact.City is 'part of address - city';
comment on column Contact.StateOrProvince is 'part of address - region';
comment on column Contact.PostalCode is 'part of address - postal code';
comment on column Contact.Country is 'two character country code (e.g. cz) from enum_country table';
comment on column Contact.Telephone is 'telephone number';
comment on column Contact.Fax is 'fax number';
comment on column Contact.Email is 'email address';
comment on column Contact.DiscloseName is 'whether reveal contact name';
comment on column contact.DiscloseOrganization is 'whether reveal organization';
comment on column Contact.DiscloseAddress is 'whether reveal address';
comment on column Contact.DiscloseTelephone is 'whether reveal phone number';
comment on column Contact.DiscloseFax is 'whether reveal fax number';
comment on column Contact.DiscloseEmail is 'whether reveal email address';
comment on column Contact.NotifyEmail is 'to this email address will be send message in case of any change in domain or nsset affecting contact';
comment on column Contact.VAT is 'tax number';
comment on column Contact.SSN is 'unambiguous identification number (e.g. Social Security number, identity card number, date of birth)';
comment on column Contact.SSNtype is 'type of identification number from enum_ssntype table';
comment on column Contact.DiscloseVAT is 'whether reveal VAT number';
comment on column Contact.DiscloseIdent is 'whether reveal SSN number';
comment on column Contact.DiscloseNotifyEmail is 'whether reveal notify email';



-- DROP TABLE NSSet CASCADE;
CREATE TABLE NSSet (
        ID INTEGER PRIMARY KEY REFERENCES object (id),
        checklevel smallint default 0
        );

-- DROP TABLE nsset_contact_map CASCADE;
CREATE TABLE nsset_contact_map (
        NSSetID INTEGER REFERENCES NSSet ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,
        ContactID INTEGER REFERENCES Contact ON UPDATE CASCADE NOT NULL,
        PRIMARY KEY (NSSetID, ContactID)
        );
CREATE INDEX nsset_contact_map_nssetid_idx ON nsset_contact_map (NSSetID);
CREATE INDEX nsset_contact_map_contactid_idx ON nsset_contact_map (ContactID);


-- DROP TABLE Host CASCADE;
CREATE TABLE Host (
        ID SERIAL PRIMARY KEY,
        NSSetID INTEGER REFERENCES NSSet ON UPDATE CASCADE,
        FQDN VARCHAR(255)   NOT NULL,  -- it cannot be UNIQUE for two different NSSET same dns host 
        UNIQUE (NSSetID, FQDN ) -- unique key
        );


CREATE INDEX host_nsset_idx ON Host (NSSetID);
CREATE INDEX host_fqdn_idx ON Host (FQDN);

comment on table Host is 'Records of relationship between nameserver and ip address';
comment on column Host.id is 'unique automatically generatet identifier';
comment on column Host.NSSetID is 'in which nameserver group belong this record';
comment on column Host.FQDN is 'fully qualified domain name that is in zone file as NS';

-- DROP TABLE  host_ipaddr_map  CASCADE;
CREATE TABLE host_ipaddr_map (
           ID SERIAL PRIMARY KEY,
           HostID  INTEGER NOT NULL REFERENCES HOST ON UPDATE CASCADE ON DELETE CASCADE,
           NSSetID INTEGER NOT NULL REFERENCES NSSET ON UPDATE CASCADE ON DELETE CASCADE, 
           IpAddr INET NOT NULL -- IP address
         );

CREATE INDEX host_ipaddr_map_hostid_idx ON host_ipaddr_map (hostid);
CREATE INDEX host_ipaddr_map_nssetid_idx ON host_ipaddr_map (nssetid);


-- DROP TABLE Domain CASCADE;
CREATE TABLE Domain (
        ID INTEGER PRIMARY KEY REFERENCES object (ID),
        Zone INTEGER REFERENCES Zone (ID),
        Registrant INTEGER NOT NULL REFERENCES Contact,
        NSSet INTEGER NULL REFERENCES NSSet, -- link to nsset can be also NULL, it can register domain without nsset
        Exdate date NOT NULL
        );
CREATE INDEX domain_zone_idx ON Domain (Zone);
CREATE INDEX domain_registrant_idx ON Domain (registrant);
CREATE INDEX domain_nsset_idx ON Domain (nsset);
CREATE INDEX domain_exdate_idx ON domain (exdate);

comment on table Domain is 'Evidence of domains';
comment on column Domain.ID is 'point to object table';
comment on column Domain.Zone is 'zone in which domain belong';
comment on column Domain.Registrant is 'domain owner';
comment on column Domain.NSSet is 'link to nameserver set, can be NULL (when is domain registered withou nsset)';
comment on column Domain.Exdate is 'domain expiry date';

-- DROP TABLE domain_contact_map CASCADE;
CREATE TABLE domain_contact_map (
        DomainID INTEGER REFERENCES Domain ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,
        ContactID INTEGER REFERENCES Contact ON UPDATE CASCADE NOT NULL,
        Role INTEGER NOT NULL DEFAULT 1,
        PRIMARY KEY (DomainID, ContactID)
        );
CREATE INDEX domain_contact_map_domainid_idx ON domain_contact_map (DomainID);
CREATE INDEX domain_contact_map_contactid_idx ON domain_contact_map (ContactID);



-- DROP TABLE DNSSEC CASCADE;
CREATE TABLE DNSSEC (
        DomainID INTEGER PRIMARY KEY REFERENCES Domain ON UPDATE CASCADE ON DELETE CASCADE,
        KeyTag varchar(255) NOT NULL,
        Alg smallint NOT NULL CHECK (Alg >= 0 AND Alg <= 255),
        DigestType smallint NOT NULL,
        Digest character varying (255) NOT NULL,
        MaxSigLive interval NULL,
        KeyFlags BIT(16) CHECK (BIT '1000000010000000' & KeyFlags = KeyFlags),
        KeyProtocol smallint CHECK (KeyProtocol = 3),
        KeyAlg smallint CHECK (KeyAlg >= 0 AND KeyAlg <= 255),
        PubKey character varying(1024)
        );        

-- DROP TABLE ENUMVal CASCADE;
CREATE TABLE ENUMVal (
        DomainID INTEGER NOT NULL PRIMARY KEY REFERENCES Domain ON UPDATE CASCADE ON DELETE CASCADE,
        ExDate date NOT NULL,
        publish BOOLEAN NOT NULL DEFAULT false
        );



CREATE TABLE OBJECT_history (
        historyID INTEGER PRIMARY KEY REFERENCES History, -- link into history
        ID INTEGER  REFERENCES object_registry (id),
        ClID INTEGER NOT NULL REFERENCES Registrar,
        UpID INTEGER REFERENCES Registrar,
        Trdate timestamp,
        UpDate timestamp,
        AuthInfoPw varchar(300)
        );


  
-- DROP TABLE Contact_History CASCADE;
CREATE TABLE Contact_History (
        HISTORYID INTEGER PRIMARY  KEY REFERENCES History,
        ID INTEGER  REFERENCES object_registry (id),
        Name varchar(1024),
        Organization varchar(1024),
        Street1 varchar(1024),
        Street2 varchar(1024),
        Street3 varchar(1024),
        City varchar(1024),
        StateOrProvince varchar(1024),
        PostalCode varchar(32),
        Country char(2) REFERENCES enum_country,
        Telephone varchar(64),
        Fax varchar(64),
        Email varchar(1024),
        DiscloseName boolean NOT NULL DEFAULT False,
        DiscloseOrganization boolean NOT NULL DEFAULT False,
        DiscloseAddress boolean NOT NULL DEFAULT False,
        DiscloseTelephone boolean NOT NULL DEFAULT False,
        DiscloseFax boolean NOT NULL DEFAULT False,
        DiscloseEmail boolean NOT NULL DEFAULT False,
        NotifyEmail varchar(1024),
        VAT varchar(32),
        SSN varchar(64),
        SSNtype integer REFERENCES enum_ssntype,
        DiscloseVAT boolean NOT NULL DEFAULT False,
        DiscloseIdent boolean NOT NULL DEFAULT False,
        DiscloseNotifyEmail boolean NOT NULL DEFAULT False
);

comment on table Contact_History is
'Historic data from contact table.
creation - actual data will be copied here from original table in case of any change in contact table';


-- DROP TABLE Domain_History CASCADE;
CREATE TABLE Domain_History (
        HISTORYID INTEGER PRIMARY KEY REFERENCES History,          
        Zone INTEGER REFERENCES Zone (ID),
        ID INTEGER   REFERENCES object_registry (id),
        ExDate date NOT NULL,
        Registrant INTEGER , -- canceled references
        NSSet INTEGER  -- canceled references
        );
CREATE INDEX domain_History_historyid_idx ON Domain_History (historyID);

comment on table Domain_History is
'Historic data from domain table

creation - in case of any change in domain table, including changes in bindings to other tables';

-- DROP TABLE domain_contact_map_history CASCADE;
CREATE TABLE domain_contact_map_history  (
        historyID INTEGER REFERENCES History,       
        DomainID INTEGER  REFERENCES object_registry (id),
        ContactID INTEGER REFERENCES object_registry (id),
        Role INTEGER NOT NULL DEFAULT 1,
-- TODO         ContactHistoryID INTEGER REFERENCES  History(id) --  Contact in state in which was by the change  
       PRIMARY KEY(historyID,DomainID,ContactID)
        );

comment on table domain_contact_map_history is
'Historic data from domain_contact_map table

creation - all contacts links which are linked to changed domain are copied here';

-- DROP TABLE NSSet_history  CASCADE;
CREATE TABLE NSSet_history  (
        historyID INTEGER PRIMARY KEY REFERENCES History, -- only one nsset 
        ID INTEGER  REFERENCES object_registry (id),
        checklevel smallint default 0 --write up check level
        );
CREATE INDEX nsset_history_historyid_idx ON NSSet_History (historyID);

comment on table NSSet_History is
'Historic data from domain nsset

creation - in case of any change in nsset table, including changes in bindings to other tables';

-- DROP TABLE nsset_contact_map_history  CASCADE;
CREATE TABLE nsset_contact_map_history (
        historyID INTEGER  REFERENCES History,
        NSSetID INTEGER REFERENCES object_registry (id), 
        ContactID INTEGER REFERENCES object_registry (id),
-- TODO   ContactHistoryID 
        PRIMARY KEY (historyID,NSSetID, ContactID)
        );

comment on table nsset_contact_map_history is
'Historic data from nsset_contact_map table

creation - all contact links which are linked to changed nsset are copied here';

-- DROP TABLE Host_history  CASCADE;
CREATE TABLE Host_history  (
        historyID INTEGER  REFERENCES History,  -- it can exist more hosts so that it isn't primary key 
        ID  INTEGER  NOT NULL,
        NSSetID INTEGER REFERENCES object_registry (id), -- REFERENCES NSSet ON UPDATE CASCADE,
        FQDN VARCHAR(255)  NOT NULL,
        PRIMARY KEY(historyID,ID)
        );
-- replaced

comment on table Host_history is
'historic data from host table

creation - all entries from host table which exist for given nsset are copied here when nsset is altering';

CREATE TABLE host_ipaddr_map_history (
	historyID INTEGER  REFERENCES History,
        ID INTEGER NOT NULL,
	HostID  INTEGER NOT NULL,
	NSSetID INTEGER REFERENCES object_registry (id),
	IpAddr INET NOT NULL,
        PRIMARY KEY(historyID,ID)
	);



-- DROP TABLE ENUMVal_history  CASCADE;
CREATE TABLE ENUMVal_history (
        historyID INTEGER PRIMARY KEY REFERENCES History, -- only one nsset 
        DomainID INTEGER REFERENCES object_registry (id),
        ExDate date NOT NULL,
        publish BOOLEAN NOT NULL DEFAULT false
        );

-- table holding data from SOA record for a zone
CREATE TABLE zone_soa (
        Zone INTEGER PRIMARY KEY REFERENCES Zone (ID),  --default period of validity of records in the zone in seconds
        TTL INTEGER NOT NULL,  --default period of validity of records in the zone in seconds
        Hostmaster VARCHAR(255) NOT NULL,  --responsible person email (in format: user@domain.tld )
        Serial INTEGER,  --serial number incremented on change in the form YYYYMMDDnn (year, month, date, revision)
        Refresh INTEGER NOT NULL,  --secondary nameservers copy of zone refresh interval in seconds
        Update_retr INTEGER NOT NULL,  --retry interval of secondary nameservers zone update (in case of failed zone refresh) in seconds
        Expiry INTEGER NOT NULL,  --zone expiration period for secondary nameservers in seconds
        Minimum INTEGER NOT NULL,  --the time a NAME ERROR = NXDOMAIN result may be cached by any resolver in seconds
        ns_fqdn VARCHAR(255) NOT NULL  --primary nameserver fully qualified name
        );

comment on table zone_soa is
'Table holding data from SOA record for a zone';
comment on column zone_soa.zone is 'zone id';
comment on column zone_soa.ttl is 'default period of validity of records in the zone in seconds';
comment on column zone_soa.hostmaster is 'responsible person email (in format: user@domain.tld )';
comment on column zone_soa.serial is 'serial number incremented on change in the form YYYYMMDDnn (year, month, date, revision)';
comment on column zone_soa.refresh is 'secondary nameservers copy of zone refresh interval in seconds';
comment on column zone_soa.update_retr is 'retry interval of secondary nameservers zone update (in case of failed zone refresh) in seconds';
comment on column zone_soa.expiry is 'zone expiration period for secondary nameservers in seconds';
comment on column zone_soa.minimum is 'the time a NAME ERROR = NXDOMAIN result may be cached by any resolver in seconds';
comment on column zone_soa.ns_fqdn is 'primary nameserver fully qualified name';

-- Nameservers for a zone
CREATE TABLE zone_ns (
        id SERIAL PRIMARY KEY,  --unique automatically generated identifier
        Zone INTEGER REFERENCES Zone (ID),  --zone id
        fqdn VARCHAR(255) NOT NULL,  --nameserver fully qualified name
        addrs INET[] NOT NULL  --nameserver ip addresses array
        );

comment on table zone_ns is
'This table contains nameservers for a zone';
comment on column zone_ns.id is 'unique automatically generated identifier';
comment on column zone_ns.zone is 'zone id';
comment on column zone_ns.fqdn is 'nameserver fully qualified name';
comment on column zone_ns.fqdn is 'nameserver ip addresses array';

-- List of status for domain zone generator classification
-- supplement missing enum type in postgresql
CREATE TABLE genzone_domain_status (  --deprecated, unused, prepared for removal
	id integer PRIMARY KEY, -- id of status
	name char(20) NOT NULL -- decriptive name
);

INSERT INTO genzone_domain_status VALUES (1,'is in zone');
INSERT INTO genzone_domain_status VALUES (2,'is deleted');
INSERT INTO genzone_domain_status VALUES (3,'is without nsset');
INSERT INTO genzone_domain_status VALUES (4,'expired');
INSERT INTO genzone_domain_status VALUES (5,'is not validated');

comment on table genzone_domain_status is
'deprecated, unused, prepared for removal
List of status for domain zone generator classification

id - name
 1 - domain is in zone
 2 - domain is deleted
 3 - domain is without nsset
 4 - domain is expired
 5 - domain is not validated';

-- History of generation of domain in zone file
CREATE TABLE genzone_domain_history ( --deprecated, unused, prepared for removal
    -- id of record
    id SERIAL PRIMARY KEY,
    -- domain  
    domain_id INTEGER REFERENCES object_registry (id), 
    -- domain version, actual in time of record creation
    domain_hid INTEGER REFERENCES domain_history (historyid), 
    -- zone identifier of domain
    zone_id INTEGER REFERENCES zone (id),
    -- status of generation
    status INTEGER REFERENCES genzone_domain_status (id), 
    -- shortage for status=1
    inzone boolean NOT NULL,
    -- time of record creation
    chdate timestamp NOT NULL DEFAULT now(), 
    -- flag of actual record
    last boolean NOT NULL DEFAULT True 
);

CREATE INDEX genzone_domain_history_domain_hid_idx 
  ON genzone_domain_history (domain_hid);
CREATE INDEX genzone_domain_history_domain_id_idx 
  ON genzone_domain_history (domain_id);

comment on table genzone_domain_history is
'deprecated, unused, prepared for removal';
CREATE TABLE "user"
(
  id serial NOT NULL, -- primary key
  firstname varchar(20) NOT NULL, -- first name
  surname varchar(40) NOT NULL, -- surname
  CONSTRAINT user_pkey PRIMARY KEY (id)
);

CREATE TABLE domain_blacklist
(
  id serial NOT NULL, -- primary key
  regexp varchar(255) NOT NULL, -- regular expression which is blocked
  valid_from timestamp NOT NULL, -- from when bloc is valid
  valid_to timestamp, -- till when bloc is valid, if it is NULL, it isn't restricted
  reason varchar(255) NOT NULL, -- reason why is domain blocked
  creator int4, -- who created a record, if it is NULL, it's systems record as a part of systems configuration
  CONSTRAINT domain_blacklist_pkey PRIMARY KEY (id),
  CONSTRAINT domain_blacklist_creator_fkey FOREIGN KEY (creator)
      REFERENCES "user" (id) MATCH SIMPLE
      ON UPDATE RESTRICT ON DELETE RESTRICT
);

comment on column domain_blacklist.regexp is 'regular expression which is blocked';
comment on column domain_blacklist.valid_from is 'from when is block valid';
comment on column domain_blacklist.valid_to is 'till when is block valid, if it is NULL, it is not restricted';
comment on column domain_blacklist.reason is 'reason why is domain blocked';
comment on column domain_blacklist.creator is 'who created this record. If it is NULL, it is system record created as a part of system configuration';

CREATE TABLE enum_filetype (
	id smallint PRIMARY KEY,
	name varchar(300)
);

INSERT INTO enum_filetype (id, name) VALUES (1, 'invoice pdf');
INSERT INTO enum_filetype (id, name) VALUES (2, 'invoice xml');
INSERT INTO enum_filetype (id, name) VALUES (3, 'accounting xml');
INSERT INTO enum_filetype (id, name) VALUES (4, 'banking statement');
INSERT INTO enum_filetype (id, name) VALUES (5, 'expiration warning letter');

comment on table enum_filetype is 'list of file types

id - name
 1 - invoice pdf
 2 - invoice xml
 3 - accounting xml
 4 - banking statement
 5 - expiration warning letter';

CREATE TABLE files (
	id SERIAL PRIMARY KEY,
	name varchar(300) NOT NULL,
	path varchar(300) NOT NULL,
	mimetype varchar(100) NOT NULL DEFAULT 'application/octet-stream',
	crdate timestamp NOT NULL DEFAULT now(),
	filesize integer NOT NULL,
	filetype smallint REFERENCES enum_filetype(id)
);

comment on table files is
'table of files';
comment on column files.id is 'unique automatically generated identifier';
comment on column files.name is 'file name';
comment on column files.path is 'path to file';
comment on column files.mimetype is 'file mimetype';
comment on column files.crdate is 'file creation timestamp';
comment on column files.filesize is 'file size';
comment on column files.filetype is 'file type from table enum_filetype';
-- filemanager's file for certification evaluation pdf #3914
INSERT INTO enum_filetype (id, name) VALUES (6, 'certification evaluation pdf');
--list of statuses when sending a general message to a contact';
CREATE TABLE enum_send_status (
    id INTEGER PRIMARY KEY,
    status_name VARCHAR(64) UNIQUE,
    description TEXT
);

comment on table enum_send_status is 'list of statuses when sending a general message to a contact';

INSERT INTO enum_send_status (id, status_name, description) VALUES (1, 'ready', 'Ready for processing/sending');
INSERT INTO enum_send_status (id, status_name, description) VALUES (2, 'waiting_confirmation', 'Waiting for manual confirmation of sending');
INSERT INTO enum_send_status (id, status_name, description) VALUES (3, 'no_processing', 'No automatic processing');
INSERT INTO enum_send_status (id, status_name, description) VALUES (4, 'send_failed', 'Delivery failed');
INSERT INTO enum_send_status (id, status_name, description) VALUES (5, 'sent', 'Successfully sent');
INSERT INTO enum_send_status (id, status_name, description) VALUES (6, 'being_sent', 'In processing, don''t touch');

-- Defaults used in templates which change rarely
-- The default names must be prefixed with 'defaults' namespace when used
--   in template
CREATE TABLE mail_defaults (
	id SERIAL PRIMARY KEY,
	name varchar(300) UNIQUE NOT NULL, -- key of default
	value text NOT NULL                -- value of default
);
INSERT INTO mail_defaults (name, value) VALUES ('company', 'CZ.NIC, z.s.p.o');
INSERT INTO mail_defaults (name, value) VALUES ('street', 'Americka 23');
INSERT INTO mail_defaults (name, value) VALUES ('postalcode', '120 00');
INSERT INTO mail_defaults (name, value) VALUES ('city', 'Praha 2');
INSERT INTO mail_defaults (name, value) VALUES ('tel', '+420 222 745 111');
INSERT INTO mail_defaults (name, value) VALUES ('fax', '+420 222 745 112');
INSERT INTO mail_defaults (name, value) VALUES ('emailsupport', 'podpora@nic.cz');
INSERT INTO mail_defaults (name, value) VALUES ('authinfopage', 'http://www.nic.cz/whois/publicrequest/');
INSERT INTO mail_defaults (name, value) VALUES ('whoispage', 'http://whois.nic.cz');

comment on table mail_defaults is 
'Defaults used in templates which change rarely.
Default names must be prefixed with ''defaults'' namespace when used in template';
comment on column mail_defaults.name is 'key of default';
comment on column mail_defaults.value is 'value of default';

-- mail footer is defined here and not in templates in order to reduce
-- size of templates
CREATE TABLE mail_footer (
	id integer PRIMARY KEY,
	footer text NOT NULL
);
INSERT INTO mail_footer (id, footer) VALUES (1,
'-- 
<?cs var:defaults.company ?>
<?cs var:defaults.street ?>
<?cs var:defaults.postalcode ?> <?cs var:defaults.city ?>
---------------------------------
tel.: <?cs var:defaults.tel ?>
fax : <?cs var:defaults.fax ?>
e-mail : <?cs var:defaults.emailsupport ?>
---------------------------------
');

comment on table mail_footer is 'Mail footer is defided in this table and not in templates in order to reduce templates size';

-- vcard is attached to every email message
--   in future it should be templated as footer is, in order to minimize
--   duplicated information
CREATE TABLE mail_vcard (
	vcard text NOT NULL,
	id SERIAL PRIMARY KEY
);
INSERT INTO mail_vcard (vcard) VALUES
('BEGIN:VCARD
VERSION:2.1
N:podpora CZ. NIC, z.s.p.o.
FN:podpora CZ. NIC, z.s.p.o.
ORG:CZ.NIC, z.s.p.o.
TITLE:zákaznická podpora
TEL;WORK;VOICE:+420 222 745 111
TEL;WORK;FAX:+420 222 745 112
ADR;WORK:;;Americká 23;Praha 2;;120 00;Česká republika
URL;WORK:http://www.nic.cz
EMAIL;PREF;INTERNET:podpora@nic.cz
REV:20070403T143928Z
END:VCARD
');

comment on table mail_vcard is 'vcard is attached to every email message';

-- some header defaults which are likely not a subject to change are specified 
-- in database and used in absence
CREATE TABLE mail_header_defaults (
	id SERIAL PRIMARY KEY,
	h_from varchar(300),           -- 'From:' header
	h_replyto varchar(300),        -- 'Reply-to:' header
	h_errorsto varchar(300),       -- 'Errors-to:' header
	h_organization varchar(300),   -- 'Organization:' header
	h_contentencoding varchar(300),-- 'Content-encoding:' header
	h_messageidserver varchar(300) -- Message id cannot be overriden by
	                               --   client, in db is stored only the
	                               --   part after '@' character
);
INSERT INTO mail_header_defaults
(h_from,
h_replyto,
h_errorsto,
h_organization,
h_contentencoding,
h_messageidserver)
VALUES
('podpora@nic.cz',
'podpora@nic.cz',
'podpora@nic.cz',
'CZ.NIC, z.s.p.o.',
'charset=UTF-8',
'nic.cz');

comment on table mail_header_defaults is
'Some header defaults which are likely not a subject to change are specified in database and used in absence';
comment on column mail_header_defaults.h_from is '''From:'' header';
comment on column mail_header_defaults.h_replyto is '''Reply-to:'' header';
comment on column mail_header_defaults.h_errorsto is '''Errors-to:'' header';
comment on column mail_header_defaults.h_organization is '''Organization:'' header';
comment on column mail_header_defaults.h_contentencoding is '''Content-encoding:'' header';
comment on column mail_header_defaults.h_messageidserver is 'Message id cannot be overriden by client, in db is stored only part after ''@'' character';

-- Here are stored email templates which represent one text attachment of
-- email message
CREATE TABLE mail_templates (
	id integer PRIMARY KEY,
	contenttype varchar(100) NOT NULL, -- subtype of content type text
	template text NOT NULL,            -- clearsilver template
	footer integer REFERENCES mail_footer(id) -- should footer be
	                                          -- concatenated with template?
	);

comment on table mail_templates is 'Here are stored email templates which represent one text attachment of email message';
comment on column mail_templates.contenttype is 'subtype of content type text';
comment on column mail_templates.template is 'clearsilver template';
comment on column mail_templates.footer is 'should footer be concatenated with template?';

-- Type of email gathers templates from which email is composed
CREATE TABLE mail_type (
	id integer PRIMARY KEY,
	name varchar(100) UNIQUE NOT NULL, -- name of type
	subject varchar(550) NOT NULL      -- template of email subject
	);

comment on table mail_type is 'Type of email gathers templates from which email is composed';
comment on column mail_type.name is 'name of type';
comment on column mail_type.subject is 'template of email subject';

-- One type may consists from multiple templates and one template may be
-- part of multiple mailtypes. This is binding table.
CREATE TABLE mail_type_template_map (
	typeid integer references mail_type(id),
	templateid integer references mail_templates(id),
        PRIMARY KEY (  typeid  , templateid  )
	);

-- Here are stored emails which are going to be sent and email which have
-- already been sent (they differ in status value).
CREATE TABLE mail_archive (
	id SERIAL PRIMARY KEY,
	mailtype integer references mail_type(id),-- email type
	crdate timestamp NOT NULL DEFAULT now(),  -- date of insertion in table
	moddate timestamp,    -- date of sending (even if unsuccesfull)
	-- status value has following meanings:
	--    0: The email was successfully sent
	--    1: The email is ready to be sent
	--    x: The email waits for manual confirmation which should change
	--       status value to 0 when the email is desired to be sent.
	--       x represents any value different from 0 and 1 (convention is
	--       number 2).
	status integer,
	message text NOT NULL,
	-- text of email which is assummed to be notification about undelivered
	-- mail.
        attempt smallint NOT NULL DEFAULT 0, -- failed attempts to send email
        -- message to be sent including headers (except date and msgid header),
        -- without non-templated attachments.
	response text
	);

CREATE INDEX mail_archive_status_idx ON mail_archive (status);
CREATE INDEX mail_archive_crdate_idx ON mail_archive (crdate);

comment on table mail_archive is
'Here are stored emails which are going to be sent and email which have
already been sent (they differ in status value).';
comment on column mail_archive.mailtype is 'email type';
comment on column mail_archive.crdate is 'date and time of insertion in table';
comment on column mail_archive.moddate is 'date and time of sending (event unsuccesfull)';
comment on column mail_archive.status is 
'status value has following meanings:
 0 - the email was successfully sent
 1 - the email is ready to be sent
 x - the email wait for manual confirmation which should change status value to 0
     when the email is desired to be sent. x represent any value different from
     0 and 1 (convention is number 2)';
comment on column mail_archive.message is 'text of email which is asssumed to be notificaion about undelivered';
comment on column mail_archive.attempt is 
'failed attempt to send email message to be sent including headers
(except date and msgid header), without non-templated attachments';

-- List of attachment ids bound to email in mail_archive
CREATE TABLE mail_attachments (
	id SERIAL PRIMARY KEY,
	mailid integer references mail_archive(id), -- id of email in archive
	attachid integer references files(id)       -- Attachment id
	);

CREATE INDEX mail_attachments_mailid_idx ON mail_attachments (mailid);

comment on table mail_attachments is 'list of attachment ids bound to email in mail_archive';
comment on column mail_attachments.mailid is 'id of email in archive';
comment on column mail_attachments.attachid is 'attachment id';

-- Handles associated with email in mail_archive
CREATE TABLE mail_handles (
	id SERIAL PRIMARY KEY,
	mailid integer references mail_archive(id),-- id of email in archive
	associd varchar(255)                       -- handle of associated object
	);

comment on table mail_handles is 'handles associated with email in mail_archive';
comment on column mail_handles.mailid is 'id of email in archive';
comment on column mail_handles.associd is 'handle of associated object';

--
-- This script may be called only on just created mail tables, because
-- we assume that sequence numbers are reset to 1 in this script.
--

INSERT INTO mail_type (id, name, subject) VALUES (1, 'sendauthinfo_pif', 'Zaslání autorizační informace / Sending authorization information');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(1, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Zaslání autorizační informace

Vážený zákazníku,

   na základě Vaší žádosti podané prostřednictvím webového formuláře
na stránkách sdružení dne <?cs var:reqdate ?>, které
bylo přiděleno identifikační číslo <?cs var:reqid ?>, Vám zasíláme požadované
heslo, příslušející <?cs if:type == #3 ?>k doméně<?cs elif:type == #1 ?>ke kontaktu s identifikátorem<?cs elif:type == #2 ?>k sadě nameserverů s identifikátorem<?cs elif:type == #4 ?>k sadě klíčů s identifikátorem<?cs /if ?> <?cs var:handle ?>.

   Heslo je: <?cs var:authinfo ?>

   V případě, že jste tuto žádost nepodali, oznamte prosím tuto
skutečnost na adresu <?cs var:defaults.emailsupport ?>.

                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Sending authorization information

Dear customer,

   Based on your request submitted via the web form on the association
pages on <?cs var:reqdate ?>, which received
the identification number <?cs var:reqid ?>, we are sending you the requested
password that belongs to the <?cs if:type == #3 ?>domain name<?cs elif:type == #1 ?>contact with identifier<?cs elif:type == #2 ?>NS set with identifier<?cs elif:type == #4 ?>Keyset with identifier<?cs /if ?> <?cs var:handle ?>.

   The password is: <?cs var:authinfo ?>

   If you did not submit the aforementioned request, please notify us about
this fact at the following address <?cs var:defaults.emailsupport ?>.


                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (1, 1);

INSERT INTO mail_type (id, name, subject) VALUES (2, 'sendauthinfo_epp', 'Zaslání autorizační informace / Sending authorization information');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(2, 'plain', 1,
' English version of the e-mail is entered below the Czech version

Zaslání autorizační informace

Vážený zákazníku,

   na základě Vaší žádosti, podané prostřednictvím registrátora
<?cs var:registrar ?>, Vám zasíláme požadované heslo
příslušející <?cs if:type == #3 ?>k doméně<?cs elif:type == #1 ?>ke kontaktu s identifikátorem<?cs elif:type == #2 ?>k sadě nameserverů s identifikátorem<?cs elif:type == #4 ?>k sadě klíčů s identifikátorem<?cs /if ?> <?cs var:handle ?>.

   Heslo je: <?cs var:authinfo ?>

   Tato zpráva je zaslána pouze na e-mailovou adresu uvedenou u příslušné
osoby v Centrálním registru doménových jmen.

   V případě, že jste tuto žádost nepodali, oznamte prosím tuto
skutečnost na adresu <?cs var:defaults.emailsupport ?>.


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Sending authorization information

Dear customer,

   Based on your request submitted via the registrar <?cs var:registrar ?>,
we are sending the requested password that belongs to
the <?cs if:type == #3 ?>domain name<?cs elif:type == #1 ?>contact with identifier<?cs elif:type == #2 ?>NS set with identifier<?cs elif:type == #4 ?>Keyset with identifier<?cs /if ?> <?cs var:handle ?>.

   The password is: <?cs var:authinfo ?>

   This message is being sent only to the e-mail address that we have on file
for a particular person in the Central Registry of Domain Names.

   If you did not submit the aforementioned request, please notify us about
this fact at the following address <?cs var:defaults.emailsupport ?>.


                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (2, 2);

INSERT INTO mail_type (id, name, subject) VALUES (3, 'expiration_notify', 'Upozornění na nutnost úhrady domény <?cs var:domain ?> / Reminder of the need to settle fees for the domain <?cs var:domain ?>');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(3, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Upozornění na nutnost úhrady domény <?cs var:domain ?>

Vážený zákazníku,

dovolujeme si Vás upozornit, že k <?cs var:checkdate ?> dosud nedošlo k prodloužení
registrace doménového jména <?cs var:domain ?>. Vzhledem k tomu, že doménové
jméno bylo za uplynulé období zaplaceno pouze do <?cs var:exdate ?>, nachází se
nyní v takzvané ochranné lhůtě. V případě, že doménové jméno nebude včas
uhrazeno, budou v souladu s Pravidly registrace doménových jmen nasledovat
tyto kroky:

<?cs var:dnsdate ?> - Znefunkčnění doménového jména (vyřazení z DNS).
<?cs var:exregdate ?> - Definitivní zrušení registrace doménového jména.

V této chvíli evidujeme následující údaje o doméně:

Doménové jméno: <?cs var:domain ?>
Držitel: <?cs var:owner ?>
Registrátor: <?cs var:registrar ?>
<?cs each:item = administrators ?>Administrativní kontakt: <?cs var:item ?>
<?cs /each ?>
Vzhledem k této situaci máte nyní následující možnosti:

1. Kontaktujte prosím svého registrátora a ve spolupráci s ním zajistěte
   prodloužení registrace vašeho doménového jména

2. Nebo si vyberte jiného určeného registrátora a jeho prostřednictvím
   zajistěte prodloužení registrace vašeho doménového jména. Seznam
   registrátorů najdete na stránkách sdružení (Seznam registrátorů)


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Reminder of the need to settle fees for the <?cs var:domain ?> domain name

Dear customer,

We would like to inform you that as of <?cs var:checkdate ?>, the registration
of the domain name <?cs var:domain ?> has not been extended. Concerning
the fact that the fee for the domain name in question has been paid only
for a period ended on <?cs var:exdate ?>, your domain name has now entered
the so-called protective period. Unless a registrar of your choice extends
your registration, the following steps will be adopted in accordance with
the Domain Name Registration Rules:

<?cs var:dnsdate ?> - The domain name will not be accessible (exclusion from DNS).
<?cs var:exregdate ?> - Final cancellation of the domain name registration.

At present, our database includes the following details concerning your domain:

Domain name: <?cs var:domain ?>
Holder: <?cs var:owner ?>
Registrar: <?cs var:registrar ?>
<?cs each:item = administrators ?>Admin contact: <?cs var:item ?>
<?cs /each ?>
To ensure adequate remedy of the existing situation, you can choose
one of the following:

1. Please contact your registrar and make sure that the registration
   of your domain name is duly extended.

2. Or choose another registrar in order to extend the registration of your
   domain name. For a list of registrars, please visit association pages
   (List of Registrars)


                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (3, 3);


INSERT INTO mail_type (id, name, subject) VALUES (4, 'expiration_dns_owner', 'Oznámení o vyřazení domény <?cs var:domain ?> z DNS / Notification about inactivation of the domain <?cs var:domain ?> from DNS');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(4, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Oznámení o vyřazení domény <?cs var:domain?> z DNS

Vážený zákazníku,

dovolujeme si Vás tímto upozornit, že doposud nebyla uhrazena platba
za prodloužení doménového jména <?cs var:domain ?>. Vzhledem k této
skutečnosti a na základě Pravidel registrace doménových jmen,
<?cs var:defaults.company ?> pozastavuje registraci doménového jména a vyřazuje
ji ze zóny <?cs var:zone ?>.

V případě, že do dne <?cs var:exregdate ?> neobdrží <?cs var:defaults.company ?> od vašeho
registrátora platbu za prodloužení platnosti doménového jména, bude
doménové jméno definitivně uvolněno pro použití dalším zájemcem, a to
ke dni <?cs var:exregdate ?>.

Prosíme kontaktujte Vašeho Určeného registrátora <?cs var:registrar ?>
za účelem prodloužení doménového jména.

V případě, že se domníváte, že platba byla provedena, prověřte nejdříve,
zda byla provedena pod spravným variabilním symbolem, na správné číslo
účtu a ve spravné výši a tyto informace svému Určenému registrátorovi
sdělte.

Harmonogram plánovaných akcí:

<?cs var:exregdate ?> - Definitivní zrušení registrace doménového jména.

V této chvíli evidujeme následující údaje o doméně:

Doménové jméno: <?cs var:domain ?>
Držitel: <?cs var:owner ?>
Registrátor: <?cs var:registrar ?>
<?cs each:item = administrators ?>Administrativní kontakt: <?cs var:item ?>
<?cs /each ?>

                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Notification about inactivation of the <?cs var:domain?> domain from DNS

Dear customer,

We would like to notify you that the payment for extension of the domain name
<?cs var:domain ?> has not been received yet. With regard to that fact
and in accordance with Rules for domain names registrations, <?cs var:defaults.company ?>
is suspending the domain name registration and is withdrawing it from the
<?cs var:zone ?> zone.

In case that by <?cs var:exregdate ?>, <?cs var:defaults.company ?> will not receive the payment
for extension of the domain name from your registrar, your domain name will
be definitely released for a use by another applicant on <?cs var:exregdate ?>.

Please, contact your designated registrar <?cs var:registrar ?>
for a purpose of extension of the domain name.

If you believe that the payment was made, please, check first if the payment
was made with the correct variable symbol, to the correct account number, and
with the correct amount, and convey this information to your designated
registrar.

Time-schedule of planned events:

<?cs var:exregdate ?> - Definitive cancellation of the domain name registration.

At this moment, we have the following information about the domain in our
records:

Domain name: <?cs var:domain ?>
Owner: <?cs var:owner ?>
Registrar: <?cs var:registrar ?>
<?cs each:item = administrators ?>Admin contact: <?cs var:item ?>
<?cs /each ?>

                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (4, 4);


INSERT INTO mail_type (id, name, subject) VALUES (5, 'expiration_register_owner', 'Oznámení o zrušení domény <?cs var:domain ?> / Notification about cancellation of the domain <?cs var:domain ?>');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(5, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Oznámení o zrušení domény <?cs var:domain ?>

Vážený zákazníku,

dovolujeme si Vás upozornit, že nebylo provedeno prodloužení registrace
pro doménové jméno <?cs var:domain ?>. Vzhledem k této skutečnosti
a na základě Pravidel registrace doménových jmen, <?cs var:defaults.company ?>
ruší registraci doménového jména.


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Notification about cancellation of the domain <?cs var:domain ?>

Dear customer,

we would like to inform you that the registration extension has not yet been
implemented for the domain name <?cs var:domain ?>. Due to this fact and
based on the Domain Name Registration Rules (Pravidla registrace domenovych
jmen), <?cs var:defaults.company ?> is cancelling the domain name registration.


                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (5, 5);

INSERT INTO mail_type (id, name, subject) VALUES (6, 'expiration_dns_tech', 'Oznámení o vyřazení domény <?cs var:domain ?> z DNS / Notification about withdrawal of the domain <?cs var:domain ?> from DNS');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(6, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Oznámení o vyřazení domény <?cs var:domain ?> z DNS

Vážený technický správce,

vzhledem k tomu, že jste vedený jako technický kontakt u sady nameserverů
<?cs var:nsset ?>, která je přiřazena k doménovému jménu <?cs var:domain ?>,
dovolujeme si Vás upozornit, že toto doménové jméno bylo ke dni
<?cs var:statechangedate ?> vyřazeno z DNS.


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Notification about withdrawal of the domain <?cs var:domain ?> from DNS

Dear technical administrator,

With regard to the fact that you are named the technical contact for the set
<?cs var:nsset ?> of nameservers, which is assigned to the <?cs var:domain ?>
domain name, we would like to notify you that the aforementioned domain name
was withdrawn from DNS as of <?cs var:statechangedate ?>.


                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (6, 6);

INSERT INTO mail_type (id, name, subject) VALUES (7, 'expiration_register_tech', 'Oznámení o zrušení domény <?cs var:domain ?> / Notification about cancellation of the domain <?cs var:domain ?>');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(7, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Oznámení o zrušení domény <?cs var:domain ?>

Vážený technický správce,

vzhledem k tomu, že jste vedený jako technický kontakt u sady nameserverů
<?cs var:nsset ?>, která je přiřazena k doménovému jménu <?cs var:domain ?>,
dovolujeme si Vás upozornit, že toto doménové jméno bylo ke dni
<?cs var:exregdate ?> zrušeno.


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Notification about cancellation of the domain <?cs var:domain ?>

Dear technical administrator,

With regard to the fact that you are named the technical contact for the set
of <?cs var:nsset ?> nameservers, which is assigned to the <?cs var:domain ?>
domain name, we would like to notify you that the aforementioned domain name
was cancelled as of <?cs var:exregdate ?>.


                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (7, 7);

INSERT INTO mail_type (id, name, subject) VALUES (8, 'expiration_validation_before', 'Oznámení vypršení validace enum domény <?cs var:domain ?> / Notification about expiration of the enum domain <?cs var:domain ?> validation');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(8, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Oznámení o blížícím se vypršení validace enum domény.

Vážený zákazníku,

dovolujeme si Vás upozornit, že k <?cs var:checkdate ?> dosud nedošlo k prodloužení
validace doménového jména <?cs var:domain ?>, která je platná do <?cs var:valdate ?>.
V případě, že hodláte obnovit validaci uvedeného doménového jména, kontaktujte
prosím svého registrátora a ve spolupráci s ním zajistěte prodloužení validace
vašeho doménového jména před tímto datem.

V této chvíli evidujeme následující údaje o doméně:

Doménové jméno: <?cs var:domain ?>
Držitel: <?cs var:owner ?>
Registrátor: <?cs var:registrar ?>
<?cs each:item = administrators ?>Administrativní kontakt: <?cs var:item ?>
<?cs /each ?>

                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Notification about approaching expiration of the enum domain validation

Dear customer,

We would like to notify you that as of <?cs var:checkdate ?>, extension of
the <?cs var:domain ?> domain name validation has not been made, yet.
Validation will expire on <?cs var:valdate ?>. If you plan to renew validation
of the aforementioned domain name, please, contact your registrar, and
together execute the extension of validation of your domain name before
this date.

At this moment, we have the following information about the domain in our
records:

Domain name: <?cs var:domain ?>
Owner: <?cs var:owner ?>
Registrar: <?cs var:registrar ?>
<?cs each:item = administrators ?>Admin contact: <?cs var:item ?>
<?cs /each ?>

                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (8, 8);

INSERT INTO mail_type (id, name, subject) VALUES (9, 'expiration_validation', 'Oznámení o vypršení validace enum domény <?cs var:domain ?> / Notification about expiration of the enum domain <?cs var:domain ?> validation');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(9, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Oznámení o vypršení validace enum domény.

Vážený zákazníku,

dovolujeme si Vás upozornit, že k <?cs var:checkdate ?> dosud nedošlo k prodloužení
validace doménového jména <?cs var:domain ?>. Vzhledem k této skutečnosti
a na základě Pravidel registrace doménových jmen, ji <?cs var:defaults.company ?>
vyřazuje ze zóny. Doménové jméno je i nadále registrováno. V případě, že
hodláte obnovit validaci uvedeného doménového jména, kontaktujte prosím svého
registrátora a ve spolupráci s ním zajistěte prodloužení validace vašeho
doménového jména.

V této chvíli evidujeme následující údaje o doméně:

Doménové jméno: <?cs var:domain ?>
Držitel: <?cs var:owner ?>
Registrátor: <?cs var:registrar ?>
<?cs each:item = administrators ?>Administrativní kontakt: <?cs var:item ?>
<?cs /each ?>

                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Notification about expiration of the enum domain validation

Dear customer,

We would like to notify you that as of <?cs var:checkdate ?>, extension of
the <?cs var:domain ?> domain name validation has not been made, yet.
With regard to this fact and in accordance with Rules for domain names
registrations, <?cs var:defaults.company ?> is withdrawing it from the zone. The domain
name continues to be registered. If you plan to renew validation of the
aforementioned domain name, please, contact your registrar, and together
execute the extension of validation of your domain name.

At this moment, we have the following information about the domain in our
records:

Domain name: <?cs var:domain ?>
Owner: <?cs var:owner ?>
Registrar: <?cs var:registrar ?>
<?cs each:item = administrators ?>Admin contact: <?cs var:item ?>
<?cs /each ?>


                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (9, 9);

INSERT INTO mail_type (id, name, subject) VALUES (10, 'notification_create', '<?cs def:typesubst(lang) ?><?cs if:lang == "cs" ?><?cs if:type == #3 ?>domény<?cs elif:type == #1 ?>kontaktu<?cs elif:type == #2 ?>sady nameserverů<?cs elif:type == #4 ?>sady klíčů<?cs /if ?><?cs elif:lang == "en" ?><?cs if:type == #3 ?>Domain<?cs elif:type == #1 ?>Contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>Keyset<?cs /if ?><?cs /if ?><?cs /def ?>Oznámení o registraci <?cs call:typesubst("cs") ?> <?cs var:handle ?> / <?cs call:typesubst("en") ?> <?cs var:handle ?> registration notification');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(10, 'plain', 1,
'<?cs def:typesubst(lang) ?><?cs if:lang == "cs" ?><?cs if:type == #3 ?>domény<?cs elif:type == #1 ?>kontaktu<?cs elif:type == #2 ?>sady nameserverů<?cs elif:type == #4 ?>sady klíčů<?cs /if ?><?cs elif:lang == "en" ?><?cs if:type == #3 ?>Domain<?cs elif:type == #1 ?>Contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>Keyset<?cs /if ?><?cs /if ?><?cs /def ?>
======================================================================
Oznámení o registraci / Registration notification
======================================================================
Registrace <?cs call:typesubst("cs") ?> / <?cs call:typesubst("en") ?> create 
Identifikátor <?cs call:typesubst("cs") ?> / <?cs call:typesubst("en") ?> handle : <?cs var:handle ?>
Číslo žádosti / Ticket :  <?cs var:ticket ?>
Registrátor / Registrar : <?cs var:registrar ?>
======================================================================

Žádost byla úspěšně zpracována, požadovaná registrace byla provedena. 
The request was completed successfully, required registration was done.<?cs if:type == #3 ?>

Při každé změně doporučujeme aktualizovat údaje o doméně, vyhnete se 
tak možným problémům souvisejícím s prodlužováním platnosti či manipulací 
s doménou osobami, které již nejsou oprávněny je provádět.
Update domain data in the registry after any changes to avoid possible 
problems with domain renewal or with domain manipulation done by persons 
who are not authorized anymore.<?cs /if ?>

Detail <?cs call:typesubst("cs") ?> najdete na <?cs var:defaults.whoispage ?>?q=<?cs var:handle ?>
For detail information about <?cs call:typesubst("en") ?> visit <?cs var:defaults.whoispage ?>?q=<?cs var:handle ?>


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (10, 10);

INSERT INTO mail_type (id, name, subject) VALUES (11, 'notification_update', '<?cs def:typesubst(lang) ?><?cs if:lang == "cs" ?><?cs if:type == #3 ?>domény<?cs elif:type == #1 ?>kontaktu<?cs elif:type == #2 ?>sady nameserverů<?cs elif:type == #4 ?>sady klíčů<?cs /if ?><?cs elif:lang == "en" ?><?cs if:type == #3 ?>domain<?cs elif:type == #1 ?>contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>keyset<?cs /if ?><?cs /if ?><?cs /def ?>Oznámení změn <?cs call:typesubst("cs") ?> <?cs var:handle ?>/ Notification of <?cs call:typesubst("en") ?> <?cs var:handle ?> changes');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(11, 'plain', 1,
'<?cs def:typesubst(lang) ?><?cs if:lang == "cs" ?><?cs if:type == #3 ?>domény<?cs elif:type == #1 ?>kontaktu<?cs elif:type == #2 ?>sady nameserverů<?cs elif:type == #4 ?>sady klíčů<?cs /if ?><?cs elif:lang == "en" ?><?cs if:type == #3 ?>Domain<?cs elif:type == #1 ?>Contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>Keyset<?cs /if ?><?cs /if ?><?cs /def ?>

<?cs def:print_value(which, varname) ?><?cs if:which == "old" ?><?cs set:lvarname = varname.old ?><?cs elif:which == "new" ?><?cs set:lvarname = varname.new ?><?cs /if ?><?cs alt:lvarname ?><?cs if:which == "old" ?>hodnota nenastavena / value not set<?cs elif:which == "new" ?>hodnota smazána / value deleted<?cs /if ?><?cs /alt ?><?cs /def ?>
<?cs def:print_value_bool(which, varname, if_true, if_false) ?><?cs if:which == "old" ?><?cs set:lvarname = varname.old ?><?cs elif:which == "new" ?><?cs set:lvarname = varname.new ?><?cs /if ?><?cs if:lvarname == "1" ?><?cs var:if_true ?><?cs elif:lvarname == "0" ?><?cs var:if_false ?><?cs /if ?><?cs /def ?>
<?cs def:print_value_list(which, varname, itemname) ?><?cs set:count = #1 ?><?cs each:item = varname ?><?cs var:itemname ?> <?cs var:count ?>: <?cs call:print_value(which, item) ?><?cs set:count = count + #1 ?>
<?cs /each ?><?cs /def ?>

<?cs def:value_list(which) ?><?cs if:changes.object.authinfo ?>Heslo / Authinfo: <?cs if:which == "old" ?>důvěrný údaj / private value<?cs elif:which == "new" ?>hodnota byla změněna / value was changed<?cs /if ?>
<?cs /if ?><?cs if:type == #1 ?><?cs if:changes.contact.name ?>Jméno / Name: <?cs call:print_value(which, changes.contact.name) ?>
<?cs /if ?><?cs if:changes.contact.org ?>Organizace / Organization: <?cs call:print_value(which, changes.contact.org) ?>
<?cs /if ?><?cs if:changes.contact.address ?>Adresa / Address: <?cs call:print_value(which, changes.contact.address) ?>
<?cs /if ?><?cs if:changes.contact.telephone ?>Telefon / Telephone: <?cs call:print_value(which, changes.contact.telephone) ?>
<?cs /if ?><?cs if:changes.contact.fax ?>Fax / Fax: <?cs call:print_value(which, changes.contact.fax) ?>
<?cs /if ?><?cs if:changes.contact.email ?>Email / Email: <?cs call:print_value(which, changes.contact.email) ?>
<?cs /if ?><?cs if:changes.contact.notify_email ?>Notifikační email / Notify email: <?cs call:print_value(which, changes.contact.notify_email) ?>
<?cs /if ?><?cs if:changes.contact.ident_type ?>Typ identifikace / Identification type: <?cs call:print_value(which, changes.contact.ident_type) ?>
<?cs /if ?><?cs if:changes.contact.ident ?>Identifikační údaj / Identification data: <?cs call:print_value(which, changes.contact.ident) ?>
<?cs /if ?><?cs if:changes.contact.vat ?>DIČ / VAT number: <?cs call:print_value(which, changes.contact.vat) ?>
<?cs /if ?><?cs if:subcount(changes.contact.disclose) > #0 ?>Viditelnost údajů / Data visibility:
<?cs if:changes.contact.disclose.name ?>  Jméno / Name: <?cs call:print_value_bool(which, changes.contact.disclose.name, "veřejné / public", "skryté / hidden") ?>
<?cs /if ?><?cs if:changes.contact.disclose.org ?>  Organizace / Organization: <?cs call:print_value_bool(which, changes.contact.disclose.org, "veřejná / public", "skrytá / hidden") ?>
<?cs /if ?><?cs if:changes.contact.disclose.email ?>  Email / Email: <?cs call:print_value_bool(which, changes.contact.disclose.email, "veřejný / public", "skrytý / hidden") ?>
<?cs /if ?><?cs if:changes.contact.disclose.address ?>  Adresa / Address: <?cs call:print_value_bool(which, changes.contact.disclose.address, "veřejná / public", "skrytá / hidden") ?>
<?cs /if ?><?cs if:changes.contact.disclose.notify_email ?>  Notifikační email / Notify email: <?cs call:print_value_bool(which, changes.contact.disclose.notify_email, "veřejný / public", "skrytý / hidden") ?>
<?cs /if ?><?cs if:changes.contact.disclose.ident ?>  Identifikační údaj / Identification data: <?cs call:print_value_bool(which, changes.contact.disclose.ident, "veřejný / public", "skrytý / hidden") ?>
<?cs /if ?><?cs if:changes.contact.disclose.vat ?>  DIČ / VAT number: <?cs call:print_value_bool(which, changes.contact.disclose.vat, "veřejné / public", "skryté / hidden") ?>
<?cs /if ?><?cs if:changes.contact.disclose.telephone ?>  Telefon / Telephone: <?cs call:print_value_bool(which, changes.contact.disclose.telephone, "veřejný / public", "skrytý / hidden") ?>
<?cs /if ?><?cs if:changes.contact.disclose.fax ?>  Fax / Fax: <?cs call:print_value_bool(which, changes.contact.disclose.fax, "veřejný / public", "skrytý / hidden") ?>
<?cs /if ?><?cs /if ?><?cs elif:type == #2 ?><?cs if:changes.nsset.check_level ?>Úroveň tech. kontrol / Check level: <?cs call:print_value(which, changes.nsset.check_level) ?>
<?cs /if ?><?cs if:changes.nsset.admin_c ?>Technické kontakty / Technical contacts: <?cs call:print_value(which, changes.nsset.admin_c) ?>
<?cs /if ?><?cs if:subcount(changes.nsset.dns) > #0 ?><?cs call:print_value_list(which, changes.nsset.dns, "Jmenný server / Name server") ?>
<?cs /if ?><?cs elif:type == #3 ?><?cs if:changes.domain.registrant ?>Držitel / Holder: <?cs call:print_value(which, changes.domain.registrant) ?>
<?cs /if ?><?cs if:changes.domain.nsset ?>Sada jmenných serverů / Name server set: <?cs call:print_value(which, changes.domain.nsset) ?>
<?cs /if ?><?cs if:changes.domain.keyset ?>Sada klíčů / Key set: <?cs call:print_value(which, changes.domain.keyset) ?>
<?cs /if ?><?cs if:changes.domain.admin_c ?>Administrativní  kontakty / Administrative contacts: <?cs call:print_value(which, changes.domain.admin_c) ?>
<?cs /if ?><?cs if:changes.domain.temp_c ?>Dočasné kontakty / Temporary contacts: <?cs call:print_value(which, changes.domain.temp_c) ?>
<?cs /if ?><?cs if:changes.domain.val_ex_date ?>Validováno do / Validation expiration date: <?cs call:print_value(which, changes.domain.val_ex_date) ?>
<?cs /if ?><?cs if:changes.domain.publish ?>Přidat do ENUM tel.sezn. / Include into ENUM dict: <?cs call:print_value_bool(which, changes.domain.publish, "ano / yes", "ne / no") ?>
<?cs /if ?><?cs elif:type == #4 ?><?cs if:changes.keyset.admin_c ?>Technické kontakty / Technical contacts: <?cs call:print_value(which, changes.keyset.admin_c) ?>
<?cs /if ?><?cs if:subcount(changes.keyset.ds) > #0 ?><?cs call:print_value_list(which, changes.keyset.ds, "DS záznam / DS record") ?>
<?cs /if ?><?cs if:subcount(changes.keyset.dnskey) > #0 ?><?cs call:print_value_list(which, changes.keyset.dnskey, "DNS klíče / DNS keys") ?>
<?cs /if ?><?cs /if ?><?cs /def ?>
=====================================================================
Oznámení změn / Notification of changes 
=====================================================================
Změna údajů <?cs call:typesubst("cs") ?> / <?cs call:typesubst("en") ?> data change 
Identifikátor <?cs call:typesubst("cs") ?> / <?cs call:typesubst("en") ?> handle : <?cs var:handle ?>
Číslo žádosti / Ticket :  <?cs var:ticket ?>
Registrátor / Registrar : <?cs var:registrar ?>
=====================================================================
 
Žádost byla úspěšně zpracována, <?cs if:changes == #1 ?>požadované změny byly provedeny<?cs else ?>žádná změna nebyla požadována, údaje zůstaly beze změny<?cs /if ?>.
The request was completed successfully, <?cs if:changes == #1 ?>required changes were done<?cs else ?>no changes were found in the request.<?cs /if ?>

<?cs if:changes == #1 ?>
Původní hodnoty / Original values:
=====================================================================
<?cs call:value_list("old") ?>


Nové hodnoty / New values:
=====================================================================
<?cs call:value_list("new") ?>

Ostatní hodnoty zůstaly beze změny. 
Other data wasn''t modified.
<?cs /if ?>


Úplný detail <?cs call:typesubst("cs") ?> najdete na <?cs var:defaults.whoispage ?>?q=<?cs var:handle ?>
For full detail information about <?cs call:typesubst("en") ?> visit <?cs var:defaults.whoispage ?>?q=<?cs var:handle ?>


<?cs if:type == #1 ?>
Chcete mít snadnější přístup ke správě Vašich údajů? Založte si mojeID. Kromě 
nástroje, kterým můžete snadno a bezpečně spravovat údaje v centrálním 
registru, získáte také prostředek pro jednoduché přihlašování k Vašim 
oblíbeným webovým službám jediným jménem a heslem.
<?cs /if ?>

                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (11, 11);

INSERT INTO mail_type (id, name, subject) VALUES (12, 'notification_transfer', '<?cs def:typesubst(lang) ?><?cs if:lang == "cs" ?><?cs if:type == #3 ?>domény<?cs elif:type == #1 ?>kontaktu<?cs elif:type == #2 ?>sady nameserverů<?cs elif:type == #4 ?>sady klíčů<?cs /if ?><?cs elif:lang == "en" ?><?cs if:type == #3 ?>Domain<?cs elif:type == #1 ?>Contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>Keyset<?cs /if ?><?cs /if ?><?cs /def ?>Oznámení o transferu <?cs call:typesubst("cs") ?> <?cs var:handle ?> / <?cs call:typesubst("en") ?> <?cs var:handle ?> transfer notification');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(12, 'plain', 1,
'<?cs def:typesubst(lang) ?><?cs if:lang == "cs" ?><?cs if:type == #3 ?>domény<?cs elif:type == #1 ?>kontaktu<?cs elif:type == #2 ?>sady nameserverů<?cs elif:type == #4 ?>sady klíčů<?cs /if ?><?cs elif:lang == "en" ?><?cs if:type == #3 ?>Domain<?cs elif:type == #1 ?>Contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>Keyset<?cs /if ?><?cs /if ?><?cs /def ?>
=====================================================================
Oznámení o transferu / Transfer notification
=====================================================================
Transfer <?cs call:typesubst("cs") ?> / <?cs call:typesubst("en") ?> transfer
Identifikátor <?cs call:typesubst("cs") ?> / <?cs call:typesubst("en") ?> handle : <?cs var:handle ?>
Číslo žádosti / Ticket :  <?cs var:ticket ?>
Registrátor / Registrar : <?cs var:registrar ?>
=====================================================================
 
Žádost byla úspěšně zpracována, transfer byl proveden. 
The request was completed successfully, transfer was completed. 

Detail <?cs call:typesubst("cs") ?> najdete na <?cs var:defaults.whoispage ?>?q=<?cs var:handle ?>
For detail information about <?cs call:typesubst("en") ?> visit <?cs var:defaults.whoispage ?>?q=<?cs var:handle ?>


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (12, 12);

INSERT INTO mail_type (id, name, subject) VALUES (13, 'notification_renew', 'Oznámení o prodloužení platnosti domény <?cs var:handle ?> / Domain name <?cs var:handle ?> renew notification');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(13, 'plain', 1,
'
=====================================================================
Oznámení o prodloužení platnosti / Notification about renewal
===================================================================== 
Obnovení domény / Domain renew
Domény / Domain : <?cs var:handle ?>
Číslo žádosti / Ticket :  <?cs var:ticket ?>
Registrátor / Registrar : <?cs var:registrar ?>
=====================================================================

Žádost byla úspěšně zpracována, prodloužení platnosti bylo provedeno. 
The request was completed successfully, domain was renewed. 

Při každé změně doporučujeme aktualizovat údaje o doméně, vyhnete se 
tak možným problémům souvisejícím s prodlužováním platnosti či manipulací 
s doménou osobami, které již nejsou oprávněny je provádět.
Update domain data in the registry after any changes to avoid possible 
problems with domain renewal or with domain manipulation done by persons 
who are not authorized anymore.

Detail domény najdete na <?cs var:defaults.whoispage ?>?q=<?cs var:handle ?>
For detail information about domain visit <?cs var:defaults.whoispage ?>?q=<?cs var:handle ?>


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (13, 13);

INSERT INTO mail_type (id, name, subject) VALUES (14, 'notification_unused', '<?cs def:typesubst(lang) ?><?cs if:lang == "cs" ?><?cs if:type == #3 ?>domény<?cs elif:type == #1 ?>kontaktu<?cs elif:type == #2 ?>sady nameserverů<?cs elif:type == #4 ?>sady klíčů<?cs /if ?><?cs elif:lang == "en" ?><?cs if:type == #3 ?>Domain<?cs elif:type == #1 ?>Contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>Keyset<?cs /if ?><?cs /if ?><?cs /def ?>Oznámení o zrušení <?cs call:typesubst("cs") ?> <?cs var:handle ?> / <?cs call:typesubst("en") ?> <?cs var:handle ?> delete notification');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(14, 'plain', 1,
'
=====================================================================
Oznámení o zrušení / Delete notification 
=====================================================================
Vzhledem ke skutečnosti, že <?cs if:type == #1 ?>kontaktní osoba<?cs elif:type == #2 ?>sada nameserverů<?cs elif:type == #4 ?>sada klíčů<?cs /if ?> <?cs var:handle ?> 
nebyla po stanovenou dobu používána, <?cs var:defaults.company ?> 
ruší ke dni <?cs var:deldate ?> uvedenou <?cs if:type == #1 ?>kontaktní osobu<?cs elif:type == #2 ?>sadu nameserverů<?cs elif:type == #4 ?>sadu klíčů<?cs /if ?>.

Zrušení <?cs if:type == #1 ?>kontaktní osoby<?cs elif:type == #2 ?>sady nameserverů<?cs elif:type == #4 ?>sady klíčů<?cs /if ?> nemá žádný vliv na funkčnost Vašich 
zaregistrovaných doménových jmen.

With regard to the fact that the <?cs if:type == #1 ?>contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>keyset<?cs /if ?> <?cs var:handle ?>
was not used during the fixed period, <?cs var:defaults.company ?>
is cancelling the aforementioned <?cs if:type == #1 ?>contact<?cs elif:type == #2 ?>set of nameservers<?cs elif:type == #4 ?>set of keysets<?cs /if ?> as of <?cs var:deldate ?>.

Cancellation of <?cs if:type == #1 ?>contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>Keyset<?cs /if ?> has no influence on functionality of your
registred domains.
=====================================================================


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (14, 14);

INSERT INTO mail_type (id, name, subject) VALUES (15, 'notification_delete', '<?cs def:typesubst(lang) ?><?cs if:lang == "cs" ?><?cs if:type == #3 ?>domény<?cs elif:type == #1 ?>kontaktu<?cs elif:type == #2 ?>sady nameserverů<?cs elif:type == #4 ?>sady klíčů<?cs /if ?><?cs elif:lang == "en" ?><?cs if:type == #3 ?>Domain<?cs elif:type == #1 ?>Contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>Keyset<?cs /if ?><?cs /if ?><?cs /def ?>Oznámení o zrušení <?cs call:typesubst("cs") ?> <?cs var:handle ?> / <?cs call:typesubst("en") ?> <?cs var:handle ?> delete notification');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(15, 'plain', 1,
'<?cs def:typesubst(lang) ?><?cs if:lang == "cs" ?><?cs if:type == #3 ?>domény<?cs elif:type == #1 ?>kontaktu<?cs elif:type == #2 ?>sady nameserverů<?cs elif:type == #4 ?>sady klíčů<?cs /if ?><?cs elif:lang == "en" ?><?cs if:type == #3 ?>Domain<?cs elif:type == #1 ?>Contact<?cs elif:type == #2 ?>NS set<?cs elif:type == #4 ?>Keyset<?cs /if ?><?cs /if ?><?cs /def ?>
=====================================================================
Oznámení o zrušení / Delete notification 
=====================================================================
Zrušení <?cs call:typesubst("cs") ?> / <?cs call:typesubst("en") ?> deletion
Identifikator <?cs call:typesubst("cs") ?> / <?cs call:typesubst("en") ?> handle : <?cs var:handle ?>
Cislo zadosti / Ticket :  <?cs var:ticket ?>
Registrator / Registrar : <?cs var:registrar ?>
=====================================================================
 
Žádost byla úspěšně zpracována, požadované zrušení bylo provedeno. 
The request was completed successfully, required delete was done. 
 
=====================================================================


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (15, 15);

INSERT INTO mail_type (id, name, subject) VALUES (16, 'techcheck', 'Výsledek technického testu / Technical check result');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(16, 'plain', 1,
'
Výsledek technické kontroly sady nameserverů <?cs var:handle ?>
Result of technical check on NS set <?cs var:handle ?>

Datum kontroly / Date of the check: <?cs var:checkdate ?>
Typ kontroly / Control type : periodická / periodic 
Číslo kontroly / Ticket: <?cs var:ticket ?>

<?cs def:printtest(par_test) ?><?cs if:par_test.name == "existence" ?>Následující nameservery v sadě nameserverů nejsou dosažitelné:
Following nameservers in NS set are not reachable:
<?cs each:ns = par_test.ns ?>    <?cs var:ns ?>
<?cs /each ?><?cs /if ?><?cs if:par_test.name == "autonomous" ?>Sada nameserverů neobsahuje minimálně dva nameservery v různých
autonomních systémech.
In NS set are no two nameservers in different autonomous systems.

<?cs /if ?><?cs if:par_test.name == "presence" ?><?cs each:ns = par_test.ns ?>Nameserver <?cs var:ns ?> neobsahuje záznam pro domény:
Nameserver <?cs var:ns ?> does not contain record for domains:
<?cs each:fqdn = ns.fqdn ?>    <?cs var:fqdn ?>
<?cs /each ?><?cs if:ns.overfull ?>    ...
<?cs /if ?><?cs /each ?><?cs /if ?><?cs if:par_test.name == "authoritative" ?><?cs each:ns = par_test.ns ?>Nameserver <?cs var:ns ?> není autoritativní pro domény:
Nameserver <?cs var:ns ?> is not authoritative for domains:
<?cs each:fqdn = ns.fqdn ?>    <?cs var:fqdn ?>
<?cs /each ?><?cs if:ns.overfull ?>    ...
<?cs /if ?><?cs /each ?><?cs /if ?><?cs if:par_test.name == "heterogenous" ?>Všechny nameservery v sadě nameserverů používají stejnou implementaci
DNS serveru.
All nameservers in NS set use the same implementation of DNS server.

<?cs /if ?><?cs if:par_test.name == "notrecursive" ?>Následující nameservery v sadě nameserverů jsou rekurzivní:
Following nameservers in NS set are recursive:
<?cs each:ns = par_test.ns ?>    <?cs var:ns ?>
<?cs /each ?><?cs /if ?><?cs if:par_test.name == "notrecursive4all" ?>Následující nameservery v sadě nameserverů zodpověděly rekurzivně dotaz:
Following nameservers in NS set answered recursively a query:
<?cs each:ns = par_test.ns ?>    <?cs var:ns ?>
<?cs /each ?><?cs /if ?><?cs if:par_test.name == "dnsseckeychase" ?>Pro následující domény přislušející sadě nameserverů nebylo možno
ověřit validitu DNSSEC podpisu:
For following domains belonging to NS set was unable to validate
DNSSEC signature:
<?cs each:domain = par_test.ns ?>    <?cs var:domain ?>
<?cs /each ?><?cs /if ?><?cs /def ?>
=== Chyby / Errors ==================================================

<?cs each:item = tests ?><?cs if:item.type == "error" ?><?cs call:printtest(item) ?><?cs /if ?><?cs /each ?>
=== Varování / Warnings =============================================

<?cs each:item = tests ?><?cs if:item.type == "warning" ?><?cs call:printtest(item) ?><?cs /if ?><?cs /each ?>
=== Upozornění / Notice =============================================

<?cs each:item = tests ?><?cs if:item.type == "notice" ?><?cs call:printtest(item) ?><?cs /if ?><?cs /each ?>
=====================================================================


                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (16, 16);

INSERT INTO mail_type (id, name, subject) VALUES (17, 'invoice_deposit', 'Přijatá záloha / Accepted advance payment');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(17, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Zaslání potvrzení o přijaté záloze

Vážený obchodní přátelé,

  v příloze zasíláme daňový doklad na přijatou zálohu pro zónu <?cs var:zone ?>. Tento daňový doklad 
slouží k uplatnění nároku na odpočet DPH přijaté zálohy

                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Accepted Advance Payment Confirmation

Dear business partners,

  Enclosed with this letter, we are sending a tax document for the advance
payment accepted for the zone <?cs var:zone ?>. This tax document can be used to claim VAT deduction for
the advance payment.

                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (17, 17);

INSERT INTO mail_type (id, name, subject) VALUES (18, 'invoice_audit', 'Měsíční vyúčtování / Monthly billing');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(18, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Zaslání měsíčního vyúčtování

Vážený obchodní přátelé,

  v příloze zasíláme daňový doklad za služby registrací doménových jmen a 
udržování záznamů o doménových jménech za období od <?cs var:fromdate ?>
do <?cs var:todate ?> pro zónu <?cs var:zone ?>.

                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Monthly Bill Dispatching

Dear business partners,

  Enclosed with this letter, we are sending a tax document for the domain name
registration services and the maintenance of domain name records for the period
from <?cs var:fromdate ?> to <?cs var:todate ?> for the zone <?cs var:zone ?>.

                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (18, 18);

INSERT INTO mail_type (id, name, subject) VALUES (19, 'invoice_noaudit', 'Měsíční vyúčtování / Monthly billing');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(19, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Zaslání měsíčního vyúčtování

Vážený obchodní přátelé,

  jelikož v období od <?cs var:fromdate ?> do <?cs var:todate ?> v zóně <?cs var:zone ?> Vaše společnost neprovedla
žádnou registraci doménového jména ani prodloužení platnosti doménového
jména a nedošlo tak k čerpání žádných placených služeb, nebude pro toto
období vystaven daňový doklad.

                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>



Monthly Bill Dispatching

Dear business partners,

  Since your company has not performed any domain name registration or domain
name validity extension in the period from <?cs var:fromdate ?> to <?cs var:todate ?> for the zone <?cs var:zone ?>,
hence not drawing any paid services, no tax document will be issued for this
period.

                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (19, 19);

INSERT INTO mail_type (id, name, subject) VALUES (20, 'request_block', 'Informace o vyřízení žádosti / Information about processing of request ');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(20, 'plain', 1,
'English version of the e-mail is entered below the Czech version

Informace o vyřízení žádosti

Vážený zákazníku,

   na základě Vaší žádosti podané prostřednictvím webového formuláře
na stránkách sdružení dne <?cs var:reqdate ?>, které bylo přiděleno identifikační 
číslo <?cs var:reqid ?>, Vám oznamujeme, že požadovaná žádost o <?cs if:otype == #1 ?>zablokování<?cs elif:otype == #2 ?>odblokování<?cs /if ?>
<?cs if:rtype == #1 ?>změny dat<?cs elif:rtype == #2 ?>transferu k jinému registrátorovi<?cs /if ?> pro <?cs if:type == #3 ?>doménu<?cs elif:type == #1 ?>kontakt s identifikátorem<?cs elif:type == #2 ?>sadu nameserverů s identifikátorem<?cs elif:type == #4 ?>sadu klíčů s identifikátorem<?cs /if ?> <?cs var:handle ?> 
byla úspěšně realizována.  
<?cs if:otype == #1 ?>
U <?cs if:type == #3 ?>domény<?cs elif:type == #1 ?>kontaktu s identifikátorem<?cs elif:type == #2 ?>sady nameserverů s identifikátorem<?cs elif:type == #4 ?>sady klíčů s identifikátorem<?cs /if ?> <?cs var:handle ?> nebude možné provést 
<?cs if:rtype == #1 ?>změnu dat<?cs elif:rtype == #2 ?>transfer k jinému registrátorovi <?cs /if ?> až do okamžiku, kdy tuto blokaci 
zrušíte pomocí příslušného formuláře na stránkách sdružení.
<?cs /if?>
                                             S pozdravem
                                             podpora <?cs var:defaults.company ?>

Information about processing of request

Dear customer,

   based on your request submitted via the web form on the association
pages on <?cs var:reqdate ?>, which received the identification number 
<?cs var:reqid ?>, we are announcing that your request for <?cs if:otype == #1 ?>blocking<?cs elif:otype == #2 ?>unblocking<?cs /if ?>
<?cs if:rtype == #1 ?>data changes<?cs elif:rtype == #2 ?>transfer to other registrar<?cs /if ?> for <?cs if:type == #3 ?>domain name<?cs elif:type == #1 ?>contact with identifier<?cs elif:type == #2 ?>NS set with identifier<?cs elif:type == #4 ?>Keyset with identifier<?cs /if ?> <?cs var:handle ?> 
has been realized.
<?cs if:otype == #1 ?>
No <?cs if:rtype == #1 ?>data changes<?cs elif:rtype == #2 ?>transfer to other registrar<?cs /if ?> of <?cs if:type == #3 ?>domain name<?cs elif:type == #1 ?>contact with identifier<?cs elif:type == #2 ?>NS set with identifier<?cs elif:type == #4 ?>Keyset with identifier<?cs /if ?> <?cs var:handle ?> 
will be possible until you cancel the blocking option using the 
applicable form on association pages. 
<?cs /if?>
                                             Yours sincerely
                                             support <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (20, 20);
-- classifier of error messages reason
-- DROP TABLE enum_bank_code  CASCADE;
CREATE TABLE enum_bank_code (
      code char(4) PRIMARY KEY,
      name_short varchar(4) UNIQUE NOT NULL , -- short cut 
      name_full varchar(64) UNIQUE  NOT NULL -- full name
);

comment on table enum_bank_code is 'list of bank codes';
comment on column enum_bank_code.code is 'bank code';
comment on column enum_bank_code.name_short is 'bank name abbrevation';
comment on column enum_bank_code.name_full is 'full bank name';

INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'ABN AMRO BANK N.V.' , 'AMRO'  , '5400' );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'HVB CZECH REPUBLIC, A. S.' , 'HVB' ,'2700' );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'BNP-DRESDNER BANK (ČR) A.S.' , 'BNP' , '4000' ); 
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'CITIBANK A.S.' , 'CITI' ,	'2600' );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'COMMERZBANK AG' , 'COMM'	, '6200'  );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'ČESKÁ SPOŘITELNA A.S.' , 'CS' ,	'0800'  );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'ČESKOMOR. HYPOTÉČNÍ BANKA A.S.' ,  'CMHB' 	,'2100');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'ČESKOMORAVSKÁ STAVEBNÍ SPOŘITELNA' , 'CMSS' 	,'7960');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'ČESKOSLOVENSKÁ OBCHODNÍ BANKA A.S.' , 'CSOB' 	,'0300' );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'DEUTSCHE BANK A.G.', 'DB'  ,	'7910');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'EBANKA', 'EB' , '2400' );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'GE CAPITAL BANK, A. S.' , 'GE' , '0600');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'HYPO STAVEBNÍ SPOŘITELNA' , 'HYPO' ,	'8070');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'IC BANKA A.S.'  , 'IC' , '6100');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'ING BANK N. V.' , 'ING' ,	'3500');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'INTERBANKA A.S.'  , 'INTB' ,  '2500' ); 
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'J & T BANKA, A. S.' , 'J&T' , 	'5800');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'KOMERČNÍ BANKA A.S.' , 'KB' ,	'0100');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'KONSOLIDAČNÍ BANKA PRAHA' ,  'KONS'	,'3300');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'PLZEŇSKÁ BANKA A.S.' , 'PILS' 	, '4600');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'PPF BANKA A.S.' , 'PPF' 	,'6000');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'RAIFFEISEN STAVEBNÍ SPOŘITELNA, A. S.' , 'RFSS', 	'7950');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'RAIFFEISENBANK A.S.' , 'RF' ,	 '5500' );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'STAVEBNÍ SPOŘITELNA ČESKÉ SPOŘITELNY, A. S.'  , 'SSCS', 	'8060' );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'UNION BANKA A.S.' , 'UB' ,	'3400' );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'VOLKSBANK CZ, A. S.' , 'VB' 	,'6800');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'VŠEOB.ÚVĚR.BANKA POB. PRAHA' , 'VUB'	,'6700');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'VŠEOBECNÁ STAV.SPOŘITELNA' , 'VSS' ,	'7990' );
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'WUSTENROT STAVEBNÍ SPOŘITELNA' , 'WS'  , 	'7970');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'ŽIVNOSTENSKÁ BANKA A.S.' , 'ZB' , 	'0400');
INSERT INTO  enum_bank_code (name_full,name_short,code) VALUES ( 'Fio, družstevní záložna', 'FIOZ', '2010');

-- classifier of priced operation ( only 2 for domains so far )
-- DROP TABLE enum_operation CASCADE;
CREATE TABLE enum_operation (
        id SERIAL PRIMARY KEY,         
        operation varchar(64) UNIQUE NOT NULL
        );

INSERT INTO enum_operation  VALUES( 1 , 'CreateDomain'); -- registration fee
INSERT INTO enum_operation  VALUES( 2 , 'RenewDomain'); -- maintainance fee
--number 3 is request fee in request_fee_dml.sql
INSERT INTO enum_operation (id, operation) VALUES (4, 'Fine'); -- annual registry contractual fine
INSERT INTO enum_operation (id, operation) VALUES (5, 'Fee'); -- annual registry contractual fee

select setval('enum_operation_id_seq', 2);

comment on table enum_operation is 'list of priced operation';
comment on column enum_operation.id is 'unique automatically generated identifier';
comment on column enum_operation.operation is 'operation';

-- tabel of VAT validity (in case that VAT is changing in the future) 
-- saving of coefficient for VAT recount

CREATE TABLE price_vat
(
  id serial PRIMARY KEY, -- primary key
  valid_to timestamp default NULL, -- date when VAT change is realized
  koef numeric, -- coefficient high for VAT recount
  VAT numeric default 19 -- VAT high
);

INSERT INTO price_vat   VALUES ( 1 , '2004-04-30 22:00:00' , 0.1803 ,  22 ); -- to be in UTC CEST +2:00
INSERT INTO price_vat  VALUES ( 2 , '2009-12-31 23:00:00' , 0.1597 , 19 );
INSERT INTO price_vat  VALUES ( 3 , NULL , 0.1667 , 20 );

select setval('price_vat_id_seq', 3);

comment on table price_vat is 'Table of VAT validity (in case that VAT is changing in the future. Stores coefficient for VAT recount)';
comment on column price_vat.id is 'unique automatically generated identifier';
comment on column price_vat.valid_to is 'date of VAT change realization';
comment on column price_vat.koef is 'coefficient high for VAT recount';
comment on column price_vat.VAT is 'VAT high';
     
-- operation price list 
CREATE TABLE price_list
(
  id serial PRIMARY KEY, -- primary key
  zone_id integer not null  REFERENCES  zone , -- link to zone, for which is price list valid if it is domain (if it isn't domain then it is NULL)
  operation_id integer NOT NULL REFERENCES  enum_operation, -- for which action is a price connected  
  valid_from timestamp NOT NULL, -- from when is record valid 
  valid_to timestamp default NULL, -- till when is record valid, if it is NULL, it isn't limited
  price numeric(10,2) NOT NULL default 0, -- cost of operation ( for year 12 months )
  quantity integer default 12, -- if it isn't periodic operation NULL 
  enable_postpaid_operation boolean DEFAULT 'false'
);

comment on table price_list is 'list of operation prices';
comment on column price_list.id is 'unique automatically generated identifier';
comment on column price_list.zone_id is 'link to zone, for which is price list valid if it is domain (if it is not domain then it is NULL)';
comment on column price_list.operation_id is 'for which action is price connected';
comment on column price_list.valid_from is 'from when is record valid';
comment on column price_list.valid_to is 'till when is record valid, if it is NULL then valid is unlimited';
comment on column price_list.price is 'cost of operation (for one year-12 months)';
comment on column price_list.quantity is 'quantity of operation or period (in months) of payment, null if it is not periodic';
comment on column price_list.enable_postpaid_operation is 'true if operation of this specific type can be executed when credit is not sufficient and create debt';

CREATE TABLE registrar_credit
(
    id BIGSERIAL PRIMARY KEY
    , credit numeric(30,2) NOT NULL DEFAULT 0
    , registrar_id bigint NOT NULL REFERENCES registrar(id)
    , zone_id bigint NOT NULL REFERENCES zone(id),
    CONSTRAINT registrar_credit_unique_key UNIQUE (registrar_id, zone_id)
);

COMMENT ON TABLE registrar_credit 
	IS 'current credit by registrar and zone';

CREATE TABLE registrar_credit_transaction
(
    id bigserial PRIMARY KEY
    , balance_change numeric(10,2) NOT NULL
    , registrar_credit_id bigint NOT NULL REFERENCES registrar_credit(id)
);

COMMENT ON TABLE registrar_credit_transaction 
	IS 'balance changes';

-- locked registrar and zone credit account insert, disabled update and delete
CREATE OR REPLACE FUNCTION registrar_credit_change_lock()
RETURNS "trigger" AS $$
DECLARE
    registrar_credit_result RECORD;
BEGIN
    IF TG_OP = 'INSERT' THEN
        SELECT id, credit FROM registrar_credit INTO registrar_credit_result
            WHERE id = NEW.registrar_credit_id FOR UPDATE;
        IF FOUND THEN
            UPDATE registrar_credit 
                SET credit = credit + NEW.balance_change
                WHERE id = registrar_credit_result.id;
        ELSE
            RAISE EXCEPTION 'Invalid registrar_credit_id';
        END IF;
    ELSE
        RAISE EXCEPTION 'Unallowed operation to registrar_credit_transaction';
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION registrar_credit_change_lock()
	IS 'check and lock insert into registrar_credit_transaction disable update and delete'; 

CREATE TRIGGER "trigger_registrar_credit_transaction"
  AFTER INSERT OR UPDATE OR DELETE ON registrar_credit_transaction
  FOR EACH ROW EXECUTE PROCEDURE registrar_credit_change_lock();



CREATE TABLE invoice_type
(
id serial NOT NULL PRIMARY KEY
, name text
);

comment on table invoice_type is
'invoice types list';


INSERT INTO invoice_type (id,name) VALUES (0,'advance');
INSERT INTO invoice_type (id,name) VALUES (1,'account');

select setval('invoice_type_id_seq', 1);

-- TODO make prefix classifier for every year so that pass between years is available

CREATE TABLE invoice_prefix
(
id serial NOT NULL PRIMARY KEY, 
zone_id INTEGER REFERENCES zone (id),
typ INTEGER REFERENCES invoice_type (id),  -- invoice type 0 advance 1 account ...
year numeric NOT NULL, --for which year  
prefix bigint -- counter with prefix of number line invoice 
, CONSTRAINT invoice_prefix_zone_key UNIQUE (zone_id, typ, year)
);

comment on column invoice_prefix.zone_id is 'reference to zone';
comment on column invoice_prefix.typ is 'invoice type (0-advanced, 1-normal)';
comment on column invoice_prefix.year is 'for which year';
comment on column invoice_prefix.prefix is 'counter with prefix of number of invoice';

--invoice number prefix

CREATE TABLE invoice_number_prefix
(
id serial NOT NULL PRIMARY KEY
, prefix integer NOT NULL
, zone_id bigint NOT NULL REFERENCES zone(id)
, invoice_type_id bigint NOT NULL REFERENCES invoice_type (id)
, CONSTRAINT invoice_number_prefix_unique_key UNIQUE (zone_id, invoice_type_id)
);

comment on table invoice_number_prefix is
'prefixes to invoice number, next year prefixes are generated according to records in this table';

comment on column invoice_number_prefix.prefix is 'two-digit number';

-- advance invoices 
CREATE TABLE invoice
(
id serial NOT NULL PRIMARY KEY, -- unique primary key
zone_id INTEGER REFERENCES zone (id),
CrDate timestamp NOT NULL DEFAULT now(),  -- date and time of invoice creation 
TaxDate date NOT NULL, -- date of taxable fulfilment ( when payment cames by advance FA)
prefix bigint UNIQUE NOT NULL , -- 9 placed number of invoice from invoice_prefix.prefix counted via TaxDate 
registrar_id INTEGER NOT NULL REFERENCES registrar, -- link to registrar
-- TODO registrarhistoryID for links to right ICO and DIC addresses
balance numeric(10,2) DEFAULT 0.0, -- credit from which is taken till zero if it is NULL it is normal invoice 
operations_price numeric(10,2) DEFAULT 0.0, -- account invoice sum price of operations  
VAT numeric NOT NULL, -- VAT percent used for this invoice)
total numeric(10,2) NOT NULL  DEFAULT 0.0 ,  -- amount without tax ( for accounting is same as price = total amount without tax);
totalVAT numeric(10,2)  NOT NULL DEFAULT 0.0 , -- tax paid (0 for accounted tax it is paid at advance invoice)
invoice_prefix_id INTEGER NOT NULL REFERENCES invoice_prefix(ID), --  invoice type  from which year is anf which type is according to prefix 
file INTEGER REFERENCES files ,-- link to generated PDF (it can be null till is generated)
fileXML INTEGER REFERENCES files -- link to generated XML (it can be null till is generated) 
);

comment on table invoice is
'table of invoices';
comment on column invoice.id is 'unique automatically generated identifier';
comment on column invoice.zone_id is 'reference to zone';
comment on column invoice.CrDate is 'date and time of invoice creation';
comment on column invoice.TaxDate is 'date of taxable fulfilment (when payment cames by advance FA)';
comment on column invoice.prefix is '9 placed number of invoice from invoice_prefix.prefix counted via TaxDate';
comment on column invoice.registrar_id is 'link to registrar';
comment on column invoice.balance is '*advance invoice: balance from which operations are charged *account invoice: amount to be paid (0 in case there is no debt)';
comment on column invoice.operations_price is 'sum of operations without tax';
comment on column invoice.VAT is 'VAT hight from account';
comment on column invoice.total is 'amount without tax';
comment on column invoice.totalVAT is 'tax paid';
comment on column invoice.invoice_prefix_id is 'invoice type - which year and type (accounting/advance) ';
comment on column invoice.file is 'link to generated PDF file, it can be NULL till file is generated';
comment on column invoice.fileXML is 'link to generated XML file, it can be NULL till file is generated';

-- invoices generation
CREATE TABLE invoice_generation
(
id serial NOT NULL PRIMARY KEY, -- unique primary key
FromDate date NOT  NULL , -- local date account period from is taken 00:00:00 
ToDate date NOT NULL  , -- 23:59:59 is taken into date
registrar_id INTEGER NOT NULL REFERENCES registrar, -- link to registrar
zone_id INTEGER REFERENCES Zone (id),
invoice_id INTEGER REFERENCES invoice (id) -- id of normal invoice
);

comment on column invoice_generation.id is 'unique automatically generated identifier';
comment on column invoice_generation.invoice_id is 'id of normal invoice';

--  account tabel of advance invoices
CREATE TABLE invoice_credit_payment_map
(
ac_invoice_id INTEGER REFERENCES invoice (id) , -- id of normal invoice
ad_invoice_id INTEGER REFERENCES invoice (id) , -- id of advance invoice
credit numeric(10,2)  NOT NULL DEFAULT 0.0, -- seized credit
balance numeric(10,2)  NOT NULL DEFAULT 0.0, -- actual tax balance advance invoice 
PRIMARY KEY (ac_invoice_id, ad_invoice_id)
);

comment on column invoice_credit_payment_map.ac_invoice_id is 'id of normal invoice';
comment on column invoice_credit_payment_map.ad_invoice_id is 'id of advance invoice';
comment on column invoice_credit_payment_map.credit is 'seized credit';
comment on column invoice_credit_payment_map.balance is 'actual tax balance advance invoice';

CREATE INDEX invoice_credit_payment_map_ac_invoice_id_idx
       ON invoice_credit_payment_map (ac_invoice_id);
CREATE INDEX invoice_credit_payment_map_ad_invoice_id_idx
       ON invoice_credit_payment_map (ad_invoice_id);

-- TODO into normal invoices make account period from when till when.

-- when is billing realized, they are substracted from advanced invoice 
-- it can occur that one object is billing twice every from different advance invoice
CREATE TABLE invoice_operation
(
id serial NOT NULL PRIMARY KEY, -- unique primary key
ac_invoice_id INTEGER REFERENCES invoice (id) , -- id of invoice for which is item counted 
CrDate timestamp NOT NULL DEFAULT now(),  -- billing date and time 
object_id integer  REFERENCES object_registry (id),
zone_id INTEGER REFERENCES zone (id),
registrar_id INTEGER NOT NULL REFERENCES registrar, -- link to registrar 
operation_id INTEGER NOT NULL REFERENCES enum_operation, -- operation type of registration or renew
date_from date,
date_to date default NULL,  -- final ExDate only for RENEW 
quantity integer default 0, -- number of unit for renew in months
registrar_credit_transaction_id bigint UNIQUE NOT NULL REFERENCES registrar_credit_transaction(id)
);

comment on column invoice_operation.id is 'unique automatically generated identifier';
comment on column invoice_operation.ac_invoice_id is 'id of invoice for which is item counted';
comment on column invoice_operation.CrDate is 'billing date and time';
comment on column invoice_operation.zone_id is 'link to zone';
comment on column invoice_operation.registrar_id is 'link to registrar';
comment on column invoice_operation.operation_id is 'operation type of registration or renew';
comment on column invoice_operation.date_to is 'expiration date only for RENEW';
comment on column invoice_operation.quantity is 'number of operations or number of months for renew';

CREATE INDEX invoice_operation_object_id_idx
       ON invoice_operation (object_id);

CREATE TABLE invoice_operation_charge_map
(
invoice_operation_id INTEGER REFERENCES invoice_operation(ID),
invoice_id INTEGER REFERENCES invoice (id), -- id of advanced invoice
price numeric(10,2) NOT NULL default 0 , -- cost for operation
PRIMARY KEY ( invoice_operation_id ,  invoice_id ) -- unique key
);

comment on column invoice_operation_charge_map.invoice_id is 'id of advanced invoice';
comment on column invoice_operation_charge_map.price is 'operation cost';

CREATE INDEX invoice_operation_charge_map_invoice_id_idx
       ON invoice_operation_charge_map (invoice_id);

CREATE TABLE invoice_mails
(
id SERIAL NOT NULL PRIMARY KEY, -- unique primary key
invoiceid INTEGER REFERENCES invoice, -- link to invoices
genid INTEGER REFERENCES invoice_generation, -- link to invoices
mailid INTEGER NOT NULL REFERENCES mail_archive -- e-mail which contains this invoice 
);

comment on column invoice_mails.invoiceid is 'link to invoices';
comment on column invoice_mails.mailid is 'e-mail which contains this invoice';

CREATE TABLE invoice_registrar_credit_transaction_map
(
    id BIGSERIAL PRIMARY KEY
    , invoice_id bigint NOT NULL REFERENCES invoice(id)
    , registrar_credit_transaction_id bigint UNIQUE NOT NULL REFERENCES registrar_credit_transaction(id)
);

COMMENT ON TABLE invoice_registrar_credit_transaction_map
	IS 'positive credit item from payment assigned to deposit or account invoice';





-- drop tables
-- drop table bank_account;

-- bank classifier 
-- CREATE TABLE enum_bank_code (
-- code char(4) PRIMARY KEY,
-- name_short varchar(4) UNIQUE NOT NULL , -- shortcut
-- name_full varchar(64) UNIQUE  NOT NULL -- full name
-- );

-- ACCOUNT -- table of our accounts
CREATE TABLE bank_account 
(
id serial NOT NULL PRIMARY KEY, -- unique primary key
Zone INTEGER REFERENCES Zone (ID), -- for which zone should be account executed
account_number char(16) NOT NULL , -- account number
account_name  char(20) , -- account name
bank_code char(4)  REFERENCES enum_bank_code,   -- bank code
balance  numeric(10,2) default 0.0, -- actual balance 
last_date date, -- date of last statement 
last_num int  -- number of last statement
);

-- coupling variable symbol of registrar is in a table registrar ( it is his ICO for CZ ) a it is valid for all zones

comment on table bank_account is
'This table contains information about registry administrator bank account';
comment on column bank_account.id is 'unique automatically generated identifier';
comment on column bank_account.zone is 'for which zone should be account executed';
comment on column bank_account.balance is 'actual balance';
comment on column bank_account.last_date is 'date of last statement';
comment on column bank_account.last_num is 'number of last statement';

CREATE TABLE bank_statement 
(
    id serial NOT NULL PRIMARY KEY, -- unique primary key
    account_id int  REFERENCES bank_account, -- processing for given account link to account tabel
    num int, -- serial number statement
    create_date date , --  create date of a statement
    balance_old_date date , -- date of a last balance
    balance_old numeric(10,2) , -- old balance
    balance_new numeric(10,2) ,  -- new balance
    balance_credit  numeric(10,2) , -- income during statement ( credit balance )
    balance_debet numeric(10,2), -- expenses during statement ( debet balance )
    file_id INTEGER REFERENCES Files default NULL
);

comment on column bank_statement.id is 'unique automatically generated identifier';
comment on column bank_statement.account_id is 'link to used bank account';
comment on column bank_statement.num is 'statements number';
comment on column bank_statement.create_date is 'statement creation date';
comment on column bank_statement.balance_old is 'old balance state';
comment on column bank_statement.balance_credit is 'income during statement';
comment on column bank_statement.balance_debet is 'expenses during statement';
comment on column bank_statement.file_id is 'xml file identifier number';


CREATE TABLE bank_payment
(
    id serial NOT NULL PRIMARY KEY, -- unique primary key
    statement_id int  REFERENCES bank_statement default null, -- link into table heads of bank statements
    account_id int  REFERENCES bank_account default null, -- link into table of accounts
    account_number text NOT NULL , -- contra-account number from which came or was sent a payment
    bank_code varchar(4) NOT NULL,   -- bank code
    code int, -- account code 1 debet item 2 credit item 4  cancel debet 5 cancel credit 
    type int NOT NULL default 1, -- transfer type
    status int, -- payment status
    KonstSym varchar(10), -- constant symbol ( it contains bank code too )
    VarSymb varchar(10), -- variable symbol
    SpecSymb varchar(10), -- constant symbol
    price numeric(10,2) NOT NULL,  -- applied amount if a debet is negative amount 
    account_evid varchar(20), -- account evidence 
    account_date date NOT NULL, --  accounting date of credit or sending 
    account_memo  varchar(64), -- note
    account_name  varchar(64), -- account name
    crtime timestamp NOT NULL default now(),
    UNIQUE(account_id, account_evid)
);

comment on column bank_payment.id is 'unique automatically generated identifier';
comment on column bank_payment.statement_id is 'link to statement head';
comment on column bank_payment.account_id is 'link to account table';
comment on column bank_payment.account_number is 'contra-account number from which came or was sent a payment';
comment on column bank_payment.bank_code is 'contra-account bank code';
comment on column bank_payment.code is 'operation code (1-debet item, 2-credit item, 4-cancel debet, 5-cancel credit)';
comment on column bank_payment.type is 'transfer type (1-not decided (not processed), 2-from/to registrar, 3-from/to bank, 4-between our own accounts, 5-related to academia, 6-other transfers';
comment on column bank_payment.status is 'payment status (1-Realized (only this should be further processed), 2-Partially realized, 3-Not realized, 4-Suspended, 5-Ended, 6-Waiting for clearing )';
comment on column bank_payment.KonstSym is 'constant symbol (contains bank code too)';
comment on column bank_payment.VarSymb is 'variable symbol';
comment on column bank_payment.SpecSymb is 'spec symbol';
comment on column bank_payment.price is 'applied positive(credit) or negative(debet) amount';
comment on column bank_payment.account_evid is 'account evidence';
comment on column bank_payment.account_date is 'accounting date';
comment on column bank_payment.account_memo is 'note';
comment on column bank_payment.account_name is 'account name';
comment on column bank_payment.crtime is 'create timestamp';

CREATE TABLE bank_payment_registrar_credit_transaction_map
(
    id BIGSERIAL PRIMARY KEY
    , bank_payment_id bigint NOT NULL REFERENCES bank_payment(id)
    , registrar_credit_transaction_id bigint UNIQUE NOT NULL REFERENCES registrar_credit_transaction(id)
);

COMMENT ON TABLE bank_payment_registrar_credit_transaction_map
	IS 'payment assigned to credit items';





--CREATE TABLE check_enum_reason (
--	id SERIAL PRIMARY KEY,
--	reason varchar(100)
--);
--INSERT INTO check_enum_reason (reason) VALUES ('EPP');
--INSERT INTO check_enum_reason (reason) VALUES ('MANUAL');
--INSERT INTO check_enum_reason (reason) VALUES ('REGULAR');
--INSERT INTO check_enum_reason (reason) VALUES ('OTHER');

CREATE TABLE check_test (
	id INTEGER PRIMARY KEY, -- provide test order
	name VARCHAR(100) NOT NULL, -- test name
	severity SMALLINT NOT NULL, -- test level
	description VARCHAR(300) NOT NULL, -- test description
	disabled BOOLEAN NOT NULL DEFAULT False,
	script VARCHAR(300) NOT NULL, -- script name, which realised test
	need_domain SMALLINT NOT NULL DEFAULT 0 -- whether test make sense only with concrete fqdn of domain
);

INSERT INTO check_test (id, name, severity, description, disabled, script,
	need_domain)
VALUES (0,  'glue_ok',          1, '', False, '', 2);
INSERT INTO check_test (id, name, severity, description, disabled, script,
	need_domain)
VALUES (1,  'existence',     1, '', False, 'existance.py', 2);
INSERT INTO check_test (id, name, severity, description, disabled, script,
	need_domain)
VALUES (10, 'autonomous',    5, '', False, 'autonomous.py', 0);
INSERT INTO check_test (id, name, severity, description, disabled, script,
	need_domain)
VALUES (20, 'presence',      2, '', False, 'presence.py', 1);
INSERT INTO check_test (id, name, severity, description, disabled, script,
	need_domain)
VALUES (30, 'authoritative', 3, '', False, 'authoritative.py', 1);
INSERT INTO check_test (id, name, severity, description, disabled, script,
	need_domain)
VALUES (40, 'heterogenous',  6, '', False, 'heterogenous.py', 0);
INSERT INTO check_test (id, name, severity, description, disabled, script,
	need_domain)
VALUES (50, 'notrecursive',     4, '', False, 'recursive.py', 2);
INSERT INTO check_test (id, name, severity, description, disabled, script,
	need_domain)
VALUES (60, 'notrecursive4all', 4, '', False, 'recursive4all.py', 0);
INSERT INTO check_test (id, name, severity, description, disabled, script,
	need_domain)
VALUES (70, 'dnsseckeychase', 3, '', False, 'dnsseckeychase.py', 3);

CREATE TABLE check_dependance (
	id SERIAL PRIMARY KEY,
	addictid INTEGER REFERENCES check_test (id),
	testid INTEGER REFERENCES check_test (id)
);

INSERT INTO check_dependance (addictid, testid) VALUES ( 1, 0);
INSERT INTO check_dependance (addictid, testid) VALUES (10, 0);
INSERT INTO check_dependance (addictid, testid) VALUES (20, 0);
INSERT INTO check_dependance (addictid, testid) VALUES (30, 0);
INSERT INTO check_dependance (addictid, testid) VALUES (40, 0);
INSERT INTO check_dependance (addictid, testid) VALUES (50, 0);
INSERT INTO check_dependance (addictid, testid) VALUES (60, 0);
INSERT INTO check_dependance (addictid, testid) VALUES (10, 1);
INSERT INTO check_dependance (addictid, testid) VALUES (20, 1);
INSERT INTO check_dependance (addictid, testid) VALUES (30, 1);
INSERT INTO check_dependance (addictid, testid) VALUES (30,20);
INSERT INTO check_dependance (addictid, testid) VALUES (40, 1);
INSERT INTO check_dependance (addictid, testid) VALUES (50, 1);
INSERT INTO check_dependance (addictid, testid) VALUES (60, 1);
INSERT INTO check_dependance (addictid, testid) VALUES (70, 1);
INSERT INTO check_dependance (addictid, testid) VALUES (70, 20);

select setval('check_dependance_id_seq', 16);

CREATE TABLE check_nsset (
	id SERIAL PRIMARY KEY,
	-- nsset version, actual in time of record creation
	nsset_hid INTEGER REFERENCES nsset_history (historyid),
	checkdate TIMESTAMP NOT NULL DEFAULT now(),
	-- 0 = UNKNOWN
	-- 1 = EPP
	-- 2 = MANUAL
	-- 3 = REGULAR
	reason SMALLINT NOT NULL DEFAULT 0,
	-- 0 = all tests were passed
	-- 1 = one or more tests failed
	-- 2 = one or more tests have unknown status and none has failed
	overallstatus SMALLINT NOT NULL,
	-- Here are stored fqdns of domains which were tested with nsset and
	-- are not part of registry
	extra_fqdns VARCHAR(300)[],
	-- if domains associated with nsset were also tested
	dig BOOLEAN NOT NULL,
	-- what attempt it is (1th, 2nd or 3rd)
	attempt SMALLINT NOT NULL DEFAULT 1
);

CREATE TABLE check_result (
	id SERIAL PRIMARY KEY,
	checkid INTEGER references check_nsset(id) ON UPDATE CASCADE ON DELETE CASCADE,
	testid INTEGER references check_test(id),
	-- three-state logic (0=passed, 1=failed, 2=unknown)
	--    unknown occurs if script failed for unknown reason
	status SMALLINT NOT NULL,
	note TEXT, -- output of test script (stderr)
	data TEXT  -- test-specific text data (stdout)
);

CREATE TABLE epp_info_buffer_content (
	id INTEGER NOT NULL, 
	registrar_id INTEGER NOT NULL REFERENCES registrar (id), 
	object_id INTEGER NOT NULL, 
	PRIMARY KEY (id,registrar_id)
);

CREATE TABLE epp_info_buffer (
	registrar_id INTEGER NOT NULL REFERENCES registrar (id),
	current INTEGER, 
	FOREIGN KEY (registrar_id, current) REFERENCES epp_info_buffer_content (registrar_id, id),
    PRIMARY KEY (registrar_id)
);

CREATE INDEX epp_info_buffer_content_registrar_id_idx ON epp_info_buffer_content (registrar_id);-- must be superuser
-- CREATE LANGUAGE 'plpgsql';

-- 
--  create temporary table and if temporary table already
--  exists truncate it for immediate usage
--
CREATE OR REPLACE FUNCTION create_tmp_table(tname VARCHAR) 
RETURNS VOID AS $$
BEGIN
 EXECUTE 'CREATE TEMPORARY TABLE ' || tname || ' (id BIGINT PRIMARY KEY)';
 EXCEPTION
 WHEN DUPLICATE_TABLE THEN EXECUTE 'TRUNCATE TABLE ' || tname;
END;
$$ LANGUAGE plpgsql;

CREATE UNIQUE INDEX object_registry_name_type_uniq 
ON object_registry (name,type) WHERE erdate IS NULL;
--
-- create object and return it's id. duplicate is not raised as exception
-- but return 0 as id instead. it expect unique index on table
-- object_registry. cannot check enum subdomains!!!
--
CREATE OR REPLACE FUNCTION create_object(
 crregid INTEGER, 
 oname VARCHAR, 
 otype INTEGER
) 
RETURNS INTEGER AS $$
DECLARE iid INTEGER;
BEGIN
 iid := NEXTVAL('object_registry_id_seq');
 INSERT INTO object_registry (id,roid,name,type,crid) 
 VALUES (
  iid,
  (ARRAY['C','N','D', 'K'])[otype] || LPAD(iid::text,10,'0') || '-' || (SELECT val FROM enum_parameters WHERE id = 13),
  CASE
   WHEN otype=1 THEN UPPER(oname)
   WHEN otype=2 THEN UPPER(oname)
   WHEN otype=3 THEN LOWER(oname)
   WHEN otype=4 THEN UPPER(oname)
  END,
  otype,
  crregid
 );
 RETURN iid;
 EXCEPTION
 WHEN UNIQUE_VIOLATION THEN RETURN 0;
END;
$$ LANGUAGE plpgsql;
-- system operational parametr
-- parameters are accessed through their id not name, so proper
-- numbering is essential

CREATE TABLE enum_parameters (
  id INTEGER PRIMARY KEY, -- primary identification 
  name VARCHAR(100) NOT NULL UNIQUE, -- descriptive name (informational)
  val VARCHAR(100) NOT NULL -- value of parameter
);

-- parametr 1 is for checking data model version and for applying upgrade
-- scripts
INSERT INTO enum_parameters (id, name, val) 
VALUES (1, 'model_version', '2.12.2');
-- parametr 2 is for updating table enum_tlds by data from url
-- http://data.iana.org/TLD/tlds-alpha-by-domain.txt
INSERT INTO enum_parameters (id, name, val) 
VALUES (2, 'tld_list_version', '2008013001');
-- parametr 3 is used to change state of domain to unguarded and remove
-- this domain from DNS. value is number of dates relative to date 
-- domain.exdate 
INSERT INTO enum_parameters (id, name, val) 
VALUES (3, 'expiration_notify_period', '-30');
-- parametr 4 is used to change state of domain to unguarded and remove
-- this domain from DNS. value is number of dates relative to date 
-- domain.exdate 
INSERT INTO enum_parameters (id, name, val) 
VALUES (4, 'expiration_dns_protection_period', '30');
-- parametr 5 is used to change state of domain to deleteWarning and 
-- generate letter with warning. value number of dates relative to date 
-- domain.exdate 
INSERT INTO enum_parameters (id, name, val) 
VALUES (5, 'expiration_letter_warning_period', '34');
-- parametr 6 is used to change state of domain to deleteCandidate and 
-- unregister domain from system. value is number of dates relative to date 
-- domain.exdate 
INSERT INTO enum_parameters (id, name, val) 
VALUES (6, 'expiration_registration_protection_period', '61');
-- parametr 7 is used to change state of domain to validationWarning1 and 
-- send poll message to registrar. value is number of dates relative to date 
-- domain.exdate 
INSERT INTO enum_parameters (id, name, val) 
VALUES (7, 'validation_notify1_period', '-30');
-- parametr 8 is used to change state of domain to validationWarning2 and 
-- send email to registrant. value is number of dates relative to date 
-- domain.exdate 
INSERT INTO enum_parameters (id, name, val) 
VALUES (8, 'validation_notify2_period', '-15');
-- parametr 9 is used to identify hour when objects are deleted
-- value is number of hours relative to date of operation
INSERT INTO enum_parameters (id, name, val) 
VALUES (9, 'regular_day_procedure_period', '0');
-- parametr 10 is used to identify time zone in which parameter 9 and 14
-- are specified
INSERT INTO enum_parameters (id, name, val) 
VALUES (10, 'regular_day_procedure_zone', 'Europe/Prague');
-- parametr 11 is used to change state of objects other than domain to
-- deleteCandidate. It is specified in granularity of months and means, period
-- during which object wasn't linked to other object and wasn't updated 
INSERT INTO enum_parameters (id, name, val) 
VALUES (11, 'object_registration_protection_period', '6');
-- parameter 12 is used to change protection period of deleted object handle
-- (contact, nsset, keyset). value is in months.
INSERT INTO enum_parameters (id, name, val)
VALUES (12, 'handle_registration_protection_period', '0');
-- parameter 13 is used as a suffix in object_registry roid string
-- this suffix should match pattern \w{1,8}
INSERT INTO enum_parameters (id, name, val)
VALUES (13, 'roid_suffix', 'EPP');
-- parametr 14 is used to identify hour when domains are moving outzone. 
-- value is number of hours relative to date of operation
INSERT INTO enum_parameters (id, name, val) 
VALUES (14, 'regular_day_outzone_procedure_period', '14');



comment on table enum_parameters is
'Table of system operational parameters.
Meanings of parameters:

1 - model version - for checking data model version and for applying upgrade scripts
2 - tld list version - for updating table enum_tlds by data from url
3 - expiration notify period - used to change state of domain to unguarded and remove domain from DNS,
    value is number of days relative to date domain.exdate
4 - expiration dns protection period - same as parameter 3
5 - expiration letter warning period - used to change state of domain to deleteWarning and generate letter
    witch warning
6 - expiration registration protection period - used to change state of domain to deleteCandidate and
    unregister domain from system
7 - validation notify 1 period - used to change state of domain to validationWarning1 and send poll
    message to registrar
8 - validation notify 2 period - used to change state of domain to validationWarning2 and send
    email to registrant
9 - regular day procedure period - used to identify hout when objects are deleted and domains
    are moving outzone
10 - regular day procedure zone - used to identify time zone in which parameter 9 is specified';
comment on column enum_parameters.id is 'primary identification';
comment on column enum_parameters.name is 'descriptive name of parameter - for information uses only';
comment on column enum_parameters.val is 'value of parameter';
---
---  new DNSSEC related tables
---

CREATE TABLE Keyset (
    id integer PRIMARY KEY REFERENCES object (id)
);

comment on table Keyset is 'Evidence of Keysets';
comment on column Keyset.id is 'reference into object table';


CREATE TABLE keyset_contact_map (
    keysetid integer REFERENCES Keyset(id) ON UPDATE CASCADE NOT NULL,
    contactid integer REFERENCES Contact(ID) ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,
    PRIMARY KEY (contactid, keysetid)
);
CREATE INDEX keyset_contact_map_contact_idx ON keyset_contact_map (contactid);
CREATE INDEX keyset_contact_map_keyset_idx ON keyset_contact_map (keysetid);

CREATE TABLE DSRecord (
    id serial PRIMARY KEY,
    keysetid integer REFERENCES Keyset(id) ON UPDATE CASCADE NOT NULL,
    keyTag integer NOT NULL,
    alg integer NOT NULL,
    digestType integer NOT NULL,
    digest varchar(255) NOT NULL,
    maxSigLife integer
);

comment on table DSRecord is 'table with DS resource records'; 
comment on column DSRecord.id is 'unique automatically generated identifier';
comment on column DSRecord.keysetid is 'reference to relevant record in Keyset table';
comment on column DSRecord.keyTag is '';
comment on column DSRecord.alg is 'used algorithm. See RFC 4034 appendix A.1 for list';
comment on column DSRecord.digestType is 'used digest type. See RFC 4034 appendix A.2 for list';
comment on column DSRecord.digest is 'digest of DNSKEY';
comment on column DSRecord.maxSigLife is 'record TTL';

CREATE TABLE dnskey (
    id serial PRIMARY KEY,
    keysetid integer REFERENCES Keyset(id) ON UPDATE CASCADE NOT NULL,
    flags integer NOT NULL,
    protocol integer NOT NULL,
    alg integer NOT NULL,
    key text NOT NULL
);

comment on table dnskey is '';
comment on column dnskey.id is 'unique automatically generated identifier';
comment on column dnskey.keysetid is 'reference to relevant record in keyset table';
comment on column dnskey.flags is '';
comment on column dnskey.protocol is 'must be 3';
comment on column dnskey.alg is 'used algorithm (see http://rfc-ref.org/RFC-TEXTS/4034/chapter11.html for further details)';
comment on column dnskey.key is 'base64 decoded key';

---
--- new DNSSEC related history tables
---

CREATE TABLE Keyset_history (
    historyid integer PRIMARY KEY REFERENCES History,
    id integer REFERENCES object_registry(id)
);

comment on table Keyset_history is 'historic data from Keyset table';

CREATE TABLE keyset_contact_map_history (
    historyid integer REFERENCES History,
    keysetid integer REFERENCES object_registry(id),
    contactid integer REFERENCES object_registry(id),
    PRIMARY KEY (historyid, contactid, keysetid)
);

CREATE TABLE DSRecord_history (
    historyid integer REFERENCES History,
    id integer NOT NULL,
    keysetid integer NOT NULL,
    keyTag integer NOT NULL,
    alg integer NOT NULL,
    digestType integer NOT NULL,
    digest varchar(255) NOT NULL,
    maxSigLife integer,
    PRIMARY KEY (historyid, id)
);

comment on table DSRecord_history is 'historic data from DSRecord table';

CREATE TABLE dnskey_history (
    historyid integer REFERENCES History,
    id integer NOT NULL,
    keysetid integer NOT NULL,
    flags integer NOT NULL,
    protocol integer NOT NULL,
    alg integer NOT NULL,
    key text NOT NULL,
    PRIMARY KEY (historyid, id)
);

comment on table dnskey_history is 'historic data from dnskey table';

---
--- changes in existing tables
---

ALTER TABLE Domain ADD COLUMN keyset integer REFERENCES Keyset(id);

comment on column Domain.keyset is 'reference to used keyset';

ALTER TABLE Domain_History ADD COLUMN keyset integer;

---
--- new records in existing tables
--- 
--- !! moved into ``reason.sql'' file
---

---
--- error reason values
---
--- !! moved into ``enum_reason.sql'' file
---

CREATE INDEX object_registry_upper_name_4_idx 
 ON object_registry (UPPER(name)) WHERE type=4;

-- all supported status types
CREATE TABLE enum_object_states (
  -- id of status
  id INTEGER PRIMARY KEY,
  -- code name for status
  name VARCHAR(50) NOT NULL,
  -- what types of objects can have this status (object_registry.type list)
  types INTEGER[] NOT NULL,
  -- if this status is set manualy
  manual BOOLEAN NOT NULL,
  -- if this status is exported to public
  external BOOLEAN NOT NULL
);

comment on table enum_object_states is 'list of all supported status types';
comment on column enum_object_states.name is 'code name for status';
comment on column enum_object_states.types is 'what types of objects can have this status (object_registry.type list)';
comment on column enum_object_states.manual is 'if this status is set manualy';
comment on column enum_object_states.external is 'if this status is exported to public';

INSERT INTO enum_object_states 
  VALUES (01,'serverDeleteProhibited','{1,2,3}','t','t');
INSERT INTO enum_object_states 
  VALUES (02,'serverRenewProhibited','{3}','t','t');
INSERT INTO enum_object_states 
  VALUES (03,'serverTransferProhibited','{1,2,3}','t','t');
INSERT INTO enum_object_states 
  VALUES (04,'serverUpdateProhibited','{1,2,3}','t','t');
INSERT INTO enum_object_states 
  VALUES (05,'serverOutzoneManual','{3}','t','t');
INSERT INTO enum_object_states 
  VALUES (06,'serverInzoneManual','{3}','t','t');
INSERT INTO enum_object_states 
  VALUES (07,'serverBlocked','{3}','t','t');
INSERT INTO enum_object_states 
  VALUES (08,'expirationWarning','{3}','f','f');
INSERT INTO enum_object_states 
  VALUES (09,'expired','{3}','f','t');
INSERT INTO enum_object_states 
  VALUES (10,'unguarded','{3}','f','f');
INSERT INTO enum_object_states 
  VALUES (11,'validationWarning1','{3}','f','f');
INSERT INTO enum_object_states 
  VALUES (12,'validationWarning2','{3}','f','f');
INSERT INTO enum_object_states 
  VALUES (13,'notValidated','{3}','f','t');
INSERT INTO enum_object_states 
  VALUES (14,'nssetMissing','{3}','f','f');
INSERT INTO enum_object_states 
  VALUES (15,'outzone','{3}','f','t');
INSERT INTO enum_object_states 
  VALUES (16,'linked','{1,2}','f','t');
INSERT INTO enum_object_states 
  VALUES (17,'deleteCandidate','{1,2,3}','f','t');
INSERT INTO enum_object_states 
  VALUES (18,'serverRegistrantChangeProhibited','{3}','t','t');
INSERT INTO enum_object_states 
  VALUES (19,'deleteWarning','{3}','f','f');
INSERT INTO enum_object_states 
  VALUES (20,'outzoneUnguarded','{3}','f','f');


-- update for keyset
update enum_object_states set types = types || array[4] where 2 = any (types);

-- descriptions fo states in different languages 
CREATE TABLE enum_object_states_desc (
  -- id of status
  state_id INTEGER NOT NULL REFERENCES enum_object_states (id),
  -- char code of language
  lang CHAR(2) NOT NULL,
  -- descriptive text
  description VARCHAR(255),
  PRIMARY KEY (state_id,lang)
);

comment on table enum_object_states_desc is 'description for states in different languages';
comment on column enum_object_states_desc.lang is 'code of language';
comment on column enum_object_states_desc.description is 'descriptive text';

INSERT INTO enum_object_states_desc 
  VALUES (01,'CS','Není povoleno smazání');
INSERT INTO enum_object_states_desc 
  VALUES (01,'EN','Delete prohibited');
INSERT INTO enum_object_states_desc 
  VALUES (02,'CS','Není povoleno prodloužení registrace objektu');
INSERT INTO enum_object_states_desc 
  VALUES (02,'EN','Registration renewal prohibited');
INSERT INTO enum_object_states_desc 
  VALUES (03,'CS','Není povolena změna určeného regsitrátora');
INSERT INTO enum_object_states_desc 
  VALUES (03,'EN','Sponsoring registrar change prohibited');
INSERT INTO enum_object_states_desc 
  VALUES (04,'CS','Není povolena aktualizace');
INSERT INTO enum_object_states_desc 
  VALUES (04,'EN','Update prohibited');
INSERT INTO enum_object_states_desc 
  VALUES (05,'CS','Doména je administrativně vyřazena ze zóny');
INSERT INTO enum_object_states_desc 
  VALUES (05,'EN','Domain is administratively kept out of zone');
INSERT INTO enum_object_states_desc 
  VALUES (06,'CS','Doména je administrativně zařazena do zóny');
INSERT INTO enum_object_states_desc 
  VALUES (06,'EN','Domain is administratively kept in zone');
INSERT INTO enum_object_states_desc 
  VALUES (07,'CS','Doména je blokována');
INSERT INTO enum_object_states_desc 
  VALUES (07,'EN','Domain blocked');
INSERT INTO enum_object_states_desc 
  VALUES (08,'CS','Doména expiruje do 30 dní');
INSERT INTO enum_object_states_desc 
  VALUES (08,'EN','Expires within 30 days');
INSERT INTO enum_object_states_desc 
  VALUES (09,'CS','Doména je po expiraci');
INSERT INTO enum_object_states_desc 
  VALUES (09,'EN','Expired');
INSERT INTO enum_object_states_desc 
  VALUES (10,'CS','Doména je 30 dnů po expiraci');
INSERT INTO enum_object_states_desc 
  VALUES (10,'EN','Domain is 30 days after expiration');
INSERT INTO enum_object_states_desc 
  VALUES (11,'CS','Validace domény skončí za 30 dní');
INSERT INTO enum_object_states_desc 
  VALUES (11,'EN','Validation of domain expire in 30 days');
INSERT INTO enum_object_states_desc 
  VALUES (12,'CS','Validace domény skončí za 15 dní');
INSERT INTO enum_object_states_desc 
  VALUES (12,'EN','Validation of domain expire in 15 days');
INSERT INTO enum_object_states_desc 
  VALUES (13,'CS','Doména není validována');
INSERT INTO enum_object_states_desc 
  VALUES (13,'EN','Domain not validated');
INSERT INTO enum_object_states_desc 
  VALUES (14,'CS','Doména nemá přiřazen nsset');
INSERT INTO enum_object_states_desc 
  VALUES (14,'EN','Domain has not associated nsset');
INSERT INTO enum_object_states_desc 
  VALUES (15,'CS','Doména není generována do zóny');
INSERT INTO enum_object_states_desc 
  VALUES (15,'EN','Domain is not generated into zone');
INSERT INTO enum_object_states_desc 
  VALUES (16,'CS','Je navázáno na další záznam v registru');
INSERT INTO enum_object_states_desc 
  VALUES (16,'EN','Has relation to other records in registry');
INSERT INTO enum_object_states_desc 
  VALUES (17,'CS','Určeno ke zrušení');
INSERT INTO enum_object_states_desc 
  VALUES (17,'EN','To be deleted');
INSERT INTO enum_object_states_desc 
  VALUES (18,'CS','Není povolena změna držitele');
INSERT INTO enum_object_states_desc 
  VALUES (18,'EN','Registrant change prohibited');
INSERT INTO enum_object_states_desc 
  VALUES (19,'CS','Registrace domény bude zrušena za 11 dní');
INSERT INTO enum_object_states_desc 
  VALUES (19,'EN','Domain will be deleted in 11 days');
INSERT INTO enum_object_states_desc 
  VALUES (20,'CS','Doména vyřazena ze zóny po 30 dnech od expirace');
INSERT INTO enum_object_states_desc 
  VALUES (20,'EN','Domain is out of zone after 30 days from expiration');

-- main table of object states and their changes
CREATE TABLE object_state (
  -- id of moment when object gain status
  id SERIAL PRIMARY KEY,
  -- id of object that has this new status
  object_id INTEGER NOT NULL REFERENCES object_registry (id),
  -- id of status
  state_id INTEGER NOT NULL REFERENCES enum_object_states (id),
  -- timestamp when object entered state
  valid_from TIMESTAMP NOT NULL,
  -- timestamp when object leaved state or null if still has status
  valid_to TIMESTAMP,
  -- history id of object in the moment of entering state  (may be NULL)
  ohid_from INTEGER REFERENCES object_history (historyid),
  -- history id of object in the moment of leaving state or null
  ohid_to INTEGER REFERENCES object_history (historyid)
);

CREATE UNIQUE INDEX object_state_now_idx ON object_state (object_id, state_id)
WHERE valid_to ISNULL;

CREATE INDEX object_state_object_id_idx ON object_state (object_id) WHERE valid_to ISNULL;
CREATE INDEX object_state_object_id_all_idx ON object_state (object_id);
CREATE INDEX object_state_valid_from_idx ON object_state (valid_from);

comment on table object_state is 'main table of object states and their changes';
comment on column object_state.object_id is 'id of object that has this new status';
comment on column object_state.state_id is 'id of status';
comment on column object_state.valid_from is 'date and time when object entered state';
comment on column object_state.valid_to is 'date and time when object leaved state or null if still has this status';
comment on column object_state.ohid_from is 'history id of object in the moment of entering state (may be null)';
comment on column object_state.ohid_to is 'history id of object in the moment of leaving state or null';

-- aggregate function for accumulation of elements into array
CREATE AGGREGATE array_accum (
  BASETYPE = anyelement,
  sfunc = array_append,
  stype = anyarray,
  initcond = '{}'
);

-- simple view for all active states of object
CREATE VIEW object_state_now AS
SELECT object_id, array_accum(state_id) AS states
FROM object_state
WHERE valid_to ISNULL
GROUP BY object_id;

-- request for setting manual state
CREATE TABLE object_state_request (
  -- id of request
  id SERIAL PRIMARY KEY,
  -- id of object gaining requested state
  object_id INTEGER NOT NULL REFERENCES object_registry (id),
  -- id of requested state
  state_id INTEGER NOT NULL REFERENCES enum_object_states (id),
  -- when object should enter requested state
  valid_from TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  -- when object should leave requested state
  valid_to TIMESTAMP,
  -- could be pointer to some list of administration actions
  crdate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
  -- could be pointer to some list of administration actions
  canceled TIMESTAMP 
);

comment on table object_state_request is 'request for setting manual state';
comment on column object_state_request.object_id is 'id of object gaining request state';
comment on column object_state_request.state_id is 'id of requested state';
comment on column object_state_request.valid_from is 'when object should enter requested state';
comment on column object_state_request.valid_to is 'when object should leave requested state';
comment on column object_state_request.crdate is 'could be pointed to some list of administation action';
comment on column object_state_request.canceled is 'could be pointed to some list of administation action';

-- simple view for all active requests for state change
CREATE VIEW object_state_request_now AS
SELECT object_id, array_accum(state_id) AS states
FROM object_state_request
WHERE valid_from<=CURRENT_TIMESTAMP 
AND (valid_to ISNULL OR valid_to>=CURRENT_TIMESTAMP) AND canceled ISNULL
GROUP BY object_id;

-- function to test date moved by offset agains current date
CREATE OR REPLACE FUNCTION date_month_test(date, varchar, varchar, varchar)
RETURNS boolean
AS $$
SELECT $1 + ($2||' month')::interval + ($3||' hours')::interval 
       <= CURRENT_TIMESTAMP AT TIME ZONE $4;
$$ IMMUTABLE LANGUAGE SQL;

-- function to test date moved by offset agains current date
CREATE OR REPLACE FUNCTION date_test(date, varchar)
RETURNS boolean
AS $$
SELECT $1 + ($2||' days')::interval <= CURRENT_DATE ;
$$ IMMUTABLE LANGUAGE SQL;

-- function to test date moved by offset agains current date with respect
-- to current time and time zone
CREATE OR REPLACE FUNCTION date_time_test(date, varchar, varchar, varchar)
RETURNS boolean
AS $$
SELECT $1 + ($2||' days')::interval + ($3||' hours')::interval 
       <= CURRENT_TIMESTAMP AT TIME ZONE $4;
$$ IMMUTABLE LANGUAGE SQL;

-- ========== 1. type ==============================
-- following views and one setting function is for global setting of all
-- states. there are view pro each type of object to catch states of ALL
-- objects. then function is defined that compare these states with
-- actual state and update states appropriatly. That function is long
-- running so it cannot be used for updating states online. That case
-- is handled in 2. type of functions 

-- view for actual domain states
-- ================= DOMAIN ========================
-- DROP VIEW domain_states
CREATE VIEW domain_states AS
SELECT
  d.id AS object_id,
  o.historyid AS object_hid,
  COALESCE(osr.states,'{}') ||
  CASE WHEN date_test(d.exdate::date,ep_ex_not.val) 
            AND NOT (2 = ANY(COALESCE(osr.states,'{}'))) -- !renewProhibited
       THEN ARRAY[8] ELSE '{}' END ||  -- expirationWarning
  CASE WHEN date_test(d.exdate::date,'0')                
            AND NOT (2 = ANY(COALESCE(osr.states,'{}'))) -- !renewProhibited
       THEN ARRAY[9] ELSE '{}' END ||  -- expired
  CASE WHEN date_time_test(d.exdate::date,ep_ex_dns.val,ep_tm2.val,ep_tz.val)
            AND NOT (2 = ANY(COALESCE(osr.states,'{}'))) -- !renewProhibited
       THEN ARRAY[10] ELSE '{}' END || -- unguarded
  CASE WHEN date_test(e.exdate::date,ep_val_not1.val)
       THEN ARRAY[11] ELSE '{}' END || -- validationWarning1
  CASE WHEN date_test(e.exdate::date,ep_val_not2.val)
       THEN ARRAY[12] ELSE '{}' END || -- validationWarning2
  CASE WHEN date_time_test(e.exdate::date,'0',ep_tm2.val,ep_tz.val)
       THEN ARRAY[13] ELSE '{}' END || -- notValidated
  CASE WHEN d.nsset ISNULL 
       THEN ARRAY[14] ELSE '{}' END || -- nssetMissing
  CASE WHEN
    d.nsset ISNULL OR
    5 = ANY(COALESCE(osr.states,'{}')) OR                -- outzoneManual
    (((date_time_test(d.exdate::date,ep_ex_dns.val,ep_tm2.val,ep_tz.val)
       AND NOT (2 = ANY(COALESCE(osr.states,'{}')))      -- !renewProhibited
      ) OR date_time_test(e.exdate::date,'0',ep_tm2.val,ep_tz.val)) AND 
     NOT (6 = ANY(COALESCE(osr.states,'{}'))))           -- !inzoneManual
       THEN ARRAY[15] ELSE '{}' END || -- outzone
  CASE WHEN date_time_test(d.exdate::date,ep_ex_reg.val,ep_tm.val,ep_tz.val)
            AND NOT (2 = ANY(COALESCE(osr.states,'{}'))) -- !renewProhibited
            AND NOT (1 = ANY(COALESCE(osr.states,'{}'))) -- !deleteProhibited
       THEN ARRAY[17] ELSE '{}' END || -- deleteCandidate
  CASE WHEN date_test(d.exdate::date,ep_ex_let.val)
            AND NOT (2 = ANY(COALESCE(osr.states,'{}'))) -- !renewProhibited
       THEN ARRAY[19] ELSE '{}' END || -- deleteWarning
  CASE WHEN date_time_test(d.exdate::date,ep_ex_dns.val,ep_tm2.val,ep_tz.val)
            AND NOT (2 = ANY(COALESCE(osr.states,'{}'))) -- !renewProhibited
            AND NOT (6 = ANY(COALESCE(osr.states,'{}'))) -- !inzoneManual
       THEN ARRAY[20] ELSE '{}' END    -- outzoneUnguarded
  AS states
FROM
  object_registry o,
  domain d
  LEFT JOIN enumval e ON (d.id=e.domainid)
  LEFT JOIN object_state_request_now osr ON (d.id=osr.object_id)
  JOIN enum_parameters ep_ex_not ON (ep_ex_not.id=3)
  JOIN enum_parameters ep_ex_dns ON (ep_ex_dns.id=4)
  JOIN enum_parameters ep_ex_let ON (ep_ex_let.id=5)
  JOIN enum_parameters ep_ex_reg ON (ep_ex_reg.id=6)
  JOIN enum_parameters ep_val_not1 ON (ep_val_not1.id=7)
  JOIN enum_parameters ep_val_not2 ON (ep_val_not2.id=8)
  JOIN enum_parameters ep_tm ON (ep_tm.id=9)
  JOIN enum_parameters ep_tz ON (ep_tz.id=10)
  JOIN enum_parameters ep_tm2 ON (ep_tm2.id=14)
WHERE d.id=o.id;

-- view for actual nsset states
-- for NOW they are not deleted
-- ================= NSSET ========================
-- DROP VIEW nsset_states
CREATE VIEW nsset_states AS
SELECT
  o.id AS object_id,
  o.historyid AS object_hid,
  COALESCE(osr.states,'{}') ||
  CASE WHEN NOT(d.nsset ISNULL) THEN ARRAY[16] ELSE '{}' END ||
  CASE WHEN d.nsset ISNULL 
            AND date_month_test(
              GREATEST(
                COALESCE(l.last_linked,o.crdate)::date,
                COALESCE(ob.update,o.crdate)::date
              ),
              ep_mn.val,ep_tm.val,ep_tz.val
            )
            AND NOT (1 = ANY(COALESCE(osr.states,'{}')))
       THEN ARRAY[17] ELSE '{}' END 
  AS states
FROM
  object ob
  JOIN object_registry o ON (ob.id=o.id AND o.type=2)
  JOIN enum_parameters ep_tm ON (ep_tm.id=9)
  JOIN enum_parameters ep_tz ON (ep_tz.id=10)
  JOIN enum_parameters ep_mn ON (ep_mn.id=11)
  LEFT JOIN (
    SELECT DISTINCT nsset FROM domain
  ) AS d ON (d.nsset=o.id)
  LEFT JOIN (
    SELECT object_id, MAX(valid_to) AS last_linked
    FROM object_state
    WHERE state_id=16 GROUP BY object_id
  ) AS l ON (o.id=l.object_id)
  LEFT JOIN object_state_request_now osr ON (o.id=osr.object_id);

-- ================= KEYSET ========================
-- DROP VIEW keyset_states
CREATE VIEW keyset_states AS
SELECT
  o.id AS object_id,
  o.historyid AS object_hid,
  COALESCE(osr.states,'{}') ||
  CASE WHEN NOT(d.keyset ISNULL) THEN ARRAY[16] ELSE '{}' END ||
  CASE WHEN d.keyset ISNULL 
            AND date_month_test(
              GREATEST(
                COALESCE(l.last_linked,o.crdate)::date,
                COALESCE(ob.update,o.crdate)::date
              ),
              ep_mn.val,ep_tm.val,ep_tz.val
            )
            AND NOT (1 = ANY(COALESCE(osr.states,'{}')))
       THEN ARRAY[17] ELSE '{}' END 
  AS states
FROM
  object ob
  JOIN object_registry o ON (ob.id=o.id AND o.type=4)
  JOIN enum_parameters ep_tm ON (ep_tm.id=9)
  JOIN enum_parameters ep_tz ON (ep_tz.id=10)
  JOIN enum_parameters ep_mn ON (ep_mn.id=11)
  LEFT JOIN (
    SELECT DISTINCT keyset FROM domain
  ) AS d ON (d.keyset=o.id)
  LEFT JOIN (
    SELECT object_id, MAX(valid_to) AS last_linked
    FROM object_state
    WHERE state_id=16 GROUP BY object_id
  ) AS l ON (o.id=l.object_id)
  LEFT JOIN object_state_request_now osr ON (o.id=osr.object_id);

-- view for actual contact states
-- ================= CONTACT ========================
-- DROP VIEW contact_states
CREATE VIEW contact_states AS
SELECT
  o.id AS object_id,
  o.historyid AS object_hid,
  COALESCE(osr.states,'{}') ||
  CASE WHEN NOT(cl.cid ISNULL) THEN ARRAY[16] ELSE '{}' END ||
  CASE WHEN cl.cid ISNULL 
            AND date_month_test(
              GREATEST(
                COALESCE(l.last_linked,o.crdate)::date,
                COALESCE(ob.update,o.crdate)::date
              ),
              ep_mn.val,ep_tm.val,ep_tz.val
            )
            AND NOT (1 = ANY(COALESCE(osr.states,'{}')))
       THEN ARRAY[17] ELSE '{}' END 
  AS states
FROM
  object ob
  JOIN object_registry o ON (ob.id=o.id AND o.type=1)
  JOIN enum_parameters ep_tm ON (ep_tm.id=9)
  JOIN enum_parameters ep_tz ON (ep_tz.id=10)
  JOIN enum_parameters ep_mn ON (ep_mn.id=11)
  LEFT JOIN (
    SELECT registrant AS cid FROM domain
    UNION
    SELECT contactid AS cid FROM domain_contact_map
    UNION
    SELECT contactid AS cid FROM nsset_contact_map
    UNION
    SELECT contactid AS cid FROM keyset_contact_map
  ) AS cl ON (o.id=cl.cid)
  LEFT JOIN (
    SELECT object_id, MAX(valid_to) AS last_linked
    FROM object_state
    WHERE state_id=16 GROUP BY object_id
  ) AS l ON (o.id=l.object_id)
  LEFT JOIN object_state_request_now osr ON (o.id=osr.object_id);

-- in next function compared arrays need to be sorted
CREATE OR REPLACE FUNCTION array_sort_dist (ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
AS $$
SELECT COALESCE(ARRAY(
    SELECT DISTINCT $1[s.i] AS "sort"
    FROM
        generate_series(array_lower($1,1), array_upper($1,1)) AS s(i)
    ORDER BY sort
),'{}');
$$ IMMUTABLE;

-- ================= UPDATE FUNCTION =================
-- CREATE LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION update_object_states(int)
RETURNS void
AS $$
BEGIN
  IF NOT EXISTS(
    SELECT relname FROM pg_class
    WHERE relname = 'tmp_object_state_change' AND relkind = 'r' AND
    pg_table_is_visible(oid)
  )
  THEN
    CREATE TEMPORARY TABLE tmp_object_state_change (
      object_id INTEGER,
      object_hid INTEGER,
      new_states INTEGER[],
      old_states INTEGER[]
    );
  ELSE
    TRUNCATE tmp_object_state_change;
  END IF;

  IF $1 = 0
  THEN
    INSERT INTO tmp_object_state_change
    SELECT
      st.object_id, st.object_hid, st.states AS new_states, 
      COALESCE(o.states,'{}') AS old_states
    FROM (
      SELECT * FROM domain_states
      UNION
      SELECT * FROM contact_states
      UNION
      SELECT * FROM nsset_states
      UNION
      SELECT * FROM keyset_states
    ) AS st
    LEFT JOIN object_state_now o ON (st.object_id=o.object_id)
    WHERE array_sort_dist(st.states)!=COALESCE(array_sort_dist(o.states),'{}');
  ELSE
    -- domain
    INSERT INTO tmp_object_state_change
    SELECT
      st.object_id, st.object_hid, st.states AS new_states, 
      COALESCE(o.states,'{}') AS old_states
    FROM domain_states st
    LEFT JOIN object_state_now o ON (st.object_id=o.object_id)
    WHERE array_sort_dist(st.states)!=COALESCE(array_sort_dist(o.states),'{}')
    AND st.object_id=$1;
    -- contact
    INSERT INTO tmp_object_state_change
    SELECT
      st.object_id, st.object_hid, st.states AS new_states, 
      COALESCE(o.states,'{}') AS old_states
    FROM contact_states st
    LEFT JOIN object_state_now o ON (st.object_id=o.object_id)
    WHERE array_sort_dist(st.states)!=COALESCE(array_sort_dist(o.states),'{}')
    AND st.object_id=$1;
    -- nsset
    INSERT INTO tmp_object_state_change
    SELECT
      st.object_id, st.object_hid, st.states AS new_states, 
      COALESCE(o.states,'{}') AS old_states
    FROM nsset_states st
    LEFT JOIN object_state_now o ON (st.object_id=o.object_id)
    WHERE array_sort_dist(st.states)!=COALESCE(array_sort_dist(o.states),'{}')
    AND st.object_id=$1;
    -- keyset
    INSERT INTO tmp_object_state_change
    SELECT
      st.object_id, st.object_hid, st.states AS new_states, 
      COALESCE(o.states,'{}') AS old_states
    FROM keyset_states st
    LEFT JOIN object_state_now o ON (st.object_id=o.object_id)
    WHERE array_sort_dist(st.states)!=COALESCE(array_sort_dist(o.states),'{}')
    AND st.object_id=$1;
  END IF;

  INSERT INTO object_state (object_id,state_id,valid_from,ohid_from)
  SELECT c.object_id,e.id,CURRENT_TIMESTAMP,c.object_hid
  FROM tmp_object_state_change c, enum_object_states e
  WHERE e.id = ANY(c.new_states) AND e.id != ALL(c.old_states);

  UPDATE object_state SET valid_to=CURRENT_TIMESTAMP, ohid_to=c.object_hid
  FROM enum_object_states e, tmp_object_state_change c
  WHERE e.id = ANY(c.old_states) AND e.id != ALL(c.new_states)
  AND e.id=object_state.state_id and c.object_id=object_state.object_id 
  AND object_state.valid_to ISNULL;
END;
$$ LANGUAGE plpgsql;

-- ========== 2. type ==============================
-- following functions and triggers are for automatic state update
-- as a reaction on normal EPP commands.

-- RACE CONTIONS! :
-- there are some places where race conditions can play a role. this is
-- because of sharing of nsset and contacts. their status 'linked' is
-- updated when they appear in EPP commands on others object and because
-- of parallel execution of these commands, linked status is 'shared resource'.
--  1. setting linked state. situation when two transactions want to add 
--     linked state is handled by UNIQUE constraint and EXCEPTION 
--     catching in status_set_state function. second setting is let to fail
--     alternative is to lock all table with states which is inefficient
--  2. clearing linked state. when test is done to clear a state, there
--     can appear transaction that change results of this before clear so
--     test and clear need to be atomic. this must be done by row locking
--     of linked state row in states table. this is done by function
--     status_clear_lock.
CREATE OR REPLACE FUNCTION status_clear_lock(integer, integer)
RETURNS boolean
AS $$
SELECT id IS NOT NULL FROM object_state 
WHERE object_id=$1 AND state_id=$2 AND valid_to IS NULL FOR UPDATE;
$$ LANGUAGE SQL;

-- set state of object if condition is satisfied. use optimistic access
-- so there is no need for locking, could be enhanced by checking of 
-- presence of state (to minimize number of failures in unique constraint)
-- but expectation is that this is faster
-- this function only set state, it won't clean it (see next function) 
CREATE OR REPLACE FUNCTION status_set_state(
  _cond BOOL, _state_id INTEGER, _object_id INTEGER
) RETURNS VOID AS $$
 BEGIN
   IF _cond THEN
     -- optimistic access, don't check if status exists
     -- but may fail on UNIQUE constraint, so catching exception 
     INSERT INTO object_state (object_id, state_id, valid_from)
     VALUES (_object_id, _state_id, CURRENT_TIMESTAMP);
   END IF;
 EXCEPTION
   WHEN UNIQUE_VIOLATION THEN
   -- do nothing
 END;
$$ LANGUAGE plpgsql;

-- clear state of object
CREATE OR REPLACE FUNCTION status_clear_state(
  _cond BOOL, _state_id INTEGER, _object_id INTEGER
) RETURNS VOID AS $$
 BEGIN
   IF NOT _cond THEN
     -- condition (valid_to IS NULL) is essential to avoid closing closed
     -- state
     UPDATE object_state SET valid_to = CURRENT_TIMESTAMP
     WHERE state_id = _state_id AND valid_to IS NULL 
     AND object_id = _object_id;
   END IF;
 END;
$$ LANGUAGE plpgsql;

-- set state of object and clear state of object according to condition
CREATE OR REPLACE FUNCTION status_update_state(
  _cond BOOL, _state_id INTEGER, _object_id INTEGER
) RETURNS VOID AS $$
 DECLARE
   _num INTEGER;
 BEGIN
   -- don't know if it's faster to not test condition twise or call EXECUTE
   -- that immidietely return (removing IF), guess is twice test is faster
   IF _cond THEN
     EXECUTE status_set_state(_cond, _state_id, _object_id);
   ELSE
     EXECUTE status_clear_state(_cond, _state_id, _object_id);
   END IF;
 END;
$$ LANGUAGE plpgsql;

-- trigger function to handle dependant state. some states depends on others
-- so trigger is fired on state table after every change and
-- dependant states are updated aproprietly
CREATE OR REPLACE FUNCTION status_update_object_state() RETURNS TRIGGER AS $$
  DECLARE
    _states INTEGER[];
  BEGIN
    IF NEW.state_id = ANY (ARRAY[5,6,10,13,14]) THEN
      -- activation is only done on states that are relevant for
      -- dependant states to stop RECURSION
      SELECT array_accum(state_id) INTO _states FROM object_state
          WHERE valid_to IS NULL AND object_id = NEW.object_id;
      -- set or clear status 15 (outzone)
      EXECUTE status_update_state(
        (14 = ANY (_states)) OR -- nsset is null
        (5  = ANY (_states)) OR -- serverOutzoneManual
        (NOT (6 = ANY (_states)) AND -- not serverInzoneManual
          ((10 = ANY (_states)) OR -- unguarded
           (13 = ANY (_states)))),  -- not validated
        15, NEW.object_id -- => set outzone
      );
      -- set or clear status 15 (outzoneUnguarded)
      EXECUTE status_update_state(
        NOT (6 = ANY (_states)) AND -- not serverInzoneManual
            (10 = ANY (_states)), -- unguarded
        20, NEW.object_id -- => set ouzoneUnguarded
      );
    END IF;
    RETURN NEW;
  END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_object_state AFTER INSERT OR UPDATE
  ON object_state FOR EACH ROW EXECUTE PROCEDURE status_update_object_state();

-- update history id of object at status opening and closing
-- it's useful to catch history id of object on state opening and closing
-- to centralize this setting, it's done by trigger here
CREATE OR REPLACE FUNCTION status_update_hid() RETURNS TRIGGER AS $$
  BEGIN
    IF TG_OP = 'UPDATE' AND NEW.ohid_to ISNULL THEN
      SELECT historyid INTO NEW.ohid_to 
      FROM object_registry WHERE id=NEW.object_id;
    ELSE IF TG_OP = 'INSERT' AND NEW.ohid_from ISNULL THEN
        SELECT historyid INTO NEW.ohid_from 
        FROM object_registry WHERE id=NEW.object_id;
      END IF;
    END IF;
    RETURN NEW;
  END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_object_state_hid BEFORE INSERT OR UPDATE
  ON object_state FOR EACH ROW EXECUTE PROCEDURE status_update_hid();

-- trigger to update state of domain, fired with every change on
-- on domain table
CREATE OR REPLACE FUNCTION status_update_domain() RETURNS TRIGGER AS $$
  DECLARE
    _num INTEGER;
    _nsset_old INTEGER;
    _registrant_old INTEGER;
    _keyset_old INTEGER;
    _nsset_new INTEGER;
    _registrant_new INTEGER;
    _keyset_new INTEGER;
    _ex_not VARCHAR;
    _ex_dns VARCHAR;
    _ex_let VARCHAR;
--    _ex_reg VARCHAR;
    _proc_tm VARCHAR;
    _proc_tz VARCHAR;
    _proc_tm2 VARCHAR;
  BEGIN
    _nsset_old := NULL;
    _registrant_old := NULL;
    _keyset_old := NULL;
    _nsset_new := NULL;
    _registrant_new := NULL;
    _keyset_new := NULL;
    SELECT val INTO _ex_not FROM enum_parameters WHERE id=3;
    SELECT val INTO _ex_dns FROM enum_parameters WHERE id=4;
    SELECT val INTO _ex_let FROM enum_parameters WHERE id=5;
--    SELECT val INTO _ex_reg FROM enum_parameters WHERE id=6;
    SELECT val INTO _proc_tm FROM enum_parameters WHERE id=9;
    SELECT val INTO _proc_tz FROM enum_parameters WHERE id=10;
    SELECT val INTO _proc_tm2 FROM enum_parameters WHERE id=14;
    -- is it INSERT operation
    IF TG_OP = 'INSERT' THEN
      _registrant_new := NEW.registrant;
      _nsset_new := NEW.nsset;
      _keyset_new := NEW.keyset;
      -- we ignore exdate, for new domain it shouldn't influence its state
      -- state: nsset missing
      EXECUTE status_update_state(
        NEW.nsset ISNULL, 14, NEW.id
      );
    -- is it UPDATE operation
    ELSIF TG_OP = 'UPDATE' THEN
      IF NEW.registrant <> OLD.registrant THEN
        _registrant_old := OLD.registrant;
        _registrant_new := NEW.registrant;
      END IF;
      IF COALESCE(NEW.nsset,0) <> COALESCE(OLD.nsset,0) THEN
        _nsset_old := OLD.nsset;
        _nsset_new := NEW.nsset;
      END IF;
      IF COALESCE(NEW.keyset,0) <> COALESCE(OLD.keyset,0) THEN
        _keyset_old := OLD.keyset;
        _keyset_new := NEW.keyset;
      END IF;
      -- take care of all domain statuses
      IF NEW.exdate <> OLD.exdate THEN
        -- at the first sight it seems that there should be checking
        -- for renewProhibited state before setting all of these states
        -- as it's done in global (1. type) views
        -- but the point is that when renewProhibited is set
        -- there is no way to change exdate so this situation can never happen 
        -- state: expiration warning
        EXECUTE status_update_state(
          date_test(NEW.exdate::date,_ex_not),
          8, NEW.id
        );
        -- state: expired
        EXECUTE status_update_state(
          date_test(NEW.exdate::date,'0'),
          9, NEW.id
        );
        -- state: unguarded
        EXECUTE status_update_state(
          date_time_test(NEW.exdate::date,_ex_dns,_proc_tm2,_proc_tz), 
          10, NEW.id
        );
        -- state: deleteWarning
        EXECUTE status_update_state(
          date_test(NEW.exdate::date,_ex_let),
          19, NEW.id
        );
        -- state: delete candidate (seems useless - cannot switch after del)
        -- for now delete state will be set only globaly
--        EXECUTE status_update_state(
--          date_time_test(NEW.exdate::date,_ex_reg,_proc_tm,_proc_tz), 
--          17, NEW.id
--        );
      END IF; -- change in exdate
      IF COALESCE(NEW.nsset,0) <> COALESCE(OLD.nsset,0) THEN
        -- state: nsset missing
        EXECUTE status_update_state(
          NEW.nsset ISNULL, 14, NEW.id
        );
      END IF; -- change in nsset
    -- is it DELETE operation
    ELSIF TG_OP = 'DELETE' THEN
      _registrant_old := OLD.registrant;
      _nsset_old := OLD.nsset; -- may be NULL!
      _keyset_old := OLD.keyset; -- may be NULL!
      -- exdate is meaningless when deleting (probably)
    END IF;

    -- add registrant's linked status if there is none
    EXECUTE status_set_state(
      _registrant_new IS NOT NULL, 16, _registrant_new
    );
    -- add nsset's linked status if there is none
    EXECUTE status_set_state(
      _nsset_new IS NOT NULL, 16, _nsset_new
    );
    -- add keyset's linked status if there is none
    EXECUTE status_set_state(
      _keyset_new IS NOT NULL, 16, _keyset_new
    );
    -- remove registrant's linked status if not bound
    -- locking must be done (see comment above)
    IF _registrant_old IS NOT NULL AND 
       status_clear_lock(_registrant_old, 16) IS NOT NULL 
    THEN
      SELECT count(*) INTO _num FROM domain
          WHERE registrant = OLD.registrant;
      IF _num = 0 THEN
        SELECT count(*) INTO _num FROM domain_contact_map
            WHERE contactid = OLD.registrant;
        IF _num = 0 THEN
          SELECT count(*) INTO _num FROM nsset_contact_map
              WHERE contactid = OLD.registrant;
          IF _num = 0 THEN
            SELECT count(*) INTO _num FROM keyset_contact_map
                WHERE contactid = OLD.registrant;
            EXECUTE status_clear_state(_num <> 0, 16, OLD.registrant);
          END IF;
        END IF;
      END IF;
    END IF;
    -- remove nsset's linked status if not bound
    -- locking must be done (see comment above)
    IF _nsset_old IS NOT NULL AND
       status_clear_lock(_nsset_old, 16) IS NOT NULL  
    THEN
      SELECT count(*) INTO _num FROM domain WHERE nsset = OLD.nsset;
      EXECUTE status_clear_state(_num <> 0, 16, OLD.nsset);
    END IF;
    -- remove keyset's linked status if not bound
    -- locking must be done (see comment above)
    IF _keyset_old IS NOT NULL AND
       status_clear_lock(_keyset_old, 16) IS NOT NULL  
    THEN
      SELECT count(*) INTO _num FROM domain WHERE keyset = OLD.keyset;
      EXECUTE status_clear_state(_num <> 0, 16, OLD.keyset);
    END IF;
    RETURN NULL;
  END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_domain AFTER INSERT OR DELETE OR UPDATE
  ON domain FOR EACH ROW EXECUTE PROCEDURE status_update_domain();

CREATE OR REPLACE FUNCTION status_update_enumval() RETURNS TRIGGER AS $$
  DECLARE
    _num INTEGER;
  BEGIN
    -- is it UPDATE operation
    IF TG_OP = 'UPDATE' AND NEW.exdate <> OLD.exdate THEN
      -- state: validation warning 1
      EXECUTE status_update_state(
        NEW.exdate::date - INTERVAL '30 days' <= CURRENT_DATE, 11, NEW.domainid
      );
      -- state: validation warning 2
      EXECUTE status_update_state(
        NEW.exdate::date - INTERVAL '15 days' <= CURRENT_DATE, 12, NEW.domainid
      );
      -- state: not validated
      EXECUTE status_update_state(
        NEW.exdate::date + INTERVAL '14 hours' <= CURRENT_TIMESTAMP, 13, NEW.domainid
      );
    END IF;
    RETURN NULL;
  END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_enumval AFTER UPDATE ON enumval
    FOR EACH ROW EXECUTE PROCEDURE status_update_enumval();

CREATE OR REPLACE FUNCTION status_update_contact_map() RETURNS TRIGGER AS $$
  DECLARE
    _num INTEGER;
    _contact_old INTEGER;
    _contact_new INTEGER;
  BEGIN
    _contact_old := NULL;
    _contact_new := NULL;
    -- is it INSERT operation
    IF TG_OP = 'INSERT' THEN
      _contact_new := NEW.contactid;
    -- is it UPDATE operation
    ELSIF TG_OP = 'UPDATE' THEN
      IF NEW.contactid <> OLD.contactid THEN
        _contact_old := OLD.contactid;
        _contact_new := NEW.contactid;
      END IF;
    -- is it DELETE operation
    ELSIF TG_OP = 'DELETE' THEN
      _contact_old := OLD.contactid;
    END IF;

    -- add contact's linked status if there is none
    EXECUTE status_set_state(
      _contact_new IS NOT NULL, 16, _contact_new
    );
    -- remove contact's linked status if not bound
    -- locking must be done (see comment above)
    IF _contact_old IS NOT NULL AND
       status_clear_lock(_contact_old, 16) IS NOT NULL 
    THEN
      SELECT count(*) INTO _num FROM domain WHERE registrant = OLD.contactid;
      IF _num = 0 THEN
        SELECT count(*) INTO _num FROM domain_contact_map
            WHERE contactid = OLD.contactid;
        IF _num = 0 THEN
          SELECT count(*) INTO _num FROM nsset_contact_map
              WHERE contactid = OLD.contactid;
          IF _num = 0 THEN
            SELECT count(*) INTO _num FROM keyset_contact_map
                WHERE contactid = OLD.contactid;
            EXECUTE status_clear_state(_num <> 0, 16, OLD.contactid);
          END IF;
        END IF;
      END IF;
    END IF;
    RETURN NULL;
  END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_domain_contact_map AFTER INSERT OR DELETE OR UPDATE
  ON domain_contact_map FOR EACH ROW 
  EXECUTE PROCEDURE status_update_contact_map();

CREATE TRIGGER trigger_nsset_contact_map AFTER INSERT OR DELETE OR UPDATE
  ON nsset_contact_map FOR EACH ROW 
  EXECUTE PROCEDURE status_update_contact_map();

CREATE TRIGGER trigger_keyset_contact_map AFTER INSERT OR DELETE OR UPDATE
  ON keyset_contact_map FOR EACH ROW 
  EXECUTE PROCEDURE status_update_contact_map();

-- object history tables are filled after normal object tables (i.e. domain)
-- and so when new state is generated as result of new row in normal 
-- table, no history table is available to reference in ohid_from
-- this trigger fix this be filling unfilled ohid_from after insert
-- into history
CREATE OR REPLACE FUNCTION object_history_insert() RETURNS TRIGGER AS $$
  BEGIN
    UPDATE object_state SET ohid_from=NEW.historyid 
    WHERE ohid_from ISNULL AND object_id=NEW.id;
    RETURN NEW;
  END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_object_history AFTER INSERT
  ON object_history FOR EACH ROW 
  EXECUTE PROCEDURE object_history_insert();

---
--- Ticket #7122 - lock object_state_request for manual state insert or update by state and object to the end of db transaction
---

CREATE TABLE object_state_request_lock
(
    id bigserial PRIMARY KEY -- lock id
    , state_id integer NOT NULL REFERENCES enum_object_states (id)
    , object_id integer NOT NULL --REFERENCES object_registry (id)
);

CREATE OR REPLACE FUNCTION lock_object_state_request_lock( f_state_id BIGINT, f_object_id BIGINT)
RETURNS void AS $$
DECLARE
BEGIN
    PERFORM * FROM object_state_request_lock
    WHERE state_id = f_state_id
    AND object_id = f_object_id ORDER BY id FOR UPDATE; --wait if locked
    IF NOT FOUND THEN
        RAISE EXCEPTION 'Failed to lock state_id: % object_id: %', f_state_id, f_object_id;
    END IF;
END;
$$ LANGUAGE plpgsql;


-- lock object_state_request for manual states
CREATE OR REPLACE FUNCTION lock_object_state_request()
RETURNS "trigger" AS $$
DECLARE
max_id_to_delete BIGINT;
BEGIN
  --lock for manual states
  PERFORM * FROM enum_object_states WHERE id = NEW.state_id AND manual = true;
  IF NOT FOUND THEN
    RETURN NEW;
  END IF;
  
  RAISE NOTICE 'lock_object_state_request NEW.id: % NEW.state_id: % NEW.object_id: %'
  , NEW.id, NEW.state_id, NEW.object_id ;
    PERFORM lock_object_state_request_lock( NEW.state_id, NEW.object_id);
  --try cleanup
  BEGIN
    SELECT MAX(id) - 100 FROM object_state_request_lock INTO max_id_to_delete;
    PERFORM * FROM object_state_request_lock
      WHERE id < max_id_to_delete FOR UPDATE NOWAIT;
    IF FOUND THEN
      DELETE FROM object_state_request_lock
        WHERE id < max_id_to_delete;
    END IF;
  EXCEPTION WHEN lock_not_available THEN
    RAISE NOTICE 'cleanup lock not available';
  END;

  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION lock_object_state_request()
IS 'lock changes of object state requests by object and state';

CREATE TRIGGER "trigger_lock_object_state_request"
  AFTER INSERT OR UPDATE ON object_state_request
  FOR EACH ROW EXECUTE PROCEDURE lock_object_state_request();

CREATE TABLE MessageType (
        ID INTEGER PRIMARY KEY,
	name VARCHAR(30) NOT NULL
);
-- do not change the number codes - current code depends on it!
INSERT INTO MessageType VALUES (01, 'credit');
INSERT INTO MessageType VALUES (02, 'techcheck');
INSERT INTO MessageType VALUES (03, 'transfer_contact');
INSERT INTO MessageType VALUES (04, 'transfer_nsset');
INSERT INTO MessageType VALUES (05, 'transfer_domain');
INSERT INTO MessageType VALUES (06, 'delete_contact');
INSERT INTO MessageType VALUES (07, 'delete_nsset');
INSERT INTO MessageType VALUES (08, 'delete_domain');
INSERT INTO MessageType VALUES (09, 'imp_expiration');
INSERT INTO MessageType VALUES (10, 'expiration');
INSERT INTO MessageType VALUES (11, 'imp_validation');
INSERT INTO MessageType VALUES (12, 'validation');
INSERT INTO MessageType VALUES (13, 'outzone');
INSERT INTO MessageType VALUES (14, 'transfer_keyset');
INSERT INTO MessageType VALUES (15, 'delete_keyset');

comment on table MessageType is
'table with message number codes and its names

id - name
01 - credit
02 - techcheck
03 - transfer_contact
04 - transfer_nsset
05 - transfer_domain
06 - delete_contact
07 - delete_nsset
08 - delete_domain
09 - imp_expiration
10 - expiration
11 - imp_validation
12 - validation
13 - outzone';

CREATE TABLE Message (
        ID SERIAL PRIMARY KEY,
        ClID INTEGER NOT NULL REFERENCES Registrar ON UPDATE CASCADE,
        CrDate timestamp NOT NULL DEFAULT now(),
        ExDate TIMESTAMP,
        Seen BOOLEAN NOT NULL DEFAULT false,
	MsgType INTEGER REFERENCES messagetype (id)
);
CREATE INDEX message_clid_idx ON message (clid);
CREATE INDEX message_seen_idx ON message (clid,seen,crdate,exdate);

comment on table Message is 'Evidence of messages for registrars, which can be picked up by epp poll funcion';

CREATE TABLE poll_credit (
  msgid INTEGER PRIMARY KEY REFERENCES message (id),
  zone INTEGER REFERENCES zone (id),
  credlimit numeric(10,2) NOT NULL,
  credit numeric(10,2) NOT NULL
);

CREATE TABLE poll_credit_zone_limit (
  zone INTEGER PRIMARY KEY REFERENCES zone(id),
  credlimit numeric(10,2) NOT NULL
);

CREATE TABLE poll_eppaction (
  msgid INTEGER PRIMARY KEY REFERENCES message (id),
  objid INTEGER REFERENCES object_history (historyid)
);

CREATE TABLE poll_techcheck (
  msgid INTEGER PRIMARY KEY REFERENCES message (id),
  cnid INTEGER REFERENCES check_nsset (id)
);

CREATE TABLE poll_stateChange (
  msgid INTEGER PRIMARY KEY REFERENCES message (id),
  stateid INTEGER REFERENCES object_state (id)
);

CREATE INDEX poll_statechange_stateid_idx ON poll_statechange (stateid);
---
--- table for poll messages used for request charging feature
---
CREATE TABLE poll_request_fee (
      msgid integer NOT NULL PRIMARY KEY REFERENCES message(id),
      period_from timestamp without time zone NOT NULL,
      period_to timestamp without time zone NOT NULL,
      total_free_count bigint NOT NULL,
      used_count bigint NOT NULL,
      price numeric(10, 2) NOT NULL
);

--- 
--- table with parameters for charging requests to registry
---
CREATE TABLE request_fee_parameter (
    id INTEGER PRIMARY KEY,
    valid_from timestamp NOT NULL,
    count_free_base INTEGER,
    count_free_per_domain INTEGER,
    zone_id INTEGER NOT NULL REFERENCES zone(id)
);


CREATE TABLE request_fee_registrar_parameter (
registrar_id INTEGER PRIMARY KEY REFERENCES registrar(id),
request_price_limit numeric(10, 2) NOT NULL,
email varchar(200) NOT NULL,
telephone varchar(64) NOT NULL
-- [ contact_id REFERENCES contact(id) ]
);


---
--- inserting new poll message type
---
INSERT INTO messagetype (id, name) VALUES (16, 'request_fee_info');

---
--- general registry operation used in price_list entry for request charging
--- 
INSERT INTO enum_operation (id, operation) VALUES (3, 'GeneralEppOperation');

-- notification processing rules - direct notifier what mails
-- need to be send and whom upon object state change
CREATE TABLE notify_statechange_map (
  id INTEGER PRIMARY KEY, 
  state_id INTEGER NOT NULL REFERENCES enum_object_states (id), 
  obj_type INTEGER NOT NULL, 
  mail_type_id INTEGER NOT NULL REFERENCES mail_type (id),
  emails INTEGER
);

comment on table notify_statechange_map is
'Notification processing rules - direct notifier what mails need to be send
and whom upon object state change';

comment on column notify_statechange_map.state_id is 'id of state to be notified by email';
comment on column notify_statechange_map.obj_type is 'type of object to be notified (1..contact, 2..nsset, 3..domain, 4..keyset)';
comment on column notify_statechange_map.mail_type_id is 'type of mail to be send';
comment on column notify_statechange_map.emails is 'type of contact group to be notified by email (1..admins, 2..techs)';

-- state: expiration, obj: domain, 
-- template: expiration_notify, emails: admins
INSERT INTO notify_statechange_map VALUES ( 1,  9, 3,  3, 1);
-- state: outzoneUnguarded, obj: domain, 
-- template: expiration_dns_owner, emails: admins
INSERT INTO notify_statechange_map VALUES ( 2, 20, 3,  4, 1);
-- state: deleteCandidate, obj: domain,
-- template: expiration_register_owner, emails: admins
INSERT INTO notify_statechange_map VALUES ( 3, 17, 3,  5, 1);
-- state: deleteCandidate, obj: nsset,
-- template: notification_unused, emails: admins
INSERT INTO notify_statechange_map VALUES ( 4, 17, 2, 14, 1);
-- state: deleteCandidate, obj: contact,
-- template: notification_unused, emails: admin
INSERT INTO notify_statechange_map VALUES ( 5, 17, 1, 14, 1);
-- state: outzoneUnguarded, obj: domain,
-- template: expiration_dns_tech, emails: techs
INSERT INTO notify_statechange_map VALUES ( 6, 20, 3,  6, 2);
-- state: deleteCandidate, obj: domain,
-- template: expiration_register_tech, emails: techs
INSERT INTO notify_statechange_map VALUES ( 7, 17, 3,  7, 2);
-- state: validationWarning2, obj: domain, 
-- template: expiration_validation_before, emails: admins
INSERT INTO notify_statechange_map VALUES ( 8, 12, 3,  8, 1);
-- state: validation, obj: domain, 
-- template: expiration_validation, emails: admins
INSERT INTO notify_statechange_map VALUES ( 9, 13, 3,  9, 1);
-- state: validation, obj: domain, 
-- template: expiration_tech_dns, emails: techs
INSERT INTO notify_statechange_map VALUES (10, 13, 3,  6, 2);
-- state: deleteCandidate, obj: keyset,
-- template: notification_unused, emails: admin
INSERT INTO notify_statechange_map VALUES (11, 17, 4, 14, 1);
-- state: outzoneUnguarded, obj: domain, 
-- template: expiration_dns_owner, emails: generic emails (like kontakt@... postmaster@... info@...)
INSERT INTO notify_statechange_map VALUES (12, 20, 3, 4, 3);

-- store information about successfull notification
CREATE TABLE notify_statechange (
  -- which statechange triggered notification
  state_id INTEGER NOT NULL REFERENCES object_state (id),
  -- what notificaton was done
  type INTEGER NOT NULL REFERENCES notify_statechange_map (id),
  -- email with result of notification (null if contacts have no email)
  mail_id INTEGER REFERENCES mail_archive (id),
  PRIMARY KEY (state_id, type)
);

comment on table notify_statechange is 'store information about successfull notification';
comment on column notify_statechange.state_id is 'which statechnage triggered notification';
comment on column notify_statechange.type is 'what notification was done';
comment on column notify_statechange.mail_id is 'email with result of notification (null if contact have no email)';

--message_archive 

CREATE TABLE comm_type
(
  id  SERIAL PRIMARY KEY,
  type VARCHAR(64) -- email, letter, sms
);

comment on table comm_type is 'type of communication with contact';

INSERT INTO comm_type (id,type) VALUES (1,'email');
INSERT INTO comm_type (id,type) VALUES (2,'letter');
INSERT INTO comm_type (id,type) VALUES (3,'sms');
INSERT INTO comm_type (id,type) VALUES (4,'registered_letter');

CREATE TABLE message_type
(
  id  SERIAL PRIMARY KEY,
  type VARCHAR(64) -- domain_expiration, mojeid_pin2, mojeid_pin3,...
);

comment on table message_type is 'type of message with respect to subject of message';

INSERT INTO message_type (id,type) VALUES (1,'domain_expiration');

CREATE TABLE message_archive
(
  id  SERIAL PRIMARY KEY,
  crdate timestamp without time zone NOT NULL DEFAULT now(), -- date of insertion in table
  moddate timestamp without time zone, -- date of sending (even if unsuccesfull)
  attempt smallint NOT NULL DEFAULT 0, -- failed attempts to send data
  status_id INTEGER REFERENCES enum_send_status (id), -- message_status
  comm_type_id INTEGER REFERENCES comm_type (id), --  communication channel
  message_type_id INTEGER REFERENCES message_type (id) --  message type
);

CREATE INDEX message_archive_crdate_idx ON message_archive (crdate);
CREATE INDEX message_archive_status_id_idx ON message_archive (status_id);
CREATE INDEX message_archive_comm_type_id_idx ON message_archive (comm_type_id);

comment on column message_archive.crdate is 'date and time of insertion in table';
comment on column message_archive.moddate is 'date and time of sending (event unsuccesfull)';
comment on column message_archive.status_id is 'status';

CREATE TABLE message_contact_history_map
(
  id  SERIAL PRIMARY KEY,
  contact_object_registry_id INTEGER,-- REFERENCES object_registry (id), -- id type contact
  contact_history_historyid INTEGER, -- REFERENCES contact_history (historyid), -- historyid 
  message_archive_id INTEGER REFERENCES message_archive (id) -- message
);

--sms archive
CREATE TABLE sms_archive
(
  id INTEGER PRIMARY KEY REFERENCES message_archive (id), -- message_archive id
  phone_number VARCHAR(64) NOT NULL, -- copy of phone number
  phone_number_id INTEGER, -- unused 
  content TEXT -- sms text content
);


-- letters sent electronically as PDF documents to postal service, address is included in the document

CREATE TABLE letter_archive
(
  id INTEGER PRIMARY KEY REFERENCES message_archive (id),
  file_id integer REFERENCES files (id), -- file with pdf about notification (null for old)
  batch_id character varying(64), -- postservis batch id - multiple letters are bundled into batches
  postal_address_name character varying(1024),
  postal_address_organization character varying(1024),
  postal_address_street1 character varying(1024),
  postal_address_street2 character varying(1024),
  postal_address_street3 character varying(1024),
  postal_address_city character varying(1024),
  postal_address_stateorprovince character varying(1024),
  postal_address_postalcode character varying(32),
  postal_address_country character varying(1024),
  postal_address_id integer
);

COMMENT ON TABLE letter_archive IS 'letters sent electronically as PDF documents to postal service, address is included in the document';
COMMENT ON COLUMN letter_archive.file_id IS 'file with pdf about notification (null for old)';
COMMENT ON COLUMN letter_archive.batch_id IS 'postservis batch id - multiple letters are bundled into batches';

CREATE INDEX letter_archive_batch_id ON letter_archive (batch_id);

CREATE TABLE notify_letters (
  -- which statechange triggered notification
  state_id INTEGER NOT NULL PRIMARY KEY REFERENCES object_state (id),
  -- which message notifies the state change
  letter_id INTEGER REFERENCES letter_archive (id)
);  

CREATE INDEX notify_letters_status_idx ON notify_letters (state_id);
CREATE INDEX notify_letters_letter_id_idx ON notify_letters (letter_id);

comment on table notify_letters is 'notifications about deleteWarning state sent as PDF letters';
comment on column notify_letters.state_id is 'which statechange triggered notification';
comment on column notify_letters.letter_id is 'which message notifies the state change';


CREATE TABLE notify_request
(
    request_id BIGINT NOT NULL, 
    message_id INTEGER UNIQUE NOT NULL REFERENCES mail_archive(id),
    PRIMARY KEY (request_id, message_id)
);

-- list of available tlds for checking of dns host tld
CREATE TABLE enum_tlds (
  tld VARCHAR(64) NOT NULL PRIMARY KEY
);

INSERT INTO enum_tlds (tld) VALUES ('AC');
INSERT INTO enum_tlds (tld) VALUES ('AD');
INSERT INTO enum_tlds (tld) VALUES ('AE');
INSERT INTO enum_tlds (tld) VALUES ('AERO');
INSERT INTO enum_tlds (tld) VALUES ('AF');
INSERT INTO enum_tlds (tld) VALUES ('AG');
INSERT INTO enum_tlds (tld) VALUES ('AI');
INSERT INTO enum_tlds (tld) VALUES ('AL');
INSERT INTO enum_tlds (tld) VALUES ('AM');
INSERT INTO enum_tlds (tld) VALUES ('AN');
INSERT INTO enum_tlds (tld) VALUES ('AO');
INSERT INTO enum_tlds (tld) VALUES ('AQ');
INSERT INTO enum_tlds (tld) VALUES ('AR');
INSERT INTO enum_tlds (tld) VALUES ('ARPA');
INSERT INTO enum_tlds (tld) VALUES ('AS');
INSERT INTO enum_tlds (tld) VALUES ('ASIA');
INSERT INTO enum_tlds (tld) VALUES ('AT');
INSERT INTO enum_tlds (tld) VALUES ('AU');
INSERT INTO enum_tlds (tld) VALUES ('AW');
INSERT INTO enum_tlds (tld) VALUES ('AX');
INSERT INTO enum_tlds (tld) VALUES ('AZ');
INSERT INTO enum_tlds (tld) VALUES ('BA');
INSERT INTO enum_tlds (tld) VALUES ('BB');
INSERT INTO enum_tlds (tld) VALUES ('BD');
INSERT INTO enum_tlds (tld) VALUES ('BE');
INSERT INTO enum_tlds (tld) VALUES ('BF');
INSERT INTO enum_tlds (tld) VALUES ('BG');
INSERT INTO enum_tlds (tld) VALUES ('BH');
INSERT INTO enum_tlds (tld) VALUES ('BI');
INSERT INTO enum_tlds (tld) VALUES ('BIZ');
INSERT INTO enum_tlds (tld) VALUES ('BJ');
INSERT INTO enum_tlds (tld) VALUES ('BM');
INSERT INTO enum_tlds (tld) VALUES ('BN');
INSERT INTO enum_tlds (tld) VALUES ('BO');
INSERT INTO enum_tlds (tld) VALUES ('BR');
INSERT INTO enum_tlds (tld) VALUES ('BS');
INSERT INTO enum_tlds (tld) VALUES ('BT');
INSERT INTO enum_tlds (tld) VALUES ('BV');
INSERT INTO enum_tlds (tld) VALUES ('BW');
INSERT INTO enum_tlds (tld) VALUES ('BY');
INSERT INTO enum_tlds (tld) VALUES ('BZ');
INSERT INTO enum_tlds (tld) VALUES ('CA');
INSERT INTO enum_tlds (tld) VALUES ('CAT');
INSERT INTO enum_tlds (tld) VALUES ('CC');
INSERT INTO enum_tlds (tld) VALUES ('CD');
INSERT INTO enum_tlds (tld) VALUES ('CF');
INSERT INTO enum_tlds (tld) VALUES ('CG');
INSERT INTO enum_tlds (tld) VALUES ('CH');
INSERT INTO enum_tlds (tld) VALUES ('CI');
INSERT INTO enum_tlds (tld) VALUES ('CK');
INSERT INTO enum_tlds (tld) VALUES ('CL');
INSERT INTO enum_tlds (tld) VALUES ('CM');
INSERT INTO enum_tlds (tld) VALUES ('CN');
INSERT INTO enum_tlds (tld) VALUES ('CO');
INSERT INTO enum_tlds (tld) VALUES ('COM');
INSERT INTO enum_tlds (tld) VALUES ('COOP');
INSERT INTO enum_tlds (tld) VALUES ('CR');
INSERT INTO enum_tlds (tld) VALUES ('CU');
INSERT INTO enum_tlds (tld) VALUES ('CV');
INSERT INTO enum_tlds (tld) VALUES ('CX');
INSERT INTO enum_tlds (tld) VALUES ('CY');
INSERT INTO enum_tlds (tld) VALUES ('CZ');
INSERT INTO enum_tlds (tld) VALUES ('DE');
INSERT INTO enum_tlds (tld) VALUES ('DJ');
INSERT INTO enum_tlds (tld) VALUES ('DK');
INSERT INTO enum_tlds (tld) VALUES ('DM');
INSERT INTO enum_tlds (tld) VALUES ('DO');
INSERT INTO enum_tlds (tld) VALUES ('DZ');
INSERT INTO enum_tlds (tld) VALUES ('EC');
INSERT INTO enum_tlds (tld) VALUES ('EDU');
INSERT INTO enum_tlds (tld) VALUES ('EE');
INSERT INTO enum_tlds (tld) VALUES ('EG');
INSERT INTO enum_tlds (tld) VALUES ('ER');
INSERT INTO enum_tlds (tld) VALUES ('ES');
INSERT INTO enum_tlds (tld) VALUES ('ET');
INSERT INTO enum_tlds (tld) VALUES ('EU');
INSERT INTO enum_tlds (tld) VALUES ('FI');
INSERT INTO enum_tlds (tld) VALUES ('FJ');
INSERT INTO enum_tlds (tld) VALUES ('FK');
INSERT INTO enum_tlds (tld) VALUES ('FM');
INSERT INTO enum_tlds (tld) VALUES ('FO');
INSERT INTO enum_tlds (tld) VALUES ('FR');
INSERT INTO enum_tlds (tld) VALUES ('GA');
INSERT INTO enum_tlds (tld) VALUES ('GB');
INSERT INTO enum_tlds (tld) VALUES ('GD');
INSERT INTO enum_tlds (tld) VALUES ('GE');
INSERT INTO enum_tlds (tld) VALUES ('GF');
INSERT INTO enum_tlds (tld) VALUES ('GG');
INSERT INTO enum_tlds (tld) VALUES ('GH');
INSERT INTO enum_tlds (tld) VALUES ('GI');
INSERT INTO enum_tlds (tld) VALUES ('GL');
INSERT INTO enum_tlds (tld) VALUES ('GM');
INSERT INTO enum_tlds (tld) VALUES ('GN');
INSERT INTO enum_tlds (tld) VALUES ('GOV');
INSERT INTO enum_tlds (tld) VALUES ('GP');
INSERT INTO enum_tlds (tld) VALUES ('GQ');
INSERT INTO enum_tlds (tld) VALUES ('GR');
INSERT INTO enum_tlds (tld) VALUES ('GS');
INSERT INTO enum_tlds (tld) VALUES ('GT');
INSERT INTO enum_tlds (tld) VALUES ('GU');
INSERT INTO enum_tlds (tld) VALUES ('GW');
INSERT INTO enum_tlds (tld) VALUES ('GY');
INSERT INTO enum_tlds (tld) VALUES ('HK');
INSERT INTO enum_tlds (tld) VALUES ('HM');
INSERT INTO enum_tlds (tld) VALUES ('HN');
INSERT INTO enum_tlds (tld) VALUES ('HR');
INSERT INTO enum_tlds (tld) VALUES ('HT');
INSERT INTO enum_tlds (tld) VALUES ('HU');
INSERT INTO enum_tlds (tld) VALUES ('ID');
INSERT INTO enum_tlds (tld) VALUES ('IE');
INSERT INTO enum_tlds (tld) VALUES ('IL');
INSERT INTO enum_tlds (tld) VALUES ('IM');
INSERT INTO enum_tlds (tld) VALUES ('IN');
INSERT INTO enum_tlds (tld) VALUES ('INFO');
INSERT INTO enum_tlds (tld) VALUES ('INT');
INSERT INTO enum_tlds (tld) VALUES ('IO');
INSERT INTO enum_tlds (tld) VALUES ('IQ');
INSERT INTO enum_tlds (tld) VALUES ('IR');
INSERT INTO enum_tlds (tld) VALUES ('IS');
INSERT INTO enum_tlds (tld) VALUES ('IT');
INSERT INTO enum_tlds (tld) VALUES ('JE');
INSERT INTO enum_tlds (tld) VALUES ('JM');
INSERT INTO enum_tlds (tld) VALUES ('JO');
INSERT INTO enum_tlds (tld) VALUES ('JOBS');
INSERT INTO enum_tlds (tld) VALUES ('JP');
INSERT INTO enum_tlds (tld) VALUES ('KE');
INSERT INTO enum_tlds (tld) VALUES ('KG');
INSERT INTO enum_tlds (tld) VALUES ('KH');
INSERT INTO enum_tlds (tld) VALUES ('KI');
INSERT INTO enum_tlds (tld) VALUES ('KM');
INSERT INTO enum_tlds (tld) VALUES ('KN');
INSERT INTO enum_tlds (tld) VALUES ('KP');
INSERT INTO enum_tlds (tld) VALUES ('KR');
INSERT INTO enum_tlds (tld) VALUES ('KW');
INSERT INTO enum_tlds (tld) VALUES ('KY');
INSERT INTO enum_tlds (tld) VALUES ('KZ');
INSERT INTO enum_tlds (tld) VALUES ('LA');
INSERT INTO enum_tlds (tld) VALUES ('LB');
INSERT INTO enum_tlds (tld) VALUES ('LC');
INSERT INTO enum_tlds (tld) VALUES ('LI');
INSERT INTO enum_tlds (tld) VALUES ('LK');
INSERT INTO enum_tlds (tld) VALUES ('LR');
INSERT INTO enum_tlds (tld) VALUES ('LS');
INSERT INTO enum_tlds (tld) VALUES ('LT');
INSERT INTO enum_tlds (tld) VALUES ('LU');
INSERT INTO enum_tlds (tld) VALUES ('LV');
INSERT INTO enum_tlds (tld) VALUES ('LY');
INSERT INTO enum_tlds (tld) VALUES ('MA');
INSERT INTO enum_tlds (tld) VALUES ('MC');
INSERT INTO enum_tlds (tld) VALUES ('MD');
INSERT INTO enum_tlds (tld) VALUES ('ME');
INSERT INTO enum_tlds (tld) VALUES ('MG');
INSERT INTO enum_tlds (tld) VALUES ('MH');
INSERT INTO enum_tlds (tld) VALUES ('MIL');
INSERT INTO enum_tlds (tld) VALUES ('MK');
INSERT INTO enum_tlds (tld) VALUES ('ML');
INSERT INTO enum_tlds (tld) VALUES ('MM');
INSERT INTO enum_tlds (tld) VALUES ('MN');
INSERT INTO enum_tlds (tld) VALUES ('MO');
INSERT INTO enum_tlds (tld) VALUES ('MOBI');
INSERT INTO enum_tlds (tld) VALUES ('MP');
INSERT INTO enum_tlds (tld) VALUES ('MQ');
INSERT INTO enum_tlds (tld) VALUES ('MR');
INSERT INTO enum_tlds (tld) VALUES ('MS');
INSERT INTO enum_tlds (tld) VALUES ('MT');
INSERT INTO enum_tlds (tld) VALUES ('MU');
INSERT INTO enum_tlds (tld) VALUES ('MUSEUM');
INSERT INTO enum_tlds (tld) VALUES ('MV');
INSERT INTO enum_tlds (tld) VALUES ('MW');
INSERT INTO enum_tlds (tld) VALUES ('MX');
INSERT INTO enum_tlds (tld) VALUES ('MY');
INSERT INTO enum_tlds (tld) VALUES ('MZ');
INSERT INTO enum_tlds (tld) VALUES ('NA');
INSERT INTO enum_tlds (tld) VALUES ('NAME');
INSERT INTO enum_tlds (tld) VALUES ('NC');
INSERT INTO enum_tlds (tld) VALUES ('NE');
INSERT INTO enum_tlds (tld) VALUES ('NET');
INSERT INTO enum_tlds (tld) VALUES ('NF');
INSERT INTO enum_tlds (tld) VALUES ('NG');
INSERT INTO enum_tlds (tld) VALUES ('NI');
INSERT INTO enum_tlds (tld) VALUES ('NL');
INSERT INTO enum_tlds (tld) VALUES ('NO');
INSERT INTO enum_tlds (tld) VALUES ('NP');
INSERT INTO enum_tlds (tld) VALUES ('NR');
INSERT INTO enum_tlds (tld) VALUES ('NU');
INSERT INTO enum_tlds (tld) VALUES ('NZ');
INSERT INTO enum_tlds (tld) VALUES ('OM');
INSERT INTO enum_tlds (tld) VALUES ('ORG');
INSERT INTO enum_tlds (tld) VALUES ('PA');
INSERT INTO enum_tlds (tld) VALUES ('PE');
INSERT INTO enum_tlds (tld) VALUES ('PF');
INSERT INTO enum_tlds (tld) VALUES ('PG');
INSERT INTO enum_tlds (tld) VALUES ('PH');
INSERT INTO enum_tlds (tld) VALUES ('PK');
INSERT INTO enum_tlds (tld) VALUES ('PL');
INSERT INTO enum_tlds (tld) VALUES ('PM');
INSERT INTO enum_tlds (tld) VALUES ('PN');
INSERT INTO enum_tlds (tld) VALUES ('PR');
INSERT INTO enum_tlds (tld) VALUES ('PRO');
INSERT INTO enum_tlds (tld) VALUES ('PS');
INSERT INTO enum_tlds (tld) VALUES ('PT');
INSERT INTO enum_tlds (tld) VALUES ('PW');
INSERT INTO enum_tlds (tld) VALUES ('PY');
INSERT INTO enum_tlds (tld) VALUES ('QA');
INSERT INTO enum_tlds (tld) VALUES ('RE');
INSERT INTO enum_tlds (tld) VALUES ('RO');
INSERT INTO enum_tlds (tld) VALUES ('RS');
INSERT INTO enum_tlds (tld) VALUES ('RU');
INSERT INTO enum_tlds (tld) VALUES ('RW');
INSERT INTO enum_tlds (tld) VALUES ('SA');
INSERT INTO enum_tlds (tld) VALUES ('SB');
INSERT INTO enum_tlds (tld) VALUES ('SC');
INSERT INTO enum_tlds (tld) VALUES ('SD');
INSERT INTO enum_tlds (tld) VALUES ('SE');
INSERT INTO enum_tlds (tld) VALUES ('SG');
INSERT INTO enum_tlds (tld) VALUES ('SH');
INSERT INTO enum_tlds (tld) VALUES ('SI');
INSERT INTO enum_tlds (tld) VALUES ('SJ');
INSERT INTO enum_tlds (tld) VALUES ('SK');
INSERT INTO enum_tlds (tld) VALUES ('SL');
INSERT INTO enum_tlds (tld) VALUES ('SM');
INSERT INTO enum_tlds (tld) VALUES ('SN');
INSERT INTO enum_tlds (tld) VALUES ('SO');
INSERT INTO enum_tlds (tld) VALUES ('SR');
INSERT INTO enum_tlds (tld) VALUES ('ST');
INSERT INTO enum_tlds (tld) VALUES ('SU');
INSERT INTO enum_tlds (tld) VALUES ('SV');
INSERT INTO enum_tlds (tld) VALUES ('SY');
INSERT INTO enum_tlds (tld) VALUES ('SZ');
INSERT INTO enum_tlds (tld) VALUES ('TC');
INSERT INTO enum_tlds (tld) VALUES ('TD');
INSERT INTO enum_tlds (tld) VALUES ('TEL');
INSERT INTO enum_tlds (tld) VALUES ('TF');
INSERT INTO enum_tlds (tld) VALUES ('TG');
INSERT INTO enum_tlds (tld) VALUES ('TH');
INSERT INTO enum_tlds (tld) VALUES ('TJ');
INSERT INTO enum_tlds (tld) VALUES ('TK');
INSERT INTO enum_tlds (tld) VALUES ('TL');
INSERT INTO enum_tlds (tld) VALUES ('TM');
INSERT INTO enum_tlds (tld) VALUES ('TN');
INSERT INTO enum_tlds (tld) VALUES ('TO');
INSERT INTO enum_tlds (tld) VALUES ('TP');
INSERT INTO enum_tlds (tld) VALUES ('TR');
INSERT INTO enum_tlds (tld) VALUES ('TRAVEL');
INSERT INTO enum_tlds (tld) VALUES ('TT');
INSERT INTO enum_tlds (tld) VALUES ('TV');
INSERT INTO enum_tlds (tld) VALUES ('TW');
INSERT INTO enum_tlds (tld) VALUES ('TZ');
INSERT INTO enum_tlds (tld) VALUES ('UA');
INSERT INTO enum_tlds (tld) VALUES ('UG');
INSERT INTO enum_tlds (tld) VALUES ('UK');
INSERT INTO enum_tlds (tld) VALUES ('UM');
INSERT INTO enum_tlds (tld) VALUES ('US');
INSERT INTO enum_tlds (tld) VALUES ('UY');
INSERT INTO enum_tlds (tld) VALUES ('UZ');
INSERT INTO enum_tlds (tld) VALUES ('VA');
INSERT INTO enum_tlds (tld) VALUES ('VC');
INSERT INTO enum_tlds (tld) VALUES ('VE');
INSERT INTO enum_tlds (tld) VALUES ('VG');
INSERT INTO enum_tlds (tld) VALUES ('VI');
INSERT INTO enum_tlds (tld) VALUES ('VN');
INSERT INTO enum_tlds (tld) VALUES ('VU');
INSERT INTO enum_tlds (tld) VALUES ('WF');
INSERT INTO enum_tlds (tld) VALUES ('WS');
INSERT INTO enum_tlds (tld) VALUES ('XN--0ZWM56D');
INSERT INTO enum_tlds (tld) VALUES ('XN--11B5BS3A9AJ6G');
INSERT INTO enum_tlds (tld) VALUES ('XN--80AKHBYKNJ4F');
INSERT INTO enum_tlds (tld) VALUES ('XN--9T4B11YI5A');
INSERT INTO enum_tlds (tld) VALUES ('XN--DEBA0AD');
INSERT INTO enum_tlds (tld) VALUES ('XN--G6W251D');
INSERT INTO enum_tlds (tld) VALUES ('XN--HGBK6AJ7F53BBA');
INSERT INTO enum_tlds (tld) VALUES ('XN--HLCJ6AYA9ESC7A');
INSERT INTO enum_tlds (tld) VALUES ('XN--JXALPDLP');
INSERT INTO enum_tlds (tld) VALUES ('XN--KGBECHTV');
INSERT INTO enum_tlds (tld) VALUES ('XN--ZCKZAH');
INSERT INTO enum_tlds (tld) VALUES ('YE');
INSERT INTO enum_tlds (tld) VALUES ('YT');
INSERT INTO enum_tlds (tld) VALUES ('YU');
INSERT INTO enum_tlds (tld) VALUES ('ZA');
INSERT INTO enum_tlds (tld) VALUES ('ZM');
INSERT INTO enum_tlds (tld) VALUES ('ZW');

comment on table enum_tlds is 'list of available tlds for checking of dns host tld';
-- login table for saved filters
-- DROP TABLE Filters CASCADE;
CREATE TABLE Filters (
	ID SERIAL PRIMARY KEY, 
	Type SMALLINT NOT NULL, 
	Name VARCHAR(255) NOT NULL, 
	UserID INTEGER NOT NULL, 
	GroupID INTEGER,
	Data TEXT NOT NULL
	);

COMMENT ON TABLE Filters is
'Table for saved object filters';

COMMENT ON COLUMN Filters.ID is 'unique automatically generated identifier';
COMMENT ON COLUMN Filters.Type is 'filter object type -- 0 = filter on filter, 1 = filter on registrar, 2 = filter on object, 3 = filter on contact, 4 = filter on nsset, 5 = filter on domain, 6 = filter on action, 7 = filter on invoice, 8 = filter on authinfo, 9 = filter on mail';
COMMENT ON COLUMN Filters.Name is 'human readable filter name';
COMMENT ON COLUMN Filters.UserID is 'filter creator';
COMMENT ON COLUMN Filters.GroupID is 'filter accessibility for group';
COMMENT ON COLUMN Filters.Data is 'filter definition';

-- New indexes into history tables

CREATE INDEX domain_history_id_idx ON domain_history (id);
CREATE INDEX domain_history_zone_idx ON domain_history (zone);
CREATE INDEX domain_history_exdate_idx ON domain_history (exdate);
CREATE INDEX domain_history_registrant_idx ON domain_history (registrant);
CREATE INDEX domain_history_nsset_idx ON domain_history (nsset);
CREATE INDEX domain_contact_map_history_contactid_idx ON domain_contact_map_history (contactid);
CREATE INDEX domain_contact_map_history_domainid_idx ON domain_contact_map_history (domainid);
CREATE INDEX nsset_history_id_idx ON nsset_history (id);
CREATE INDEX host_history_nssetid_idx ON host_history (nssetid);
CREATE INDEX host_history_id_idx ON host_history (id);
CREATE INDEX host_ipaddr_map_history_id_idx ON host_ipaddr_map_history (id);
CREATE INDEX host_ipaddr_map_history_hostid_idx ON host_ipaddr_map_history (hostid);
CREATE INDEX host_ipaddr_map_history_nssetid_idx ON host_ipaddr_map_history (nssetid);
CREATE INDEX nsset_contact_map_history_nssetid_idx ON nsset_contact_map_history (nssetid);
CREATE INDEX nsset_contact_map_history_contactid_idx ON nsset_contact_map_history (contactid);
CREATE INDEX contact_history_id_idx ON contact_history (id);
CREATE INDEX enumval_history_domainid_idx ON enumval_history (domainid);
CREATE INDEX object_history_id_idx ON object_history (id);
CREATE INDEX object_history_clid_idx ON object_history (clid);
CREATE INDEX object_history_upid_idx ON object_history (upid);
-- Public requests

CREATE TABLE public_request (
  id serial NOT NULL PRIMARY KEY,
  request_type smallint NOT NULL, -- vsechny typy zadosti
-- further description in src/register/public_request.h, enum Type
  create_time timestamp without time zone DEFAULT now() NOT NULL,
  status smallint NOT NULL,
-- Request status, values: PRS_NEW,       ///< Request was created and waiting for autorization 
--                         PRS_ANSWERED,  ///< Email with answer was sent
--                         PRS_INVALID    ///< Time passed without authorization   
  resolve_time timestamp without time zone,
  reason character varying(512),
  email_to_answer character varying(255),
  answer_email_id integer REFERENCES mail_archive(id),
  registrar_id integer REFERENCES registrar(id),
  create_request_id bigint,
  resolve_request_id bigint
);

comment on table public_request is 'table of general requests give in by public users';
comment on column public_request.request_type is 'code of request';
comment on column public_request.create_time is 'request creation time';
comment on column public_request.status is 'code of request actual status';
comment on column public_request.resolve_time is 'time when request was processed (closed)';
comment on column public_request.reason is 'reason';
comment on column public_request.email_to_answer is 'manual entered email by user for sending answer (if it is automatic from object contact it is NULL)';
comment on column public_request.answer_email_id is 'reference to mail which was send after request was processed';
comment on column public_request.registrar_id is 'reference to registrar when request is submitted via EPP protocol (otherwise NULL)';

CREATE TABLE public_request_objects_map (
  request_id integer REFERENCES public_request(id) PRIMARY KEY,
  object_id integer REFERENCES object_registry(id)
);

comment on table public_request_objects_map is 'table with objects associated with given request';

CREATE TABLE public_request_state_request_map (
  state_request_id integer PRIMARY KEY REFERENCES object_state_request(id),
  block_request_id integer NOT NULL REFERENCES public_request(id),
  unblock_request_id integer REFERENCES public_request(id)
);

comment on table public_request_state_request_map is 'table with state request associated with given request';


CREATE TABLE public_request_auth (
      id integer PRIMARY KEY NOT NULL REFERENCES public_request(id),
      identification varchar(32) NOT NULL UNIQUE,
      password varchar(64) NOT NULL
);

CREATE TABLE public_request_messages_map
(
  id serial PRIMARY KEY NOT NULL,
  public_request_id INTEGER REFERENCES public_request (id),
  message_archive_id INTEGER, -- REFERENCES message_archive (id), 
  mail_archive_id INTEGER, -- REFERENCES mail_archive (id),
  UNIQUE (public_request_id, message_archive_id),
  UNIQUE (public_request_id, mail_archive_id)
);

CREATE TABLE enum_public_request_type
(
  id INTEGER PRIMARY KEY NOT NULL,
  name VARCHAR(64) UNIQUE NOT NULL,
  description VARCHAR(256)
);

CREATE TABLE enum_public_request_status
(
  id INTEGER PRIMARY KEY NOT NULL,
  name VARCHAR(32) UNIQUE NOT NULL,
  description VARCHAR(128)
);

-- #7122 lock public_request insert or update by its type and object to the end of db transaction

CREATE TABLE public_request_lock
(
    id bigserial PRIMARY KEY -- lock id
    , request_type smallint NOT NULL REFERENCES enum_public_request_type(id)
    , object_id integer NOT NULL --REFERENCES object_registry (id)
);

CREATE OR REPLACE FUNCTION lock_public_request_lock( f_request_type_id BIGINT, f_object_id BIGINT)
RETURNS void AS $$
DECLARE
BEGIN
    PERFORM * FROM public_request_lock
    WHERE request_type = f_request_type_id
    AND object_id = f_object_id ORDER BY id FOR UPDATE; --wait if locked
    IF NOT FOUND THEN
        RAISE EXCEPTION 'Failed to lock request_type_id: % object_id: %', f_request_type_id, f_object_id;
    END IF;
END;
$$ LANGUAGE plpgsql;

-- lock public request
CREATE OR REPLACE FUNCTION lock_public_request() 
RETURNS "trigger" AS $$
DECLARE
  nobject RECORD;
  max_id_to_delete BIGINT;
BEGIN
  RAISE NOTICE 'lock_public_request start NEW.id: % NEW.request_type: %'
  , NEW.id, NEW.request_type;

  FOR nobject IN SELECT prom.object_id
    FROM public_request_objects_map prom
    JOIN object_registry obr ON obr.id = prom.object_id
    WHERE prom.request_id = NEW.id
  LOOP
    RAISE NOTICE 'lock_public_request nobject.object_id: %'
    , nobject.object_id;
    PERFORM lock_public_request_lock( NEW.request_type, nobject.object_id);
  END LOOP;

  --try cleanup
  BEGIN
    SELECT MAX(id) - 100 FROM public_request_lock INTO max_id_to_delete;
    PERFORM * FROM public_request_lock
      WHERE id < max_id_to_delete FOR UPDATE NOWAIT;
    IF FOUND THEN
      DELETE FROM public_request_lock
        WHERE id < max_id_to_delete;
    END IF;
  EXCEPTION WHEN lock_not_available THEN
    RAISE NOTICE 'cleanup lock not available';
  END;

  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION lock_public_request()
IS 'lock changes of public requests by object and request type';

CREATE TRIGGER "trigger_lock_public_request"
  AFTER INSERT OR UPDATE ON public_request
  FOR EACH ROW EXECUTE PROCEDURE lock_public_request();

---
--- public request basic dml script
---

INSERT INTO enum_public_request_status (id, name, description) VALUES (0, 'new', 'New');
INSERT INTO enum_public_request_status (id, name, description) VALUES (1, 'answered', 'Answered');
INSERT INTO enum_public_request_status (id, name, description) VALUES (2, 'invalidated', 'Invalidated');


---
--- Public request types for sending authinfo
---

INSERT INTO enum_public_request_type (id, name, description) VALUES (0, 'authinfo_auto_rif', 'AuthInfo (EPP/Auto)');
INSERT INTO enum_public_request_type (id, name, description) VALUES (1, 'authinfo_auto_pif', 'AuthInfo (Web/Auto)');
INSERT INTO enum_public_request_type (id, name, description) VALUES (2, 'authinfo_email_pif', 'AuthInfo (Web/Email)');
INSERT INTO enum_public_request_type (id, name, description) VALUES (3, 'authinfo_post_pif', 'AuthInfo (Web/Post)');


---
--- Public request types for block/unblock transfer/changes
---

INSERT INTO enum_public_request_type (id, name, description) VALUES (4, 'block_changes_email_pif', 'Block changes (Web/Email)');
INSERT INTO enum_public_request_type (id, name, description) VALUES (5, 'block_changes_post_pif', 'Block changes (Web/Post)');
INSERT INTO enum_public_request_type (id, name, description) VALUES (6, 'block_transfer_email_pif', 'Block transfer (Web/Email)');
INSERT INTO enum_public_request_type (id, name, description) VALUES (7, 'block_transfer_post_pif', 'Block transfer (Web/Post)');

INSERT INTO enum_public_request_type (id, name, description) VALUES (8, 'unblock_changes_email_pif', 'Unblock changes (Web/Email)');
INSERT INTO enum_public_request_type (id, name, description) VALUES (9, 'unblock_changes_post_pif', 'Unblock changes (Web/Post)');
INSERT INTO enum_public_request_type (id, name, description) VALUES (10, 'unblock_transfer_email_pif', 'Unblock transfer (Web/Email)');
INSERT INTO enum_public_request_type (id, name, description) VALUES (11, 'unblock_transfer_post_pif', 'Unblock transfer (Web/Post)');


---
--- Public request types for contact verification
---

INSERT INTO enum_public_request_type (id, name, description) VALUES (12, 'mojeid_contact_conditional_identification', 'MojeID conditional identification');
INSERT INTO enum_public_request_type (id, name, description) VALUES (13, 'mojeid_contact_identification', 'MojeID full identification');
INSERT INTO enum_public_request_type (id, name, description) VALUES (14, 'mojeid_contact_validation', 'MojeID validation');
INSERT INTO enum_public_request_type (id, name, description) VALUES (17, 'mojeid_conditionally_identified_contact_transfer', 'MojeID conditionally identified contact transfer');
INSERT INTO enum_public_request_type (id, name, description) VALUES (18, 'mojeid_identified_contact_transfer', 'MojeID identified contact transfer');


INSERT INTO enum_public_request_type (id, name, description) VALUES (15, 'contact_conditional_identification', 'Conditional identification');
INSERT INTO enum_public_request_type (id, name, description) VALUES (16, 'contact_identification', 'Full identification');


---
--- don't forget to update database schema version
---
UPDATE enum_parameters SET val = '<insert version here>' WHERE id = 1;

---
--- Ticket #3747
---

-- DROP TABLE registrar_group_map;
-- DROP TABLE registrar_group;
-- DROP TABLE registrar_certification;
-- DROP DOMAIN classification_type;

CREATE DOMAIN classification_type AS integer NOT NULL
	CONSTRAINT classification_type_check CHECK (VALUE IN (0, 1, 2, 3, 4, 5)); 

COMMENT ON DOMAIN classification_type 
	IS 'allowed values of classification for registrar certification';

CREATE TABLE registrar_certification
(
    id serial PRIMARY KEY, -- certification id
    registrar_id integer NOT NULL REFERENCES registrar(id), -- registrar id
    valid_from date NOT NULL, --  registrar certification valid from
    valid_until date NOT NULL, --  registrar certification valid until = valid_from + 1year
    classification classification_type NOT NULL, -- registrar certification result checked 0-5
    eval_file_id integer NOT NULL REFERENCES files(id) -- link to pdf file
);


-- check whether registrar_certification life is valid
CREATE OR REPLACE FUNCTION registrar_certification_life_check() 
RETURNS "trigger" AS $$
DECLARE
    last_reg_cert RECORD;
BEGIN
    IF NEW.valid_from > NEW.valid_until THEN
        RAISE EXCEPTION 'Invalid registrar certification life: valid_from > valid_until';
    END IF;

    IF TG_OP = 'INSERT' THEN
        SELECT * FROM registrar_certification INTO last_reg_cert
            WHERE registrar_id = NEW.registrar_id AND id < NEW.id
            ORDER BY valid_from DESC, id DESC LIMIT 1;
        IF FOUND THEN
            IF last_reg_cert.valid_until > NEW.valid_from  THEN
                RAISE EXCEPTION 'Invalid registrar certification life: last valid_until > new valid_from';
            END IF;
        END IF;
    ELSEIF TG_OP = 'UPDATE' THEN
        IF NEW.valid_from <> OLD.valid_from THEN
            RAISE EXCEPTION 'Change of valid_from not allowed';
        END IF;
        IF NEW.valid_until > OLD.valid_until THEN
            RAISE EXCEPTION 'Certification prolongation not allowed';
        END IF;
        IF NEW.registrar_id <> OLD.registrar_id THEN
            RAISE EXCEPTION 'Change of registrar not allowed';
        END IF;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION registrar_certification_life_check()
	IS 'check whether registrar_certification life is valid'; 

CREATE TRIGGER "trigger_registrar_certification"
  AFTER INSERT OR UPDATE ON registrar_certification
  FOR EACH ROW EXECUTE PROCEDURE registrar_certification_life_check();


CREATE INDEX registrar_certification_valid_from_idx ON registrar_certification(valid_from);
CREATE INDEX registrar_certification_valid_until_idx ON registrar_certification(valid_until);

COMMENT ON TABLE registrar_certification IS 'result of registrar certification';
COMMENT ON COLUMN registrar_certification.registrar_id IS 'certified registrar id';
COMMENT ON COLUMN registrar_certification.valid_from IS
    'certification is valid from this date';
COMMENT ON COLUMN registrar_certification.valid_until IS
    'certification is valid until this date, certification should be valid for 1 year';
COMMENT ON COLUMN registrar_certification.classification IS
    'registrar certification result checked 0-5';
COMMENT ON COLUMN registrar_certification.eval_file_id IS
    'evaluation pdf file link';

CREATE TABLE registrar_group
(
    id serial PRIMARY KEY, -- registrar group id
    short_name varchar(255) NOT NULL UNIQUE, -- short name of the group
    cancelled timestamp -- when the group was cancelled
);


--check whether registrar_group is empty and not cancelled
CREATE OR REPLACE FUNCTION cancel_registrar_group_check() RETURNS "trigger" AS $$
DECLARE
    registrars_in_group INTEGER;
BEGIN
    IF OLD.cancelled IS NOT NULL THEN
        RAISE EXCEPTION 'Registrar group already cancelled';
    END IF;

    IF NEW.cancelled IS NOT NULL AND EXISTS(
        SELECT * 
          FROM registrar_group_map 
         WHERE registrar_group_id = NEW.id
          AND registrar_group_map.member_from <= CURRENT_DATE
          AND (registrar_group_map.member_until IS NULL 
                  OR (registrar_group_map.member_until >= CURRENT_DATE 
                          AND  registrar_group_map.member_from 
                              <> registrar_group_map.member_until))) 
    THEN 
        RAISE EXCEPTION 'Unable to cancel non-empty registrar group';
    END IF;
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION cancel_registrar_group_check()
	IS 'check whether registrar_group is empty and not cancelled'; 

CREATE TRIGGER "trigger_cancel_registrar_group"
  AFTER UPDATE  ON registrar_group
  FOR EACH ROW EXECUTE PROCEDURE cancel_registrar_group_check();


CREATE INDEX registrar_group_short_name_idx ON registrar_group(short_name);

COMMENT ON TABLE registrar_group IS 'available groups of registars';
COMMENT ON COLUMN registrar_group.id IS 'group id';
COMMENT ON COLUMN registrar_group.short_name IS 'group short name';
COMMENT ON COLUMN registrar_group.cancelled IS 'time when the group was cancelled';

CREATE TABLE registrar_group_map
(
    id serial PRIMARY KEY, -- membership of registrar in group id
    registrar_id integer NOT NULL REFERENCES registrar(id), -- registrar id
    registrar_group_id integer NOT NULL REFERENCES registrar_group(id), -- registrar group id
    member_from date NOT NULL, --  registrar membership in the group from this date
    member_until date --  registrar membership in the group until this date or unspecified
);

CREATE OR REPLACE FUNCTION registrar_group_map_check() RETURNS "trigger" AS $$
DECLARE
    last_reg_map RECORD;
BEGIN
    IF NEW.member_until IS NOT NULL AND NEW.member_from > NEW.member_until THEN
        RAISE EXCEPTION 'Invalid registrar membership life: member_from > member_until';
    END IF;

    IF TG_OP = 'INSERT' THEN
        SELECT * INTO last_reg_map
           FROM registrar_group_map 
          WHERE registrar_id = NEW.registrar_id
            AND registrar_group_id = NEW.registrar_group_id
            AND id < NEW.id
          ORDER BY member_from DESC, id DESC 
          LIMIT 1;
        IF FOUND THEN
            IF last_reg_map.member_until IS NULL THEN
                UPDATE registrar_group_map 
                   SET member_until = NEW.member_from
                  WHERE id = last_reg_map.id;
                last_reg_map.member_until := NEW.member_from;
            END IF;
            IF last_reg_map.member_until > NEW.member_from  THEN
                RAISE EXCEPTION 'Invalid registrar membership life: last member_until > new member_from';
            END IF;
        END IF;

    ELSEIF TG_OP = 'UPDATE' THEN
        IF NEW.member_from <> OLD.member_from THEN
            RAISE EXCEPTION 'Change of member_from not allowed';
        END IF;
        
        IF NEW.member_until IS NULL AND OLD.member_until IS NOT NULL THEN
            RAISE EXCEPTION 'Change of member_until not allowed';
        END IF;
        
        IF NEW.member_until IS NOT NULL AND OLD.member_until IS NOT NULL 
            AND NEW.member_until <> OLD.member_until THEN
            RAISE EXCEPTION 'Change of member_until not allowed';
        END IF;
        
        IF NEW.registrar_group_id <> OLD.registrar_group_id THEN
            RAISE EXCEPTION 'Change of registrar_group not allowed';
        END IF;
        
        IF NEW.registrar_id <> OLD.registrar_id THEN
            RAISE EXCEPTION 'Change of registrar not allowed';
        END IF;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION registrar_group_map_check()
	IS 'check whether registrar membership change is valid'; 

CREATE TRIGGER "trigger_registrar_group_map"
  AFTER INSERT OR UPDATE ON registrar_group_map
  FOR EACH ROW EXECUTE PROCEDURE registrar_group_map_check();


CREATE INDEX registrar_group_map_member_from_idx ON registrar_group_map(member_from);
CREATE INDEX registrar_group_map_member_until_idx ON registrar_group_map(member_until);

COMMENT ON TABLE registrar_group_map IS 'membership of registar in group';
COMMENT ON COLUMN registrar_group_map.id IS 'registrar group membership id';
COMMENT ON COLUMN registrar_group_map.registrar_id IS 'registrar id';
COMMENT ON COLUMN registrar_group_map.registrar_group_id IS 'group id';
COMMENT ON COLUMN registrar_group_map.member_from 
	IS 'registrar membership in the group from this date';
COMMENT ON COLUMN registrar_group_map.member_until 
	IS 'registrar membership in the group until this date or unspecified';

CREATE TABLE registrar_disconnect (
    id SERIAL PRIMARY KEY,
    registrarid INTEGER NOT NULL REFERENCES registrar(id),
    blocked_from TIMESTAMP NOT NULL DEFAULT now(),
    blocked_to TIMESTAMP,
    unblock_request_id BIGINT
);

---
--- messages templates
---
INSERT INTO mail_type (id, name, subject) VALUES (21, 'mojeid_identification', '[mojeID] Založení účtu - PIN1 pro aktivaci mojeID');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(21, 'plain', 1,
'
Vážený uživateli,

před tím, než Vám aktivujeme účet mojeID, musíme ověřit správnost Vašich
kontatních údajů, a to prostřednictvím kódů PIN1 a PIN2.

PIN1: <?cs var:passwd ?>
PIN2: Vám byl zaslán pomocí SMS.

Do formuláře pro zadání těchto kódů budete přesměrováni po kliknutí na
následující odkaz:

https://<?cs var:hostname ?>/identify/email-sms/<?cs var:identification ?>/?password1=<?cs var:passwd ?>

Po úspěšném odeslání formuláře budete moci začít Váš účet mojeID používat.
Zároveň Vám pošleme poštou dopis s kódem PIN3, po jehož zadání bude Váš
účet plně aktivní.

Základní údaje o Vašem účtu:

účet mojeID: <?cs var:handle ?>
jméno:       <?cs var:firstname ?>
příjmení:    <?cs var:lastname ?>
e-mail:      <?cs var:email ?>

Váš tým <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (21, 21);

INSERT INTO mail_type (id, name, subject) VALUES (22, 'mojeid_validation', 'Validace účtu mojeID <?cs if:status == #1 ?>provedena<?cs else ?>neprovedena<?cs /if ?>');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(22, 'plain', 1,
'
<?cs if:status == #1 ?>
Na základě žádosti číslo <?cs var:reqid ?> ze dne <?cs var:reqdate ?> byla provedena validace účtu mojeID.<?cs else ?>
Váš účet mojeID:<?cs /if ?>

Jméno : <?cs var:name ?><?cs if:org ?>
Organizace : <?cs var:org ?><?cs /if ?><?cs if:ic ?>
IČ : <?cs var:ic ?><?cs /if ?><?cs if:birthdate ?>
Datum narození : <?cs var:birthdate ?><?cs /if ?>
Adresa : <?cs var:address ?>
<?cs if:status != #1 ?>
u kterého bylo požádáno o validaci žádostí číslo <?cs var:reqid ?> ze dne <?cs var:reqdate ?> nebyl validován.
<?cs /if ?>
Váš tým <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (22, 22);

INSERT INTO mail_type (id, name, subject) VALUES (24, 'mojeid_email_change', 'MojeID - změna emailu');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(24, 'plain', 1,
'Vážený uživateli,

k dokončení procedury změny emailu zadejte prosím kód PIN1: <?cs var:pin ?>

Váš tým CZ.NIC');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (24, 24);

INSERT INTO mail_type (id, name, subject) VALUES (27, 'mojeid_verified_contact_transfer', 'Založení účtu mojeID');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(27, 'plain', 1,
'
Vážený uživateli,

tento e-mail potvrzuje úspěšné založení účtu mojeID s těmito údaji:

účet mojeID: <?cs var:handle ?>
jméno:       <?cs var:firstname ?>
příjmení:    <?cs var:lastname ?>
e-mail:      <?cs var:email ?>

Pro aktivaci Vašeho účtu je nutné vložit kód PIN1.

PIN1: <?cs var:passwd ?>

Aktivaci účtu proveďte kliknutím na následující odkaz:

https://<?cs var:hostname ?>/identify/email/<?cs var:identification ?>/?password1=<?cs var:passwd ?>

Váš tým <?cs var:defaults.company ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (27, 27);


---
--- sms types
---
INSERT INTO message_type (id, type) VALUES (2, 'mojeid_pin2');
INSERT INTO message_type (id, type) VALUES (3, 'mojeid_pin3');
INSERT INTO message_type (id, type) VALUES (4, 'mojeid_sms_change');
INSERT INTO message_type (id, type) VALUES (8, 'mojeid_pin3_reminder');

---
--- file types
---
INSERT INTO enum_filetype (id, name) VALUES (7, 'mojeid contact identification request');


---
--- contact states
---
INSERT INTO enum_object_states VALUES (21,'conditionallyIdentifiedContact','{1}','t','t');
INSERT INTO enum_object_states VALUES (22,'identifiedContact','{1}','t','t');
INSERT INTO enum_object_states VALUES (23,'validatedContact','{1}','t','t');
INSERT INTO enum_object_states VALUES (24,'mojeidContact','{1}','t','t');

INSERT INTO enum_object_states_desc VALUES (21, 'CS', 'Kontakt je podmínečně identifikován');
INSERT INTO enum_object_states_desc VALUES (21, 'EN', 'Contact is conditionally identified');
INSERT INTO enum_object_states_desc VALUES (22, 'CS', 'Kontakt je identifikován');
INSERT INTO enum_object_states_desc VALUES (22, 'EN', 'Contact is identified');
INSERT INTO enum_object_states_desc VALUES (23, 'CS', 'Kontakt je validován');
INSERT INTO enum_object_states_desc VALUES (23, 'EN', 'Contact is validated');
INSERT INTO enum_object_states_desc VALUES (24, 'CS', 'MojeID kontakt');
INSERT INTO enum_object_states_desc VALUES (24, 'EN', 'MojeID contact');




---
--- Ticket #5102 - contact reminder
---

CREATE TABLE reminder_registrar_parameter (
    registrar_id integer NOT NULL PRIMARY KEY REFERENCES registrar(id),
    template_memo text,
    reply_to varchar(200)
);



CREATE TABLE reminder_contact_message_map (
    reminder_date date NOT NULL,
    contact_id integer NOT NULL REFERENCES object_registry(id),
    message_id integer REFERENCES mail_archive(id),
    PRIMARY KEY(reminder_date, contact_id)
);


---
--- Ticket #5102 - reminder - mail template
--- Ticket #5739 - fixed missing translations of identification type
---

INSERT INTO mail_type (id, name, subject) VALUES (23, 'annual_contact_reminder', 'Ověření správnosti údajů');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
 (23, 'plain', 1,
'
This is a bilingual message. Please see below for the English version

Vážená paní, vážený pane,

dovolujeme si Vás zdvořile požádat o kontrolu správnosti údajů,
které nyní evidujeme u Vašeho kontaktu v centrálním registru
doménových jmen.

ID kontaktu v registru: <?cs var:handle ?>
Organizace: <?cs var:organization ?>
Jméno: <?cs var:name ?>
Adresa: <?cs var:address ?><?cs if:ident_type != "" ?>
<?cs if:ident_type == "RC"?>Datum narození: <?cs 
elif:ident_type == "OP"?>Číslo OP: <?cs 
elif:ident_type == "PASS"?>Číslo pasu: <?cs 
elif:ident_type == "ICO"?>IČO: <?cs 
elif:ident_type == "MPSV"?>Identifikátor MPSV: <?cs 
elif:ident_type == "BIRTHDAY"?>Datum narození: <?cs 
/if ?> <?cs var:ident_value ?><?cs 
/if ?>
DIČ: <?cs var:dic ?>
Telefon: <?cs var:telephone ?>
Fax: <?cs var:fax ?>
E-mail: <?cs var:email ?>
Notifikační e-mail: <?cs var:notify_email ?>
Určený registrátor: <?cs var:registrar_name ?> (<?cs var:registrar_url ?>)
<?cs if:registrar_memo_cz ?>Další informace poskytnuté registrátorem:
<?cs var:registrar_memo_cz ?><?cs /if ?>

Se žádostí o opravu údajů se neváhejte obrátit na svého vybraného registrátora.
V případě, že zde uvedené údaje odpovídají skutečnosti, není nutné na tuto zprávu reagovat.

Aktuální, úplné a správné informace v registru znamenají Vaši jistotu,
že Vás důležité informace o Vaší doméně zastihnou vždy a včas na správné adrese.
Nedočkáte se tak nepříjemného překvapení v podobě nefunkční či zrušené domény.

Dovolujeme si Vás rovněž upozornit, že nesprávné, nepravdivé, neúplné
či zavádějící údaje mohou být v souladu s Pravidly registrace doménových jmen
v ccTLD .cz důvodem ke zrušení registrace doménového jména!

Úplný výpis z registru obsahující všechny domény a další objekty přiřazené
k shora uvedenému kontaktu naleznete v příloze.

Váš tým CZ.NIC.

Příloha:

<?cs if:domains.0 ?>Seznam domén kde je kontakt v roli držitele nebo administrativního
kontaktu:<?cs each:item = domains ?>
<?cs var:item ?><?cs /each ?><?cs else ?>Kontakt není uveden u žádného doménového jména.<?cs /if ?><?cs if:nssets.0 ?>

Seznam sad jmenných serverů, kde je kontakt v roli technického kontaktu:<?cs each:item = nssets ?>
<?cs var:item ?><?cs /each ?><?cs /if ?><?cs if:keysets.0 ?>

Seznam sad klíčů, kde je kontakt v roli technického kontaktu:<?cs each:item = keysets ?>
<?cs var:item ?><?cs /each ?><?cs /if ?>



Dear Sir or Madam,

Please check the correctness of the information we currently have on file
for your contact in the central registry of domain names.

Contact ID in the registry: <?cs var:handle ?>
Organization: <?cs var:organization ?>
Name: <?cs var:name ?>
Address: <?cs var:address ?><?cs if:ident_type != "" ?>
<?cs if:ident_type == "RC"?>Birth date: <?cs 
elif:ident_type == "OP"?>Personal ID: <?cs 
elif:ident_type == "PASS"?>Passport number: <?cs 
elif:ident_type == "ICO"?>ID number: <?cs 
elif:ident_type == "MPSV"?>MSPV ID: <?cs 
elif:ident_type == "BIRTHDAY"?>Birth day: <?cs 
/if ?> <?cs var:ident_value ?><?cs 
/if ?>
VAT No.: <?cs var:dic ?>
Phone: <?cs var:telephone ?>
Fax: <?cs var:fax ?>
E-mail: <?cs var:email ?>
Notification e-mail: <?cs var:notify_email ?>
Designated registrator: <?cs var:registrar_name ?> (<?cs var:registrar_url ?>)
<?cs if:registrar_memo_en ?>Other information provided by registrar:
<?cs var:registrar_memo_en ?><?cs /if ?>

Do not hesitate to contact your designated registrar with a correction request.

Having up-to-date, complete and correct information in the registry is crucial
to reach you with all the important information about your domain name in a timely manner
and at the correct contact address. Check you contact details now and avoid unpleasant
surprises such as a non-functional or expired domain.

We would also like to inform you that in accordance with the Rules of Domain Name
Registration for the .cz ccTLD, incorrect, false, incomplete or misleading
information can be grounds for the cancellation of a domain name registration.

Please do not hesitate to contact us for additional information.

You can find a complete summary of your domain names, and other objects
associated with your contact attached below.


Your CZ.NIC team.

Attachment:

<?cs if:domains.0 ?>Domains where the contact is a holder or an administrative contact:<?cs each:item = domains ?>
<?cs var:item ?><?cs /each ?><?cs else ?>Contact is not linked to any domain name.<?cs /if ?><?cs if:nssets.0 ?>

Sets of name servers where the contact is a technical contact:<?cs each:item = nssets ?>
<?cs var:item ?><?cs /each ?><?cs /if ?><?cs if:keysets.0 ?>

Keysets where the contact is a technical contact:<?cs each:item = keysets ?>
<?cs var:item ?><?cs /each ?><?cs /if ?>
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (23, 23);

---
--- sms types
---
INSERT INTO message_type (id, type) VALUES (5, 'monitoring');
---
--- sequence for epp session identifiers
---
CREATE SEQUENCE epp_login_id_seq;

---
--- sms types
---

INSERT INTO message_type (id, type) VALUES (6, 'contact_verification_pin2');
INSERT INTO message_type (id, type) VALUES (7, 'contact_verification_pin3');

---
--- email types
---

INSERT INTO mail_type (id, name, subject) VALUES (25, 'conditional_contact_identification', 'Podmíněná identifikace kontaktu');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(25, 'plain', 1,
'
English version of the e-mail is entered below the Czech version

Vážený uživateli,

tento e-mail potvrzuje úspěšné zahájení procesu ověření kontaktu v Centrálním registru:

ID kontaktu: <?cs var:handle ?>
jméno:       <?cs var:firstname ?>
příjmení:    <?cs var:lastname ?>
e-mail:      <?cs var:email ?>

Pro dokončení prvního ze dvou kroků ověření je nutné zadat kódy PIN1 a PIN2.

PIN1: <?cs var:passwd ?>
PIN2: Vám byl zaslán pomocí SMS.

Zadání PIN1 a PIN2 bude možné po kliknutí na následující odkaz:
https://<?cs var:hostname ?>/verification/identify/email-sms/<?cs var:identification ?>/?password1=<?cs var:passwd ?>

Váš tým <?cs var:defaults.company ?>



Dear User,

This e-mail confirms that the process of verifying your contact data in the central registry has been successfully initiated:

contact ID: <?cs var:handle ?>
first name: <?cs var:firstname ?>
last name:  <?cs var:lastname ?>
e-mail:     <?cs var:email ?>

To complete the first of the two verification steps, authorisation with your PIN1 and PIN2 codes is required.

PIN1: <?cs var:passwd ?>
PIN2: was sent to you by a text message (SMS).

You will be able to enter your PIN1 and PIN2 by following this link:
https://<?cs var:hostname ?>/verification/identify/email-sms/<?cs var:identification ?>/?password1=<?cs var:passwd ?>

Your <?cs var:defaults.company ?> team
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (25, 25);



INSERT INTO mail_type (id, name, subject) VALUES (26, 'contact_identification', 'Identifikace kontaktu');
INSERT INTO mail_templates (id, contenttype, footer, template) VALUES
(26, 'plain', 1,
'
English version of the e-mail is entered below the Czech version

Vážený uživateli,

první část ověření kontaktu v Centrálním registru je úspěšně za Vámi.

identifikátor: <?cs var:handle ?>
jméno:         <?cs var:firstname ?>
příjmení:      <?cs var:lastname ?>
e-mail:        <?cs var:email ?>

V nejbližších dnech ještě očekávejte zásilku s kódem PIN3, jehož pomocí
ověříme Vaši poštovní adresu. Zadáním kódu PIN3 do formuláře na stránce
https://<?cs var:hostname ?>/verification/identify/letter/?handle=<?cs var:handle ?>
dokončíte proces ověření kontaktu.

Rádi bychom Vás také upozornili, že až do okamžiku zadání kódu PIN3
nelze údaje v kontaktu měnit. Případná editace údajů v této fázi
ověřovacího procesu by měla za následek jeho přerušení.

Děkujeme za pochopení.

Váš tým <?cs var:defaults.company ?>



Dear User,

The first step of the verification of the central registry contact details provided below
has been successfully completed.

contact ID: <?cs var:handle ?>
first name: <?cs var:firstname ?>
last name:  <?cs var:lastname ?>
e-mail:     <?cs var:email ?>

Your PIN3 has now also been generated; you will receive it by mail within a few days
at the address listed in the contact.

Verification of this contact will be complete once you enter your PIN3
into the corresponding field at this address:
https://<?cs var:hostname ?>/verification/identify/letter/?handle=<?cs var:handle ?>

Your <?cs var:defaults.company ?> team
');
INSERT INTO mail_type_template_map (typeid, templateid) VALUES (26, 26);



-- 
--  create temporary table and if temporary table already
--  exists truncate it for immediate usage (used for querying)
--
CREATE OR REPLACE FUNCTION create_tmp_table(tname VARCHAR) 
RETURNS VOID AS $$
BEGIN
 EXECUTE 'CREATE TEMPORARY TABLE ' || tname || ' (id BIGINT PRIMARY KEY)';
 EXCEPTION
 WHEN DUPLICATE_TABLE THEN EXECUTE 'TRUNCATE TABLE ' || tname;
END;
$$ LANGUAGE plpgsql;


CREATE TABLE session (
	id bigserial primary key,
	user_name varchar(255) not null,       -- user name for Webadmin or id from registrar table for EPP
	login_date timestamp not null, 
	logout_date timestamp,
        user_id integer
);

CREATE TABLE service (
	id SERIAL PRIMARY KEY,
	partition_postfix varchar(10) UNIQUE NOT NULL,
	name varchar(64) UNIQUE NOT NULL
);

CREATE TABLE request_type (
        id SERIAL PRIMARY KEY, 
        name varchar(64) NOT NULL,
        service_id integer NOT NULL REFERENCES service(id)
);
ALTER TABLE request_type ADD UNIQUE(name, service_id);

CREATE TABLE result_code (
    id SERIAL PRIMARY KEY,
    service_id INTEGER REFERENCES service(id),
    result_code INTEGER NOT NULL,
    name VARCHAR(64) NOT NULL    
);

CREATE TABLE request_object_type (
    id SERIAL PRIMARY KEY,
    name VARCHAR(64)
);


ALTER TABLE result_code ADD CONSTRAINT result_code_unique_code  UNIQUE (service_id, result_code );
ALTER TABLE result_code ADD CONSTRAINT result_code_unique_name  UNIQUE (service_id, name );

COMMENT ON TABLE result_code IS 'all possible operation result codes';
COMMENT ON COLUMN result_code.id IS 'result_code id';
COMMENT ON COLUMN result_code.service_id IS 'reference to service table. This is needed to distinguish entries with identical result_code values';
COMMENT ON COLUMN result_code.result_code IS 'result code as returned by the specific service, it''s only unique within the service';
COMMENT ON COLUMN result_code.name IS 'short name for error (abbreviation) written in camelcase';

-- for CloseRequest result_code_id updates, exception commented out until request.result_code_id optional
CREATE OR REPLACE FUNCTION get_result_code_id( integer, integer) 
RETURNS integer AS $$
DECLARE
    result_code_id INTEGER;
BEGIN

    SELECT id FROM result_code INTO result_code_id
        WHERE service_id=$1 and result_code=$2 ; 

    IF result_code_id is null THEN
        RAISE WARNING 'result_code.id not found for service_id=% and result_code=% ', $1, $2;
    END IF;
    RETURN result_code_id;
END;
$$ LANGUAGE plpgsql;

CREATE TABLE request (
	id BIGSERIAL PRIMARY KEY,
	time_begin timestamp NOT NULL,	-- begin of the transaction
	time_end timestamp,		-- end of transaction, it is set if the information is complete 
					-- e.g. if an error message from backend is successfully logged, it's still set	
					-- NULL in cases like crash of the server
	source_ip INET,
	service_id integer NOT NULL REFERENCES service(id),   -- service_id code - enum LogServiceType in IDL
	request_type_id integer REFERENCES request_type(id) DEFAULT 1000,
	session_id  bigint,            --  REFERENCES session(id),
        user_name varchar(255),         -- name of the user who issued the request (from session table)
		
	is_monitoring boolean NOT NULL, 
	result_code_id INTEGER,
        user_id INTEGER
);

CREATE TABLE request_object_ref (
    id BIGSERIAL PRIMARY KEY,
    request_time_begin TIMESTAMP NOT NULL,
    request_service_id INTEGER  NOT NULL,                                     
    request_monitoring BOOLEAN NOT NULL,                                      
    request_id BIGINT NOT NULL REFERENCES request(id),                       

    object_type_id INTEGER  NOT NULL REFERENCES request_object_type(id),             
    object_id INTEGER NOT NULL
);


ALTER TABLE request ADD FOREIGN KEY (result_code_id) REFERENCES result_code(id); 

COMMENT ON COLUMN request.result_code_id IS 'result code as returned by the specific service, it''s only unique within the service';

CREATE TABLE request_data (
        id BIGSERIAL PRIMARY KEY,
	request_time_begin timestamp NOT NULL, -- TEMP: for partitioning
	request_service_id integer NOT NULL, -- TEMP: for partitioning
	request_monitoring boolean NOT NULL, -- TEMP: for partitioning

	request_id bigint NOT NULL REFERENCES request(id),
	content text NOT NULL,
	is_response boolean DEFAULT False -- true if the content is response, false if it's request
);

CREATE TABLE request_property_name (
	id SERIAL PRIMARY KEY,
	name varchar(256) UNIQUE NOT NULL
);
	
CREATE TABLE request_property_value (
	request_time_begin timestamp NOT NULL, -- TEMP: for partitioning
	request_service_id integer NOT NULL, -- TEMP: for partitioning
	request_monitoring boolean NOT NULL, -- TEMP: for partitioning
	
	id BIGSERIAL PRIMARY KEY,
	request_id bigint NOT NULL REFERENCES request(id), 
	property_name_id integer NOT NULL REFERENCES request_property_name(id),
	value text NOT NULL,		-- property value
	output boolean DEFAULT False,		-- whether it's output (response) property; if False it's input (request)

	parent_id bigint REFERENCES request_property_value(id)
						-- in case of child property, the id of the parent, NULL otherwise
);

CREATE INDEX request_time_begin_idx ON request(time_begin);
CREATE INDEX request_time_end_idx ON request(time_end);
CREATE INDEX request_source_ip_idx ON request(source_ip);
CREATE INDEX request_service_idx ON request(service_id);
CREATE INDEX request_action_type_idx ON request(request_type_id);
CREATE INDEX request_monitoring_idx ON request(is_monitoring);
CREATE INDEX request_user_name_idx ON request(user_name);
CREATE INDEX request_user_id_idx ON request(user_id);

CREATE INDEX request_data_entry_time_begin_idx ON request_data(request_time_begin);
CREATE INDEX request_data_entry_id_idx ON request_data(request_id);
CREATE INDEX request_data_is_response_idx ON request_data(is_response);

CREATE INDEX request_property_name_idx ON request_property_name(name); 

CREATE INDEX request_property_value_entry_time_begin_idx ON request_property_value(request_time_begin);
CREATE INDEX request_property_value_entry_id_idx ON request_property_value(request_id); 
CREATE INDEX request_property_value_name_id_idx ON request_property_value(property_name_id); 
CREATE INDEX request_property_value_value_idx ON request_property_value(value); 
CREATE INDEX request_property_value_output_idx ON request_property_value(output); 
CREATE INDEX request_property_value_parent_id_idx ON request_property_value(parent_id); 

CREATE INDEX request_object_ref_id_idx ON request_object_ref(request_id);
CREATE INDEX request_object_ref_time_begin_idx ON request_object_ref(request_time_begin);
CREATE INDEX request_object_ref_service_id_idx ON request_object_ref(request_service_id);
CREATE INDEX request_object_ref_object_type_id_idx ON request_object_ref(object_type_id);
CREATE INDEX request_object_ref_object_id_idx ON request_object_ref(object_id);

CREATE INDEX session_user_name_idx ON session(user_name);
CREATE INDEX session_login_date_idx ON session(login_date);
CREATE INDEX session_user_id_idx ON session(user_id);
 

   
COMMENT ON TABLE request_type IS 
'List of requests which can be used by clients

id  - status
100 - ClientLogin
101 - ClientLogout
105 - ClientGreeting
120 - PollAcknowledgement
121 - PollResponse
200 - ContactCheck
201 - ContactInfo
202 - ContactDelete
203 - ContactUpdate
204 - ContactCreate
205 - ContactTransfer
400 - NSsetCheck
401 - NSsetInfo
402 - NSsetDelete
403 - NSsetUpdate
404 - NSsetCreate
405 - NSsetTransfer
500 - DomainCheck
501 - DomainInfo
502 - DomainDelete
503 - DomainUpdate
504 - DomainCreate
505 - DomainTransfer
506 - DomainRenew
507 - DomainTrade
600 - KeysetCheck
601 - KeysetInfo
602 - KeysetDelete
603 - KeysetUpdate
604 - KeysetCreate
605 - KeysetTransfer
1000 - UnknownAction
1002 - ListContact
1004 - ListNSset
1005 - ListDomain
1006 - ListKeySet
1010 - ClientCredit
1012 - nssetTest
1101 - ContactSendAuthInfo
1102 - NSSetSendAuthInfo
1103 - DomainSendAuthInfo
1104 - Info
1106 - KeySetSendAuthInfo
1200 - InfoListContacts
1201 - InfoListDomains
1202 - InfoListNssets
1203 - InfoListKeysets
1204 - InfoDomainsByNsset
1205 - InfoDomainsByKeyset
1206 - InfoDomainsByContact
1207 - InfoNssetsByContact
1208 - InfoNssetsByNs
1209 - InfoKeysetsByContact
1210 - InfoGetResults

1300 - Login
1301 - Logout 
1302 - DomainFilter
1303 - ContactFilter
1304 - NSSetFilter
1305 - KeySetFilter
1306 - RegistrarFilter
1307 - InvoiceFilter
1308 - EmailsFilter
1309 - FileFilter
1310 - ActionsFilter
1311 - PublicRequestFilter 

1312 - DomainDetail
1313 - ContactDetail
1314 - NSSetDetail
1315 - KeySetDetail
1316 - RegistrarDetail
1317 - InvoiceDetail
1318 - EmailsDetail
1319 - FileDetail
1320 - ActionsDetail
1321 - PublicRequestDetail 

1322 - RegistrarCreate
1323 - RegistrarUpdate 

1324 - PublicRequestAccept
1325 - PublicRequestInvalidate 

1326 - DomainDig
1327 - FilterCreate 

1328 - RequestDetail
1329 - RequestFilter

1330 - BankStatementDetail
1331 - BankStatementFilter

1400 -  Login 
1401 -  Logout

1402 -  DisplaySummary
1403 -  InvoiceList
1404 -  DomainList
1405 -  FileDetail';

INSERT INTO service (id, partition_postfix, name) VALUES 
(0, 'whois_', 'Unix whois');

INSERT INTO request_type (service_id, id, name) VALUES 
(0, 1105, 'Info');

INSERT INTO result_code (service_id, result_code, name) VALUES 
(0, 101 , 'NoEntriesFound'),
(0, 107 , 'UsageError'),
(0, 108 , 'InvalidRequest'),
(0, 501 , 'InternalServerError'),
(0, 0   , 'Ok');

INSERT INTO service (id, partition_postfix, name) VALUES 
(1, 'webwhois_', 'Web whois');

INSERT INTO request_type (service_id, id, name) VALUES 
(1, 1104, 'Info');

INSERT INTO result_code (service_id, result_code, name) VALUES 
(1, 0 , 'Ok'),
(1, 1 , 'NotFound'),
(1, 2 , 'Error');


INSERT INTO service (id, partition_postfix, name) VALUES
(2, 'pubreq_', 'Public Request');

INSERT INTO request_type (service_id, id, name) VALUES
(2, 1600, 'AuthInfo'),
(2, 1601, 'BlockTransfer'),
(2, 1602, 'BlockChanges'),
(2, 1603, 'UnblockTransfer'),
(2, 1604, 'UnblockChanges'),
(2, 1605, 'Verification'),
(2, 1606, 'ConditionalIdentification'),
(2, 1607, 'Identification');
INSERT INTO service (id, partition_postfix, name) VALUES 
(3, 'epp_', 'EPP');

INSERT INTO request_type (service_id, id, name) VALUES 
(3, 100,  'ClientLogin'),
(3, 101,  'ClientLogout'),
(3, 105,  'ClientGreeting'),
(3, 120,  'PollAcknowledgement'),
(3, 121,  'PollResponse'),
(3, 200,  'ContactCheck'),
(3, 201,  'ContactInfo'),
(3, 202,  'ContactDelete'),
(3, 203,  'ContactUpdate'),
(3, 204,  'ContactCreate'),
(3, 205,  'ContactTransfer'),
(3, 400,  'NSsetCheck'),
(3, 401,  'NSsetInfo'),
(3, 402,  'NSsetDelete'),
(3, 403,  'NSsetUpdate'),
(3, 404,  'NSsetCreate'),
(3, 405,  'NSsetTransfer'),
(3, 500,  'DomainCheck'),
(3, 501,  'DomainInfo'),
(3, 502,  'DomainDelete'),
(3, 503,  'DomainUpdate'),
(3, 504,  'DomainCreate'),
(3, 505,  'DomainTransfer'),
(3, 506,  'DomainRenew'),
(3, 507,  'DomainTrade'),
(3, 1000, 'UnknownAction'),
(3, 1002, 'ListContact'),
(3, 1004, 'ListNSset'), 
(3, 1005, 'ListDomain'),
(3, 1010, 'ClientCredit'),
(3, 1012, 'nssetTest'),
(3, 1101, 'ContactSendAuthInfo'),
(3, 1102, 'NSSetSendAuthInfo'),
(3, 1103, 'DomainSendAuthInfo'),
(3, 1106, 'KeySetSendAuthInfo'),
(3, 600,  'KeysetCheck'),
(3, 601,  'KeysetInfo'),
(3, 602,  'KeysetDelete'),
(3, 603,  'KeysetUpdate'),
(3, 604,  'KeysetCreate'),
(3, 605,  'KeysetTransfer'),
(3, 1006, 'ListKeySet'),
(3, 1200, 'InfoListContacts'),
(3, 1201, 'InfoListDomains'),
(3, 1202, 'InfoListNssets'),
(3, 1203, 'InfoListKeysets'),
(3, 1204, 'InfoDomainsByNsset'),
(3, 1205, 'InfoDomainsByKeyset'),
(3, 1206, 'InfoDomainsByContact'),
(3, 1207, 'InfoNssetsByContact'),
(3, 1208, 'InfoNssetsByNs'),
(3, 1209, 'InfoKeysetsByContact'),
(3, 1210, 'InfoGetResults');

INSERT INTO result_code (service_id, result_code, name) VALUES 
(3, 1000, 'CommandCompletedSuccessfully'),
(3, 1001, 'CommandCompletedSuccessfullyActionPending'),
(3, 1300, 'CommandCompletedSuccessfullyNoMessages'),
(3, 1301, 'CommandCompletedSuccessfullyAckToDequeue'),
(3, 1500, 'CommandCompletedSuccessfullyEndingSession'),
(3, 2000, 'UnknownCommand'),
(3, 2001, 'CommandSyntaxError'),
(3, 2002, 'CommandUseError'),
(3, 2003, 'RequiredParameterMissing'),
(3, 2004, 'ParameterValueRangeError'),
(3, 2005, 'ParameterValueSyntaxError'),
(3, 2100, 'UnimplementedProtocolVersion'),
(3, 2101, 'UnimplementedCommand'),
(3, 2102, 'UnimplementedOption'),
(3, 2103, 'UnimplementedExtension'),
(3, 2104, 'BillingFailure'),
(3, 2105, 'ObjectIsNotEligibleForRenewal'),
(3, 2106, 'ObjectIsNotEligibleForTransfer'),
(3, 2200, 'AuthenticationError'),
(3, 2201, 'AuthorizationError'),
(3, 2202, 'InvalidAuthorizationInformation'),
(3, 2300, 'ObjectPendingTransfer'),
(3, 2301, 'ObjectNotPendingTransfer'),
(3, 2302, 'ObjectExists'),
(3, 2303, 'ObjectDoesNotExist'),
(3, 2304, 'ObjectStatusProhibitsOperation'),
(3, 2305, 'ObjectAssociationProhibitsOperation'),
(3, 2306, 'ParameterValuePolicyError'),
(3, 2307, 'UnimplementedObjectService'),
(3, 2308, 'DataManagementPolicyViolation'),
(3, 2400, 'CommandFailed'),
(3, 2500, 'CommandFailedServerClosingConnection'),
(3, 2501, 'AuthenticationErrorServerClosingConnection'),
(3, 2502, 'SessionLimitExceededServerClosingConnection');

INSERT INTO service (id, partition_postfix, name) VALUES 
(4, 'webadmin_', 'WebAdmin');

INSERT INTO request_type (service_id, id, name) VALUES 
(4, 1300, 'Login'),
(4, 1301, 'Logout'), 
(4, 1302, 'DomainFilter'),
(4, 1303, 'ContactFilter'),
(4, 1304, 'NSSetFilter'),
(4, 1305, 'KeySetFilter'),
(4, 1306, 'RegistrarFilter'),
(4, 1307, 'InvoiceFilter'),
(4, 1308, 'EmailsFilter'),
(4, 1309, 'FileFilter'),
(4, 1310, 'ActionsFilter'),
(4, 1311, 'PublicRequestFilter'), 
(4, 1312, 'DomainDetail'),
(4, 1313, 'ContactDetail'),
(4, 1314, 'NSSetDetail'),
(4, 1315, 'KeySetDetail'),
(4, 1316, 'RegistrarDetail'),
(4, 1317, 'InvoiceDetail'),
(4, 1318, 'EmailsDetail'),
(4, 1319, 'FileDetail'),
(4, 1320, 'ActionsDetail'),
(4, 1321, 'PublicRequestDetail'), 
(4, 1322, 'RegistrarCreate'),
(4, 1323, 'RegistrarUpdate'), 
(4, 1324, 'PublicRequestAccept'),
(4, 1325, 'PublicRequestInvalidate'), 
(4, 1326, 'DomainDig'),
(4, 1327, 'FilterCreate'), 
(4, 1328, 'RequestDetail'),
(4, 1329, 'RequestFilter'), 
(4, 1330, 'BankStatementDetail'),
(4, 1331, 'BankStatementFilter'), 
(4, 1332, 'PaymentPair'),
(4, 1333, 'SetInZoneStatus'),
(4, 1334, 'SaveFilter'),
(4, 1335, 'LoadFilter'),
(4, 1336, 'CreateRegistrarGroup'),
(4, 1337, 'DeleteRegistrarGroup'),
(4, 1338, 'UpdateRegistrarGroup'),
(4, 1339, 'MessageDetail'),
(4, 1340, 'MessageFilter');

INSERT INTO result_code (service_id, result_code, name) VALUES 
(4, 1 , 'Success'),
(4, 2 , 'Fail'),
(4, 3 , 'Error');

INSERT INTO service (id, partition_postfix, name) VALUES 
(5, 'intranet_', 'Intranet');

INSERT INTO request_type (service_id, id, name) VALUES 
(5, 1400, 'Login'),
(5, 1401, 'Logout'),
(5, 1402, 'DisplaySummary'),
(5, 1403, 'InvoiceList'),
(5, 1404, 'DomainList'),
(5, 1405, 'FileDetail');

INSERT INTO service (id, partition_postfix, name) VALUES 
(6, 'mojeid_', 'MojeID');

-- Important! If you add an item here, do not forget to add a translation in 
--      enum/nicms/base/trunk/apps/nicommon/logger/history_reader.py: request_type_codes

INSERT INTO request_type (service_id, id, name) VALUES 
(6, 1500, 'OpenIDRequest'),
(6, 1501, 'Login'),
(6, 1502, 'Logout'),
(6, 1504, 'UserChange'),
(6, 1507, 'PasswordResetRequest'),
(6, 1509, 'TrustChange'),
(6, 1511, 'AccountStateChange'),
(6, 1512, 'AuthChange');

INSERT INTO result_code (service_id, result_code, name) VALUES 
(6, 1 , 'Success'),
(6, 2 , 'Fail'),
(6, 3 , 'Error');

INSERT INTO service (id, partition_postfix, name) VALUES 
(7, 'd_browser_', 'Domainbrowser');

INSERT INTO request_type (service_id, id, name) VALUES 
(7, 1700, 'Login'),
(7, 1701, 'Logout'),
(7, 1702, 'BlockingAction'),
(7, 1703, 'DiscloseAction'),
(7, 1704, 'Browse'),
(7, 1705, 'Detail');

INSERT INTO result_code (service_id, result_code, name) VALUES 
(7, 1 , 'Success'),
(7, 2 , 'Fail'),
(7, 3 , 'Error'),
(7, 4 , 'NotValidated'),
(7, 5 , 'Warning');
-- Set sequences beginnings
SELECT setval('request_type_id_seq', (SELECT MAX(id) FROM request_type));

-- fill object types for logger request_object_ref table
INSERT INTO request_object_type (id, name) VALUES (1, 'contact');
INSERT INTO request_object_type (id, name) VALUES (2, 'nsset');
INSERT INTO request_object_type (id, name) VALUES (3, 'domain');
INSERT INTO request_object_type (id, name) VALUES (4, 'keyset');
INSERT INTO request_object_type (id, name) VALUES (5, 'registrar');
INSERT INTO request_object_type (id, name) VALUES (6, 'mail');
INSERT INTO request_object_type (id, name) VALUES (7, 'file');
INSERT INTO request_object_type (id, name) VALUES (8, 'publicrequest');
INSERT INTO request_object_type (id, name) VALUES (9, 'invoice');
INSERT INTO request_object_type (id, name) VALUES (10, 'bankstatement');
INSERT INTO request_object_type (id, name) VALUES (11, 'request');
INSERT INTO request_object_type (id, name) VALUES (12, 'message');

--
-- have to be done manually (logger will be in separate database)
--
-- SELECT setval('request_id_seq', (SELECT max(id) FROM action));


INSERT INTO request_property_name(id, name) VALUES
(1,	    'registrarId'),
(2,	    'lang'),
(3,	    'password'),
(4,	    'clTRID'),
(5,	    'svTRID'),
(6,	    'rc'),
(7,	    'msg'),
(8,	    'searchAxis'),
(9,	    'type'),
(10,	'handle'),
(11,	'recursion'),
(12,	'status'),
(13,	'queryType'),
(14,	'id'),
(15,	'name'),
(16,	'registrant'),
(17,	'period'),
(18,	'timeunit'),
(19,	'creationDate'),
(20,	'newPassword'),
(21,	'checkId'),
(22,	'available'),
(23,	'reason'),
(24,	'curExDate'),
(25,	'renewPeriod'),
(26,	'nsset'),
(27,	'keyset'),
(28,	'authInfo'),
(29,	'username'),
(30,	'session_id'),
(31,	'result_size'),
(32,	'filter_Service'),
(33,	'negation'),
(34,	'object_id'),
(35,	'pi.name'),
(36,	'pi.organization'),
(37,	'pi.street'),
(38,	'pi.city'),
(39,	'pi.postalCode'),
(40,	'pi.countryCode'),
(41,	'email'),
(42,	'discl.policy'),
(43,	'discl.name'),
(44,	'discl.org'),
(45,	'discl.addr'),
(46,	'discl.voice'),
(47,	'discl.fax'),
(48,	'discl.email'),
(49,	'discl.vat'),
(50,	'discl.ident'),
(51,	'discl.notifyEmail'),
(52,	'ident'),
(53,	'identType'),
(54,	'admin'),
(55,	'reportLevel'),
(56,	'ns.name'),
(57,	'techC'),
(58,	'filter_TimeBegin'),
(59,	'msgId'),
(60,	'url'),
(61,	'errorType'),
(62,	'voice'),
(63,	'fax'),
(64,	'filter_IsMonitoring'),
(65,	'filter_Type'),
(66,	'filter_CreateTime'),
(67,	'filter_ZoneFqdn'),
(68,	'filter_Handle'),
(69,	'filter_AccountDate'),
(70,	'vat'),
(71,	'notifyEmail'),
(72,	'addAdmin'),
(73,	'remAdmin'),
(74,	'errors'),
(75,	'ns.addr'),
(76,	'pi.state'),
(77,	'domainId'),
(78,	'remTmpcontact'),
(79,	'filter_Registrant.Handle'),
(80,	'filter_Registrar.Handle'),
(81,	'filter_KeySet.Handle'),
(82,	'filter_or'),
(83,	'filter_RequestHandle'),
(84,	'filter_SvTRID'),
(85,	'filter_Time'),
(86,	'filter_AdminContact.Handle'),
(87,	'filter_TempContact.Handle'),
(88,	'filter_Name'),
(89,	'addNs.name'),
(90,	'remNs'),
(91,	'filter_CancelDate'),
(92,	'filter_OutZoneDate'),
(93,	'filter_Registrant.Name'),
(94,	'filter_ExpirationDate'),
(95,	'addNs.addr'),
(96,	'filter_NSSet.Handle'),
(97,	'filter_Organization'),
(98,	'filter_Ssn'),
(99,	'addTechC'),
(100,	'remTechC'),
(101,	'publicrequest_id'),
(102,	'filter_TechContact.Handle'),
(103,	'keys.flags'),
(104,	'keys.protocol'),
(105,	'keys.alg'),
(106,	'keys.publicKey'),
(107,	'techContact'),
(108,	'filter_Email'),
(109,	'result'),
(110,	'filter_Message'),
(111,	'payment_id'),
(112,	'registrar_handle'),
(113,	'filter_HostIP'),
(114,	'filter_HostFQDN'),
(115,	'filter_TechContact.Email'),
(116,	'filter_TechContact.Name'),
(117,	'set_countryCode'),
(118,	'set_telephone'),
(119,	'set_zones'),
(120,	'set_id'),
(121,	'set_city'),
(122,	'set_ico'),
(123,	'set_access'),
(124,	'set_varSymb'),
(125,	'set_hidden'),
(126,	'set_email'),
(127,	'set_vat'),
(128,	'set_fax'),
(129,	'set_handle'),
(130,	'set_street1'),
(131,	'set_street2'),
(132,	'set_street3'),
(133,	'set_postalcode'),
(134,	'set_stateorprovince'),
(135,	'set_name'),
(136,	'set_url'),
(137,	'set_dic'),
(138,	'set_organization'),
(139,	'filter_Registrant.Email'),
(140,	'addKeys.flags'),
(141,	'addKeys.protocol'),
(142,	'addKeys.alg'),
(143,	'addKeys.publicKey'),
(144,	'remKeys.flags'),
(145,	'remKeys.protocol'),
(146,	'remKeys.alg'),
(147,	'remKeys.publicKey'),
(148,	'filter_Object.Handle'),
(149,	'filter_Response'),
(150,	'filter_AccountNumber'),
(151,	'filter_VarSymb'),
(152,	'filter_TaxDate'),
(153,	'filter_Registrar.Name'),
(154,	'filter_NotifyEmail'),
(157,	'filter_Id'),
(158,	'filter_Vat'),
(159,	'filter_EmailToAnswer'),
(160,	'filter_ResolveTime'),
(161,	'filter_DeleteTime'),
(162,	'filter_ActionType'),
(163,	'filter_Object.AuthInfo'),
(164,	'filter_Number'),
(165,	'filter_TimeEnd'),
(166,	'filter_UserName'),
(167,	'filter_Status'),
(168,	'addTech'),
(169,	'filter_Registrar.Organization'),
(156,	'filter_RequestPropertyValue.Value'),
(171,	'filter_CreateRegistrar.Handle'),
(172,	'count'),
(173,	'zone'),
(174,	'credit'),
(175,	'set_visible_fieldsets_ids'),
(176,	'set_password'),
(177,	'set_md5Cert'),
(178,	'set_DELETE'),
(179,	'set_fromDate'),
(180,	'set_toDate'),
(183,	'filter_InvoiceId'),
(184,	'filter_ServiceType'),
(185,	'filter_CrDate'),
(186,	'account_state'),
(187,	'method'),
(188,	'username_from_handle'),
(189,	'send_me_news'),
(190,	'first_name'),
(191,	'last_name'),
(192,	'phone_number'),
(193,	'street1'),
(194,	'street2'),
(195,	'street3'),
(196,	'city'),
(197,	'postal_code'),
(198,	'country'),
(199,	'request_hash'),
(200,	'request_mode'),
(201,	'realm'),
(202,	'assoc_handle'),
(203,	'return_to'),
(204,	'identity'),
(205,	'claimed_id'),
(206,	'pape_max_auth_age'),
(207,	'response_mode'),
(208,	'response_claimed_id'),
(209,	'pape_auth_time'),
(210,	'nickname'),
(211,	'sreg_required'),
(212,	'sreg_optional'),
(213,	'sreg_returned'),
(214,	'realmbag'),
(215,	'trusted_attr'),
(216,	'trusted'),
(217,	'ax_required'),
(218,	'ax_returned'),
(219,	'pape_preferred_auth_policies'),
(220,	'ax_optional'),
(221,	'distrusted_attr'),
(222,	'student'),
(223,	'id_card_num'),
(224,	'birth_date'),
(225,	'filter_MessageType'),
(226,	'Address'),
(227,	'OPERATION'),
(228,	'passport_num'),
(229,	'disclose_email'),
(230,	'disclose_phone'),
(231,	'disclose_vat'),
(232,	'disclose_ident'),
(233,	'disclose_notify_email'),
(234,	'disclose_fax'),
(235,	'image'),
(236,	'organization'),
(237,	'vat_reg_num'),
(238,	'vat_id_num'),
(239,	'filter_RequestType'),
(240,	'filter_CommType'),
(241,	'state'),
(242,	'IMAccount'),
(243,	'URLAddress'),
(244,	'pape_auth_policies'),
(245,	'Phone'),
(246,	'number'),
(247,	'Email'),
(248,	'ssn_id_num'),
(249,	'remTech'),
(250,	'filter_SourceIp'),
(251,	'filter_NSSet.HostFQDN'),
(252,	'filter_ObjectState.StateId'),
(253,	'source'),
(254,	'prefix'),
(255,	'set_country'),
(256,	'test_domain'),
(155,	'filter_RequestPropertyValue.Name'),
(170,	'filter_NSSet.TechContact.Handle'),
(181,	'filter_Registrant.Registrar.Organization'),
(182,	'filter_Registrant.Organization'),
(257,	'filter_AccountId'),
(258,	'filter_ClTRID'),
(259,	'filter_MessageContact.Handle'),
(260,	'filter_PhoneNumber'),
(261,	'filter_SmsPhoneNumber'),
(262,	'address'),
(263,	'phone'),
(264,	'pape_preferred_auth_level_types'),
(265,	'auth_info'),
(266,	'filter_TransferTime'),
(267,	'filter_UpdateTime'),
(268,	'filter_ModDate'),
(269,	'level'),
(270,	'ax_store_succeeded'),
(271,	'ax_store_error'),
(272,	'filter_ModifyTime'),
(273,	'filter_CrTime'),
(274,	'send_info'),
(275,	'registration_nonce'),
(276,	'immediate'),
(277,	'email_change_request'),
(278,	'urladdress'),
(279,	'imaccount'),
(280,	'number_change_request'),
(281,	'filter_Registrant.Ssn'),
(282,	'filter_Registrant.NotifyEmail'),
(283,	'filter_AdminContact.Email'),
(284,	'filter_AdminContact.NotifyEmail'),
(285,	'filter_TempContact.Email'),
(286,	'set_evaluation_file_id'),
(287,	'set_score'),
(288,	'set_uploaded_file'),
(289,	'set_evaluation_file'),
(290,	'display_trust'),
(291,	'password_active'),
(292,	'filter_Registrant.Vat'),
(293,	'certificate_active'),
(294,	'filter_Attempt'),
(295,	'filter_LetterAddrName'),
(296,	'keep_session'),
(297,	'filter_TechContact.CreateTime'),
(298,	'filter_UpdateRegistrar.Organization'),
(299,	'filter_NSSet.TechContact.Email'),
(300,	'filter_CreateRegistrar.Name'),
(301,	'filter_AuthInfo');


SELECT setval('request_property_name_id_seq', (SELECT MAX(id) FROM request_property_name));

-- public request result code
INSERT INTO result_code (service_id, result_code, name) VALUES
(2, 0 , 'Ok'),
(2, 1 , 'Error'),
(2, 2, 'Fail');


-- CREATE OR REPLACE FUNCTION tr_request RETURNS trigger AS $tr_request$

/*
functions for each table: 
 - tr_* 'trigger' 
 - create_* creating a new partition
 - create_indexes_* which CREATE indexes (used by create_*)

*/

CREATE OR REPLACE FUNCTION bool_to_str(b BOOLEAN) RETURNS CHAR
AS $bool_to_str$
BEGIN
        RETURN (SELECT CASE WHEN b THEN 't' ELSE 'f' END);
END;
$bool_to_str$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION tr_request(id BIGINT, time_begin TIMESTAMP WITHOUT TIME ZONE, time_end TIMESTAMP WITHOUT TIME ZONE, source_ip INET, service_id INTEGER, request_type_id INTEGER, session_id BIGINT, user_name VARCHAR(255), user_id INTEGER, is_monitoring BOOLEAN ) RETURNS VOID AS $tr_request$
DECLARE 
        table_name VARCHAR(50);
        stmt       TEXT;
BEGIN
        table_name = quote_ident('request_' || partition_postfix(time_begin, service_id, is_monitoring));

        stmt := 'INSERT INTO ' || table_name || ' (id, time_begin, time_end, source_ip, service_id, request_type_id, session_id, user_name, user_id, is_monitoring) VALUES (' 
                || COALESCE(id::TEXT, 'NULL')           || ', ' 
                || COALESCE(quote_literal(time_begin), 'NULL')           || ', '
                || COALESCE(quote_literal(time_end), 'NULL')             || ', '
                || COALESCE(quote_literal(host(source_ip)), 'NULL')      || ', '
                || COALESCE(service_id::TEXT, 'NULL')      || ', '
                || COALESCE(request_type_id::TEXT, 'NULL')  || ', '
                || COALESCE(session_id::TEXT, 'NULL')   || ', '
                || COALESCE(quote_literal(user_name), 'NULL')            || ', '
                || COALESCE(user_id::TEXT, 'NULL')                       || ', '
                || '''' || bool_to_str(is_monitoring)   || ''') ';
        
        -- raise notice 'request Generated insert: %', stmt;
        EXECUTE stmt;

EXCEPTION
        WHEN undefined_table THEN
        BEGIN
                PERFORM create_tbl_request(time_begin, service_id, is_monitoring);
        
                EXECUTE stmt;
        END;
END;
$tr_request$ LANGUAGE plpgsql;


-- reuqest_object_ref trigger
CREATE OR REPLACE FUNCTION tr_request_object_ref(id BIGINT, request_time_begin TIMESTAMP WITHOUT TIME ZONE, request_service_id INTEGER, request_monitoring BOOLEAN, request_id BIGINT, object_type_id INTEGER, object_id INTEGER) RETURNS VOID AS $tr_request_object_ref$
DECLARE 
        table_name VARCHAR(50);
        stmt TEXT;
BEGIN
        table_name := quote_ident('request_object_ref_' || partition_postfix(request_time_begin, request_service_id, request_monitoring));
        stmt := 'INSERT INTO ' || table_name || ' (id, request_time_begin, request_service_id, request_monitoring, request_id, object_type_id, object_id) VALUES ('
            || COALESCE(id::TEXT, 'NULL')                       || ', '
            || COALESCE(quote_literal(request_time_begin), 'NULL') || ', '
            || COALESCE(request_service_id::TEXT, 'NULL')       || ', '
            || '''' || bool_to_str(request_monitoring)          || ''', ' 
            || COALESCE(request_id::TEXT, 'NULL')               || ', ' 
            || COALESCE(object_type_id::TEXT, 'NULL')           || ', '
            || COALESCE(object_id::TEXT, 'NULL')                
            || ') ';
    
        raise notice 'generated SQL: %', stmt;
        EXECUTE stmt;
EXCEPTION
        WHEN undefined_table THEN
        BEGIN
                raise notice 'In exception handler..... ';
                PERFORM create_tbl_request_object_ref(request_time_begin, request_service_id, request_monitoring);
                EXECUTE stmt;
        END;
END;
$tr_request_object_ref$ LANGUAGE plpgsql;

-- session is partitioned according to date only
CREATE OR REPLACE FUNCTION tr_session(id BIGINT, user_name VARCHAR(255), user_id INTEGER, login_date timestamp, logout_date timestamp) RETURNS VOID AS $tr_session$
DECLARE 
        table_name VARCHAR(50);
        stmt  TEXT;
BEGIN
        table_name := quote_ident('session_' || partition_postfix(login_date, -1, false));
        stmt := 'INSERT INTO ' || table_name || ' (id, user_name, user_id, login_date, logout_date) VALUES (' 
                || COALESCE(id::TEXT, 'NULL')           || ', ' 
                || COALESCE(quote_literal(user_name), 'NULL')                 || ', '
                || COALESCE(user_id::TEXT, 'NULL')                       || ', '
                || COALESCE(quote_literal(login_date), 'NULL')           || ', '
                || COALESCE(quote_literal(logout_date), 'NULL')          

                || ')';

        -- raise notice 'session Generated insert: %', stmt;
        EXECUTE stmt;

EXCEPTION
        WHEN undefined_table THEN
        BEGIN
                PERFORM create_tbl_session(login_date);
        
                EXECUTE stmt;
        END;
END;
$tr_session$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION tr_request_data(request_time_begin timestamp, request_service_id INTEGER,  request_monitoring BOOLEAN, request_id BIGINT, content TEXT, is_response BOOLEAN) RETURNS VOID AS $tr_request_data$
DECLARE 
        table_name VARCHAR(50);
        stmt  TEXT;
BEGIN
        table_name := quote_ident('request_data_' || partition_postfix(request_time_begin, request_service_id, request_monitoring));
        stmt := 'INSERT INTO ' || table_name || '(request_time_begin, request_service_id, request_monitoring, request_id,  content, is_response) VALUES (' 
            || COALESCE(quote_literal(request_time_begin), 'NULL')                 || ', ' 
            || COALESCE(request_service_id::TEXT, 'NULL')            || ', '
            || '''' || bool_to_str(request_monitoring)            || ''', ' 
            || COALESCE(request_id::TEXT, 'NULL')                 || ', ' 
            || COALESCE(quote_literal(content), 'NULL')                          || ', '
            || COALESCE('''' || bool_to_str(is_response) || '''' , 'NULL') || ') ';  

        -- raise notice 'request_data Generated insert: %', stmt;
        EXECUTE stmt;

EXCEPTION
        WHEN undefined_table THEN
        BEGIN
                PERFORM create_tbl_request_data(request_time_begin, request_service_id, request_monitoring);
        
                EXECUTE stmt;
        END;
END;
$tr_request_data$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION tr_request_property_value(request_time_begin TIMESTAMP WITHOUT TIME ZONE, request_service_id INTEGER, request_monitoring BOOLEAN, id BIGINT, request_id BIGINT, property_name_id INTEGER, value TEXT, output BOOLEAN, parent_id BIGINT) RETURNS VOID AS $tr_request_property_value$
DECLARE 
        table_name VARCHAR(50);
        stmt  TEXT;
BEGIN
        table_name := quote_ident( 'request_property_value_' || partition_postfix(request_time_begin, request_service_id, request_monitoring));
        stmt := 'INSERT INTO ' || table_name || '(request_time_begin, request_service_id, request_monitoring, id, request_id, property_name_id, value, output, parent_id) VALUES (' 
            || COALESCE(quote_literal(request_time_begin), 'NULL')    || ', ' 
            || COALESCE(request_service_id::TEXT, 'NULL')                || ', '
            || '''' || bool_to_str(request_monitoring)                || ''', '
            || COALESCE(id::TEXT, 'NULL')                           || ', '
            || COALESCE(request_id::TEXT, 'NULL')                     || ', '
            || COALESCE(property_name_id::TEXT, 'NULL')                      || ', '
            || COALESCE(quote_literal(value), 'NULL')               || ', '
            || COALESCE('''' || bool_to_str(output) || '''', 'NULL') || ', ' 
            || COALESCE(parent_id::TEXT, 'NULL')                    || ')'; 
        -- raise notice 'request_property_value Generated insert: %', stmt;
        EXECUTE stmt;

EXCEPTION
        WHEN undefined_table THEN
        BEGIN
                PERFORM create_tbl_request_property_value(request_time_begin, request_service_id, request_monitoring);
        
                EXECUTE stmt;
        END;
END;
$tr_request_property_value$ LANGUAGE plpgsql;

-- can handle years from 2000 to 2099
-- this dependes on LogServiceType in log_impl.h AND in _dataTypes.idl
-- but slightly faster than the latter version
/*
CREATE OR REPLACE FUNCTION partition_postfix(rec_time TIMESTAMP WITHOUT TIME ZONE, service_id INTEGER, is_monitoring BOOLEAN ) RETURNS VARCHAR(40) AS 
$partition_postfix$
DECLARE 
        date_part VARCHAR(5);
BEGIN
        date_part := to_char(date_trunc('month', rec_time), 'YY_MM');

        IF (service_id = -1) THEN
                -- for session which is not partitioned by service_id
                RETURN date_part;
        elsif (is_monitoring) THEN
                RETURN 'mon_' || date_part;     
                -- separate partition for monitoring requests
        elsif (service_id = 0) THEN
                RETURN 'whois_' || date_part;
        elsif (service_id = 1) THEN                 
                RETURN 'webwhois_' || date_part;
        elsif (service_id = 2) THEN                 
                RETURN 'pubreq_' || date_part;
        elsif (service_id = 3) THEN                 
                RETURN 'epp_' || date_part;
        elsif (service_id = 4) THEN                 
                RETURN 'webadmin_' || date_part;
        elsif (service_id = 5) THEN 
                RETURN 'intranet_' || date_part;
        END IF;
        
        raise exception 'Unknown service_id type number: % ', service_id;

END;
$partition_postfix$ LANGUAGE plpgsql;
*/


/**
Output should be processed by quote_ident
*/
CREATE OR REPLACE FUNCTION partition_postfix(rec_time TIMESTAMP WITHOUT TIME ZONE, serv INTEGER, is_monitoring BOOLEAN ) RETURNS VARCHAR(40) AS 
$partition_postfix_alt$
DECLARE 
        date_part VARCHAR(5);
        service_postfix VARCHAR(10);
BEGIN
        date_part := to_char(date_trunc('month', rec_time), 'YY_MM');

        IF (serv = -1) THEN
                RETURN date_part;
        elsif (is_monitoring) THEN
                RETURN 'mon_' || date_part;     
        ELSE
                SELECT partition_postfix into service_postfix from service where id = serv;
                RETURN service_postfix || date_part;
        END IF;
END;
$partition_postfix_alt$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION create_tbl_request(time_begin TIMESTAMP WITHOUT TIME ZONE, service_id INTEGER, monitoring BOOLEAN) RETURNS VOID AS $create_tbl_request$
DECLARE 
        table_name VARCHAR(60);
        create_table    TEXT;
        spec_alter_table TEXT;
        month INTEGER;
        lower TIMESTAMP WITHOUT TIME ZONE;
        upper  TIMESTAMP WITHOUT TIME ZONE;

BEGIN
        table_name := quote_ident('request' || '_' || partition_postfix(time_begin, service_id, monitoring));

        LOCK TABLE request IN SHARE UPDATE EXCLUSIVE MODE;

        lower := to_char(date_trunc('month', time_begin), 'YYYY-MM-DD');
        upper := to_char(date_trunc('month', time_begin + interval '1 month'), 'YYYY-MM-DD');

-- CREATE table
        IF monitoring = true THEN
                -- special constraints for monitoring table
                create_table := 'CREATE TABLE ' || table_name || '    (CHECK (time_begin >= TIMESTAMP ''' || lower || ''' AND time_begin < TIMESTAMP ''' 
                || upper || ''' AND is_monitoring = ''' || bool_to_str(monitoring) || ''') ) INHERITS (request)';
        ELSE
                create_table := 'CREATE TABLE ' || table_name || '    (CHECK (time_begin >= TIMESTAMP ''' || lower || ''' AND time_begin < TIMESTAMP ''' 
                || upper || ''' AND service_id = ' || service_id || ' AND is_monitoring = ''' || bool_to_str(monitoring) || ''') ) INHERITS (request)';          
        END IF; 
         
        
        spec_alter_table := 'ALTER TABLE ' || table_name || ' ADD PRIMARY KEY (id); ';

        EXECUTE create_table;
        EXECUTE spec_alter_table;

        PERFORM create_indexes_request(table_name);

EXCEPTION
    WHEN duplicate_table THEN
        NULL;
END;
$create_tbl_request$ LANGUAGE plpgsql;

/** parameter table_name must already be processed by quote_ident
*/
CREATE OR REPLACE FUNCTION create_indexes_request(table_name VARCHAR(50)) RETURNS VOID AS $create_indexes_request$
DECLARE 
        create_indexes TEXT;
BEGIN
        create_indexes := 'CREATE INDEX ' || table_name || '_time_begin_idx ON ' || table_name || '(time_begin);'
                       || 'CREATE INDEX ' || table_name || '_time_end_idx ON ' || table_name || '(time_end);'
                       || 'CREATE INDEX ' || table_name || '_source_ip_idx ON ' || table_name || '(source_ip);'         
                       || 'CREATE INDEX ' || table_name || '_service_idx ON ' || table_name || '(service_id);'  
                       || 'CREATE INDEX ' || table_name || '_action_type_idx ON ' || table_name || '(request_type_id);' 
                       || 'CREATE INDEX ' || table_name || '_monitoring_idx ON ' || table_name || '(is_monitoring);'
                       || 'CREATE INDEX ' || table_name || '_user_name_idx ON ' || table_name || '(user_name);'
                       || 'CREATE INDEX ' || table_name || '_user_id_idx ON ' || table_name || '(user_id);';
        EXECUTE create_indexes;
END;
$create_indexes_request$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION create_tbl_request_data(time_begin TIMESTAMP WITHOUT TIME ZONE, service_id INTEGER, monitoring BOOLEAN) RETURNS VOID AS $create_tbl_request_data$
DECLARE 
        table_name VARCHAR(60);
        table_postfix VARCHAR(40);
        create_table    TEXT;
        spec_alter_table TEXT;
        month INTEGER;
        lower TIMESTAMP WITHOUT TIME ZONE;
        upper  TIMESTAMP WITHOUT TIME ZONE;
BEGIN
        table_postfix := quote_ident(partition_postfix(time_begin, service_id, monitoring));
        table_name := 'request_data_' || table_postfix;

        LOCK TABLE request_data IN SHARE UPDATE EXCLUSIVE MODE;

        lower := to_char(date_trunc('month', time_begin), 'YYYY-MM-DD');
        upper := to_char(date_trunc('month', time_begin + interval '1 month'), 'YYYY-MM-DD');

        IF monitoring = true THEN
                create_table  =  'CREATE TABLE ' || table_name || ' (CHECK (request_time_begin >= TIMESTAMP ''' || lower || ''' AND request_time_begin < TIMESTAMP ''' || upper || ''' AND request_monitoring = ''' || bool_to_str(monitoring) || ''') ) INHERITS (request_data) ';   
        ELSE 
                create_table  =  'CREATE TABLE ' || table_name || ' (CHECK (request_time_begin >= TIMESTAMP ''' || lower || ''' AND request_time_begin < TIMESTAMP ''' || upper || ''' AND request_service_id = ' || service_id || ' AND request_monitoring = ''' || bool_to_str(monitoring) || ''') ) INHERITS (request_data) ';
        END IF;
        
        spec_alter_table = 'ALTER TABLE ' || table_name || ' ADD PRIMARY KEY (id); '
             || 'ALTER TABLE ' || table_name || ' ADD CONSTRAINT ' || table_name || '_entry_id_fkey FOREIGN KEY (request_id) REFERENCES request_' || table_postfix || '(id); '; 

        EXECUTE create_table;
        EXECUTE spec_alter_table;
        
        PERFORM create_indexes_request_data(table_name);

EXCEPTION
    WHEN duplicate_table THEN
        NULL;
END;
$create_tbl_request_data$ LANGUAGE plpgsql;

-- CREATE index on content removed (too large rows)
/** parameter table_name must already be processed by quote_ident
*/
CREATE OR REPLACE FUNCTION create_indexes_request_data(table_name VARCHAR(50)) RETURNS VOID AS $create_indexes_request_data$
DECLARE 
        create_indexes TEXT;
BEGIN
        create_indexes = 'CREATE INDEX ' || table_name || '_entry_time_begin_idx ON ' || table_name || '(request_time_begin); CREATE INDEX ' || table_name || '_entry_id_idx ON ' || table_name || '(request_id); CREATE INDEX ' || table_name || '_is_response_idx ON ' || table_name || '(is_response);';
        EXECUTE create_indexes;
END;
$create_indexes_request_data$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION create_tbl_request_property_value(time_begin TIMESTAMP WITHOUT TIME ZONE, service_id INTEGER, monitoring BOOLEAN) RETURNS VOID AS $create_tbl_request_property_value$
DECLARE 
        table_name VARCHAR(60);
        table_postfix VARCHAR (40);
        create_table    TEXT;
        spec_alter_table TEXT;
        month INTEGER;
        lower TIMESTAMP WITHOUT TIME ZONE;
        upper  TIMESTAMP WITHOUT TIME ZONE;
BEGIN
        table_postfix := quote_ident(partition_postfix(time_begin, service_id, monitoring));
        table_name := 'request_property_value_' || table_postfix; 

        LOCK TABLE request_property_value IN SHARE UPDATE EXCLUSIVE MODE;

        lower := to_char(date_trunc('month', time_begin), 'YYYY-MM-DD');
        upper := to_char(date_trunc('month', time_begin + interval '1 month'), 'YYYY-MM-DD');

        IF monitoring = true THEN
                create_table  =  'CREATE TABLE ' || table_name || ' (CHECK (request_time_begin >= TIMESTAMP ''' || lower || ''' AND request_time_begin < TIMESTAMP ''' || upper || '''  AND request_monitoring = ''' || bool_to_str(monitoring) || ''') ) INHERITS (request_property_value) ';
        ELSE 
                create_table  =  'CREATE TABLE ' || table_name || ' (CHECK (request_time_begin >= TIMESTAMP ''' || lower || ''' AND request_time_begin < TIMESTAMP ''' || upper || '''  AND request_service_id = ' || service_id || ' AND request_monitoring = ''' || bool_to_str(monitoring) || ''') ) INHERITS (request_property_value) ';
        END IF;         

        spec_alter_table = 'ALTER TABLE ' || table_name || ' ADD PRIMARY KEY (id); ALTER TABLE ' || table_name || ' ADD CONSTRAINT ' || table_name || '_entry_id_fkey FOREIGN KEY (request_id) REFERENCES request_' || table_postfix || '(id); ALTER TABLE ' || table_name || ' ADD CONSTRAINT ' || table_name || '_name_id_fkey FOREIGN KEY (property_name_id) REFERENCES request_property_name(id); ALTER TABLE ' || table_name || ' ADD CONSTRAINT ' || table_name || '_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES ' || table_name || '(id); ';

        EXECUTE create_table;
        EXECUTE spec_alter_table;
        PERFORM create_indexes_request_property_value(table_name);
EXCEPTION
    WHEN duplicate_table THEN
        NULL;

END;
$create_tbl_request_property_value$ LANGUAGE plpgsql;


/** parameter table_name must already be processed by quote_ident
*/
CREATE OR REPLACE FUNCTION create_indexes_request_property_value(table_name VARCHAR(50)) RETURNS VOID AS $create_indexes_request_property_value$
DECLARE 
        create_indexes TEXT;
BEGIN
        create_indexes = 'CREATE INDEX ' || table_name || '_entry_time_begin_idx ON ' || table_name || '(request_time_begin); CREATE INDEX ' || table_name || '_entry_id_idx ON ' || table_name || '(request_id); CREATE INDEX ' || table_name || '_name_id_idx ON ' || table_name || '(property_name_id); CREATE INDEX ' || table_name || '_value_idx ON ' || table_name || '(value); CREATE INDEX ' || table_name || '_output_idx ON ' || table_name || '(output); CREATE INDEX ' || table_name || '_parent_id_idx ON ' || table_name || '(parent_id);';
        EXECUTE create_indexes;

END;
$create_indexes_request_property_value$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION create_tbl_request_object_ref(time_begin TIMESTAMP WITHOUT TIME ZONE, service_id INTEGER, monitoring BOOLEAN) RETURNS VOID AS $create_tbl_request_object_ref$
DECLARE 
        table_name VARCHAR(60);
        table_postfix VARCHAR (40);
        create_table    TEXT;
        spec_alter_table TEXT;
        month INTEGER;
        lower TIMESTAMP WITHOUT TIME ZONE;
        upper  TIMESTAMP WITHOUT TIME ZONE;
BEGIN
        table_postfix := quote_ident(partition_postfix(time_begin, service_id, monitoring));
        table_name := 'request_object_ref_' || table_postfix; 

        LOCK TABLE request_property_value IN SHARE UPDATE EXCLUSIVE MODE;

        lower := to_char(date_trunc('month', time_begin), 'YYYY-MM-DD');
        upper := to_char(date_trunc('month', time_begin + interval '1 month'), 'YYYY-MM-DD');

        IF monitoring = true THEN
                create_table  =  'CREATE TABLE ' || table_name || ' (CHECK (request_time_begin >= TIMESTAMP ''' || lower || ''' AND request_time_begin < TIMESTAMP ''' || upper || '''  AND request_monitoring = ''' || bool_to_str(monitoring) || ''') ) INHERITS (request_object_ref) ';
        ELSE 
                create_table  =  'CREATE TABLE ' || table_name || ' (CHECK (request_time_begin >= TIMESTAMP ''' || lower || ''' AND request_time_begin < TIMESTAMP ''' || upper || '''  AND request_service_id = ' || service_id || ' AND request_monitoring = ''' || bool_to_str(monitoring) || ''') ) INHERITS (request_object_ref) ';
        END IF;         

        spec_alter_table = 'ALTER TABLE ' || table_name || ' ADD PRIMARY KEY (id); ALTER TABLE ' || table_name || ' ADD CONSTRAINT ' || table_name || '_entry_id_fkey FOREIGN KEY (request_id) REFERENCES request_' || table_postfix || '(id); ALTER TABLE ' || table_name || ' ADD CONSTRAINT ' || table_name || '_object_type_id_fkey FOREIGN KEY (object_type_id) REFERENCES request_object_type(id); ';

        EXECUTE create_table;
        EXECUTE spec_alter_table;
        PERFORM create_indexes_request_object_ref(table_name);
EXCEPTION
    WHEN duplicate_table THEN
        NULL;

END;
$create_tbl_request_object_ref$ LANGUAGE plpgsql; 

CREATE OR REPLACE FUNCTION create_indexes_request_object_ref(table_name VARCHAR(50)) RETURNS VOID as $create_indexes_request_object_ref$ 
DECLARE
        create_indexes TEXT;
BEGIN
        create_indexes := 
       'CREATE INDEX ' || table_name || '_id_idx ON ' || table_name || '(request_id);' ||
       'CREATE INDEX ' || table_name || '_time_begin_idx ON ' || table_name || '(request_time_begin); ' ||
       'CREATE INDEX ' || table_name || '_service_id_idx ON ' || table_name || '(request_service_id);' ||
       'CREATE INDEX ' || table_name || '_object_type_id_idx ON ' || table_name || '(object_type_id);' ||
       'CREATE INDEX ' || table_name || '_object_id_idx ON ' || table_name || '(object_id);';
        EXECUTE create_indexes;
END;
$create_indexes_request_object_ref$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION create_tbl_session(time_begin TIMESTAMP WITHOUT TIME ZONE) RETURNS VOID AS $create_tbl_session$
DECLARE 
        table_name VARCHAR(60);
        create_table    TEXT;
        spec_alter_table TEXT;
        month INTEGER;
        lower TIMESTAMP WITHOUT TIME ZONE;
        upper  TIMESTAMP WITHOUT TIME ZONE;

BEGIN
        table_name := quote_ident('session_' || partition_postfix(time_begin, -1, false));

        LOCK TABLE session IN SHARE UPDATE EXCLUSIVE MODE;

        lower := to_char(date_trunc('month', time_begin), 'YYYY-MM-DD');
        upper := to_char(date_trunc('month', time_begin + interval '1 month'), 'YYYY-MM-DD');

        create_table =  'CREATE TABLE ' || table_name || '    (CHECK (login_date >= TIMESTAMP ''' || lower || ''' AND login_date < TIMESTAMP ''' || upper || ''') ) INHERITS (session) ';

        spec_alter_table = 'ALTER TABLE ' || table_name || ' ADD PRIMARY KEY (id); ';


        EXECUTE create_table;
        EXECUTE spec_alter_table;

        PERFORM create_indexes_session(table_name);

EXCEPTION
    WHEN duplicate_table THEN
        NULL;
END;
$create_tbl_session$ LANGUAGE plpgsql;

/** parameter table_name must already be processed by quote_ident
*/
CREATE OR REPLACE FUNCTION create_indexes_session(table_name VARCHAR(50)) RETURNS VOID AS $create_indexes_session$
DECLARE 
        create_indexes TEXT;
BEGIN
        create_indexes = 'CREATE INDEX ' || table_name || '_name_idx ON ' || table_name || '(user_name); CREATE INDEX ' || table_name || '_user_id_idx ON ' || table_name || '(user_id); CREATE INDEX ' || table_name || '_login_date_idx ON ' || table_name || '(login_date);'; 
        EXECUTE create_indexes;

END;
$create_indexes_session$ LANGUAGE plpgsql;

CREATE OR REPLACE RULE request_insert_function AS ON INSERT TO request DO INSTEAD SELECT tr_request ( NEW.id, NEW.time_begin, NEW.time_end, NEW.source_ip, NEW.service_id, NEW.request_type_id, NEW.session_id, NEW.user_name, NEW.user_id, NEW.is_monitoring); 

CREATE OR REPLACE RULE request_data_insert_function AS ON INSERT TO request_data DO INSTEAD SELECT tr_request_data ( NEW.request_time_begin, NEW.request_service_id, NEW.request_monitoring, NEW.request_id, NEW.content, NEW.is_response); 

CREATE OR REPLACE RULE request_property_value_insert_function AS ON INSERT TO request_property_value DO INSTEAD SELECT tr_request_property_value ( NEW.request_time_begin, NEW.request_service_id, NEW.request_monitoring, NEW.id, NEW.request_id, NEW.property_name_id, NEW.value, NEW.output, NEW.parent_id);

CREATE OR REPLACE RULE session_insert_function AS ON INSERT TO session
DO INSTEAD SELECT tr_session ( NEW.id, NEW.user_name, NEW.user_id, NEW.login_date, NEW.logout_date); 

CREATE OR REPLACE RULE request_object_ref_insert_function AS ON INSERT TO request_object_ref 
DO INSTEAD SELECT tr_request_object_ref (NEW.id, NEW.request_time_begin, NEW.request_service_id, NEW.request_monitoring, NEW.request_id, NEW.object_type_id, NEW.object_id);

--- this was originally contained in the file create_parts.sql

-- CREATE partitions for a specific month
CREATE OR REPLACE FUNCTION create_parts_for_month(part_time TIMESTAMP WITHOUT TIME ZONE) RETURNS VOID AS 
$create_parts_for_month$ DECLARE
        serv INTEGER;
        cur REFCURSOR;
BEGIN

        -- a chance for minor optimization: create_tbl_* needs partitions_postfix 
        --- which can be selected from table service. 
        OPEN cur FOR SELECT id FROM service;
        LOOP
            FETCH cur INTO serv;
            EXIT WHEN NOT FOUND;

            PERFORM create_tbl_request(part_time, serv, false);
            PERFORM create_tbl_request_data(part_time, serv, false);
            PERFORM create_tbl_request_property_value(part_time, serv, false);
            PERFORM create_tbl_request_object_ref(part_time, serv, false);
            
        END LOOP;

        close cur;

        -- monitoring (service type doesn't matter here - specifying 1)
        PERFORM create_tbl_request(part_time, 1, true);
        PERFORM create_tbl_request_data(part_time, 1, true);
        PERFORM create_tbl_request_property_value(part_time, 1, true);
        PERFORM create_tbl_request_object_ref(part_time, 1, true);

        -- now service type -1 for session tables
        PERFORM create_tbl_session(part_time);
            
END;
$create_parts_for_month$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION create_parts(start_date TIMESTAMP WITHOUT TIME ZONE, term_date TIMESTAMP WITHOUT TIME ZONE) RETURNS VOID AS $create_parts$
DECLARE
        term_month_beg TIMESTAMP WITHOUT TIME ZONE;
        cur_month_beg  TIMESTAMP WITHOUT TIME ZONE;

BEGIN
        cur_month_beg := date_trunc('month', start_date);

        term_month_beg := date_trunc('month', term_date);

        LOOP 
            PERFORM create_parts_for_month(cur_month_beg);

            EXIT WHEN cur_month_beg = term_month_beg;
            cur_month_beg := cur_month_beg + interval '1 month';
        END LOOP;

END;
$create_parts$ LANGUAGE plpgsql;
                

