Migrar Base de Datos SIGA-VB-Postgres a SIGA-PHP-Postgres (Versión 2)
De CidesaWiki
Aquí, explicaremos detalladamente como convertir una BD-Postgres-Siga-VB, en BD-Postgres-SGA-SL.
1.) Exportamos la BD-Postgres-Siga-VB en formato plano (PLAIN - Insert Commands), preferiblemente lo colocamos al archivo una extensiòn .sql.
2.) Luego, el archivo seguramente estará en LATIN8 o cualquier otro formato diferente a UTF-8. Hay que convertirlo a UTF-8 de la siguiente manera:
iconv --from-code=ISO-8859-1 --to-code=UTF-8 /ruta_archivo/archivocreado.sql > /ruta/archivo_nuevoutf.sql
Fijense, que hay que colocar la ruta y nombre de los archivos, tanto el viejo como el nuevo.
3.) Luego, hay que ejecutar el nuevo archivo "archivo_nuevo"utf.sql creado. El PGAdmin, por falta de memoria no podrá ejecutarlo, así que hay que hacerlo por por consola. Esta BD debe ser una version mayor o igual a 8.2 de Postgres:
#su postgres #psql nombre_BD > /ruta/archivo_nuevoutf.sql
4.) Ya debe haberse creado el Esquema y todos sus datos. Ahora hay que crear las secuencias y el campo ID que necesita SYMFONY. Existe una función llamada crea_id(esquema). La misma debe ser proporcionada por CIDESA. Ejecutamos la siguiente instrucción en el PGAdmin:
set search_path to "esquema"; select crea_id('esquema');
Esta instrucción debería durar solo unos minutos, dependiendo de la cantidad de datos existentes.
5.) Ya creados los ID, se debe quitar los blancos a la derecha y/o izquierda (TRIM) de los campos tipo STRING de la BD. Se debe utilizar la función trimear(esquema). La misma debe ser proporcionada por CIDESA. Esta instrucción puede durar HORAS, dependiendo del tamaño de la BD. Inclusive pudiera dar errores de campos únicos duplicados. En cada caso, el usuario debe resolver los problemas manualmente para que la función pueda correr sin problemas. Ejecutamos la siguiente instrucción en el PGAdmin:
set search_path to "esquema"; select trimear('esquema');
Esta instrucción debe ser ejecutada por un usuarios de Postgres con rol SUPERUSUARIO.
Ejemplo de SQL para conseguir datos duplicados en las tabla de que error:
Select * from TABLAERROR where trim(CAMPORERROR) in (Select trim(CAMPOERROR) from TABLAERROR group by trim(CAMPOERROR) having count(trim(CAMPOERROR))>1) order by trim(CAMPOERROR);
Donde CAMPOERROR y TABLAERROR deben cambiarlo por el nombre de la tabla y campo del error de Constraint.
6.) Por último, hay que correr el CHECK DATABASE y el comando INSERT de SYMFONY conocidos por todos, para actualizar la BD con respecto al modelo del SIGA.
Aquí, dejamos las funciones crea_id y trimear.
CREATE OR REPLACE FUNCTION crea_id(esquema character varying) RETURNS boolean AS $BODY$ DECLARE REGISTRO RECORD; TABLAS CURSOR IS SELECT TABLE_NAME FROM "information_schema".TABLES WHERE table_schema=ESQUEMA AND TABLE_TYPE='BASE TABLE' ORDER BY TABLE_NAME; begin OPEN TABLAS; FETCH TABLAS INTO REGISTRO; IF FOUND THEN LOOP IF EXISTS (SELECT * FROM "information_schema".COLUMNS WHERE table_schema=ESQUEMA and TABLE_NAME=REGISTRO.TABLE_NAME and COLUMN_NAME='id') THEN EXECUTE 'ALTER TABLE '||REGISTRO.TABLE_NAME||' DROP COLUMN ID CASCADE'; END IF; IF EXISTS (SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN ( SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND relname = REGISTRO.TABLE_NAME||'_seq' AND nspname = ESQUEMA)) THEN EXECUTE 'DROP SEQUENCE "'||ESQUEMA||'".'||REGISTRO.TABLE_NAME||'_seq CASCADE'; END IF; IF EXISTS (SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN ( SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND relname = REGISTRO.TABLE_NAME||'_id_seq' AND nspname = ESQUEMA)) THEN EXECUTE 'DROP SEQUENCE "'||ESQUEMA||'".'||REGISTRO.TABLE_NAME||'_id_seq CASCADE'; END IF; EXECUTE 'CREATE SEQUENCE "'||ESQUEMA||'".'||REGISTRO.TABLE_NAME||'_seq'; EXECUTE 'ALTER TABLE '||REGISTRO.TABLE_NAME||' ADD COLUMN "id" INTEGER NOT NULL DEFAULT nextval(''"'||ESQUEMA||'".'||REGISTRO.TABLE_NAME||'_seq''::regclass)'; FETCH TABLAS INTO REGISTRO; IF NOT FOUND THEN EXIT; END IF; END LOOP; END IF; CLOSE TABLAS; return(true); end; $BODY$ LANGUAGE plpgsql VOLATILE COST 100;
y la función Trimear
CREATE OR REPLACE FUNCTION trimear(esquema character varying) RETURNS boolean AS $BODY$ DECLARE REGISTRO RECORD; --CAMPOS DE TABLAS QUE NO TIENEN FOREING KEY NI SON REFERENCIADAS POR ALGUN FOREING KEY CAMPOS CURSOR IS SELECT a.* FROM "information_schema".tables c,"information_schema".COLUMNS a left outer join (select distinct(b.relname) as tabla from pg_constraint a,pg_class b,"information_schema".tables c where a.contype ='f' and a.conrelid=b.oid and c.table_schema=ESQUEMA and c.table_type='BASE TABLE' and b.relname=c.table_name union all select distinct(b.relname) as tabla from pg_constraint a,pg_class b,"information_schema".tables c where a.contype ='f' and a.confrelid=b.oid and c.table_schema=ESQUEMA and c.table_type='BASE TABLE' and b.relname=c.table_name) b on a.TABLE_NAME=b.tabla WHERE c.table_schema=ESQUEMA and c.table_type='BASE TABLE' and a.table_schema=ESQUEMA and a.DATA_TYPE='character varying' and a.column_name <> 'fundec' and b.tabla is null and a.table_name=c.table_name ORDER BY a.TABLE_NAME,a.COLUMN_NAME; --CAMPOS DE TABLAS QUE TIENEN FOREING KEY Y/O SON REFERENCIADAS POR OTROS FOREING KEY CAMPOS2 CURSOR IS SELECT DISTINCT a.* FROM "information_schema".COLUMNS a left outer join (select distinct(b.relname) as tabla from pg_constraint a,pg_class b,"information_schema".tables c where a.contype ='f' and a.conrelid=b.oid and c.table_schema=ESQUEMA and c.table_type='BASE TABLE' and b.relname=c.table_name union all select distinct(b.relname) as tabla from pg_constraint a,pg_class b,"information_schema".tables c where a.contype ='f' and a.confrelid=b.oid and c.table_schema=ESQUEMA and c.table_type='BASE TABLE' and b.relname=c.table_name) b on a.TABLE_NAME=b.tabla WHERE a.table_schema=ESQUEMA and a.DATA_TYPE='character varying' and b.tabla is not null and a.column_name <> 'fundec' ORDER BY a.TABLE_NAME,a.COLUMN_NAME; MITABLA CHARACTER VARYING; MISET CHARACTER VARYING; begin OPEN CAMPOS; MITABLA:=''; MISET:=''; FETCH CAMPOS INTO REGISTRO; IF FOUND THEN LOOP IF MITABLA<>REGISTRO.TABLE_NAME THEN IF MITABLA<>'' THEN BEGIN RAISE NOTICE 'Actualizando tabla : (%)',MITABLA; EXECUTE 'UPDATE '||MITABLA||MISET; END ; END IF; MITABLA:=REGISTRO.TABLE_NAME; MISET:=' SET '||REGISTRO.COLUMN_NAME||'=TRIM('||REGISTRO.COLUMN_NAME||')'; ELSE MISET:=MISET||','||REGISTRO.COLUMN_NAME||'=TRIM('||REGISTRO.COLUMN_NAME||')'; END IF; FETCH CAMPOS INTO REGISTRO; IF NOT FOUND THEN EXIT; END IF; END LOOP; END IF; CLOSE CAMPOS; BEGIN MITABLA:=''; MISET:=''; OPEN CAMPOS2; FETCH CAMPOS2 INTO REGISTRO; IF FOUND THEN update pg_trigger set tgdeferrable=true; SET CONSTRAINTS ALL DEFERRED; LOOP IF MITABLA<>REGISTRO.TABLE_NAME THEN IF MITABLA<>'' THEN BEGIN RAISE NOTICE 'Actualizando tabla : (%)',MITABLA; EXECUTE 'UPDATE '||MITABLA||MISET; END ; END IF; MITABLA:=REGISTRO.TABLE_NAME; MISET:=' SET '||REGISTRO.COLUMN_NAME||'=TRIM('||REGISTRO.COLUMN_NAME||')'; ELSE MISET:=MISET||','||REGISTRO.COLUMN_NAME||'=TRIM('||REGISTRO.COLUMN_NAME||')'; END IF; FETCH CAMPOS2 INTO REGISTRO; IF NOT FOUND THEN EXIT; END IF; END LOOP; END IF; CLOSE CAMPOS2; update pg_trigger set tgdeferrable=false; END; return(true); end;$BODY$ LANGUAGE plpgsql VOLATILE COST 100;