непонятки в FAQ про BLOB

ЧАстые Вопросы и Ответы

Модераторы: kdv, CyberMax

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

непонятки в FAQ про BLOB

Сообщение July » 13 сен 2006, 00:16

Здравствуйте!

Поясните, пожалуйста, кто может, следующую фразу из FAQ (http://ibase.ru/ibfaq.htm#blob):
"Также, вопреки документации, давно (по крайней мере в версии IB 4.0 и выше) можно спокойно передавать и принимать blob как параметры процедуры. Существует, однако, обязательное условие - поскольку blob это дисковая структура, записываемый blob должен быть сохранен в столбце таблицы (insert/update), а считываемый blob должен быть выбран из таблицы (хотя можно из из функции чтения blob, например LoadBlobFromFile из UDFDEMO)."

Во-первых, уточните, плиз, допустимо ли все таки использовать тип блоб не только для входных-выходных параметров процедуры, но и в локальных переменных?
Если да, то при присвоении этой переменной результата запроса значения блоб-поля из таблицы, что туда записывается, id блоба?

Если потом значение этой переменной передать в запрос insert - в новую запись запишется id такой же, как у записи источника или все таки создается копия блоба, сохраняется и в новую запись запишется уже новый id?

И, наконец, собственно выделенный текст - опишите, пожалуйста немного подробнее, что здесь имеется в виду?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 13 сен 2006, 09:54

допустимо ли все таки использовать тип блоб не только для входных-выходных параметров процедуры, но и в локальных переменных?
допустимо. кто запрещает?
Если да, то при присвоении этой переменной результата запроса значения блоб-поля из таблицы, что туда записывается, id блоба?
ну да.
Если потом значение этой переменной передать в запрос insert - в новую запись запишется id такой же, как у записи источника или все таки создается копия блоба, сохраняется и в новую запись запишется уже новый id?
конечно копия. А попробовать нельзя? К чему эти петиции - сначала попробуй, а если не работает - спрашивай здесь.
И, наконец, собственно выделенный текст - опишите, пожалуйста немного подробнее, что здесь имеется в виду?
здесь это в FAQ? К примеру, нельзя передать блоб в процедуру, изменить его, и выдать обратно, не записывая на диск. Вот что имелось в виду.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 13 сен 2006, 10:19

Более того: его нельзя передать в процедуру и потом записать дважды. Первая же попытка записи делает его инвалидным (если, конечно, он новый).

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

Сообщение July » 13 сен 2006, 12:45

конечно копия. А попробовать нельзя? К чему эти петиции - сначала попробуй, а если не работает - спрашивай здесь.
Да потому и спрашиваю, что пробовали.
В IB5 при удалении записи, из которой делалась копия блоба в другую запись (через локальную переменную в хранимой процедуре) - возникали ошибки и при обращении к блоб-полю в других записях, в которые он якобы должен был быть скопирован. Отсюда сделали вывод, что копировалась только ссылка на тоже самое значение блоб-поля и изменения в нем отражались на всех ссылающися на него записях.
Это было достаточно давно, так что подробный сценарий восстановить не смогу.
Сейчас в IB7 пробуем смоделировать ту же ситуацию - вроде бы нет проблемы, т.е. создается копия блоба и при изменении или удалении исходной записи в новых не наблюдается никаких изменений.
Подумали, что в IB7 изменилась обработка.
Но! Попробовали то же повторить снова в IB5 - не возникает той проблемы!
Значит неправильными были наши выводы и проблема была в другом.
Т.е. опять вернулись к отправной точке, в которой до конца не понимаем, что происходит "за кулисами" на сервере при попытке обращения к блоб-полям через параметры, а тем паче параметры в ХП, а не пришедшие с запросом от приложения-клиента. А если все-таки вспомнить что в документации пока явно указано, что нельзя блобы в параметрах ХП использовать, выходит что работаем на свой страх и риск, основываясь только на догадках.

Вот одна из тестовых процедур:

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

CREATE PROCEDURE COPY_TO_SELF_TABLE1(
    ID INTEGER)
AS
DECLARE VARIABLE SOURSBLOB BLOB;
BEGIN
  /*Считали Blob*/
  SELECT BLOB1 FROM TABLE_1
  WHERE ID = :ID
  INTO :SOURSBLOB;

  INSERT INTO TABLE_1 (ID)
  values(38);

  /*заполнили  Blob*/
  UPDATE TABLE_1 SET BLOB1 = :SOURSBLOB
  WHERE ID = 38;

/*другой вариант создания
  INSERT INTO TABLE_1 (ID, blob1)
  values(38, :SOURSBLOB);
*/

END
Хочется понять, что происходит с блоб_ид на каждом шаге и чем отличаются по обработке варианты c insert и с update, чтобы не писать косяков в процедурах.
Вычитала в одной статье про неочевидный, как в ней сказано, нюанс, что
"сервер при фиксации изменений записи ПРЕОБРАЗУЕТ полученный BLOB_ID"
Там хоть речь не о ХП шла, но все таки..
Можно ли рассуждать так - только что записанный в новую запись блоб в той же транзакции пытаться прочитать нельзя, потому что ид его до фиксации транзакции еще некорректный, отсюда растут корни у ошибок типа "blob not found"? А вообще, если не трогать в той же транзакции этот "новорожденный" блоб, манипуляции типа процедуры COPY_TO_SELF_TABLE1 считать вполне корректными?
здесь это в FAQ? К примеру, нельзя передать блоб в процедуру, изменить его, и выдать обратно, не записывая на диск. Вот что имелось в виду.
Дурацкий вопрос, конечно, но под записыванием на диск в контексте ХП подразумевается вставка значения переменной типа блоб в таблицу посредством SQL-операторов?

Т.е. пытаться менять само значение блоб-поля в теле процедуры нельзя,
если надо - следует писать UDF. Можно передавать из приложения в процедуру и обратно, между процедурами, между UDF и процедурами - с помощью параметров типа блоб. Объявлять локальные переменные такого типа и передавать их в запросы можно также как и лок. переменные другого типа.
Так?

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

Сообщение July » 13 сен 2006, 12:47

Dimitry Sibiryakov писал(а):Более того: его нельзя передать в процедуру и потом записать дважды. Первая же попытка записи делает его инвалидным (если, конечно, он новый).
Т.е. если я передам в ХП блоб входным параметром (неважно откуда - из приложения ли я вызвала эту процедуру и присвоила что-то этому параметру, из другой ли процедуры, в которой в этот параметр записала значение локальной переменной, которая в свою очередь была заполнена результатом какого-то запроса) и в этой самой ХП insert-ом вставлю этот блоб куда-нибудь, то тут же в этой же процедуре нельзя написать дальше второй insert и пытаться вставить тот же блоб в другую, например таблицу? Так?

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 13 сен 2006, 13:08

Ключевые слова - IB4 и IB5. Были там такие баги с указателями блобов. И в IB6 были. За IB3 вот не помню...

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

Сообщение July » 13 сен 2006, 13:24

Merlin писал(а):Ключевые слова - IB4 и IB5. Были там такие баги с указателями блобов. И в IB6 были. За IB3 вот не помню...
Ну мне сейчас не до хронологии багов :)
Нужно понять как оно сейчас в IB7 работает. См. мой трактат выше :)
Господа знатоки, прокомментируйте, пожалуйста.

Нашла ссылку на статью, где прочитала о "неочевидных фактах" про непостоянство blob_id:
http://www.devrace.com/ru/fibplus/articles/2261.php
И попутный вопрос - где еще можно прочитать что-то внятное об этих нюансах?
Так же или лучше БОЛЕЕ ПОДРОБНО?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 13 сен 2006, 14:51

но под записыванием на диск в контексте ХП подразумевается вставка значения переменной типа блоб в таблицу посредством SQL-операторов?
натюрлих.

Девушка, вы излишне нервничаете. передавать блобы в процедуры и обратно - можно, и было можно всегда. В документации косяк.
В вашем коде я вообще не вижу проблем. ну прочитали блоб, записали. Да, блоб копируется. Потому что между записями блоб не "расшаривается". Собственно, все.

если же напишете такой код, который приведет к ошибке, то вы эту ошибку увидите сразу. "тайных ошибок", которые работают но делают не то, в сервере нет. То есть, "потом" ошибки с блобами не вылезают. они проявляются сразу.
И попутный вопрос - где еще можно прочитать что-то внятное об этих нюансах?
Так же или лучше БОЛЕЕ ПОДРОБНО?
есть предложение - не читать и не забивать себе этим голову.

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

Сообщение July » 13 сен 2006, 15:33

kdv писал(а): если же напишете такой код, который приведет к ошибке, то вы эту ошибку увидите сразу. "тайных ошибок", которые работают но делают не то, в сервере нет. То есть, "потом" ошибки с блобами не вылезают. они проявляются сразу.
Значит, есть косяк в работе оператора insert с блобами, потому что если приведенную выше процедуру запускать update - т.е. записывать блоб-значение не сразу в insert, а дописывать после - все действительно работает, как Вы и пишите. И копируется, и при изменениях все остается на месте.
Что не может не радовать :)
Но если сразу через insert пытаться всю запись вместе блобом заполнить (а блоб - содраный в переменную из другой записи), в некоторых случаях в дальнейшей работе вываливается blob not found, когда исходную запись изменишь.
И попутный вопрос - где еще можно прочитать что-то внятное об этих нюансах?
Так же или лучше БОЛЕЕ ПОДРОБНО?
есть предложение - не читать и не забивать себе этим голову.
Да с я бы с удовольствием :)
Поставлена задача довести анализ проблемы до практических выводов.

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 13 сен 2006, 15:38

kdv писал(а):Девушка, вы излишне нервничаете. передавать блобы в процедуры и обратно - можно, и было можно всегда. В документации косяк
Не совсем так. Т.е. простые действия с блобами в процедурах действительно можно было делать если не всегда, то достаточно давно. Но и багов там тоже хватало. Отсюда фраза в доке
kdv писал(а):В вашем коде я вообще не вижу проблем. ну прочитали блоб, записали. Да, блоб копируется. Потому что между записями блоб не "расшаривается". Собственно, все
Это так должно быть. Но именно баг с копированием blob_id, а не содержимого блоба, правился в FB давным-давно

July - выполните свою процедуру и посмотрите на полученные blob_id - если они все разные, то всё в порядке. Иначе - баги

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

Сообщение July » 13 сен 2006, 15:46

hvlad писал(а): July - выполните свою процедуру и посмотрите на полученные blob_id - если они все разные, то всё в порядке. Иначе - баги
А как вот так просто взять и посмотреть на blob_id? :roll:

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 13 сен 2006, 15:57

July писал(а):
hvlad писал(а): July - выполните свою процедуру и посмотрите на полученные blob_id - если они все разные, то всё в порядке. Иначе - баги
А как вот так просто взять и посмотреть на blob_id? :roll:
Давайте подумаем :
UPDATE ? вроде не то...
DELETE ? хорошо - место освобождается, но тоже не совсем то, что нужно...
может CREATE ? опять чепуха получается...

Аааа, наверное таки SELECT ?!

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

Сообщение July » 13 сен 2006, 16:44

hvlad писал(а):
July писал(а):
hvlad писал(а): July - выполните свою процедуру и посмотрите на полученные blob_id - если они все разные, то всё в порядке. Иначе - баги
А как вот так просто взять и посмотреть на blob_id? :roll:
Давайте подумаем :
UPDATE ? вроде не то...
DELETE ? хорошо - место освобождается, но тоже не совсем то, что нужно...
может CREATE ? опять чепуха получается...
Аааа, наверное таки SELECT ?!
? что-то я не понимаю юмора..
если Вы имеете в виду, что нужно судить о том, разные blob_id или не разные по косвенным признакам, то так мы до сих пор и делали и предполагаем, что есть какой-то баг в выполнении оператора insert (см. мой ответ kdv выше)

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

Сообщение July » 13 сен 2006, 17:00

Поняла.
Но я незнаю, откуда надо написать select, чтобы в результирующем списке отобразилось именно значение blob_id - пишется или "memo" или, если в
IBExpert - само значение блоба вытаскивается.
Разве что х.процедурой в цикле прочитывать в переменные эти ид и сравнивать их..

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 13 сен 2006, 17:32

isql показывает blob_id

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

Сообщение July » 13 сен 2006, 17:38

hvlad писал(а):isql показывает blob_id
Да ничего подобного. Пишет "memo" в столбце для поля блоб-типа.
А по нажатию на кнопочку с многоточием в конктертной записи показывает значение самого блоб-а в отдельном окошке. В моем случае - текст.

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 13 сен 2006, 17:52

July писал(а):
hvlad писал(а):isql показывает blob_id
Да ничего подобного. Пишет "memo" в столбце для поля блоб-типа.
А по нажатию на кнопочку с многоточием в конктертной записи показывает значение самого блоб-а в отдельном окошке. В моем случае - текст.
isql и "кнопочка с многоточием" - вещи не совместимые :lol:
Советую читать то, что пишут, а не то, что кажется :wink:

isql != IBE
isql != IBConsole

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 13 сен 2006, 18:59

Но если сразу через insert пытаться всю запись вместе блобом заполнить (а блоб - содраный в переменную из другой записи), в некоторых случаях в дальнейшей работе вываливается blob not found, когда исходную запись изменишь.
Вы выражайтесь точнее.

select.. blob
ok
insert blob
ok
update blob
error?

Если да, то есть такая последовательность приводит к ошибке update, то да, может быть такое. И это либо баг, либо имеющаяся особенность сервера, и вы совершенно зря пытаетесь тут "углядеть" непонятно что путем "просмотра blob_id".

Какая Вам разница, какой у конкретного блоба идентификатор, если ошибка происходит в процедуре, где вы никакой blob_id перехватить и посмотреть не можете? (если только не занимаетесь отладкой кода сервера)

Вот честное слово, мне бы и в голову не пришло заниматься подобными "изысканиями". Если есть проблема - вы сделайте пример для воспроизведения, и поместите сюда с вопросом - почему это не работает. И все.

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

Сообщение July » 14 сен 2006, 00:43

hvlad писал(а):isql и "кнопочка с многоточием" - вещи не совместимые :lol:
Если Вы говорите о программе Interbase Interactive SQL, то у меня в Interbase 7.5 она отображает результат запроса в виде таблицы в нижней части окна. Именно там я узрела "memo" и кнопочки с многоточиями в блоб-полях.

July
Сообщения: 16
Зарегистрирован: 12 сен 2006, 23:48

Сообщение July » 14 сен 2006, 01:08

kdv писал(а): Если да, то есть такая последовательность приводит к ошибке update,
Нет, нет. Ошибок при работе самой процедуры не возникает.
Они возникают потом:
в том случае, если
1) блоб записан в таблицу одним insert, т.е. прямо сразу заполнены и обычные поля и блоб (как в закомментированном тексте приведенной выше процедуры, если же запись сначала добавлена с пустым блоб-полем, а потом оно дописано update-ом - никаких проблем не возникает)
2)если наплодить т.о. несколько копий одной записи, а потом модифицировать блоб в любой из них, модификация проходит, но при попытке чтения затем любой из этих записей валится blob not found.
Но не всегда. Удалось даже уловить некоторую закономерность - точно возникает, если каждую новую создаваемую копию брать не самой первой записи-источника, а с последней добавленной.
Т.е. - была с id=1 какая-то запись, содержащая какой-то блоб
(кстати, hvlad, id в моих примерах - это просто имя поля, первичного ключа, а никакой не blob_id, может отсюда путаница?)
С нее сделали копию и записали в новую запись с id=2.
Потом со второй - в новую с id=3, потом с 3 - в четвертую. И т.д. несколько раз.
Взяли и модифицировали запись, например, с id=3.
Пытаемся читать 2-ю, 4-ю, 5-ю - валится ошибка.
kdv писал(а): Какая Вам разница, какой у конкретного блоба идентификатор, если ошибка происходит в процедуре, где вы никакой blob_id перехватить и посмотреть не можете? (если только не занимаетесь отладкой кода сервера)
Мне совершенно никакой, но hvlad утверждает, что blob_id можно увидеть с помощью select-а, вот и стало любопытно, где это - может пригодилось бы потом.

Ответить