Filtering Blob Data

From InterBase
Jump to: navigation, search

A Blob filter is a routine that translates Blob data from one subtype to another. InterBase includes a set of special internal Blob filters that convert from subtype 0 (unstructured data) to subtype 1 (TEXT), and from subtype 1 to subtype 0.

In addition to using these standard filters, you can write your own external filters to provide special data translation. For example, you might develop a filter to convert one image format to another, for instance to display the same image on monitors with different resolutions. Or you might convert a binary Blob to plain text and back again to be able to move the file more easily from one system to another.

If you define filters, you can assign them subtype identifiers from –32,768 to –1.

The following sections provide an overview of how to write Blob filters, followed by details of how to write an application that requires filtering. For more information about writing Blob filters, see the Embedded SQL Guide.

Using Your Own Filters

Unlike the standard InterBase filters that convert between subtype 0 and subtype 1, an external Blob filter is generally part of a library of routines you create and link to an application.

You can write Blob filters in C or Pascal (or any language that can be called from C). To use your own filters, follow these steps:

  1. Decide which filters you need to write.
  2. Write the filters in a host language.
  3. Build a shared filter library.
  4. Make the filter library available.
  5. Define the filters to the database.
  6. Write an application that requests filtering.

Steps numbered 2, 5, and 6 are described in greater detail in the following sections.

Declaring an External Blob Filter to the Database

To declare an external filter to a database, use the DECLARE FILTER statement. For example, the following statement declares the filter, SAMPLE:

DECLARE FILTER SAMPLE
INPUT TYPE –1 OUTPUT_TYPE –2
ENTRY POINT 'FilterFunction'
MODULE_NAME 'filter.dll';

In the example, the filter’s input subtype is defined as –1 and its output subtype as –2. If subtype –1 specifies lowercase text, and subtype –2 uppercase text, then the purpose of filter SAMPLE would be to translate Blob data from lowercase text to uppercase text.

The ENTRY_POINT and MODULE_NAME parameters specify the external routine that InterBase calls when the filter is invoked. The MODULE_NAME parameter specifies filter.dll, the dynamic link library containing the filter’s executable code. The ENTRY_POINT parameter specifies the entry point into the DLL. Although the example shows only a simple file name, it is good practice to specify a fully qualified path name, since users of your application need to load the file.

Writing an External Blob Filter

If you choose to write your own filters, you must have a detailed understanding of the datatypes you plan to translate. InterBase does not do strict datatype checking on Blob data; it is your responsibility.

Defining the Filter Function

When writing a filter, you must include an entry point, known as a filter function, in the declaration section of the program. InterBase calls the filter function when an application performs a Blob access operation on a Blob specified to use the filter. All communication between InterBase and the filter is through the filter function. The filter function itself may call other functions that comprise the filter executable.

You declare the name of the filter function and the name of the filter executable with the ENTRY_POINT and MODULE_NAME parameters of the DECLARE FILTER statement.

A filter function must have the following declaration calling sequence:

filter_function_name(short action, isc_blob_ctl control);

The parameter, action, is one of eight possible action macro definitions, and the parameter, control, is an instance of the isc_blob_ctl Blob control structure, defined in the InterBase header file, ibase.h. These parameters are discussed later in this chapter.

The following listing of a skeleton filter declares the filter function, jpeg_filter:

#include <ibase.h>
#define SUCCESS 0
#define FAILURE 1
ISC_STATUS jpeg_filter(short action, isc_blob_ctl control)
{
ISC_STATUS status = SUCCESS;
switch (action) {
case isc_blob_filter_open:
. . .
break;
case isc_blob_filter_get_segment:
. . .
break;
case isc_blob_filter_create:
. . .
break;
case isc_blob_filter_put_segment:
. . .
break;
case isc_blob_filter_close:
. . .
break;
case isc_blob_filter_alloc:
. . .
break;
case isc_blob_filter_free:
. . .
break;
case isc_blob_filter_seek:
. . .
break;
default:
. . .
break;
}
return status;
}

InterBase passes one of eight possible actions to the filter function, jpeg_filter, by way of the action parameter, and also passes an instance of the Blob control structure, isc_blob_ctl, by way of the parameter, control.

The ellipses (…) in the previous listing represent code that performs some operations based on each action, or event, that is listed in the case statement. Most of the actions correspond to API functions called by an application. For more information regarding the types of code to write for each action, see the Embedded SQL Guide.

Defining the Blob Control Structure

The isc_blob_ctl Blob control structure provides the fundamental method of data exchange between InterBase and a filter.

The Blob control structure is defined as a typedef, isc_blob_ctl, in ibase.h, as follows:

typedef struct isc_blob_ctl {ISC_STATUS (*ctl_source)();
/* Internal InterBase Blob access routine. */
struct isc_blob_ctl *ctl_source_handle;
/* Instance of isc_blob_ctl to pass to internal
* InterBase Blob access routine. */
short ctl_to_sub_type; /* Target subtype. */
short ctl_from_sub_type; /* Source subtype. */
unsigned short ctl_buffer_length; /* Length of ctl_buffer. */
unsigned short ctl_segment_length; /* Length of current segment. */
unsigned short ctl_bpb_length; /* Blob parameter buffer length. */
char *ctl_bpb; /* Pointer to Blob parameter buffer. */
unsigned char *ctl_buffer; /* Pointer to segment buffer. */
ISC_LONG ctl_max_segment; /* Length of longest Blob segment. */
ISC_LONG ctl_number_segments; /* Total number of segments. */
ISC_LONG ctl_total_length; /* Total length of Blob. */
ISC_STATUS *ctl_status; /* Pointer to status vector. */
long ctl_data[8]; /* Application-specific data. */
} *ISC_Blob_CTL;

The purpose of certain isc_blob_ctl fields depend on the action being performed.

For example, when an application calls the isc_put_segment() API function, InterBase passes an isc_blob_filter_put_segment action to the filter function. The buffer pointed to by the ctl_buffer field of the control structure passed to the filter function contains the segment data to be written, as specified by the application in its call to isc_put_segment(). Because the buffer contains information passed into the filter function, it is called an IN field. The filter function should include instructions in the case statement under the isc_blob_filter_put_segment case for performing the filtering and then passing the data on for writing to the database. This can be done by calling the *ctl_source internal InterBase Blob access routine. For more information about ctl_source, see the Embedded SQL Guide.

On the other hand, when an application calls the isc_get_segment() API function, the buffer pointed to by ctl_buffer in the control structure passed to a filter function is empty. In this situation, InterBase passes an isc_blob_filter_get_segment action to the filter function. The filter function isc_blob_filter_get_segment action handling should include instructions for filling ctl_buffer with segment data from the database to return to the application. This can be done by calling the *ctl_source internal InterBase Blob access routine. In this case, because the buffer is used for filter function output, it is called an OUT field.

The following table describes each of the fields in the isc_blob_ctl Blob control structure, and whether they are used for filter function input (IN), or output (OUT).

Table 7.4 isc_blob_ctl Structure Field Descriptions

Field Name Description
(*ctl_source)() Pointer to the internal InterBase Blob access routine (IN)

*ctl_source_handle Pointer to an instance of isc_blob_ctl to be passed to the internal InterBase Blob access routine (IN)
ctl_to_sub_type Target subtype: information field provided to support multipurpose filters that can perform more than one kind of translation; this field and the next one enable such a filter to decide which translation to perform (IN)
ctl_from_sub_type Source subtype: information field provided to support multipurpose filters that can perform more than one kind of translation; this field and the previous one enable such a filter to decide which translation to perform (IN)
ctl_buffer_length For isc_blob_filter_put_segment, field is an IN field that contains the length of the segment data contained in ctl_buffer For isc_blob_filter_get_segment, field is an IN field set to the size of the buffer pointed at by ctl_buffer, which is used to store the retrieved Blob data
ctl_segment_length Length of current segment. For isc_blob_filter_put_segment, field is not used.

For isc_blob_filter_get_segment, field is an OUT field set to the size of the retrieved segment (or partial segment, in the case when the buffer length ctl_buffer_length is less than the actual segment length)

ctl_bpb_length Length of the Blob parameter buffer
*ctl_buffer Pointer to segment buffer. For isc_blob_filter_put_segment, field is an IN field that contains the segment data

For isc_blob_filter_get_segment, field is an OUT field the filter function fills with segment data for return to the application

ctl_max_segment Length, in bytes, of the longest segment in the Blob. Initial value is 0. The filter function sets this field. This field is information only.
ctl_number_segments Total number of segments in the Blob. Initial value is 0. The filter function sets this field. This field is information only.
ctl_total_length Total length, in bytes, of the Blob. Initial value is 0. The filter function sets this field. This field is information only.
*ctl_status Pointer to InterBase status vector. (OUT).
ctl_data [8] 8-element array of application-specific data. Use this field to store resource pointers, such as memory pointers and file handles created by the isc_blob_filter_open handler, for example. Then, the next time the filter function is called, the resource pointers will be available for use.(IN/OUT).

Programming Filter Function Actions

When an application invokes a Blob API function on a Blob to be filtered, InterBase passes a corresponding action message to the filter function by way of the action parameter. There are eight possible actions. The following action macro definitions are declared in the ibase.h file:

#define isc_blob_filter_open 0
#define isc_blob_filter_get_segmen 1
#define isc_blob_filter_close 2
#define isc_blob_filter_create 3
#define isc_blob_filter_put_segment 4
#define isc_blob_filter_alloc 5
#define isc_blob_filter_free 6
#define isc_blob_filter_seek 7

The following table lists the actions, and specifies when the filter function is invoked with each particular action. Most of the actions are the result of events that occur when an application invokes a Blob API function.

Table 7.5 Action Constants

Action When Filter is Invoked with Corresponding Action
isc_blob_filter_open Invoked when an application calls isc_open_blob2()
isc_blob_filter_get_segment Invoked when an application calls isc_get_segment()
isc_blob_filter_close Invoked when an application calls isc_close_blob()
isc_blob_filter_create Invoked when an application calls isc_create_blob2()
isc_blob_filter_put_segment Invoked when an application calls isc_put_segment()
isc_blob_filter_put_segment Invoked when an application calls isc_put_segment()
isc_blob_filter_alloc Invoked when InterBase initializes filter processing; not a result of a particular application action
isc_blob_filter_free Invoked when InterBase ends filter processing; not a result of a particular application action
isc_blob_filter_seek Reserved for internal filter use; not used by external filters
This concludes the overview of writing Blob filters. For detailed information about filters and how to program filter function actions, as well as a reference to a filter application example, see the Embedded SQL Guide.

Advance to Next Section