Ошибка при использовании PgDump

Обсуждение возникших проблем, предложений и ошибок PgDAC компонентов
Закрыто
aBourg
Сообщения: 11
Зарегистрирован: Сб 24 авг 2013 03:23

Ошибка при использовании PgDump

Сообщение aBourg » Пн 30 дек 2013 15:24

Добрый день!
поставил новую версию 4.2.5 под D2006
теперь ошибка при выполнении

Код: Выделить всё

PgDump1.Connection := DM.PgConnection1;
PgDump1.OnBackupProgress := PgDumpBackupProgress;
PgDump1.TableNames := 'table1;table2;table3;';
PgDump1.Options.CompleteInsert := True;
PgDump1.SQL.Clear;
PgDump1.BackupToFile('c:\bak');
текст ошибки: 'column "enumsortorder" does not exist'
возникает в модуле PgDump.pas в строке 563

свойства PgDump - по-умолчанию
версия postgreSQL - 8.4.17

Alexp
Devart Team
Сообщения: 349
Зарегистрирован: Пн 27 дек 2010 10:34

Re: Ошибка при использовании PgDump

Сообщение Alexp » Вт 31 дек 2013 08:51

Добрый день,

Спасибо за информацию, мы воспроизвели и исправили проблему, это исправление войдет в следующую версию. В данный момент для решения проблемы Вы можете отключить backup типов

Код: Выделить всё

PgDump1.ObjectTypes := PgDump1.ObjectTypes - [doTypes];

aBourg
Сообщения: 11
Зарегистрирован: Сб 24 авг 2013 03:23

Re: Ошибка при использовании PgDump

Сообщение aBourg » Вс 08 июн 2014 08:33

Добрый день
версия postgreSQL - 8.4.17
При использовании PgDump (v4.2.6) в D2006 сделал для себя изменения в модуле PgDump.pas:
1) procedure TPgDumpProcessor.BackupTables

Код: Выделить всё

Add(Format('DROP TABLE IF EXISTS %s CASCADE;', [TableName])); // <-- Добавил
Add(Format('CREATE TABLE %s (', [TableName]));
2) procedure TPgDumpProcessor.BackupSequences

Код: Выделить всё

Add(Format('DROP SEQUENCE IF EXISTS %s;', [SeqName])); // <-- Добавил
Sql := 'CREATE SEQUENCE ' + SeqName;
3) procedure TPgDumpProcessor.BackupConstraints

Код: Выделить всё

// 8.4.17 ругается, если такой нет, а "IF EXISTS" написать нельзя...
Add(Format('ALTER TABLE %s DROP CONSTRAINT %s;', [TableName, ConName])); // <-- Добавил
4) procedure TPgDumpProcessor.BackupIndexes;

Код: Выделить всё

var
  indName: string;  // <-- Добавил
begin
  FQuery.SQL.Text :=
	'SELECT n.nspname, pg_get_indexdef(c.oid), c.relname ' +  // <-- Добавил
...
indName := VarToStr(FQuery.Fields[2].Value);     // <-- Добавил
indName := QuoteName(indName);                   // <-- Добавил
...
Add(Format('DROP INDEX IF EXISTS %s;', [indName]));      // <-- Добавил
триггеров, views и тп нет в базе пока что...
Зачем сделано?

Пользователь время от времени делает бакап базы, причем не всей а рабочих таблиц без статичных классификаторов..
в программе это примерно так:

Код: Выделить всё

PgDump1.Connection := DM.PgConnection1;
PgDump1.OnBackupProgress := PgDumpBackupProgress;
PgDump1.TableNames := 'table1;table2;table3;';
PgDump1.Options.CompleteInsert := True;
PgDump1.SQL.Clear;
PgDump1.BackupToFile('c:\bak');
затем, работая с базой, решает восстановить из сохраненной ранее копии. т.е. откатиться на несколько дней назад..
в программе это вот так примерно:

Код: Выделить всё

PgDump1.RestoreFromFile('c:\bak');
плюс обработчик ошибок при восстановлении

Код: Выделить всё

procedure TfrmPG.PgDump1Error(Sender: TObject; E: Exception; SQL: string; var Action: TErrorAction);
begin
Action := eaContinue;
end;
Без моих изменений по предварительному удалению Tables, Sequences, Indexes, и Constraints
после восстановления добавление новых записей не работает как надо. последовательности возвращают повторяющиеся значения, Constraints ругаются на повторы.. в общем, каша

Что не так?

Alexp
Devart Team
Сообщения: 349
Зарегистрирован: Пн 27 дек 2010 10:34

Re: Ошибка при использовании PgDump

Сообщение Alexp » Чт 12 июн 2014 10:44

Спасибо за примеры. Мы планируем полный рефакторинг PgDump, и при реализации постараемся учесть Ваши замечания.

aBourg
Сообщения: 11
Зарегистрирован: Сб 24 авг 2013 03:23

Re: Ошибка при использовании PgDump

Сообщение aBourg » Вс 07 сен 2014 09:04

Добрый день!
Имеем
PgDAC 4.3.9, PostgreSql 8.4.17, Delphi XE2, приложение Win32

Еще проблема с PgDump

есть поле в таблице с типом bytea - содержимое файла хранится...
Файлы большие - это и jpg, и tiff, и pdf и тп.
В поле примерно это выглядит вот так (PgAdmin III показывает):
"\377\330\377\340\000\020JFIF\000\001\001\001\001,\001,\000\000\377\333\000C\000\010\006\006\007\006\005\010\007\007\007\011\011\010\012\014\024\015\014\013\013\014\031\022\023\017\024\035\032\037\036\035\032\034\034 ..... и т.д. ....."

При создании резервной копии

Код: Выделить всё

PgDump1.Connection := DM.PgConnection1;
PgDump1.OnBackupProgress := PgDumpBackupProgress;
PgDump1.TableNames := 'тут таблица с полем [b]bytea[/b]';
PgDump1.Options.CompleteInsert := True;
PgDump1.SQL.Clear;
PgDump1.BackupToFile('c:\bak');
имеем ошибку "Out of Memory" - программа реально съедает всю имеющуюся память
в коде библиотеки
PgServices.pas (строка 638)

Код: Выделить всё

TPgTextConverter.ValueToText(Query.Fields[i].Value, dtString, dtString, False, [b]True[/b], False ..
вызывает в дальнейшем из PgClasses.pas ( строка 3628)

Код: Выделить всё

class function TPgTextConverter.ValueToText 
и попадаем для поля типа bytea всегда сюда - строка 3786

Код: Выделить всё

Result := EscapeString(Result, Quote, DataType = dtBlob, LoaderQuote, EscapeSign);
ну а дальше понятно, что StringBuilder съедает всю память своими Append

Что я сделал?
Для этого поля вызываю
TPgTextConverter.ValueToText(Query.Fields.Value, dtString, dtString, False, False, False.....
и в итоге вываливаюсь из функции EscapeString в строке 3152 модуля PgClasses.pas

Что не так и как можно исправить данную ошибку, не прибегая к махинациями с вызовом ValueToText в зависимости от имени поля...


Но в результате восстановления из такой резервной копии опять же имеем Out of Memory
в TParser.CopyText ( CRParser.pas строка 1333 )
:?: :?: :?:

AndreyZ
Devart Team
Сообщения: 328
Зарегистрирован: Чт 08 сен 2011 13:18

Re: Ошибка при использовании PgDump

Сообщение AndreyZ » Вт 09 сен 2014 10:37

Спасибо за информацию. Мы будем исследовать это поведение и сообщим вам о полученных результатах.

aBourg
Сообщения: 11
Зарегистрирован: Сб 24 авг 2013 03:23

Re: Ошибка при использовании PgDump

Сообщение aBourg » Вт 16 сен 2014 16:38

AndreyZ писал(а):Спасибо за информацию. Мы будем исследовать это поведение и сообщим вам о полученных результатах.
Добрый день!

В версии PgDAC 4.4 от 15.09 проблемы, описанные выше, не решены еще?

aBourg
Сообщения: 11
Зарегистрирован: Сб 24 авг 2013 03:23

Re: Ошибка при использовании PgDump

Сообщение aBourg » Чт 02 окт 2014 17:38

Добрый день!

Сегодня установил версию PgDAC Version 4.4.11 (01-Oct-2014)
в history.html написано:
Backup of huge BLOB-fields with TPgDump is fixed
Нет. к сожалению, не решены.
пришлось опять в файле PgServices.pas (строка 631) писать

Код: Выделить всё

  xBool := (Query.Fields[i].FieldName <> 'binarycontext'); // поле с типом bytea
  Sql := Sql + TPgTextConverter.ValueToText(Query.Fields[i].Value, dtString, dtString, False, xBool, False, .....
Бакап создался, но не востанавливается по причине опять же Out of memory
Записей в таблице - 97 всего
Файл с полученным sql-файлом этой таблицы могу отправить любым удобным Вам способом.
размер rar-архива 65 метров ( в развернутом 556M)

ZEuS
Devart Team
Сообщения: 11
Зарегистрирован: Пт 06 апр 2012 06:10

Re: Ошибка при использовании PgDump

Сообщение ZEuS » Пн 06 окт 2014 08:14

Мы исследовали проблему.
1. Изменение в модуле PgServices.pas, которое Вы привели, не является решением проблемы с созданием бэкапа. Более того, оно делает файл бэкапа неприменимым для восстановления. Если установить параметр Quote метода TPgTextConverter.ValueToText в значение False для BYTEA-полей, то в файле бэкапа содержимое таких полей не заключается в кавычки, т.е. было:

Код: Выделить всё

INSERT INTO test(id, bytea_field) VALUES ('1', '\\001\\014\\000\\004\\010...');
После изменений стало:

Код: Выделить всё

INSERT INTO test(id, bytea_field) VALUES ('1', \\001\\014\\000\\004\\010...);
Очевидно, что полученное INSERT-выражение не является валидным.

2. Проблема с "Out of memory" при бэкапе\восстановлении BYTEA-полей связана с форматом их представления в INSERT-выражении:
- если используется PostgreSQL версии ниже 9.0, то для представления содержимого BYTEA-поля используется bytea escape-формат ( http://www.postgresql.org/docs/9.0/stat ... inary.html )
- очевидно, что в таком случае длина результирующей строки в INSERT-выражении может получиться в 5 раз больше размера данных BYTEA-поля. Оперирование строками очень больших размеров и вызывает "Out of memory", что связано с ограничениями ресурсов операционной системы.

До сих пор мы не получали жалоб от пользователей по поводу данной проблемы. Если Вам необходимо выполнять бэкап\восстановление BYTEA-полей очень больших размеров, Вы можете проголосовать за эту функциональность на нашей UserVoice странице: http://devart.uservoice.com/forums/1046 ... postgresql . Предложения с большим количеством голосов будут реализованы быстрее.

aBourg
Сообщения: 11
Зарегистрирован: Сб 24 авг 2013 03:23

Re: Ошибка при использовании PgDump

Сообщение aBourg » Чт 13 ноя 2014 20:43

Alexp писал(а):... Мы планируем полный рефакторинг PgDump,....
Добрый день!
Если ли новости о рефакторинге?

У себя, кстати, пришлось добавить "CASCADE":

Код: Выделить всё

Add(Format('DROP SEQUENCE IF EXISTS %s CASCADE;', [SeqName]));
т.к. поле может быть описано не как serial, а, к примеру, так:

Код: Выделить всё

... DEFAULT nextval('mytable_id_seq'::regclass);

AndreyZ
Devart Team
Сообщения: 328
Зарегистрирован: Чт 08 сен 2011 13:18

Re: Ошибка при использовании PgDump

Сообщение AndreyZ » Пт 14 ноя 2014 13:42

Рефакторинг PgDump находится в планах, но, к сожалению, сейчас у нас есть задачи с более высоким приоритетом. Спасибо за интерес к нашим продуктам, мы обязательно постараемся учесть Ваши замечания.

Закрыто