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;