Преобразование столбца bytea в OID с сохранением значений

Я пытаюсь изменить столбец bytea, чтобы он имел тип oid и при этом сохранить значения.

Я пробовал использовать такие запросы, как:

ALTER TABLE mytable ADD COLUMN mycol_tmp oid;
UPDATE mytable SET mycol_tmp = CAST(mycol as oid);
ALTER TABLE mytable DROP COLUMN mycol;
ALTER TABLE mytable RENAME mycol_tmp TO mycol;

Но это просто дает мне ошибку:

ERROR: cannot cast type bytea to oid

Есть ли способ добиться того, чего я хочу?


person Petter    schedule 13.04.2012    source источник
comment
Связано: stackoverflow.com/questions/29433041/   -  person Erwin Brandstetter    schedule 03.04.2015


Ответы (5)


Столбец типа Oid — это просто ссылка на двоичное содержимое, которое фактически хранится в системной таблице pg_largeobject. С точки зрения хранения, Oid представляет собой 4-байтовое целое число. С другой стороны, столбец типа bytea является фактическим содержимым.

Чтобы передать bytea в большой объект, новый большой объект должен быть создан с файловым API больших объектов: lo_create() для получения нового OID, затем lo_open() в режиме записи, затем записывает с помощью lo_write() или lowrite(), а затем lo_close().

Это не может быть разумно сделано только с помощью гипса.

По сути, вам нужно написать примерно 10 строк кода на выбранном вами языке (по крайней мере, на том, который поддерживает API больших объектов, включая plpgsql), чтобы выполнить это преобразование.

person Daniel Vérité    schedule 13.04.2012
comment
Спасибо за Ваш ответ! Я понимаю, что OID очень отличается от bytea, но я подумал, что есть некоторый запрос, который можно использовать для помещения содержимого bytea в ссылку на oid. Однако не будет большой проблемой использовать для этого другой язык. Спасибо еще раз! - person Petter; 13.04.2012
comment
Я ошибался насчет отсутствия функции записи на стороне сервера для записи данных в большой объект, поэтому я соответствующим образом отредактировал ответ. Оказывается, он называется lowrite (не lo_write) и не упоминается в документах, но его, безусловно, можно использовать для этапа копирования. - person Daniel Vérité; 17.04.2012

Postgres 9.4 добавляет встроенная функция для этого:

lo_from_bytea(loid oid, string bytea)

Из примечаний к выпуску:

  • Добавление функций SQL, позволяющих [чтение/запись больших объектов][12] с произвольным смещением (Павел Штехуле)

Для старых версий это более эффективно, чем то, что было опубликовано ранее:

CREATE OR REPLACE FUNCTION blob_write(bytea)
  RETURNS oid AS
$func$
DECLARE
   loid oid := lo_create(0);
   lfd   int := lo_open(loid, 131072);  -- = 2^17 = x2000
   -- symbolic constant defined in the header file libpq/libpq-fs.h
   -- #define   INV_WRITE   0x00020000
BEGIN
   PERFORM lowrite(lfd, $1);
   PERFORM lo_close(lfd);
   RETURN loid;
END
$func$  LANGUAGE plpgsql VOLATILE STRICT;

Модификатор STRICT умнее, чем обработка NULL вручную.

Скрипт SQL.

Подробнее в этом связанном ответе:

person Erwin Brandstetter    schedule 03.04.2015

Я думаю, что лучший ответ можно найти по адресу Блог Грейс Батумбья, полностью:

Алгоритм довольно прост, получить двоичные данные, если они равны нулю, вернуть нуль. В противном случае создайте большой объект и в функции lowrite передайте ему двоичное значение вместо пути к файлу.

Код процедуры приведен ниже. Обратите внимание, что для этого должен быть установлен пакет lo_manage.

create or replace function blob_write(lbytea bytea)
   returns oid
   volatile
   language plpgsql as
$f$
   declare
      loid oid;
      lfd integer;
      lsize integer;
begin
   if(lbytea is null) then
      return null;
   end if;

   loid := lo_create(0);
   lfd := lo_open(loid,131072);
   lsize := lowrite(lfd,lbytea);
   perform lo_close(lfd);
   return loid;
end;
$f$;
CREATE CAST (bytea AS oid) WITH FUNCTION blob_write(bytea) AS ASSIGNMENT;

Итак, теперь работает следующий код: CREATE TABLE bytea_to_lo (lo largeObj);

INSERT INTO bytea_to_lo VALUES ( DECODE('00AB','hex'));

Я пробовал это и работает как шарм.

person Paulo Cristovão Filho    schedule 03.05.2013

Я уверен, что уже поздно, но для тех, у кого будет такая же проблема в будущем.

Я также столкнулся с аналогичной проблемой, когда у меня были старые данные в столбцах текста непосредственно в столбцах, а не в виде OID. И когда я пытался использовать эти данные с обновленным приложением, я тоже получал

Я использовал знания этой темы, чтобы решить эту проблему. Я твердо уверен, что тот, кто наткнется на этот вопрос, наверняка захочет взглянуть на это здесь

person Tyagi Akhilesh    schedule 07.04.2015

Чтобы решить эту проблему, я успешно использовал процедуру blob_write из блога Грейс Батумбья: http://gbatumbya.wordpress.com/2011/06/.

person Gunta    schedule 28.08.2012
comment
Пожалуйста, уточните, по крайней мере, процитировав наиболее важные фрагменты. Бывает гниение ссылок. - person ЯegDwight; 28.08.2012