A partir da versão 12 (já tem um tempinho…) o Postgres deixa de suportar o uso da coluna oculta “OID” ou “Object Identifier” que até então era opcional em tabelas normais, e também se torna uma coluna explícita nas tabelas do catálogo do sistema. Até a versão 11, você poderia criar uma tabela com a opção “WITH OIDS” que criava uma coluna oculta, chamada ‘oid’, que funcionava como uma chave primária (PK) artificial. Desde a versão 8.0 do Postgres (que foi lançada em janeiro de 2005!), o parâmetro “default_with_oids” está desligado por padrão, o que significa que se você não disser nada, por padrão, ao criar uma tabela, a coluna oculta oid não será criada. Então 14 anos depois, o pessoal resolveu aposentar esta opção e finalmente eliminar definitivamente esta coluna de tabelas criadas pelo usuário.

E não é que vira e mexe ainda tem gente que usa? Bom, então como lidar com elas? Existem algumas situações diferentes.

ALTER TABLE minha_tabela SET WITHOUT OIDS;
SELECT coalesce(max(oid)::integer,0) + 1 FROM minha_tabela;
ALTER TABLE minha_tabela ADD COLUMN id integer GENERATED BY DEFAULT AS IDENTITY (START WITH 12345);
UPDATE minha_tabela SET id = OID;
ALTER TABLE minha_tabela ADD PRIMARY KEY (id);
ALTER TABLE minha_tabela SET WITHOUT OIDS;

Algumas obervações:

Automatizando tarefas

Bom, tá na hora de fazer esse negócio andar de forma um pouco mais rápida. Pequei esses dias um cliente com centenas de tabelas que ainda utilizam OID. Então fiz este roteiro aqui para facilitar.

Verificando tabelas com OID

SELECT relnamespace::regnamespace AS table_schema, relname AS table_name
FROM pg_class c
WHERE 
	relkind IN ('r', 'm', 'p') AND
	relhasoids = TRUE AND
	relnamespace NOT IN ('pg_catalog'::regnamespace::oid,'information_schema'::regnamespace::oid)
ORDER BY relnamespace::regnamespace, relname;

Criando a coluna ID em tabelas sem chave primária (PK)

BEGIN;
DO $$DECLARE 
    r	    record;
    v_start integer;
BEGIN
    FOR r IN SELECT relnamespace::regnamespace AS table_schema, relname AS table_name
        FROM pg_class c
	WHERE 
	    relkind IN ('r', 'm', 'p') AND
	    relhasoids = TRUE AND
	    NOT EXISTS (SELECT 1 FROM pg_constraint WHERE contype = 'p' AND conrelid = c.oid) AND
	    NOT EXISTS (SELECT 1 FROM pg_attribute a WHERE c.oid = a.attrelid AND attname = 'id') AND
	    relnamespace NOT IN ('pg_catalog'::regnamespace::oid,'information_schema'::regnamespace::oid)
	ORDER BY relnamespace::regnamespace, relname
    LOOP
        EXECUTE format('SELECT coalesce(max(oid)::integer,0) + 1 FROM %I.%I',r.table_schema, r.table_name)
	    INTO v_start;
	RAISE WARNING 'Creating identity column for table %.% starting with %', 
            r.table_schema, r.table_name, v_start;
	EXECUTE format('ALTER TABLE %I.%I ADD COLUMN id integer GENERATED BY DEFAULT AS IDENTITY 
            (START WITH ' || v_start || ')',r.table_schema, r.table_name);
	RAISE WARNING 'UPDATE id';
	EXECUTE format('UPDATE %I.%I SET id = oid',r.table_schema, r.table_name);
	RAISE WARNING 'CREATE PK';
	EXECUTE format('ALTER TABLE %I.%I ADD PRIMARY KEY(id)',r.table_schema, r.table_name);
	RAISE WARNING 'REMOVE oid';
	EXECUTE format('ALTER TABLE %I.%I SET WITHOUT OIDS',r.table_schema, r.table_name);
    END LOOP;
END$$;
COMMIT;

Removendo a coluna OID em tabelas com chave primária (PK)

BEGIN;
SELECT 'ALTER TABLE ' || relnamespace::regnamespace || '.' || relname || ' SET WITHOUT OIDS; --' command
FROM pg_class c
WHERE 
    relkind IN ('r', 'm', 'p') AND
    relhasoids = TRUE AND
    EXISTS (SELECT 1 FROM pg_constraint WHERE contype = 'p' AND conrelid = c.oid) AND
    relnamespace NOT IN ('pg_catalog'::regnamespace::oid,'information_schema'::regnamespace::oid)
ORDER BY relnamespace::regnamespace, relname
\gexec 

E por enquanto é isso… Espero que você não se depare com esse tipo de situação no quotidiano, mas se aparecer, isso deve quebrar um galho!

Deixe uma resposta

plugins premium WordPress
%d blogueiros gostam disto: