Что такое код ibase_blob_cancel


Содержание

Что такое код ibase_blob_cancel

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_blob_cancel — Cancel creating blob

Description bool ibase_blob_cancel ( resource blob_handle )

This function will discard a BLOB created by ibase_create_blob() if it has not yet been closed by ibase_blob_close() . Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.

Пред. Начало След.
ibase_blob_add Уровень выше ibase_blob_close

Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:

Операции над BLOB данными

Interbase поддерживает следующие операции над BLOB данными:

Вставка новой строки включающей BLOB данные

Замена данных ссылающихся на BLOB столбец.

Обновление данных ссылающихся на BLOB столбец.

API Функции динамического SQL (DSQL) и структура данных XSQLD A необходимы, чтобы выполнить SELECT, INSERT, и инструкции UPDATE, требующиеся, чтобы выбирать, вставлять, или модифицировать уместные данные Blob.

6.1.Чтение данных из BLOB.

Эти шесть шагов требуются для чтения данных из существующего BLOB:

1. Создается обычная инструкция SELECT для выбора строки содержащей BLOB столбец.

2. Подготавливается структура для вывода данных XSQLDA.

3. Подготавливается SELECT инструкция.

4. Выполняется инструкция.

5. Выбираем строки одну задругой

6. Читаем и обрабатываем BLOB данные для каждой строки.

Опишем все это подробнее, для непонимающих.

6.2.Создание SELECT инструкции

«SELECT PROJ_NAME, PROJ_DESC, PRODUCT FROM PROJECT WHERE \

PRODUCT IN («software», «hardware»,»other») ORDER BY PROJ_NAME»;

Подготовка структуры вывода XSQLDA

1. Объявляем переменную содержащую XSQLDA

2. Выделяем память

out_sqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(3));

3.Ставим версию и число выходных параметров

Подготовка SELECT инструкции для выполнения

После создания XSQLDA для содержания данных столбцов каждой выбранной строки,

Строку инструкции нужно подготовить к выполнению.

1. Объявляем и инициализируем дескриптор SQL инструкции,

с помощью известной нам функции isc_dsql_allocate_statement():

isc_stmt_handle stmt; /*Объявление дескриптора инструкции */

stmt = NULL; /* Установка дескриптора в NULL перед выполнением */

3. Подготавливаем строку для выполнения с помощью isc_dsql_prepare(),которая проверяет строку(str) на синтаксические ошибки, переводит строку в формат для эффективного выполнения, и устанавливает в дескриптор инструкции (stmt) ссылку на этот созданный формат (blr что ли). Дескриптор инструкции используется позднее в функции isc_dsql_execute().

Если isc_dsql_prepare()передан указатель на XSQLDA вывода, как в следующем примере, она будет заполнять большинство полей в XSQLDA и всех подструктур XSQLVAR информацией о типа данных, длине, и имени столбца в инструкции.

Пример вызова isc_dsql_prepare():

&trans, /* Устанавливается предварительным вызовом isc_start_transaction()*/

&stmt, /*Дескриптор инструкции устанавливается в вызове этой функции. */

0, /* Определяет что инструкция- строка заканчивается 0*/

str, /* Инструкция — строка */

SQLDA_VERSION1,/* Номер версии XSQLDA */

out_sqlda /* XSQLDA для хранения данных столбцов после выполнения инструкции */

3. Устанавливаем XSQLVAR структуру для каждого столбца:

— Определяем тип столбца ( если он не был установлен isc_dsql_prepare())

— Связываем указатель структуры XSQLVAR sqldata с соответствующей локальной переменной.

Для столбцов чьи типы неизвестных этому моменту:

Приводим элементы типа данных(необязательно), к примеру, из SQL_VARYING к SQL_TEXT.

Динамически выделяем место для хранения данных на которые указывает sqldata

— Определяем число байт данных передаваемых в sqldata

— Предоставляем значение NULL индикатора для параметров

Выбранные данные для Blob (и массивов)столбцов отличаются от других типов столбцов, так что поля XSQLVAR должны быть установлены по-другому. Для не -BLOB (и не массивов) столбцов, isc_dsql_prepare () устанавливают для каждый sqltype к соответствующему типу поля, и выбранные данные помещаются в область памяти на которую указывают соответствующие sqldata, при каждой операции fetch. Для столбцов Blob, тип должен быть установлен в SQL _Blob (или SQL _Blob + 1, если нужен индикатор NULL). InterBase сохраняет внутренний идентификатор Blob (BlobID), а не данные Blob, в памяти на которую кажет sqldata, когда строки данных выбраны, так что sqldata должна указывать на память с размером нужным для хранения BlobID.

Следующий пример кода иллюстрирует назначения для Blob и столбцов не-Blob, чей тип известен ко времени компиляции.

#define PROJLEN 20

#define TYPELEN 12

char proj_name[PROJLEN + 1];

char prod_type[TYPELEN + 1];

short flag0, flag1, flag2;

out_sqlda->sqlvar[0].sqltype = SQL_TEXT + 1;

out_sqlda->sqlvar[1].sqltype = SQL_Blob + 1;

out_sqlda->sqlvar[2].sqltype = SQL_TEXT + 1;

Выполнение инструкции

После того как инструкция подготовлена можно ее выполнить.

&trans, /* Устанавливается предварительным вызовом isc_start_transaction()*/

&stmt, /* выделяется isc_dsql_allocate_statement() */

1, /* XSQLDA version number */

NULL/* NULL так как нет входных параметров */

Эта инструкция создает список выбора, это строки возвращаемые после выполнения инструкции.

6.2.Извлечение выбранных строк

Конструкция цикла извлечения используется, чтобы извлечь(в XSQLDA вывода) данные столбцов для отдельной строки из списка выбора и обработать каждую строку прежде, чем следующая строка будет выбрана. Каждое выполнение isc_dsql_fetch () выбирает данные столбцов соответствующие подструктуры XSQLVAR структуры out_sqlda. Для столбца Blob, выбирается BlobID не являющийся фактическими данными, а просто указатель на них.

isc_dsql_fetch(status_vector, &stmt,1, out_sqlda))

printf(«\nPROJECT: %–20s TYPE:%–15s\n\n»,

/* Read and process the Blob data (seenext section) */

if (fetch_stat != 100L)

/* isc_dsql_fetch returns 100 if no morerows remain to be

Чтение и обработка BLOB данных

Для чтения и обработки BLOB данных

Объявите и инициализируйте BLOB дескриптор

isc_blob_handle blob_handle; /* Объявление BLOB дескриптора. */

blob_handle= NULL; /* Уставите его в NULL перед использованием*/

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

3. Объявите беззнаковую short переменную в которую IB будет хранить фактическую длину каждого прочитанного сегмента:

unsigned short actual_seg_len;

4. Открываем BLOB c извлеченным ранее blob_id

&blob_handle,/*Устанавливается этой функцией для ссылки на BLOB */

&blob_id,/* Blob ID полученный из out_sqlda которую заполнил isc_dsql_fetch() */

0,/* BPB length = 0; фильтр не будем использовать */

NULL/* NULL BPB, фильтр не будем использовать */

5.Читаем все BLOB данные вызывая повторно isc_get_segment(), берущую каждый Blob сегмент и его длину. Обрабатываем каждый прочитаны сегмент.

&blob_handle, /* Устанавливается isc_open_blob2()*/


&actual_seg_len,/* Длина прочитанного сегмента */

sizeof(blob_segment),/* Длина буфера сегмента */

blob_segment/* буфер сегмента */

while (blob_stat == 0 ||status_vector[1] == isc_segment)

/*isc_get_segment возвращает 0 если сегмент был полностью прочитан.

/*status_vector[1] устанавливается в isc_segment только часть */

/*сегмента была прочитана из-за буфера (blob_segment) не являющегося */

/*достаточно большим. В этом случае придется делать дополнительные вызовы */

/*isc_get_segment() для дочитывания. */

printf(«%*.*s»,actual_seg_len, actual_seg_len, blob_segment);

blob_stat =isc_get_segment(status_vector, &blob_handle,

6. Закрываем BLOB

6.2.Запись данных в BLOB

Перед тем как создать новый BLOB и записать туда данные вы должны сделать следующее.

Включить BLOB данные в строку вставляемую в таблицу

Заменить данные ссылающиеся на BLOB столбец строки

Обновить данные ссылающиеся на BLOB столбец строки

Вносимый в столбец Blob фактически не содержит данных Blob. Он содержит BlobID ссылающийся на данные, которые сохранены в другом месте. Так, чтобы установить или изменить столбец Blob, Вы должны установить (или сбросить) BlobID, сохраненный в нем. Если столбец Blob содержит BlobID, и Вы изменяете столбцы относящиеся к различным Blob (или содержащим NULL), Blob на который ссылается предварительно сохраненный BlobID будет удален в течение следующей сборки «мусора».(. )

Все эти операции требуют следующих шагов:

1. Подготовьте соответствующую инструкцию DSQL. Это будет инструкция INSERT, если Вы вставляете новую строку в таблицу, или инструкция UPDATE для изменения строки. Каждая из этих инструкций будет нуждаться в соответствующей структуре ввода XSQLDA для передачи параметров инструкции во время выполнения. BlobID нового Blob будет одним переданных значений

2. Создайте новый BLOB, и запишите в него данные.

3. Свяжите BLOB ID нового BLOB со столбцом таблицы строк над которой вы будете выполнять INSERT и UPDATE.

Примечание: вы не можете непосредственно обновлять BLOB данные. Если вы желаете модифицировать BLOB данные, вы должны:

Создать новый BLOB

Прочитать данные из старого BLOBA в буфер где вы сможете отредактировать и модифицировать их.

Записать измененные данные в новый BLOB.

Подготовить и выполнить инструкцию UPDATE которая модифицирует BLOB столбец содержащий BLOBID нового BLOB, заменяющий старый BLOB ID.

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

Подготовка UPDATE или INSERT инструкции.

1. Создаем саму строку для обновления

«UPDATE PROJECT SET PROJ_DESC = ? WHERE PROJ_ >

или для вставки

char *in_str = «INSERT INTO PROJECT(PROJ_NAME, PROJ_DESC, PRODUCT,

2. Объявляем переменную содержащую структуру входных параметров

3. in_sqlda = (XSQLDA*)malloc(XSQLDA_LENGTH(2));

4. in_sqlda->version = SQLDA_VERSION1;

5.Установить XSQLVAR структуру в XSQLDA для каждого передаваемого параметра.

Определяем типы данных элементов

Для параметров типы которых известны во время компиляции: указатель sqldata связываем с локальной переменной содержащей передаваемый данные.

Для параметров типы которых неизвестны во время выполнения: выделяем память для хранения данных на которые указывает sqldata

Определяем число байт данных(размер)

Следующий код иллюстрирует все это для столбца BLOB и одного столбца тип данных которого известен во время компиляции.

#define PROJLEN 5

char proj_id[PROJLEN + 1];

in_sqlda->sqlvar[0].sqltype =SQL_Blob + 1;

Proj_id должна быть инициализирована во время выполнения (если значение не известно во времени компиляции). Blob_id должна быть установлена, чтобы обращаться к недавно созданному Blob, как описано в следующих секциях

Создание нового BLOB и хранения данных

1. Объявление и инициализация BLOB дескриптора:

isc_blob_handle blob_handle; /* Объявления BLOB дескриптора */

blob_handle= NULL; /* Устанавливаем дескриптор в NULL перед использованием*/

2. Объявление и инициализация BLOB ID:

ISC_QUAD blob_id; /* Объявление Blob ID. */

3. Создание нового BLOB вызовомisc_create_blob2():

&blob_handle,/* устанавливается этой функцией ссылка на новый Blob */

&blob_id,/* Blob ID устанавливается этой функцией*/

0, /* Blob Parameter Buffer length = 0;no filter will be used*/

NULL /* NULL Blob Parameter Buffer, since no filter will be used*/

Эта функция создает новый BLOB открывает его для записи, и устанавливает blob_handle к указателю на новый BLOB

isc_create_blob2() также связывает BLOB с BLOBID, и устанавливает blob_id к указателю на BLOBID.

4. Записываем все данные, которые будут записаны в Blob, делая ряд вызовов isc_put_segment (). Следующий пример читает строки данных, и связывает каждый Blob с упомянутым blob_handle. (Get_line () читает следующую строку данных, которые будут написаны.)

unsigned short len;

&blob_handle,/* set by previousisc_create_blob2() */

len,/* длина буфера содержащего данные для записи */

line/* буфер содержащий данные для записи в BLOB*/

if (status_vector[0] == 1 &&status_vector[1])

5. Закрываем BLOB

Связывание нового BLOB с BLOB столбцом

Выполнение инструкции UPDATE связывает новый BLOB с BLOB столбцом в строке выбранной инструкции.

6.3.Удаление BLOB

существуют четыре способа удаления BLOB.

Удаляем строку содержащую BLOB. Вы можете использовать DSQL для выполнения DELETE инструкции.

Заменяем различные BLOB. Если Blob столбец содержит BlobID, и вы модифицируете столбец ссылающийся на разные BLOB, ранее сохраненный BLOB будет удален следующей сборкой “мусора”.

Сбрасываем в NULL столбец ссылающийся на BLOB, к примеру, используя DSQL инструкцию как следующую:

UPDATE PROJECT SET PROJ_DESC = NULLWHERE PROJ_

Blob на который указывал удаленный blob_id будет удален следующей сборкой «мусора»

— Отказываемся от BLOB, после того как он был создан но, не был связан еще с определенным столбцом в таблице, используя isc_cancel_blob() функцию.

Запрос информации об открытом BLOB

После того, как приложение открывает Blob, оно может получить информацию о Blob.

Isc_blob_info () позволяет приложению сделать запрос для информации о Blob типа общего количества

Илон Маск рекомендует:  Выравнивание кнопок-изображений в формах

числа сегментов в Blob, или о длине, в байтах, самого длинного сегмента. В дополнение к указателю на вектор состояния ошибки и дескриптор Blob, isc_blob_info () требует двух предоставляемых приложением буферов, буфера списков элементов, где приложение определяет информацию, которая требуется, и буфер результатов, куда InterBase возвращает требуемую информацию. Приложение заполняет буфер списков элементов с информационными запросами для isc_blob_info(), и передает ему указатель на буфер списков элементов, а также размер, в байтах, этого буфера.

Приложение должно также создать буфер результата, достаточно большой, чтобы хранить информацию, возвращенную InterBase. Оно передает указатель на буфер результата, и размер, в байтах, этого буфера в isc_blob_info(). Если InterBase пытается поместить, больше информации чем может вместить буфер результатов, она помещает значение, isc_info_truncated, определенное в ibase.h, в последний байт буфера результатов.

Буфер списка элементов запрашиваемой информации и буфер результатов.

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

Соответствующие константны определены в ibase.h

#define isc_info_blob_num_segments 4

#define isc_info_blob_max_segment 5

#define isc_info_blob_total_length 6

#define isc_info_blob_type 7

Буфер результатов содержит серию кластеров информации по каждому запрошенному элементу. Каждый кластер содержит три части.

Первый байт определяет тип возвращенной информации.

Второй байт – число определяющее число байт до конца кластера (длина инфо)

Значение хранимое в переменном числе байт, которое интерпретируется в зависимости от типа первого байта кластера

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


Элемент Возвращаемое значение

Запрашиваемый и возвращаемый элемент

Полное число сегментов

Длина самого длинного сегмента

Полный размер в байтах BLOB

Тип BLOB(0:сегментированный, 1:поток)

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

Результирующий буфер слишком маленький для хранения запрашиваемой информации

Запрашиваемая информация неопеределена. Проверьте status_vector и сообщения.

6.4.Пример вызова isc_blob_info( )

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

char res_buffer[20], *p, item;

SLONG max_size = 0L, num_segments = 0L;

&db_handle, /* database handle, setby isc_attach_database() */

&tr_handle, /* transaction handle, setby isc_start_transaction()

&blob_handle, /* set by thisfunction to refer to the Blob */

&blob_id, /* Blob ID of the Blob toopen */

0, /* BPB length = 0; no filter will beused */

NULL /* NULL BPB, since no filter willbe used */

if (status_vector[0] == 1 &&status_vector[1])

&blob_handle, /* Set inisc_open_blob2() call above. */

sizeof(blob_items),/* Length ofitem-list buffer. */

blob_items, /* Item-list buffer. */

sizeof(res_buffer),/* Length of resultbuffer. */

res_buffer /* Result buffer */

if (status_vector[0] == 1 &&status_vector[1])

/* An error occurred. */

/* Extract the values returned in theresult buffer. */

for (p = res_buffer; *p != isc_info_end;)

length = (short)isc_vax_integer(p, 2);

max_size = isc_vax_integer(p, length);

6.5.Blob дескрипторы

Blob дескриптор используется для предоставления динамического доступа к BLOB информации. К примеру, он может быть использован для хранения информации о BLOB данных для фильтрации, еще как кодовая страница для текстовых BLOB данных и информации о подтипе текстовых данных и не текстовых данных.

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

BLOB дескриптор это структура определенная в заголовочном файле ibase.h как следующая:

short blob_desc_subtype; /* type of Blobdata */

short blob_desc_charset; /* characterset */

short blob_desc_segment_size; /* segmentsize */

unsigned char blob_desc_field_name [32];/* Blob column name */

unsigned char blob_desc_relation_name[32]; /* table name */

Размер сегмента BLOB есть максимальное число байт в приложении

Размер сегмента Blob -максимальное число байтов, которые приложение, как ожидается, запишет или будет читать из Blob. Вы можете использовать этот размер, чтобы выделить ваши собственные буфера. Blob_desc_relation_name и blob_desc_field_name поля содержащие строки с нулевым символом в конце.

Заполнение blob дескриптора

Есть четыре варианта для заполнения blob дескриптора

Вызываем isc_blob_default_desc(). И заполняем ей поля дескриптора значениями по умолчанию. Подтип по умолчанию есть 1 (TEXT), сегмент размером 80 байт, кодовая страница по умолчанию есть страница установленная для вашего процесса.

Вызываем isc_blob_lookup_desc(). Она обращается к системным таблицам и берет оттуда информацию о BLOB и заполняет ею поля дескриптора.

Вызываем isc_blob_set_desc(). Она инициализирует дескриптор из параметров вызова, быстрее нежели получать доступ к метаданным.

Устанавливаем поля дескриптора напрямую.

Следующий пример вызывает isc_blob_lookup_desc () чтобы узнать текущий подтип и информацию о наборе символов для столбца Blob по имени PROJ_DESC в таблице PROJECT. Функция сохраняет информацию в исходном описателе from_desс.

&db_handle; /* Set by previousisc_attach_database() call. */

&tr_handle, /* Set by previousisc_start_transaction() call. */

«PROJECT», /* имя таблицы */

«PROJ_DESC»,/* название столбца */

&from_desc,/* Blob дескриптор заполняется этой функцией. */

&global/* глобальное название колонки возвращаемое этой функцией */

Фильтрация BLOB данных

Фильтр Blob это подпрограмма, которая транслирует данные Blob из одного подтипа в другой.

InterBase включает набор специальных внутренних фильтров Blob, которые преобразовывают подтип 0

( Неструктурные данные) в подтип1 (ТЕКСТ), и из подтипа 1 к подтипу 0.

В дополнение к использованию этих стандартных фильтров, Вы можете создавать ваши собственные внешние фильтры, чтобы обеспечивать специальное конвертирование данных. Например, Вы могли бы разрабатывать фильтр, чтобы преобразовывать один формат изображения к другому, например отображать то же самое изображение на мониторах с различными разрешающими способностями. Или Вы могли бы конвертировать двоичный Blob к простому тексту , чтобы легко файл переносить от одной системы к другой. Если Вы определяете фильтры, Вы можете назначать их идентификаторы подтипа от -32,768 до -1. Следующие разделы дают краткий обзор того, как писать фильтры Blob, и сопровождаются подробностями , как написать приложение, которое требует фильтрации.

Обратите внимание, что фильтры Blob доступны для баз данных, находящихся на всех платформах сервера InterBase кроме Системы Netware, где фильтры Blob не могут быть созданы.

6.6.Использование ваших собственных фильтров

В отличие от стандарта фильтров InterBase, которые конвертируют подтипом 0 в подтип 1 и наоборот, внешний фильтр Blob — вообще часть библиотеки подпрограмм, которые Вы создаете и связываете с приложением. Вы можете писать, Blob на C или Паскаль (или любой язык, который может называться из C).Чтобы использовать ваши собственные фильтры, следуйте по этим шагами:

1. Решите, какой фильтр Вы, должны написать.

2. Напишите фильтры в базовом языке.

3. Сформируйте общедоступную библиотеку фильтров.

4. Сделайте библиотеку фильтров доступной.

5. Определить фильтры для базы данных.

6. Напишите приложение, которое требует фильтрацию.

Шаги 2, 5 и 6 будут лучшеописаны в следующих разделах.

6.7.Объявление внешнего фильтра BLOB для БД

Для объявления внешнего фильтра для БД, используйте инструкции DECLARE FILTER. К примеру, следующая инструкция объявляет фильтр, SAMPLE:

DECLARE FILTER SAMPLE

INPUT TYPE –1 OUTPUT_TYPE –2

ENTRY POINT «FilterFunction»

В примере, входной подтип фильтра определен как -1 и его выходной подтип как -2. Если подтип -1определяет текст нижнего регистра, а подтип -2 текст верхнего регистра, то цель фильтра SAMPLE состояла бы в том, чтобы перевести данные Blob из текста нижнего регистра в текст верхнего регистра.

Параметры ENTRY_POINT И MODULE_NAME определяют внешнюю подпрограмму, которую вызывает, когда вызывается фильтр. Параметр MODULE_NAME определяет filter.dll, динамически загружаемую библиотеку, содержащую выполнимый код фильтра. Параметр ENTRY_POINT определяет точку входа в DLL. Хотя пример показывает только простое имя файла, это — хорошая практика для определения полного квалифицированного пути, начиная с пользователей вашего приложения желающих загрузить файл.

6.8.Создание внешних Blob фильтров

Если Вы хотите создавать ваши собственные фильтры, Вы должны иметь детальное понимание типов данных , которые Вы планируете конвертировать. InterBase не делает строгой проверки типа данных на данные Blob; это — ваша ответственность.

Определений функций фильтров

При написании фильтра, Вы должны включить точку входа, известной функции фильтра, в секции объявления программы. InterBase вызывает функцию фильтра, когда приложение выполняет операции на Blob, определенные для использования фильтра. Вся связь между InterBase и фильтром происходит через функцию фильтра. Функция самого фильтра может вызывать другие функции, которые включает исполняемая программу фильтра.

Вы объявляете имя функции фильтра и имя выполняемой программы — фильтра с параметрами ENTRY_POINT И MODULE_NAME в инструкции DECLAREFILTER.

Функция фильтрадолжна иметь следующее объявление, вызывающее последовательность:

filter_function_name(short action, isc_blob_ctl control);

Параметр, action, является одним из восьми возможных макроопределений действия, и параметр, control- элемент isc_blob_ctl, управляющей структуры Blob, определенной в файле заголовка InterBase, ibase.h. Эти параметры обсуждаются позже в этой главе.

Следующий листинг скелетного фильтра описывает функцию фильтра, jpeg_filter:

#define SUCCESS 0

#define FAILURE 1

ISC_STATUS jpeg_filter(short action, isc_blob_ctl control)

ISC_STATUS status = SUCCESS;

InterBase передает одно из восьми возможных действий к функции фильтра, jpeg_filter, посредством параметра action, и также передает экземпляр управляющей структуры Blob, isc_blob_ctl, посредством параметра, control. ellipses (…) в предыдущем листинге представляют код, который выполняет некоторые операции, для каждого действии, или случая, который перечислен в инструкции case.

6.9.Определение управляющей структуры BLOB

Управляющая структура BLOB предоставляет основные методы обмена данными между фильтром и Interbase.


Управляющая структура BLOB определена при помощи typedef, isc_blob_ctl. в ibase.h вот так:

typedef struct isc_blob_ctl <

/* Указатель на внутреннюю InterBase Blob подпрограмму доступа.(функтор) */

struct isc_blob_ctl *ctl_source_handle;

/* Экземпляр ofisc_blob_ctl передаваемый во внутреннюю подпрограмму доступа IB*/

short ctl_to_sub_type;/* Целевой подтип */

short ctl_from_sub_type;/* Исходный подтип */

unsigned short ctl_buffer_length; /* Длина ctl_buffer. */

unsigned short ctl_segment_length; /* Длина текущего сегмента */

unsigned short ctl_bpb_length; /* Длина буфера параметров BLOB. */

char *ctl_bpb; /* Указатель на буфер параметров BLOB */

unsigned char*ctl_buffer; /* Указатель на сегментный буфер */

ISC_LONGctl_max_segment; /* Длина самого длинного BLOB сегмента */

ISC_LONGctl_number_segments; /* Полное число сегментов */

ISC_LONGctl_total_length; /* Полная длина BLOB*/

ISC_STATUS*ctl_status;/* Указатель на статус вектор */

long ctl_data[8];/* Данные определяемые приложением */

Семантика некоторых isc_blob_ctl полей зависит от выполняемого действия.

Например, когда приложение вызывает isc_put_segment () функцию API, InterBase передает isc_blob_filter_put_segment — действие функции фильтра. Буфер, указатель на буфер, ctl_buffer — поле управляющей структуры, передаваемый функции фильтра, содержит сегмент данных, которые будут записано, как определено приложением в его запросе к isc_put_segment (). Поскольку буфер содержит информацию, передаваемую в функцию фильтра, это называется полем IN. Функция фильтра должна включить инструкции в инструкцию case под isc_blob_filter_put_segment для выполнения фильтрации и затем передачи данных для записи в базу данных. Это может быть сделано, вызовом *ctl_source подпрограммы доступной внутри Interbase подпрограммы. Для подробной информации относительно ctl_source, см. Руководство Программиста.

С другой стороны, когда приложение вызывает isc_get_segment () функцию API, и буфер, на него указывает ctl_buffer в управляющей структуре переданной функции фильтра, пуст. В этом случае, InterBase передает isc_blob_filter_get_segment действие- функции фильтра. Обработка действия- функции isc_blob_filter_get_segment фильтра должна включить команды для заполнения ctl_buffer сегментом данных из базы данных, чтобы возвратить его приложению. Это может быть сделано, вызовом *ctl_source подпрограммы доступной внутри IB. В этом случае, буфер используется для вывода информации функцией фильтра, и называется полем OUT.

Следующая таблица описывает каждое из полей в isc_blob_ctl управляющей структуре Blob, используются ли они для ввода функции фильтра (IN), или вывода (OUT).

ibase_blob_cancel

ibase_blob_cancel — Cancel creating blob

Описание

This function will discard a BLOB if it has not yet been closed by ibase_blob_close() .

Список параметров

A BLOB handle opened with ibase_blob_create() .

Возвращаемые значения

Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.

Смотрите также

  • ibase_blob_close() — Close blob
  • ibase_blob_create() — Create a new blob for adding data
  • ibase_blob_import() — Create blob, copy file in it, and close it

ibase_blob_cancel

ibase_blob_cancel — Cancel creating blob

Description

This function will discard a BLOB if it has not yet been closed by ibase_blob_close() .

Parameters

A BLOB handle opened with ibase_blob_create() .

Return Values

Returns TRUE on success or FALSE on failure.

See Also

  • ibase_blob_close() — Close blob
  • ibase_blob_create() — Create a new blob for adding data
  • ibase_blob_import() — Create blob, copy file in it, and close it

Что такое URL-адрес blob и почему он используется?

У меня очень много проблем с URL-адресом blob.

Я искал src видео-тега на YouTube, и я обнаружил, что видео src было похоже:

Я открыл URL-адрес blob, который был в src видео, он дал ошибку, и я не могу открыть, но работал с тегом src . Как это возможно?

  • Что такое URL-адрес blob?
  • Почему он используется?
  • Могу ли я создать свой собственный URL-адрес blob на сервере?
  • Если у вас есть дополнительные сведения
Илон Маск рекомендует:  Работа с библиотеками динамической компоновки (dll)

URL-адреса Blob (ref W3C , официальное имя) или Object-URLs (ссылка MDN и имя метода) используются с объектом Blob или File .

src = «blob: https: //crap.crap » Я открыл url blob, который был в src видео, он дал ошибку, и я не могу открыть, но работал с тегом src, как это возможно?

URL-адреса Blob могут генерироваться только браузером. URL.createObjectURL() создаст специальную ссылку на объект Blob или File, который позже может быть выпущен с помощью URL.revokeObjectURL() . Эти URL-адреса могут использоваться только локально в одном экземпляре браузера и в том же сеансе (т. Е. В жизни страницы / документа).

Что такое URL-адрес blob?
Почему он используется?

URL-адрес Blob URL / Object – псевдопротокол, позволяющий использовать объекты Blob и File в качестве источника URL-адреса для таких вещей, как изображения, ссылки для загрузки для двоичных данных и т. Д.

Например, вы не можете передать исходные байтовые данные объекта Image, поскольку он не знал, что с ним делать. Для загрузки URL-адресов требуется, например, изображения (которые являются двоичными данными). Это относится ко всему, что требует URL-адреса в качестве источника. Вместо того, чтобы загружать двоичные данные, затем отсылайте их обратно через URL-адрес, лучше использовать дополнительный локальный шаг, чтобы иметь возможность напрямую обращаться к данным, не проходя через сервер.

Это также лучшая альтернатива Data-URI, которые являются строками, закодированными как Base-64 . Проблема с Data-URI заключается в том, что каждый символ принимает два байта в JavaScript. Кроме того, из-за кодировки Base-64 добавляется 33%. Blobs – это чистые двоичные байт-массивы, которые не имеют значительных служебных данных, как Data-URI, что делает их более быстрыми и меньшими для обработки.

Могу ли я создать свой собственный код blob на сервере?

Нет, URL-адреса Blob / URL-адреса объектов могут быть сделаны только внутри браузера. Вы можете сделать Blobs и получить объект File через API чтения файлов, хотя BLOB просто означает Binary Large OBject и хранится в виде байтовых массивов. Клиент может запросить отправку данных как ArrayBuffer или как Blob. Сервер должен отправлять данные как чистые двоичные данные. Базы данных часто используют Blob для описания двоичных объектов, и в основном мы говорим в основном о байтовых массивах.

если у вас есть дополнительная информация

Вам необходимо инкапсулировать двоичные данные как объект BLOB, а затем использовать URL.createObjectURL() для создания локального URL-адреса для него:

Обратите внимание, что URL может быть префикс в webkit-браузерах, поэтому используйте:

Что такое URL-адрес blob? Почему он используется?

BLOB – это просто последовательность байтов. Браузер распознает его как поток байтов. Он используется для получения байтового потока из источника.

Объект Blob представляет собой файловый объект неизменных необработанных данных. Blob представляют собой данные, которые не обязательно в формате JavaScript. Интерфейс File основан на Blob, наследует функциональность blob и расширяет ее для поддержки файлов в системе пользователя.

Могу ли я создать свой собственный код blob на сервере?

Новые книги

Монография известного физика и математика Роджера Пенроуза посвящена изучению проблемы искусственного интеллекта на основе всестороннего анализа достижений современных наук. Возможно ли моделирование разума? Чтобы найти ответ на этот вопрос, Пенроуз обсуждает широчайший круг явлений: алгоритмизацию математического мышления, машины Тьюринга, теорию сложности, теорему Геделя, телепортацию материи, парадоксы квантовой физики, энтропию, рождение Вселенной, черные дыры, строение мозга и многое другое.

Книга вызовет несомненный интерес как у специалистов гуманитарных и естественнонаучных дисциплин, так и у широкого круга читателей.

ibase_blob_cancel

(PHP 3>= 3.0.7, PHP 4)

ibase_blob_cancel — отменяет создание blob.

Описание

int ibase_blob_cancel (int blob_id)

Учебник РНР
НазадВперёд

Эта функция в настоящее время ещё не задокументирована; имеется только список аргументов.

Что такое код ibase_blob_cancel

(PHP 3>= 3.0.7, PHP 4)

ibase_blob_cancel — отменяет создание blob.

Описание

int ibase_blob_cancel (int blob_id)

Предупреждение!

Эта функция в настоящее время ещё не задокументирована; имеется только список аргументов.

Предупреждение!

Назад Оглавление Вперёд
ibase_blob_add Вверх ibase_blob_close

Материалы, которые находятся на этой страничке, любезно предоставлены Игорем Ивановым

Firebird 3.0 OO API

Введение

Это руководство описывает объектно-ориентированную версию API Firebird 3.0.


Данный документ является переводом файла doc/Using_OO_API.html, который входит в поставку Firebird.

Описываемые интерфейсы находятся в файле include/firebird/FirebirdInterface. >CLOOP на основе этого > >Firebird.pas).

CLOOP — Cross Language Object Oriented Programming. Этот инструмент не входит в поставку Firebird. Его можно найти в исходных кодах https://github.com/FirebirdSQL/firebird/tree/master/extern/cloop. После того как инструмент будет собран, можно сгенерировать API для вашего языка программирования. Для Object pascal это делается следующей коммандой:

Файлы Pascal.interface.pas, Pascal.implementation.pas и fb_get_master_interface.pas можно найти по адресу https://github.com/FirebirdSQL/firebird/tree/master/src/misc/pascal.

1. Firebird interfaces

Объектно-оринтированный API Firebird (далее OO API) базируется на использовании интерфейсов. Эти интерфейсы, хотя и рассматриваются с точки зрения сравнения с OLE2-интерфейсами (некоторые из них имеют методы addRef() и release() ), являются нестандартными и имеют функции, отсутствующие в других широко используемых типах интерфейсов. Прежде всего, интерфейсы Firebird не зависят от языка — это означает, что для их определения/использования им не нужно использовать конструкции, специфичные для языка, такие как класс в C++, интерфейс может быть определен с использованием любого языка, имеющего понятие массива и указателя на процедуру/функцию. Кроме того, интерфейсы версионны — то есть мы поддерживаем разные версии одного и того же интерфейса. Бинарная компоновка интерфейсов предназначеная для поддержки этих функций очень эффективна (нет необходимости в дополнительных виртуальных вызовах таких как, например, в OLE2/COM с QueryInterface), но это не удобно для непосредственного использования в большинстве языков. Поэтому для упрощения использования API лучше использовать языково-ориентированные обертки для разных языков. В настоящее время у нас есть обертки для C++ и Pascal, скоро появится Java. Для конечного пользователя вызовы POV из C++ и Pascal нет никакой разницы, хотя в Pascal отсутствуют некоторые дополнительные языковые функции, присутствующие в C++ (например, возможность отключить автоматическую проверку статуса после вызовов API).

Обычно API базы данных используется для доступа к данным, хранящимся в базе данных. Firebird OO API, безусловно, выполняет эту задачу, кроме того оно поддерживает создание собственных плагинов — модулей, которые позволяют расширить возможности Firebird в соответствии с вашими потребностями. Поэтому этот документ содержит две большие части — доступ к базам данных и написание плагинов. Некоторые интерфейсы (например, вектор состояния) используются в обеих частях API, они будут обсуждаться в части доступа к данным, позже при обсуждении плагинов мы будем свободно ссылаться на них. Поэтому, даже если вы планируете написать какой-то плагин, лучше начать с чтения первой части этого документа. Кроме того, многим плагинам необходимо обращаться к самим базам данных, и для этого необходим API доступа к данным.

Пакет установки Firebird содержит ряд живых примеров использования OO API — они находятся в каталогах examples/interfaces (доступ к базе данных) и examples/dbcrypt (плагин, выполняющий фиктивное шифрование базы данных). Предполагается, что читатель знаком с ISC API, используемым в Firebird, со времён Interbase.

Данный документ не претендует на полноту документации Firebird 3 — он просто описывает новый объектно-ориентированный API, и читатель должен быть знаком с основными концепциями Firebird, кроме того очень приветствуются знания о ISC API. Например, при описании работы со службами нет объяснения, что такое служба и для чего она необходима, только описание того, как получить интерфейс IService и как его использовать. Кроме того, обратите внимание на то, что примеры кода не используют множество мощных возможностей C++. Не используются указатели с подсчетом ссылок, не используются другие хранители RAII, не используются шаблоны (кроме одного в публичных заголовках firebird) и т. д. Основная цель — сделать этот текст применимым не только для программистов C++, потому что наш API ориентирован на поддержку не только C++ но для других, более простых языков тоже.

1.1. Доступ к базам данных

1.1.1. Созданеи базы данных и соедиенение с существующей базой данных

Прежде всего нам нужно получить доступ к интерфейсу IMaster. IMaster — это основной интерфейс Firebird, необходимый для доступа ко всем остальным интерфейсам. Поэтому существует особый способ доступа к нему — единственное, что нужно это использование простой функции OO API, называемой fb_get_master_interface() . Эта функция не имеет параметров и всегда успешна. Существует один и только один экземпляр IMaster для каждой клиентской библиотеки Firebird, поэтому не нужно заботиться об освобождении памяти, используемой мастер-интерфейсом. Самый простой способ получить к нему доступ из вашей программы — иметь соответствующую глобальную или статическую переменную:

Для многих методов, используемых в API Firebird, первым параметром является интерфейс IStatus. Это логичная замена ISC_STATUS_ARRAY, но работает отдельно с ошибками и предупреждениями (не смешивая их в одном массиве), может содержать неограниченное количество ошибок внутри и (это важно, если вы планируете реализовать IStatus самостоятельно) всегда сохраняет строки на которые он ссылается внутри интерфейса. Обычно для вызова других методов требуется хотя бы один экземпляр IStatus . Вы можете получить его из IMaster :

Если по какой-либо причине метод getStatus() не работает (OOM для примера), то он возврщает NULL — в этом случае очевидно, что мы не можем использовать общий метод для сообщений об ошибке, основанный на IStatus .

При подключении к существующей базе данных или создании новой часто требуется передать множество дополнительных параметров (логин/пароль, размер страницы для новой базы данных и т.д.) вызову API. Наличие отдельных параметров на уровне языка мало реально — нам придётся слишком часто менять вызов при добавлении новых параметров, и их число будет слишком большим, независимо от того, что многие из них обычно можно пропускать. Поэтому для передачи дополнительных параметров используется специальная структура данных в памяти, называемая блок параметров базы данных (database parameters block или DPB). Её формат чётко определён, и это даёт возможность построить DPB байт за байтом. Однако гораздо проще испольовать специальный интефейс IXpbBuilder, который упрощает создание различных блоков параметров. Чтобы получить экземпляр IXpbBuilder , необходимо знать об ещё одном универсальном интерфейсе Firebird API — IUtil. Это своего рода контейнер для вызовов, которые плохо подходят для размещения в других местах. Итак мы делаем сделующее

Этот код создает пустой конструктор блоков параметров типа DPB. Теперь добавление необходимого параметра в него тривиально:

будет создавать базу данных с размером страницы 4 Кб и значениями

ibase_blob_add

ibase_blob_add — Add data into a newly created blob

Описание

ibase_blob_add() adds data into a blob created with ibase_blob_create() .

Список параметров

A blob handle opened with ibase_blob_create() .

The data to be added.

Возвращаемые значения

Эта функция не возвращает значения после выполнения.

Смотрите также

  • ibase_blob_cancel() — Cancel creating blob
  • ibase_blob_close() — Close blob
  • ibase_blob_create() — Create a new blob for adding data
  • ibase_blob_import() — Create blob, copy file in it, and close it
НОВОСТИ ФОРУМА
Рыцари теории эфира
01.10.2020 — 05:20: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]69vJGqDENq4[/Youtube][/center]
[center]14:36[/center]
Osievskii Global News
29 сент. Отправлено 05:20, 01.10.2020 г.’ target=_top>Просвещение от Вячеслава Осиевского — Карим_Хайдаров.
30.09.2020 — 12:51: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Ok]376309070[/Ok][/center]
[center]11:03[/center] Отправлено 12:51, 30.09.2020 г.’ target=_top>Просвещение от Дэйвида Дюка — Карим_Хайдаров.
30.09.2020 — 11:53: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]VVQv1EzDTtY[/Youtube][/center]
[center]10:43[/center]

интервью Раввина Борода https://cursorinfo.co.il/all-news/rav.
мой телеграмм https://t.me/peshekhonovandrei
мой твиттер https://twitter.com/Andrey54708595
мой инстаграм https://www.instagram.com/andreipeshekhonow/

[b]Мой комментарий:
Андрей спрашивает: Краснодарская синагога — это что, военный объект?
— Да, военный, потому что имеет разрешение от Росатома на манипуляции с радиоактивными веществами, а также иными веществами, опасными в отношении массового поражения. Именно это было выявлено группой краснодарцев во главе с Мариной Мелиховой.

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

Delphi-Help

Работа с BLOB-полями в клиентских приложениях InterBase и Firebird на основе компонентов FIBPlus

  • размер шрифта уменьшить размер шрифтаувеличить размер шрифта
  • Печать

Работа с BLOB-полями в клиентских приложениях InterBase и Firebird на основе компонентов FIBPlus

Достаточно часто желательно хранить в базе данных разнообразные неструктурированные данные: изображения, OLE-объекты, звук и т.д. Специально для этих целей существует специальный тип данных — BLOB. Прежде чем рассматривать работу FIBPlus с полями этого типа на примерах, вспомним о том, как сам сервер реализовывает работу с ними. Важно знать и помнить следующее: В отличие от всех других полей, данные BLOB поля не хранятся непосредственно в записи таблицы. В записи таблицы хранится лишь идентификатор BLOB (BLOB_ID), а само тело BLOB хранится на отдельных страницах базы данных и доступ к ним осуществляется специальными функциями IB API. Эта особенность позволяет хранить в BLOB полях данные нефиксированного размера. FIBPlus максимально скрывает эти нюансы непосредственно от разработчика, от вас не требуется самостоятельно вызывать вышеупомянутые функции IB API, но, тем не менее, полезно знать, что происходит «за кулисами» .

Итак, продемонстрируем использование BLOB-полей на примере следующей таблицы:

Использование TpFIBDataSet при работе с BLOB-полями

Рис . 1. Внешний вид формы приложения для работы с BLOB-полями.

Для вывода изображений, сохраненных в поле GRAPHIC, мы будем использовать стандартный компонент DBIMage1: TDBImage. Очевидно также, что запросы при работе с BLOB-полями внешне ничем не отличаются от запросов со стандартными типами полей:

Нюансы при чтении:

Сразу же акцентируем внимание на первом скрытом нюансе. Выполнение «SELECT * FROM BIOLIFE» не вычитывает данные из BLOB полей на клиента. В поле «GRAPHIC» возвращается идентификатор BLOB’a. Далее «за кулисами» происходит следующее: Компонент DBImage1 хочет отобразить содержимое поля из первой записи. Он обращается к pFIBDataSet1 за этим содержимым, и тот «втайне» от нас обращается к серверу через специальные функции IB API непосредственно за телом BLOB поля, пользуясь Blob_ID поля из ПЕРВОЙ записи. Таким образом, мы должны понимать, что в отображенной на иллюстрации ситуации мы «вытащили» на клиента содержимое BLOB поля только первой записи. По мере скроллирования по записям в TpFIBDataSet, DBImage1 будет обращаться за данными других записей, и эти обращения будут транслироваться к серверу.

Нюансы при модификации:

BLOB- поля в TFIBDataSet представлены потомками от TBlobField , и как следствие, наследуют четыре специальных метода модификации таких полей: методы LoadFromFile, LoadFromStream, SaveToFile и SaveToStream.

Первый метод (LoadFromFile) используется для сохранения в поле данных из внешнего файла, второй (LoadFromStream) — для сохранения из любого объекта типа TStream.

Например, если мы хотим сохранить в нашем поле изображение из внешнего файла, то мы можем написать следующий обработчик нажатия на кнопку:

Обратите внимание на важный момент: перед тем, как присваивать значение BLOB-полю, необходимо перевести pFIBDataSet в состояние редактирования данных. В данном случае это делается безусловным вызовом метода Edit. После загрузки данных остается только сохранить изменения вызовом метода Post.

Второй важный момент — необходимо прописать явное приведение поля к типу TBlobField. Дело в том, что FieldByName возвращает объект типа TField, а он не имеет нужных нам методов.

Помимо специальных методов LoadFromXXX, для модификации BLOB полей можно использовать и простые методы типа FieldByName(…).AsString:=’asfdsafsadfsad’;

Методами SaveToFile, SaveToStream мы можем сохранить значение BLOB-поля в некоторый внешний файл или TStream.

Пример сохранения в файл:

Пример очистки поля.

Иногда также нужно знать, является ли BLOB-поле пустым или нет. При использовании визуальных компонентов типа TDBImage мы не можем быть в этом уверены. Согласитесь, что никто не мешает нам «нарисовать» пустую картинку и сохранить ее в BLOB-поле. В этом случае, мы не сможем отличить «на глаз»: есть ли какое-то изображение в BLOB-поле, или нет. Однако мы можем написать обработчик события OnDataChange компонента DataSource1: TDataSource:

Это событие вызывается, в частности, при навигации по DBGrid1, таким образом, мы всегда можем узнать, является ли текущее поле пустым или нет.

Итак, с внешней стороной дела мы разобрались, давайте теперь заглянем «за кулисы». Что происходит при модификациях записи, содержащей BLOB поле?

Вариант 1. Если BLOB поле не изменялось в процессе редактирования, то в соответствующий параметр UPDATE SQL попадет прежний BLOB_ID. Само содержимое BLOB поля на сервер не передается.

Вариант 2. BLOB поле подверглось модификации. Фактически для записи нового содержимого производится несколько действий. Во-первых, с помощью IB API функций isc_create_blob2, isc_put_segment, isc_close_blob в базе данных сохраняется тело НОВОГО BLOB. Так же при этом действии клиент узнает и запоминает BLOB_ID для нового поля. Во-вторых, в UPDATE SQL передается этот новый BLOB_ID, и UPDATE запускается на выполнение. В-третьих (ОЧЕНЬ НЕОЧЕВИДНЫЙ НЮАНС), сервер при фиксации изменений записи ПРЕОБРАЗУЕТ полученный BLOB_ID. То есть, тот BLOB_ID, который передавался клиентом, становится негодным к повторному использованию.

Из упомянутых нюансов, можно сделать несколько практических выводов. Во-первых, для TpDataSet, в которых вы будете модифицировать BLOB поля, просто необходимо использовать опцию poRefreshAfterPost (если используются две транзакции и не используется AutoCommit, то свойство датасета «RefreshTransactionKind» должно иметь значение «tkUpdateTransaction»). При этом действии FIBPlus получит преобразованный сервером BLOB_ID и подменит им тот, который уже стал невалидным. Во-вторых, мы видим, что тело BLOB поля передается на сервер ДО выполнения модификации записи. Если по каким-либо причинам последующая модификация записи будет отвергнута сервером (например, через constraints), то при повторной попытке модификации нам придется передавать тело BLOB поля заново. Это может быть накладно и с точки зрения сетевого трафика, и с точки зрения «разбухания» базы. Поэтому иногда имеет смысл разделить два процесса: отдельным запросом делать модификации всех не BLOB полей, a после успешного завершения этих модификацй отдельно отправлять изменения BLOB полей. (для TpFIBDataSet с автогенерацией модифицирующих запросов в FIBPlus есть специальная опция, регулирующая такое поведение: AutoUpdateOptions. SeparateBlobUpdate).

Использование TpFIBQuery при работе с BLOB-полями

Если вы используете TpFIBQuery для работы с BLOB-полями, то общий принцип остается тем же — можно использовать либо файлы, либо методы работы с TStream. Например, мы можем написать следующую процедуру для сохранения всех изображений из нашей таблицы в файлы:

pFIBQuery.SQL: SELECT * FROM BIOLIFE

Примечание: Метод FN является аналогом метода FieldByName.

Смысл кода, приведенного выше, совершенно очевиден: мы получаем все записи из таблицы BIOLIFE, в цикле берем от сервера очередную запись из запроса, сохраняем в файл значение поля GRAPHIC при помощи метода SaveToFile и запрашиваем следующую запись при помощи метода Next. Аналогичным образом мы могли бы присваивать значение BLOB-параметру:

Данный пример вставляет три новые записи в таблицу BIOLIFE и сохраняет в них изображения из некоторых файлов “1.bmp”, “2.bmp” и “3.bmp”.

Примечание: поскольку в данном примере для сохранения изменений использовался метод Commit, то необходимо перезапустить приложение, чтобы увидеть вставленные записи в DBGrid1.

Поиск по BLOB полям

До сих пор мы рассматривали только операции чтения/модификации BLOB полей. Рассмотрим ситуацию, когда BLOB поля присутствуют в условиях выборки. Если BLOB параметр присутствует в where клаузе, то нужно понимать, что при выполнении запроса сравниваются не содержимое BLOB поля и параметра, а BLOB_ID поля и BLOB_ID параметра. Поэтому нам следует избегать появления BLOB параметров и не пользоваться методами LoadFromFile или LoadFromStream.
Поскольку если вы загружаете в параметр значения через TStream, в реальности вы создаете НОВЫЙ BLOB на сервере с НОВЫМ BLOB_ID. BLOB_ID получается ВРЕМЕННЫЙ, и не предназначен для сравнения с чем-либо. Поэтому сервер в ответ на такую попытку, выдает сообщение о внутренней ошибке. Если вам крайне необходимо сравнивать BLOB поле с неким содержимым, то у вас есть две возможности:

Ситуация, когда нужно найти записи, в которых BLOB поле сравнивается со строкой менее 32 Kб.

Вам необходимо присвоить искомое значение в параметр через свойство AsString. В этом случае на сервер уйдет параметр типа SQL_TEXT и сервер сам произведет необходимую конвертацию значения, необходимую для сравнения.
Например, так::

Если нужно сравнить BLOB поле со значением большим, чем 32 Кб, то придется использовать специальные udf.
Например, так::

В этом примере blobCRC -это udf, а blobCRCPas — функция Pascal.
Обе функции должны быть идентичными, то есть возвращать один и тот же результат для одних и тех же входных данных.

И последнее (почти очевидное) замечание: «Волшебная» цифра 32 Кб — это максимальный размер значений типа CHAR и VARCHAR.

Уникальные возможности FIBPlus: Client BLOB-filters. «Прозрачное» сжатие BLOB-полей..

Многие из вас знают о технологии BLOB фильтров в Firebird/InterBase. Эти пользовательские функции позволяют обрабатывать (т.е. кодировать/декодировать, сжимать и т.д.) BLOB поля на сервере прозрачно для клиентского приложения. Особенно это полезно, если вам нужно заархивировать BLOB поля в базе данных, так как для этого не нужно вносить изменения в клиентскую программу. Но, используя такой подход, вы не сможете снизить сетевой трафик, потому что сервер и приложение в любом случае будут обмениваться несжатыми полями.

В FIBPlus есть механизм клиентских BLOB фильтров, очень схожий с аналогичным механизмом на серерве. Но преимущество локальных BLOB фильтров FIBPlus в том, что они значительно снижают сетевой трафик приложения, если BLOB поле сжимается до отправки на клиентское приложение и распаковывается после того, как оно получено на клиенте. Вы можете сделать это путем регистрации двух процедур: чтения и записи BLOB полей в TpFIBDatabase. После этого FIBPlus будет автоматически использовать эти процедуры для того, чтобы обрабатывать все BLOB поля заданного типа во всех TpFIBDataSet’ах, используя один экземпляр TpFIBDatabase. Проиллюстрируем этот механизм примером:

Сначала мы создадим таблицу с BLOB полями и триггер для генерации уникальных значений первичного ключа:

Обратите внимание, что sub_type должен иметь отрицательное значение!

Примечание: «Существует несколько предопределенных подтипов BLOB, которые встроены в InterBase. Все эти подтипы имеют неотрицательные номера, например subtype 0 — это данные неопределенного типа, subtype 1 — текст, subtype 2 — BLR (Binary Language Representation, см. глоссарий и главу «Структура базы данных InterBase») и т. д. Пользователь также может определять свои подтипы BLOB, которые могут иметь отрицательные значения.». Мир InterBase, А. Ковязин, С. Востриков.

Теперь положите следующие компоненты на форму:

Свяжите компоненты FIBPlus и сгенерируйте запросы для pFIBDataSet1 (только для таблицы “BlobTable”) с SQL Generator. Получится следующая форма:

Рис.2. Приложение с использованием BLOB-фильтров FIBPlus

Напишем обработчик нажатия на кнопку:

Теперь создадим функции сжатия/распаковки BLOB полей:

Не забудьте добавить два модуля в секцию uses: zStream, IBBlobFilter. Первый модель предназначен доя создания архива с данными, второй входит в FIBPlus и отвечает за контроль над BLOB фильтрами. Теперь нам остается только зарегистрировать BLOB фильтры. Это можно сделать путем вызова функции RegisterBlobFilter. Значение первого параметра — это тип BLOB поля (в нашем случае оно равно -15). Второй и третий параметры — это функции кодирования и декодирования BLOB поля:

Запустите приложение, удалите записи, которые уже содержались в нем и добавьте новые. Вы не увидите никакой разницы, но если заглянуть на то, что реально было сохранено в BLOB поле, станет ясно, что данные были заархивированы:

Рис. 3. Данные в BLOB-поле, упакованные при помощи локального фильтра FIBPlus.

Итак, приложение отсылает на сервер (и получает с сервера) уже заархивированные BLOB поля, и, таким образом, сетевой трафик значительно снижается! Конечно, вы можете упаковывать BLOB поля, не используя вышеописанный механизм BLOB фильтров. Например, вы можете сжимать поле в процедуре Button1Click перед его сохранением, а затем распаковывать его в обработчике AfterScroll (или делать что-то подобное). Но, во-первых, предлагаемый централизованный механизм значительно упрощает ваш код (так как BLOB поля обрабатываются независимо от других частей программы), а, во-вторых, он помогает избежать типичных ошибок (например, когда вы пакуете BLOB поля в одной части программы и не делаете то же самое в другой).

Если запись «фильтрованных» BLOB осуществляется через хранимые процедуры, то в процедуре обязательно должен быть указан подтип входного параметра. Например:

В том случае, если подтип входного параметра не будет указан, при вызове этой процедуры BLOB-параметр будет иметь подтип ноль, и, соответственно, фильтрации на клиенте не произойдет.

Илон Маск рекомендует:  Что такое код set database
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL