Creating DataBlade Module Objects
The following sections describe the objects that you can define in a BladeSmith project:
BladeSmith uses wizards to create and edit objects. To start a wizard to create or add an object to your project, choose Edit Insert ObjectName. The last page of the wizard displays the SQL that BladeSmith generates for your object, if there is any.
If you are generating an object that can be secured, the last page of most wizards also allows you to specify privileges. You have these privilege options:
All users can access the object, but only the owner can delete it. The owner of an object is the user ID of the user that created the object in the database.
Only the owner can access or delete the object. Use this option only when there is a specific need to protect a type or routine.
See the Informix Guide to SQL: Tutorial manual for more information on privileges.
Creating Aggregates
An aggregate is a function that returns information about a set of query results. For example, the SUM aggregate adds all the query results together and returns the result. An aggregate is invoked in SQL as a single function but is implemented as one to four support functions.
You can use BladeSmith to create two types of aggregates:
You can define two aggregates that have the same name but operate on different data types. An aggregate acts as a template: the aggregate support functions must have the same names for both aggregates. If you overload an aggregate, you cannot add, remove, or change the names of its support functions. Use your new object prefix to begin the name of your aggregate to avoid accidentally overloading an aggregate in another DataBlade module.
The following table describes the properties you specify when you create an aggregate.
For information on how aggregates behave, see the Informix Guide to SQL: Syntax.
The following sections describe properties of aggregates.
Aggregate Name
If you are creating a new aggregate, use the new object prefix to begin the name of your aggregate. The aggregate name cannot be the same as another user-defined routine or aggregate unless you are overloading an aggregate in another DataBlade module. See "New Object Prefix" for more information on the new object prefix.
To overload a built-in aggregate, type the name of one of the built-in aggregates in the Aggregate Name field. The built-in aggregates are AVG, COUNT, MAX, MIN, SUM, RANGE, STDEV, and VARIANCE. The COUNT aggregate is automatically defined for all data types and does not require associated functions; therefore, do not create it in BladeSmith. For more information on these aggregates, see the Informix Guide to SQL: Syntax.
When you overload an existing aggregate, do not specify any of the aggregate's associated functions; BladeSmith uses the aggregate's template to generate the proper SQL and skips the intervening wizard pages.
Initialization Parameter
The initialization parameter is an argument in the initialization function to customize the aggregation computation. For example, if you defined an aggregate to return the top n values of a query, your initialization parameter can be 3 to select the top three.
State Type
The state type holds the partial result information during the aggregation computation. The database server never accesses the state type, so it can be any data type or structure appropriate for the partial results. For example, if you have an aggregate that returns the three largest values from a query result set, your state type can be an array of three integers.
If you are overloading an existing aggregate, the state type must be different for each aggregate.
Select the POINTER data type from the data type list to indicate that your data type is not known to the database server.
Initialization Function
The initialization function initializes the data structures required by the rest of the aggregation computation. For example, it can set up large objects or temporary files for storing intermediate results.
The initialization function can take an optional initialization parameter to customize the aggregate computation.
The initialization function is not required for simple binary operators that have a state type that is the same as the iteration type.
Iteration Function
The iteration function merges a single value of the iteration type with the partial result of the state type, and returns the updated partial result.
You can specify whether the iteration function handles null values. If it does not, any null values returned by the query are ignored. If it does handle null values, the iteration function includes them in its computations.
Combine Function
The database server can break up the aggregation computation into several pieces and compute them in parallel. Each piece is computed sequentially; then the results from all pieces are combined into a single result using the combine function. The parallel computation must give the same result as the sequential computation.
The combine function merges partial results of the state type and returns the updated partial result. It can also perform clean-up work by releasing resources acquired by the initialization function.
The combine function can be the same as the iterator function if the aggregate is derived from a simple binary operator whose result type is the same as the state type.
Final Function
The final function converts a partial result of the state type into the result type. It can also release resources acquired by the initialization function to clean up the result type.
If you do not include a final function, the database server returns the final state type. The final function is not required for aggregates derived from simple binary operators whose result type is the same as the state type.
Creating Casts
A cast is a conversion from one data type to another. The cast accepts the source data type as its argument and returns the target data type.
The following table describes the properties you specify when you create a cast.
See the Informix Guide to SQL: Tutorial for general information on casting.
The following sections describe properties of casts.
Source and Target Data Types
You cannot create a cast between two built-in or qualified data types.
You also cannot create a cast that includes any of the following data types as either the source type or target type for the cast:
Implicit and Explicit Casts
You can specify whether a cast is called for implicit conversions. Implicit conversions allow the database server to use the cast when it is not called explicitly in an SQL statement.
For example, if the SUM function is called with a DOLLAR argument, the database server searches for an implicit cast from DOLLAR to a data type for which the SUM function is defined. If an implicit cast exists, the database server calls the conversion function and then calls the SUM function without error. If no cast is specified with implicit conversion, the SUM function call results in an error message from the database server.
In this example, you create an implicit cast from DOLLAR to DOUBLE PRECISION to permit the database server to execute all functions defined for DOUBLE PRECISION on DOLLAR values. However, if you define a cast from DOLLAR to INTEGER, you do not want that cast to be implicit, because the conversion function truncates dollar values, resulting in inaccurate results.
See Extending INFORMIX-Universal Server: Data Types for more information on implicit and explicit casts.
Casting Functions
If the source and target data types do not have the same binary representation, the database server calls a casting function to perform the conversion. If the two types have the same binary representation, a casting function might not be needed.
The name of the casting function is automatically generated; this function is never called directly by the user. The casting function is named typeCast, where type is the name of the data type the casting function returns.
See Extending INFORMIX-Universal Server: Data Types for more information on creating casting functions.
Defining Errors
DataBlade module routines can print error messages and trace messages. Error messages are printed with the mi_db_error_raise() function. Trace messages are written to a trace file with the DBDK_TRACE macros or the gl_dprintf() macro. See "Tracing and Error Handling" for more information on tracing and error handling.
Although it is possible to hard-code messages in your routines, defining them in BladeSmith makes them easier to edit. Also, BladeSmith generates code that uses the Informix Global Language Support (GLS) API, so messages that you create in BladeSmith can be easily localized.
The following table lists the properties you specify when you create an error.
The following sections describe properties of errors.
SQL Error Code
Error codes are allocated for your DataBlade module by the Informix DataBlade Developers Program registry, to ensure that your error codes do not conflict with built-in error codes and those of other DataBlade modules.
See "Contacting the Informix Registry" for information on how to design and register your error codes.
Error Locale
The error locale enables the database server to select a translated error or trace message for a localized database. The locale is specified using the format language_country.codeset. Be sure to create messages for all of the locales where your DataBlade module executes.
The default BladeSmith locale, en_us.8859-1, is for U.S. English using code set 8859. This is the default locale for the Informix database server on UNIX platforms.
The default code set for the Informix database server on Windows NT is 1252. Create U.S. English messages using locale en_us.1252 for Windows NT database servers.
For more information on locales, see the Guide to GLS Functionality.
SQL Error Text
The SQL error text is displayed with the error code in the language specified by the message locale. To specify parameters in messages, assign each parameter a unique name enclosed in percent characters ( % ). For example, an input function could send the following message when it is unable to translate an input value:
For information about tracing and calling error messages, see the DataBlade API Programmer's Manual.
Defining Interfaces
If you expect other DataBlade modules to use the functionality provided by your DataBlade module, create an interface. DataBlade developers can include the interface in a DataBlade module to ensure that BladeManager registers the DataBlade module with the interface before registering the DataBlade module dependent on the interface.
The interface you define encompasses all of your DataBlade module.
The following table lists the properties you specify when you create an interface.
Creating Routines
You can define public or private user-defined routines that support your DataBlade module. You can specify if the routine is called by SQL or is an internal routine.
Routines can be functions, which return values, or procedures, which do not return values. Routines can be written in the C programming language or the Informix Stored Procedure Language (SPL).
Use the New Routine wizard to:
Existing routines can be built-in or user-defined. Built-in routines include operator and other arithmetic functions, and support routines. See Extending INFORMIX-Universal Server: Data Types for a list of built-in routines you can overload.
The following table lists the properties you specify when you create a routine.
The following sections describe properties of routines.
Routine Name
Specify the name of an existing routine to overload it for a new data type, or specify a unique routine name to create a new routine.
You can overload built-in operator and other arithmetic functions for collection, row, and distinct data types. (You can overload most arithmetic functions for opaque data types with the New Opaque Type wizard.) How arithmetic functions operate on collection and row data types is determined by the code you write for them. For example, if you overload the Sum function for a row data type, it might either:
See Extending INFORMIX-Universal Server: Data Types for a list of built-in routines you can overload.
Although it is not necessary, you can create new support functions for collection, row, and distinct data types.
Routine Arguments
A routine can accept 0 to 20 arguments.
Arguments passed to a routine have the following properties:
Statement Local Variables
If you want your function to return two values, check the Local Variable check box. Then the last argument for your function is defined as an OUT parameter. The OUT parameter corresponds to a value the function returns indirectly, through a pointer, to a statement local variable (SLV). The value the function returns through the pointer is an extra value, in addition to the value it returns explicitly.
The SLV provides a temporary name that a single statement can manipulate. An SQL statement uses each SLV to transmit the output from a single function to other parts of the SQL statement.
See the Informix Guide to SQL: Syntax for more information.
Variant Functions
By default, user-defined functions are variant. Variant functions can return different values or have varying side effects, given the same arguments. For example, a function that returns the current date or time is a variant function. However, a function that appears nonvariant can also have varying side effects, such as updating a table or external file.
The cost of defining a nonvariant function as variant is low: you might experience slightly diminished performance. However, the cost of defining a function that exhibits variant behavior as nonvariant can be high because a query might return incorrect results.
Most functions are not variant; marking them as nonvariant improves performance. If the function is nonvariant, the database server might cache the return values of expensive functions or run parallel queries. Functional indexes are only allowed on nonvariant functions.
See the Informix Guide to SQL: Syntax for more information.
Parallelizable Routines
Mark a routine as parallelizable if it can be executed within a parallel database query (PDQ) statement. PDQ statements allow the Informix database server to distribute the executions of one query among several processors by dividing the query into subqueries. The database server then allocates subqueries to separate threads for parallel processing and thus improves performance. See the INFORMIX-Universal Server Administrator's Guide for more information about PDQ.
Use routine parallelization if your routine is used as an expression in qualification clauses, in GROUP BY lists, or as an overloaded comparison operator.
A routine cannot be parallelizable if it accepts row or collection data types as arguments.
Parallelizable routines can only call DataBlade API routines listed in the following categories from the DataBlade API Programmer's Manual:
See the DataBlade API Programmer's Manual for more information about the routines under each category.
C Routine Name
SQL allows overloading of routine names; however, the C language does not. Therefore, if you overload a routine, you must give it a unique C name.
Routine Behavior
A routine is well-behaved within the context of Informix database server architecture if it:
If your routine violates one of these conditions, mark it as poorly behaved and type the name of a user-defined virtual processor in the user-defined virtual processor class field. See "User-Defined Virtual Processors" for more information on when to use user-defined virtual processors.
User-Defined Virtual Processor Class Name
The name of the grouping class for the user-defined virtual processor must be 18 alphanumeric characters or fewer, and must be unique. The class name is case insensitive. Informix recommends that you begin the name of your virtual processor class with your DataBlade module new object prefix. If you want to have your DataBlade module certified by Informix, virtual processor classes must begin with the DataBlade module prefix.
See "User-Defined Virtual Processors" for more information on creating and configuring a user-defined virtual processor.
Stack Size
Stack space is allocated from a common region in shared memory that can be overrun if a routine consumes more stack space than is allocated for it. To avoid stack overrun:
When you specify a stack size for a user-defined routine, the database server allocates the specified amount of memory for every execution iteration of the routine.
See the INFORMIX-Universal Server Administrator's Guide for more information on stacks.
Cost of Routine
The relative cost of the routine is used by the query optimizer to determine in which order to process WHERE clauses in a SELECT statement. Expensive routines are called after inexpensive routines. A cost of 0 indicates that the routine costs relatively the same as the routines in the reference list that have a cost of 0 . The reference list shows all user-defined routines created in the project. The standard formula for computing routine cost is:
Because the optimizer compares routine costs, the actual cost is irrelevant; only the relative cost matters. However, follow the general formula to ensure that your routines interact with other DataBlade module routines in a predictable way.
Related Routines
To optimize the execution of your function when it is called in the WHERE clause of a SELECT statement, specify related functions.
If the function returns a Boolean result, specify a commutator and a negator function. These routines can be called instead of the original function if the query optimizer determines that they are faster.
Specify a selectivity function to estimate the percentage of rows that might be returned by your function, given a set of arguments. Use the selectivity function to determine the cost of your function; the query optimizer can determine when it is most efficient to call your function.
Creating Data Types
You can create the extended data types described in the following sections in BladeSmith:
In addition, you must define qualified built-in data types (see "Qualified Data Type") before you can use them in a BladeSmith project.
Collection Data Type
A collection data type is a set of another data type. A collection is made up of elements of a single data type. Collection elements can never be null.
You can overload existing user-defined routines and built-in routines to work on your collection data type. You can also define custom support routines for your collection data type. See "Creating Routines" for instructions.
The following table lists the properties you specify when you create a collection data type.
See the Informix Guide to SQL: Tutorial for general information on collection data types.
The following sections describe properties of collection data types.
Valid Element Data Types
You can create a collection with elements of any data type listed in your project except SERIAL or SERIAL8. You can define a collection type of an existing collection or row data type. For example, you can define a list of a set of integers in SQL:
You can also create collections of opaque or distinct data types.
Type Constructors
The type constructor determines the structure of the collection. The following table shows the options between the type constructors.
See the Informix Guide to SQL: Reference for more information about collection type constructors.
Distinct Data Type
A distinct data type has an internal and external representation identical to another data type, but the database server treats it as a different data type. Any existing routines on the source data type are automatically registered on the distinct data type. However, you can define new routines that operate only on the distinct data type.
You can define custom support routines and user-defined routines for your distinct data type. You can also overload existing user-defined routines and built-in routines to work on your distinct type. See "Creating Routines" for instructions.
The following table lists the properties you specify when you create a distinct data type.
When you create a distinct data type, the database server automatically creates explicit casts between the source data type and the distinct data type; therefore, the distinct data type cannot be cast to the source data type automatically.
See the Informix Guide to SQL: Reference for more information on distinct data types.
Opaque Data Type
An opaque data type is a C structure or ActiveX/C++ class. The database server does not interpret the contents of the structure. Instead, it calls support routines that you provide to manipulate the structure.
BladeSmith generates much of the code for the support routines. You complete the code and compile the source into a shared object file or dynamic link library using the generated makefiles.
The following table lists the properties you specify when you create an opaque data type.
See Extending INFORMIX-Universal Server: Data Types for more information on opaque data types.
The following sections describe the properties of opaque data types you need to define when you create an opaque data type with BladeSmith.
Definition of Internal Structure
The internal structure of the opaque data type is not known to the database server. The support routines you define for the opaque data type operate on the internal structure.
If you define the internal structure of your opaque data type to BladeSmith, BladeSmith generates useful code for it. If you do not specify the internal structure, BladeSmith generates code that operates as if your opaque data type is a stream of bytes.
The internal structure of C++ server data types must be defined; undefined structures are not supported.
Fixed or Variable Size
An opaque data type can have a fixed size that is determined by the sum of the sizes of the data structures within the opaque data type. The maximum size is 32 KB.
Alternatively, an opaque data type can have a variable size if one of its internal data structures does not have a fixed size. Typically, variable data structures are smart large objects or other opaque data types. Variable-length data structures can have a maximum size. Variable-length opaque data types are treated as bit-varying types.
C++ server data types must always be marked as fixed size; variable-length opaque data types are not supported.
Member Information
Specify the following information about the internal members of your opaque data type:
If you choose to create a variable-length opaque data type, a member is automatically added as an mi_int1 of variable size. Then change the mi_int1 data structure to be the one you need. Be sure to list the variable-length member last.
Maximum Size
If you create a variable-length opaque data type, specify the maximum allocated length of that data type. The database server does not allow an opaque data type to grow beyond its maximum length. If you choose to specify a maximum length, the maximum value is 32,767 bytes. This value, however, is the maximum size of a row in a database table. Therefore, if your opaque data type is 32,767 bytes, you cannot have any other columns in your table.
Memory Alignment
If you do not specify the internal structure of your opaque data type in BladeSmith, you must choose the memory alignment of the first member; your compiler aligns the other members with this value. Choose an alignment value that corresponds to the greatest alignment requirement in the data structure. The default alignment is 4. If you do not know the alignment of the member with the greatest alignment, choose 8.
See Extending INFORMIX-Universal Server: Data Types for more information on memory alignment.
Support Routines
You can define these routines to support your opaque data type:
- Basic text input and output functions, OpaqueTypeNameIn and OpaqueTypeNameOut, convert between the text representation of the opaque data type and the internal database server format.
- Binary send and receive functions, OpaqueTypeNameSend and OpaqueTypeNameRecv, transfer the binary representation of the opaque data type to and from the client.
- Text file import and export functions, OpaqueTypeNameImpT and OpaqueTypeNameExpT, transfer the text representation of the opaque data type to and from a flat file.
- Binary file import and export functions, OpaqueTypeNameImpB and OpaqueTypeNameExpB, transfer the binary representation of the opaque data type to and from a flat file.
- The Assign function and the Destroy procedure perform tasks before storing or deleting an opaque data type on disk: for example, to ensure proper reference counting on smart large objects. These routines are not available for C++ database server implementations.
- The LOhandles function retrieves a list of the pointer structures for the smart large objects embedded in the opaque data type. This routine is not available for C++ database server implementations.
- Type comparison functions, Compare, Equal, and NotEqual, compare two opaque data types, for example, to support an ORDER BY clause in a query. These functions are necessary to support development in Microsoft Visual Basic.
- B-tree strategy and support functions, Compare, Equal, LessThan, GreaterThan, LessThanOrEqual, and GreaterThanOrEqual, support using the B-tree secondary access method to create an index on your opaque data type column.
- R-tree strategy and support functions, Equal, Overlap, Contains, Within, Union, Size, and Inter, support using the R-tree secondary access method to create an index on your opaque data type column.
- Binary arithmetic operators, Plus, Minus, Times, and Divide, are overloaded for your opaque data type.
- Unary arithmetic operators, Positive and Negate, are overloaded for your opaque data type.
- The Concat operator is overloaded for your opaque data type.
- The Hash function is overloaded for your opaque data type if the database server cannot use the built-in hashing function to cache its return values.
The first four sets of functions on the list and the type comparison support functions are generated by default and are recommended for all opaque data types. If your opaque data type contains a smart large object, also define the LOhandles, Assign, and Destroy routines.
See Extending INFORMIX-Universal Server: Data Types for more information on these routines.
Qualified Data Type
A qualified data type is a built-in data type with additional specifications that provide information about the storage size, range of values, or precision of the data type. For example, CHAR is a built-in data type, but CHAR(16) is a qualified data type because you are fixing its length. You must add a qualified data type to a BladeSmith project before you can use it as a component of an extended data type.
When you create a qualified data type in a BladeSmith project, it is added to the list of data types from which you choose when creating extended data types. No SQL or source code is generated for qualified data types.
For example, to create a collection data type that stores sets of 16-byte character strings, you must first create a CHAR(16) qualified data type. Then create the collection data type, choosing CHAR(16) as the base data type and SET as the constructor function. The new data type has the following SQL definition:
The following table lists the data types that take qualifications.
BladeSmith restricts your input for qualification values to valid choices.
See Informix Guide to SQL: Reference for more information about qualified data types.
Row Data Type
A row data type is a group of fields of existing data types arranged like a row in a table. The fields of a row data type can be almost any data type that exists in your project, including other row data types.
You can overload existing user-defined routines and built-in routines to work on your row type. See "Creating Routines" for instructions.
The following table lists the properties you specify when you create a row data type.
The following sections describe properties of row data types.
Named and Unnamed Row Data Types
You can create a named or an unnamed row data type.
A named row data type has these general characteristics:
An unnamed row type has these general characteristics:
See the Informix Guide to SQL: Tutorial for more information on named and unnamed row data types.
Row Data Type Inheritance
Named row data types can inherit from other named row data types. A child row data type inherits its parent's fields and can be passed to all routines defined for the parent data type.
You can add additional fields and routines that are only valid for the child data type.
See the Informix Guide to SQL: Tutorial for more information on inheritance.
Row Data Type Fields
Fields in row data types can be any existing data type except SERIAL and SERIAL8.
|