| 1 | create or replace function build_history_table() returns void as |
|---|
| 2 | $$ |
|---|
| 3 | --this function creates a table that will hold some interesting values for managing history tables |
|---|
| 4 | --later functions will be added |
|---|
| 5 | BEGIN |
|---|
| 6 | |
|---|
| 7 | IF exists(select 1 FROM information_schema.tables WHERE table_name = 'historic_information') = true THEN |
|---|
| 8 | raise notice 'The table historic_information already exists. Could not create it.'; |
|---|
| 9 | ELSE |
|---|
| 10 | execute 'create table historic_information(table_id serial not null,table_name varchar(100) not null,primary_field varchar(100) not null, geometry_field varchar(100) not null, constraint history_tables_pk primary key(table_id,table_name));'; |
|---|
| 11 | END IF; |
|---|
| 12 | |
|---|
| 13 | END |
|---|
| 14 | $$ |
|---|
| 15 | language 'plpgsql'; |
|---|
| 16 | |
|---|
| 17 | --end build_history_table |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | --im open to suggestions for the names of the functions. |
|---|
| 21 | --just realized that one is build_history_table and the other create_... |
|---|
| 22 | CREATE OR REPLACE FUNCTION create_history_table(p_schema text,p_table text,p_geometry_field text) returns boolean as |
|---|
| 23 | $$ |
|---|
| 24 | DECLARE |
|---|
| 25 | |
|---|
| 26 | v_current_table text; |
|---|
| 27 | v_history_table text; |
|---|
| 28 | |
|---|
| 29 | v_geometry_type text; --checks for the type of p_geometry_field |
|---|
| 30 | v_dimensions integer; --checks for the ndims in p_geometry_field |
|---|
| 31 | v_srid integer; --checks for the srid in p_geometry_field |
|---|
| 32 | v_gid text; --checks the name of the pk column in p_table |
|---|
| 33 | |
|---|
| 34 | --SQL statement that will create the historic table |
|---|
| 35 | v_table_sql text; |
|---|
| 36 | |
|---|
| 37 | --SQL statement that will perform an update on geometry_columns |
|---|
| 38 | v_update_geometry_sql text; |
|---|
| 39 | |
|---|
| 40 | --SQL statement that will perform an update on historic_tables |
|---|
| 41 | v_update_history_sql text; |
|---|
| 42 | |
|---|
| 43 | BEGIN |
|---|
| 44 | |
|---|
| 45 | --determines the name of current table |
|---|
| 46 | v_current_table:= p_schema || '.' || p_table; |
|---|
| 47 | --determines the name of historic table |
|---|
| 48 | v_history_table:= p_schema || '.' || p_table || '_history'; |
|---|
| 49 | |
|---|
| 50 | --sql to determine the values of geometry type, srid and ndims |
|---|
| 51 | v_geometry_type:= (SELECT "type" FROM public.geometry_columns WHERE f_table_schema = p_schema AND f_table_name = p_table AND f_geometry_column = p_geometry_field); |
|---|
| 52 | v_dimensions:= (SELECT coord_dimension FROM public.geometry_columns WHERE f_table_schema = p_schema AND f_table_name = p_table AND f_geometry_column = p_geometry_field); |
|---|
| 53 | v_srid:= (SELECT srid FROM public.geometry_columns WHERE f_table_schema = p_schema AND f_table_name = p_table AND f_geometry_column = p_geometry_field); |
|---|
| 54 | v_gid:= (SELECT column_name FROM information_schema.key_column_usage WHERE table_schema = p_schema AND table_name = p_table); |
|---|
| 55 | --end sql |
|---|
| 56 | |
|---|
| 57 | --generate sql for creating the historic table |
|---|
| 58 | v_table_sql:= 'CREATE TABLE ' || v_history_table || |
|---|
| 59 | '(' || |
|---|
| 60 | 'history_id serial not null,' || |
|---|
| 61 | 'date_added timestamp not null default now(),' || |
|---|
| 62 | 'date_deleted timestamp default null,' || |
|---|
| 63 | 'operation varchar(30) not null,' || |
|---|
| 64 | 'active_user varchar(90) not null default CURRENT_USER,' || |
|---|
| 65 | 'current_version text not null,' || |
|---|
| 66 | 'like ' || v_current_table || ',' || |
|---|
| 67 | 'CONSTRAINT ' || p_table || '_history_pk primary key(history_id));'; |
|---|
| 68 | --end sql |
|---|
| 69 | |
|---|
| 70 | --update geometry columns |
|---|
| 71 | v_update_geometry_sql:='INSERT INTO public.geometry_columns(f_table_catalog,f_table_schema,f_table_name,f_geometry_column,coord_dimension,srid,type) values (' || |
|---|
| 72 | quote_literal('') || ',' || |
|---|
| 73 | quote_literal(p_schema) || ',' || |
|---|
| 74 | quote_literal(p_table || '_history') || ',' || |
|---|
| 75 | quote_literal(p_geometry_field) || ',' || |
|---|
| 76 | v_dimensions::text || ',' || |
|---|
| 77 | v_srid::text || ',' || |
|---|
| 78 | quote_literal(v_geometry_type) || ');'; |
|---|
| 79 | --end update geometry_columns |
|---|
| 80 | |
|---|
| 81 | --insert into historic_tables |
|---|
| 82 | v_update_history_sql:='INSERT INTO public.historic_information(table_id,table_name,primary_field,geometry_field) VALUES (' || |
|---|
| 83 | 'DEFAULT,' || |
|---|
| 84 | quote_literal(v_history_table) || ',' || |
|---|
| 85 | quote_literal(v_gid) || ',' || |
|---|
| 86 | quote_literal(p_geometry_field) || ');'; |
|---|
| 87 | --end update historic tables |
|---|
| 88 | |
|---|
| 89 | execute v_table_sql; |
|---|
| 90 | execute v_update_geometry_sql; |
|---|
| 91 | execute v_update_history_sql; |
|---|
| 92 | |
|---|
| 93 | execute add_insert_rule(p_schema,p_table,v_gid); |
|---|
| 94 | execute add_delete_rule(p_schema,p_table,v_gid); |
|---|
| 95 | execute add_update_rule(p_schema,p_table,v_gid); |
|---|
| 96 | execute create_history_indexes(p_schema,p_table,p_geometry_field); |
|---|
| 97 | |
|---|
| 98 | return true; |
|---|
| 99 | |
|---|
| 100 | END |
|---|
| 101 | $$ |
|---|
| 102 | language 'plpgsql'; |
|---|
| 103 | |
|---|
| 104 | --end create_history_table |
|---|
| 105 | |
|---|
| 106 | --add_insert_rule |
|---|
| 107 | CREATE OR REPLACE FUNCTION add_insert_rule(p_schema text,p_table text,p_gid_field text) returns void as |
|---|
| 108 | $$ |
|---|
| 109 | DECLARE |
|---|
| 110 | |
|---|
| 111 | v_sql text; |
|---|
| 112 | |
|---|
| 113 | BEGIN |
|---|
| 114 | |
|---|
| 115 | v_sql:= 'CREATE OR REPLACE RULE ' || p_table || '_history_insert as ON INSERT TO ' || p_schema || '.' || p_table || |
|---|
| 116 | ' DO (' || |
|---|
| 117 | 'INSERT INTO ' || p_schema || '.' || p_table || '_history VALUES(' || |
|---|
| 118 | 'DEFAULT,' || --history_id nextval() |
|---|
| 119 | 'DEFAULT,' || --date_added now() |
|---|
| 120 | 'NULL,' || --date_deleted |
|---|
| 121 | quote_literal('INSERT') || ',' || --operation |
|---|
| 122 | 'DEFAULT,' || |
|---|
| 123 | 'NEW.' || p_gid_field || ',' || |
|---|
| 124 | 'NEW.*));'; |
|---|
| 125 | |
|---|
| 126 | execute v_sql; |
|---|
| 127 | |
|---|
| 128 | END |
|---|
| 129 | $$ |
|---|
| 130 | language 'plpgsql'; |
|---|
| 131 | --end add_insert_rule |
|---|
| 132 | |
|---|
| 133 | --add_update_rule |
|---|
| 134 | CREATE OR REPLACE FUNCTION add_update_rule(p_schema text,p_table text,p_gid_field text) returns void as |
|---|
| 135 | $$ |
|---|
| 136 | DECLARE |
|---|
| 137 | |
|---|
| 138 | v_sql text; |
|---|
| 139 | |
|---|
| 140 | BEGIN |
|---|
| 141 | |
|---|
| 142 | v_sql:= 'CREATE OR REPLACE RULE ' || p_table || '_history_update as ON UPDATE TO ' || p_schema || '.' || p_table || |
|---|
| 143 | ' DO (' || |
|---|
| 144 | 'UPDATE ' || p_schema || '.' || p_table || '_history SET ' || |
|---|
| 145 | 'date_deleted = now(),' || |
|---|
| 146 | 'active_user = CURRENT_USER,' || |
|---|
| 147 | 'current_version = ' || 'NEW.' || p_gid_field || ',' || |
|---|
| 148 | 'operation = ' || quote_literal('UPDATE') || |
|---|
| 149 | 'WHERE ' || p_gid_field || ' = OLD.' || p_gid_field || ';' || -- end of the update statement |
|---|
| 150 | 'INSERT INTO ' || p_schema || '.' || p_table || '_history VALUES (' || |
|---|
| 151 | 'DEFAULT,' || --history_id nextval() |
|---|
| 152 | 'DEFAULT,' || --date_added now() |
|---|
| 153 | 'NULL,' || --date_deleted |
|---|
| 154 | quote_literal('INSERT') || ',' || --operation |
|---|
| 155 | 'DEFAULT,' || |
|---|
| 156 | 'NEW.' || p_gid_field || ',' || |
|---|
| 157 | 'NEW.*););'; |
|---|
| 158 | |
|---|
| 159 | execute v_sql; |
|---|
| 160 | |
|---|
| 161 | END |
|---|
| 162 | $$ |
|---|
| 163 | language 'plpgsql'; |
|---|
| 164 | --end add_update_rule |
|---|
| 165 | |
|---|
| 166 | --add_delete_rule |
|---|
| 167 | CREATE OR REPLACE FUNCTION add_delete_rule(p_schema text,p_table text,p_gid_field text) returns void as |
|---|
| 168 | $$ |
|---|
| 169 | DECLARE |
|---|
| 170 | |
|---|
| 171 | v_sql text; |
|---|
| 172 | |
|---|
| 173 | BEGIN |
|---|
| 174 | |
|---|
| 175 | v_sql:= 'CREATE OR REPLACE RULE ' || p_table || '_history_delete as ON DELETE TO ' || p_schema || '.' || p_table || |
|---|
| 176 | ' DO (' || |
|---|
| 177 | 'UPDATE ' || p_schema || '.' || p_table || '_history SET ' || |
|---|
| 178 | 'date_deleted = now(),' || |
|---|
| 179 | 'active_user = CURRENT_USER,' || |
|---|
| 180 | 'current_version = ' || quote_literal('-9999') || ',' || |
|---|
| 181 | 'operation = ' || quote_literal('DELETED') || |
|---|
| 182 | 'WHERE ' || p_gid_field || ' = OLD.' || p_gid_field || ');'; |
|---|
| 183 | |
|---|
| 184 | execute v_sql; |
|---|
| 185 | |
|---|
| 186 | END |
|---|
| 187 | $$ |
|---|
| 188 | language 'plpgsql'; |
|---|
| 189 | --end ad__delete_rule |
|---|
| 190 | |
|---|
| 191 | --create indexes function |
|---|
| 192 | CREATE OR REPLACE FUNCTION create_history_indexes(p_schema text, p_table text, p_geometry_field text) returns void as |
|---|
| 193 | $$ |
|---|
| 194 | DECLARE |
|---|
| 195 | |
|---|
| 196 | v_geomindex_sql text; |
|---|
| 197 | v_dateindex_sql text; |
|---|
| 198 | v_userindex_sql text; |
|---|
| 199 | v_operindex_sql text; |
|---|
| 200 | |
|---|
| 201 | BEGIN |
|---|
| 202 | v_geomindex_sql:= 'CREATE INDEX ' || 'idx_' || p_table || '_geometry_history' || |
|---|
| 203 | ' ON ' || p_schema || '.' || p_table || '_history USING GIST(' || p_geometry_field || ');'; |
|---|
| 204 | |
|---|
| 205 | v_dateindex_sql:= 'CREATE INDEX ' || 'idx_' || p_table || '_date_history' || |
|---|
| 206 | ' ON ' || p_schema || '.' || p_table || '_history (date_added,date_deleted);'; |
|---|
| 207 | |
|---|
| 208 | v_userindex_sql:= 'CREATE INDEX ' || 'idx_' || p_table || '_user_history' || |
|---|
| 209 | ' ON ' || p_schema || '.' || p_table || '_history(active_user);'; |
|---|
| 210 | |
|---|
| 211 | v_operindex_sql:= 'CREATE INDEX ' || 'idx_' || p_table || '_oper_history' || |
|---|
| 212 | ' ON ' || p_schema || '.' || p_table || '_history (operation);'; |
|---|
| 213 | |
|---|
| 214 | execute v_geomindex_sql; |
|---|
| 215 | execute v_dateindex_sql; |
|---|
| 216 | execute v_userindex_sql; |
|---|
| 217 | execute v_operindex_sql; |
|---|
| 218 | |
|---|
| 219 | END |
|---|
| 220 | $$ |
|---|
| 221 | language 'plpgsql' |
|---|
| 222 | --end create indexes |
|---|
| 223 | |
|---|
| 224 | /*TODO LIST: |
|---|
| 225 | |
|---|
| 226 | CREATE A FUNCTION THAT WILL DROP A CERTAIN HISTORIC TABLE AND REMOVE ITS ITENS FROM GEOMERTY_COLUMNS AND HISTORIC_INFORMATION |
|---|
| 227 | CREATE A FUNCTION TO POPULATE ALL THE EXISTING RECORDS TO THE HISTORIC TABLE, AS A INSERT |
|---|
| 228 | */ |
|---|