Summary:
See also: Programs, Installation and Setup.
With C-Extensions, you can integrate your own C libraries in the runtime system, to call C function from the BDL code. This feature allows you to extend the language with custom libraries, or existing standard libraries, just by writing some 'wrapper functions' to interface with BDL.
C-Extensions are implemented with shared libraries. Using shared libraries avoids the need to re-link the fglrun program and simplifies deployment.
Function parameters and returned values are passed/returned on the legal BDL stack, using pop/push functions. Be sure to pop and push the exact number of parameters/returns expected by the caller; otherwise, a fatal stack error will be raised at runtime.
Inside the C Extension, you can manipulate 4GL-specific data types with the C API functions supported by Genero BDL. For example, you can do DECIMAL computation.
In order to use a C-Extension in your program, you typically specify the library name with the IMPORT instruction at the beginning of the BDL module calling the C-Extension functions. The compiler can then check for function existence and the library will be automatically loaded at runtime.
To compile C Extensions using complex data types such as DECIMAL, DATETIME/INTERVAL or BYTE/TEXT, you need IBM Informix ESQL/C data type structure definitions such as dec_t, dtime_t, intrvl_t, as well as macros like DECLEN() or TU_ENCODE(). These definitions are not required if you use standard C types such as short, int or char[].
The definition of the ESQL/C structures like dec_t are property of IBM and cannot be provided in the Genero BDL package. Note also that some definitions are platform specific, for example, the mlong typedef is different on 32bit and 64bit machines.
The IBM Informix CSDK must be installed on the development machine in order to get the ESQL/C structures and macro definitions specific to Informix data types. Understand that the IBM Informix CSDK is only required on the computer used for development, where you compile and link your C Extensions shared libraries: It is not required to install the CSDK on the production machines, except of course if you want to connect to an IBM Informix database server.
The INFORMIXDIR environment variable must be set and point to the directory where the IBM Informix CSDK is installed.
Custom C Extensions must be provided to the runtime system as Shared Objects (.so) on UNIX, and as Dynamically Loadable Libraries (.DLL) on Windows.
In order to create a C-Extension, you must:
In your C source files, you must include the fglExt.h header file in the following way:
01
#include <f2c/fglExt.h>
When migrating from IBM Informix 4GL, it is possible that existing C extension sources include Informix specific headers like sqlhdr.h or decimal.h. You can either remove or keep the original includes, but if you want to keep them, the Informix specific header files must be included before the fglExt.h header file, in order to let fglExt.h detect that typedefs such as dec_t or dtime_t are already defined by Informix headers. If you include Informix headers after fglExt.h, you will get a compilation error. As fglExt.h defines all Informix-like typedef structures, you can remove the inclusion of Informix specific header files.
Your C functions must be known by the runtime system. To do so, each C extension library must publish its functions in a UsrFunction array, which is read by the runtime system when the module is loaded. The UsrFunction array describes the user functions by specifying the name of the function, the C function pointer, the number of parameters and the number of returned values. You typically define the UsrFunction array in the C interface file.
After compiling the C sources, you must link them together with the libfgl runtime system library. See below for examples.
Carefully read the man page of the ld dynamic loader, and any documentation of your operating system related to shared libraries. Some platforms require specific configuration and command line options when linking a shared library, or when linking a program using a shared library (+s option on HP for example).
Linux command-line example:
gcc -c -I $FGLDIR/include -fPIC myext.c gcc -c -I $FGLDIR/include -fPIC cinterf.c gcc -shared -o myext.so myext.o cinterf.o -L$FGLDIR/lib -lfgl
Windows command-line example using Microsoft Visual C++ 8.0 and higher (with SxS manifest for the DLL!):
cl /DBUILDDLL /I%FGLDIR%/include /c myext.c cl /DBUILDDLL /I%FGLDIR%/include /c cintref.c link /dll /manifest /out:myext.dll myext.obj cinterf.obj %FGLDIR%\lib\libfgl.lib mt -manifest myext.dll.manifest -outputresource:myext.dll
Note that if you build your DLL with a version of Microsoft Visual C++ that is different from the version used to build FGLRUN.EXE, the DLL must get private dependencies other than the process default. For example, when the C Extension DLL needs the Visual C 9.0 runtime library MSVCR90.DLL, while the FGLRUN.EXE was build with VC 10 and needs MSVCR100.DLL. Private dependencies is specified with the resource id ISOLATIONAWARE_MANIFEST_RESOURCE_ID, by adding the ;2 modifier at the end of the -outputresource option (after the file name):
mt -manifest myext.dll.manifest -outputresource:myext.dll;2
You can create user extension libraries from ESQL/C sources, as long as you have an ESQL/C compiler which is compatible with your Genero runtime system. In order to create these user extensions, you must first compile the .ec sources to object files by including the fglExt.h header file. Then you must create the shared library by linking with additional SQL libraries to resolve the functions used in the .ec source to execute SQL statements.
You can compile .ec extensions with the native Informix esql compiler. This section describes how to use the Informix esql compiler.
The following example shows how to compile and link an extension library with Informix esql compiler:
Linux command-line example:
esql -c -I$FGLDIR/include myext.ec gcc -c -I$FGLDIR/include -fPIC cinterf.c gcc -shared -o myext.so myext.o cinterf.o -L$FGLDIR/lib -lfgl \ -L$INFORMIXDIR/lib -L$INFORMIXDIR/lib/esql `esql -libs`
Windows command-line example (using Microsoft Visual C++):
esql -c myext.ec -I%FGLDIR%/include cl /DBUILDDLL /I%FGLDIR%/include /c cintref.c esql -target:dll -o myext.dll myext.obj cinterf.obj %FGLDIR%\lib\libfgl.lib
When using Informix esql, you link the extension library with Informix client libraries. These libraries will be shared by the extension module and the Informix database driver loaded by the Genero runtime system. Since both the extension functions and the runtime database driver use the same functions to execute SQL queries, you can share the current SQL connection opened in the Genero program to execute SQL queries in the extension functions. However, mixing connection management instructions (DATABASE, CONNECT TO) as well as database creation can produce unexpected results. For example you cannot do a CREATE DATABASE in your ESQL/C extension, and expect that the Genero BDL code can use it to execute SQL statements.
To make your C functions visible to the runtime system, you must define all the functions in the C Interface File. This is a C source file that defines the usrFunctions array. This array defines C functions that can be called from BDL. The last record of each array must be a line with all the elements set to 0, to define the end of the list.
The first member of a usrFunctions element is the BDL name of the function, provided as a character string. The second member is the C function symbol. Therefore, you typically do a forward declaration of the C functions before the usrFunctions array initializer. The third member is the number of BDL parameters passed thru the stack to the function. The last member is the number of values returned by the function; you can use -1 to specify a variable number of arguments.
01
#include <f2c/fglExt.h>02
03
int c_log(int);04
int c_cos(int);05
int c_sin(int);06
07
UsrFunction usrFunctions[]={08
{"log",c_log,1,1},09
{"cos",c_cos,1,1},10
{"sin",c_sin,1,1},11
{0,0,0,0}12
};
When creating a 42r program or 42x library, the Genero BDL linker needs to resolve all function names, including C extension functions. Thus, if extension modules are not specified explicitly in the source files with the IMPORT directive, you must give the extension modules with the -e option in the command line:
fgllink -e myext1,myext2,myext3 -o myprog.42r moduleA.42m moduleB.42m ...
The -e option is not needed when using the default userextension module, or if C extensions are specified with the IMPORT directive.
The runtime system can load several C-Extensions libraries, allowing you to properly split your libraries by defining each group of functions in separate C interface files.
Directories are searched for the C-Extensions libraries according to the FGLLDPATH environment variable rules. See environment variable definition for more details.
If the C-Extension library depends from other shared libraries, make sure that the library loader of the operating system can find theses shared objects: You may need to set the LD_LIBRARY_PATH environment variable on UNIX or the PATH environment variable on Windows to point to the directory where these other libraries are located.
There are three ways to bind a C Extension with the runtime system:
The IMPORT instruction allows you to declare an external module in a .4gl source file. It must appear at the beginning of the source file.
Note that the name of the module specified after the IMPORT keyword is converted to lowercase by the compiler. Therefore it is recommended to use lowercase file names only.
The compiler and the runtime system automatically know which C extensions must be loaded, based on the IMPORT instruction:
01
IMPORT mylib102
MAIN03
CALL myfunc1("Hello World") -- defined in mylib104
END MAIN
When the IMPORT instruction is used, no other action has to be taken at runtime: The module name is stored in the 42m pcode and is automatically loaded when needed.
For more details, see Importing modules.
Normally, all Genero BDL modules using a function from a C extension should now use the IMPORT instruction. This could be a major change in your sources.
To simplify migration of existing C extensions, the runtime system loads by default a module with the name userextension. Create this shared library with your existing C extensions, and the runtime system will load it automatically if it is in the directories specified by FGLLDPATH.
In some cases you need several C extension libraries, which are used by different group of programs, so you can't use the default userextension solution. However, you don't want to review all your sources in order to use the IMPORT instruction.
You can specify the C Extensions to be loaded by using the -e option of fglrun. The -e option takes a comma-separated list of module names, and can be specified multiple times in the command line. The next example loads five extension modules:
fglrun -e myext1,myext2,myext3 -e myext4,myext5 myprog.42r
By using the -e option, the runtime system loads the modules specified in the command line instead of loading the default userextension module.
To pass values between a C function and a program, the C function and the runtime system use the BDL stack. The int parameter of the C function defines the number of input parameters passed on the stack, and the function must return an int value defining the number of values returned on the stack. The parameters passed to the C function must be popped from the stack at the beginning of the C function, and the return values expected by the 4gl call must be pushed on the stack before leaving the C function. If you don't pop / push the specified number of parameters / return values, you corrupt the stack and get a fatal error.
The runtime system library includes a set of functions to retrieve the values passed as parameters on the stack. The following table shows the library functions provided to pop values from the stack into C buffers:
Function | BDL Type | Notes |
void popdate(int4 *dst); | DATE | 4-byte integer value corresponding to days since 12/31/1899. |
void popboolean(signed char *dst); | BOOLEAN | 1-byte integer boolean (1/0/-1) |
void popbigint(bigint *dst); | BIGINT | 8-byte integer value |
void popint(mint *dst); | INTEGER | System dependent integer value (int) |
void popshort(int2 *dst); | SMALLINT | 2-byte integer value |
void poplong(int4 *dst); | INTEGER | 4-byte integer value |
void popflo(float *dst); | SMALLFLOAT | 4-byte floating point value |
void popdub(double *dst); | FLOAT | 8-byte floating point value |
void popdec(dec_t *dst); | DECIMAL | See structure definition in $FGLDIR/include/f2c headers |
void popquote(char *dst, int len); | CHAR(n) | len = strlen(val)+1 (for the '/0') |
void popvchar(char *dst, int len); | VARCHAR(n) | len = strlen(val)+1 (for the '/0') |
void popdtime(dtime_t *dst, int size); | DATETIME | See structure definition in $FGLDIR/include/f2c headers size = TU_DTENCODE(start, end) |
void popinv(intrvl_t* dst, int size); | INTERVAL | See structure definition in $FGLDIR/include/f2c headers size = TU_IENCODE(len, start, end) |
void poplocator(loc_t **dst); | BYTE, TEXT | See structure definition in $FGLDIR/include/f2c headers Warning: this function pops the pointer of a loc_t object! |
When using a pop function, the value is copied from the stack to the local C variable and the value is removed from the stack.
In BDL, Strings (CHAR, VARCHAR) are not terminated by '\0'. Therefore, the C variable must have one additional character to store the '\0'. For example, the equivalent of a VARCHAR(100) in BDL is a char [101] in C.
To return a value from the C function, you must use one of the following functions provided in the runtime system library:
Function | BDL Type | Notes |
void pushdate(int4 val); | DATE | 4-byte integer value corresponding to days since 12/31/1899. |
void pushdec(const dec_t* val, const unsigned decp); | DECIMAL | See structure definition in $FGLDIR/include/f2c headers |
void pushboolean(const signed char); | BOOLEAN | 1-byte integer boolean (1/0/-1) |
void pushbigint(bigint val); | BIGINT | 8-byte integer value |
void pushint(mint val); | INTEGER | System dependent integer value (int) |
void pushlong(int4 val); | INTEGER | 4-byte integer value |
void pushshort(int2 val); | SMALLINT | 2-byte integer value |
void pushflo( float* val); | SMALLFLOAT | 4-byte floating point value. Warning: function takes a pointer! |
void pushdub( double* val); | FLOAT | 8-byte floating point value. Warning: function takes a pointer! |
void pushquote(const char *val, int l); | CHAR(n) | len = strlen(val) (without '\0') |
void pushvchar(const char *val, int l); | VARCHAR(n) | len = strlen(val) (without '\0') |
void pushdtime(const dtime_t *val); | DATETIME | See structure definition in $FGLDIR/include/f2c headers |
void pushinv(const intrvl_t *val); | INTERVAL | See structure definition in $FGLDIR/include/f2c headers |
When using a push function, the value of the C variable is copied at the top of the stack.
The following C types are used to write C Extensions for Genero BDL:
Type name | Description |
bigint | signed integer with a size of 8 bytes |
ubigint | unsigned integer with a size of 8 bytes |
int4 | signed integer with a size of 4 bytes |
uint4 | unsigned integer with a size of 4 bytes |
int2 | signed integer with a size of 2 bytes |
uint2 | unsigned integer with a size of 2 bytes |
int1 | signed integer with a size of 1 byte |
uint1 | unsigned integer with a size of 1 byte |
mint | signed machine-dependent C int |
muint | unsigned machine-dependent C int |
mlong | signed machine-dependent C long |
mulong | unsigned machine-dependent C long |
dec_t | DECIMAL data type structure |
dtime_t | DATETIME data type structure |
intrvl_t | INTERVAL data type structure |
loc_t | TEXT / BYTE Locator structure |
Basic data types such as bigint, int4 and int2 are provided to define variables that must hold BIGINT (bigint), SMALLINT (int2), INTEGER (int4) and DATE (int4) values. Standard char array can be used to hold CHAR and VARCHAR data.
No specific typedef exists for DATEs; you can use the int4 type to store a DATE value.
The dec_t structure is provided to hold DECIMAL and MONEY values.
The internals of dec_t structure can be ignored during C extension programming, because decimal API functions are provided to manipulate any aspects of a decimal.
The dtime_t structure holds a DATETIME value.
Before manipulating a dtime_t, you must initialize its qualifier qt_qual, by using the TU_DTENCODE macro, as in the following example:
01
dtime_t dt;02
dt.dt_qual = TU_DTENCODE(TU_YEAR, TU_SECOND);03
dtcvasc( "2004-02-12 12:34:56", &dt );
The intrvl_t structure holds an INTERVAL value.
Before manipulating a intrvl_t, you must initialize its qualifier in_qual, by using the TU_IENCODE macro, as in the following example:
01
intrvl_t in;02
in.in_qual = TU_IENCODE(5, TU_YEAR, TU_MONTH);03
incvasc( "65234-02", &in );
The loc_t structure is used to declare host variables for a TEXT/BYTE values (simple large objects). Because the potential size of the data can be quite large, this is a locator structure that contains information about the size and location of the TEXT/BYTE data, rather than containing the actual data.
The fields of the loc_t structure are:
Field name | Data Type | Description |
loc_indicator | int4 | Null indicator; a value of -1 indicates a null TEXT/BYTE value. Your program can set the field to indicate the insertion of a null value. Database client libraries set the value for selects and fetches. |
loc_type | int4 | Data type - SQLTEXT (for TEXT values) or SQLBYTES (for BYTE values). |
loc_size | int4 | Size of the TEXT/BYTE value in bytes; your program sets the size of the large object for insertions. Database client libraries set the size for selects and fetches. |
loc_loctype | int2 | Location - LOCMEMORY (in memory) or LOCFNAME (in a named file). Set loc_loctype after you declare the locator variable and before this declared variable receives the large object value. |
loc_buffer | char * | If loc_loctype is LOCMEMORY, this is the location of the TEXT/BYTE value; your program must allocate space for the buffer and store its address here. |
loc_bufsize | int4 | IF loc_loctype is LOCMEMORY, this is the size of the buffer loc_buffer; If you set loc_bufsize to -1, database client libraries will allocate the memory buffer for selects and fetches. Otherwise, it is assumed that your program will handle memory allocation and de-allocation. |
loc_fname | char * | IF loc_loc_type is LOCFNAME, this is the address of the pathname string that contains the file. |
Example:
01
loc_t *pb102
double ratio;03
char *source = NULL, *psource = NULL;04
int size;05
06
if (pb1->loc_loctype == LOCMEMORY) {07
psource = pb1->loc_buffer;08
size = pb1->loc_size;09
} else if (pb1->loc_loctype == LOCFNAME) {10
int fd;11
struct stat st;12
fd = open(pb1->loc_fname, O_RDONLY);13
fstat(fd, &st);14
size = st.st_size;15
psource = source = (char *) malloc(size);16
read(fd, source, size);17
close(fd);18
}
The following macros allow you to obtain the size information stored by the database server for a VARCHAR column:
Macro | Description |
MAXVCLEN (255) | Returns maximum number of characters allowed in a VARCHAR column |
VCMIN(size) | Returns minimum number of characters that you can store in a VARCHAR column |
VCLENGTH(len) | Returns length of the host variable |
VCMAX(size) | Returns maximum number of characters that you can store in a VARCHAR column |
VCSIZ(max, min) | Returns encoded size for the VARCHAR column |
Decimals are defined by an encoded length - the total number of significant digits (precision), and the significant digits to the right of the decimal (scale). The following macros handle decimal length:
Macro | Description |
DECLEN(m,n) | Calculates the minimum number of bytes necessary to hold a decimal ( m = precision, n = scale) |
DECLENGTH(length) | Calculates the minimum number of bytes necessary to hold a decimal, given the encoded length |
DECPREC(size) | Calculates a default precision, given the size (the number of bytes used to store a number) |
PRECTOT(length) | Returns the precision from an encoded length |
PRECDEC(length) | Returns the scale from an encoded length |
PRECMAKE(p,s) | Returns the encoded decimal length from a precision and scale |
Datetime and Interval need qualifiers (ex: YEAR TO MONTH) to complete the type definition. The following macros can be used to manage those qualifiers and set the qt_qual or in_qual members of dtime_t and intrvl_t structures.
Macro | Description |
TU_YEAR | Defines the YEAR qualifier |
TU_MONTH | Defines the MONTH qualifier |
TU_DAY | Defines the DAY qualifier |
TU_HOUR | Defines the HOUR qualifier |
TU_MINUTE | Defines the MINUTE qualifier |
TU_SECOND | Defines the SECOND qualifier |
TU_FRAC | Defines default FRACTION(3) qualifier |
TU_F1 | Defines the FRACTION(1) qualifier |
TU_F2 | Defines the FRACTION(2) qualifier |
TU_F3 | Defines the FRACTION(3) qualifier |
TU_F4 | Defines the FRACTION(4) qualifier |
TU_F5 | Defines the FRACTION(5) qualifier |
TU_END(q) | Returns the end qualifier of a composed qualifier |
TU_START(q) | Returns the start qualifier of a composed qualifier |
TU_LEN(q) | Returns the length in digits of a datetime qualifier |
TU_DTENCODE(q1,q2) | Build a datetime qualifier as DATETIME q1 TO q2 |
TU_IENCODE(len,q1,q2) | Build an interval qualifier as INTERVAL q1(len) TO q2 |
TU_CURRQUAL | Default qualifier used by current |
The following macros are used by functions like rsetnull(), risnull(), rtypalign(), rtypmsize():
SQL Types | |
Macro name | Description |
SQLBOOL | SQL BOOLEAN data type |
SQLINFXBIGINT | SQL BIGINT data type |
SQLCHAR | SQL CHAR data type |
SQLSMINT | SQL SMALLINT data type |
SQLINT | SQL INTEGER data type |
SQLFLOAT | SQL FLOAT data type |
SQLSMFLOAT | SQL SMALLFLOAT data type |
SQLDECIMAL | SQL DECIMAL data type |
SQLSERIAL | SQL SERIAL data type |
SQLDATE | SQL DATE data type |
SQLMONEY | SQL MONEY data type |
SQLDTIME | SQL DATETIME data type |
SQLBYTES | SQL BYTE data type |
SQLTEXT | SQL TEXT data type |
SQLVCHAR | SQL VARCHAR data type |
SQLINTERVAL | SQL INTERVAL data type |
SQLNCHAR | SQL NCHAR data type |
SQLNVCHAR | SQL NVARCHAR data type |
SQLINT8 | SQL INT8 data type |
SQLSERIAL8 | SQL SERIAL8 data type |
C Types | |
Macro name | Description |
CBOOLTYPE | C boolean data type (signed char) |
CBIGINTTYPE | C bigint data type (long long) |
CCHARTYPE | C char data type |
CSHORTTYPE | C short int data type |
CINTTYPE | C int4 data type |
CLONGTYPE | C long data type |
CFLOATTYPE | C float data type |
CDOUBLETYPE | C double data type |
CDECIMALTYPE | C dec_t data type |
CFIXCHARTYPE | C fixchar data type |
CSTRINGTYPE | C string data type |
CDATETYPE | C int4/date data type |
CMONEYTYPE | C dec_t data type |
CDTIMETYPE | C dtime_t data type |
CLOCATORTYPE | C loc_t data type |
CVCHARTYPE | C varchar data type |
CINVTYPE | C intrvl_t data type |
With C-Extensions you can call C functions from the program in the same way that you call normal functions.
The C functions that can be called from BDL must use the following signature:
int function-name( int )
Note that function-name must be written in lowercase letters. The fglcomp compiler converts all BDL functions names to lowercase.
The C function must be declared in the usrFunctions array in the C Interface File, as described below.
It is possible to call an BDL function from a C function, by using the fgl_call macro in your C function, as follows:
fgl_call ( function-name, nbparams );
function-name is the name of the BDL function to call, and nbparams is the number of parameters pushed on the stack for the BDL function.
Note that function-name must be written in lowercase letters (The fglcomp compiler converts all BDL functions names to lowercase)
The fgl_call macro is converted to a function that returns the number of values returned on the stack. The BDL function parameters must be pushed on the stack before the call, and the return values must be popped from the stack after returning. See Calling C functions from BDL for more details about push and pop library functions.
01
#include <stdio.h>02
#include <f2c/fglExt.h>03
int c_fct( int n )04
{05
int rc, r1, r2;06
pushint(123456);07
rc = fgl_call( fgl_fct, 1 );08
if (rc != 2) ... error ...09
popint(&r1);10
popint(&r2);11
return 0;12
}
In order to share the global variables declared in your BDL program, you must do the following:
1. Generate the .c and .h interface files by using fglcomp -G with the BDL module defining the global variables:
01
GLOBALS02
DEFINE g_name CHAR(100)03
END GLOBALS
fglcomp -G myglobals.4gl
This will produce two files named myglobals.h and myglobals.c.
2. In the C module, include the generated header file and use the global variables directly:
01
#include <string.h>02
#include <f2c/fglExt.h>03
#include "myglobals.h"04
05
int myfunc1(int c)06
{07
strcpy(g_name, "new name");08
return 0;09
}
3. When creating the C Extension library, compile and link with the myglobals.c generated file.
Tip: It is not recommended to use global variables, because it makes your code much more difficult to maintain. If you need persistent variables, use BDL module variables and write set/get functions that you can interface with.
This example shows how to create a C extension library on Linux using gcc. The command line options to compile and link shared libraries can change depending on the operating system and compiler/linker used.
01
#include <string.h>02
#include <f2c/fglExt.h>03
04
int fgl_split( int in_num );05
int fgl_split( int in_num )06
{07
char c1[101];08
char c2[101];09
char z[201];10
char *ptr_in;11
char *ptr_out;12
popvchar(z, 200); /* Getting input parameter */13
strcpy(c1, "");14
strcpy(c2, "");15
ptr_out = c1;16
ptr_in = z;17
while (*ptr_in != ' ' && *ptr_in != '\0')18
{19
*ptr_out = *ptr_in;20
ptr_out++;21
ptr_in++;22
}23
*ptr_out=0;24
ptr_in++;25
ptr_out = c2;26
while (*ptr_in != '\0')27
{28
*ptr_out = *ptr_in;29
ptr_out++;30
ptr_in++;31
}32
*ptr_out=0;33
pushvchar(c1, 100); /* Returning the first output parameter */34
pushvchar(c2, 100); /* Returning the second output parameter */35
return 2; /* Returning the number of output parameters (MANDATORY) */36
}
01
#include <f2c/fglExt.h>02
03
int fgl_split(int);04
05
UsrFunction usrFunctions[]={06
{ "fgl_split", fgl_split, 1, 2 },07
{ 0,0,0,0 }08
};
gcc -c -I $FGLDIR/include -fPIC split.c gcc -c -I $FGLDIR/include -fPIC splitext.c
gcc -shared -o libsplit.so split.o splitext.o -L$FGLDIR/lib -lfgl
01
IMPORT libsplit02
MAIN03
DEFINE str1, str2 VARCHAR(100)04
CALL fgl_split("Hello World") RETURNING str1, str205
DISPLAY "1: ", str106
DISPLAY "2: ", str207
END MAIN
fglcomp split.4gl
fglrun split
Function | Description |
bycmpr() | Compares two groups of contiguous bytes |
byleng() | Returns the number of bytes as significant characters in the specified string |
bycopy() | Copies a specified number of bytes to another location in memory |
byfill() | Fills a specified number of bytes in memory |
risnull() | Checks whether a given value is NULL |
rsetnull() | Sets a variable to NULL for a given data type |
rgetmsg() | Returns a message text |
rgetlmsg() | Returns a message text |
rtypalign() | Returns the position to align a variable at the proper boundary for its data type |
rtypmsize() | Returns the size in bytes required for a specified data type |
rtypname() | Returns the name of a specified data type |
rtypwidth() | Returns the minimum number of characters required to convert a specified data type to a character data type |
rdatestr() | Converts a date to a string |
rdayofweek() | Returns the week day of a date |
rdefmtdate() | Converts a string to a date by using a specific format |
ifx_defmtdate() | Converts a string to a date by using a specific format, with century option |
rfmtdate() | Converts a date to a string by using a specific format |
rjulmdy() | Extracts month, day and year from a date |
rleapyear() | Checks whether a year is a leap year |
rmdyjul() | Builds a date from month, day, year |
rstrdate() | Converts a string to a date |
ifx_strdate() | Converts a date to a string by using a specific format, with the century option |
rtoday() | Returns the current date |
ldchar() | Copies a fixed-length string into a null-terminated string without trailing spaces |
rdownshift() | Converts a string to lowercase characters |
rfmtdouble() | Formats a double value in a specified format |
rfmtint4() | Formats a 4-byte int value in a specified format |
rstod() | Converts a string to a double |
rstoi() | Converts a string to a 2-byte integer (but it takes an int pointer as parameter!) |
rstol() | Converts a string to a 4-byte integer (but it takes an long pointer as parameter!) |
rupshift() | Converts a string to uppercase characters |
stcat() | Concatenates a null-terminated string to another |
stchar() | Concatenates a null-terminated string to a fixed char |
stcmpr() | Compares two strings |
stcopy() | Copies a string into another |
stleng() | Returns the number of bytes of significant characters, including trailing spaces |
decadd() | Adds two decimals |
deccmp() | Compares two decimals |
deccopy() | Copies one decimal into another |
deccvasc() | Converts a string to a decimal |
deccvdbl() | Converts a double to a decimal |
deccvflt() | Converts a float to a decimal |
deccvint() | Converts a 4-byte integer to a decimal (parameter is a machine-dependent int pointer) |
deccvlong() | Converts a 4-byte integer to a decimal |
decdiv() | Divides a decimal by another decimal |
dececvt() | To convert a decimal value to a string value, specifying the length of the string (the total number of digits) |
decfcvt() | To convert a decimal value to a string value, specifying the number of digits to the right of the decimal point |
decmul() | Multiplies a decimal by another |
decround() | Rounds a decimal to the specified number of digits |
decsub() | Subtracts two decimals |
dectoasc() | Formats a decimal |
dectodbl() | Converts a decimal to a double |
dectoflt() | Converts a decimal to a float |
dectoint() | Converts a decimal to a 2-byte integer (parameter is machine-dependent int pointer) |
dectolong() | Converts a decimal to a 4-byte integer |
dectrunc() | Truncates a decimal to a given number of digits |
rfmtdec() | Formats a decimal |
dtaddinv() | Adds an interval to a datetime |
dtcurrent() | Returns the current datetime |
dtcvasc() | Converts a string in ISO format to a datetime |
ifx_dtcvasc() | Converts a string in ISO format to a datetime, with century option |
dtcvfmtasc() | Converts a string to a datetime by using a specific format |
ifx_dtcvfmtasc() | Converts a string to a datetime by using a specific format, with the century option |
dtextend() | Extends a datetime |
dtsub() | Subtracts a datetime from another datetime |
dtsubinv() | Subtracts an interval from a datetime |
dttoasc() | Formats a datetime in ISO format |
dttofmtasc() | Formats a datetime in a specified format |
ifx_dttofmtasc() | Formats a datetime in a specified format, with the century option |
incvasc() | Converts a string in ISO format to an interval |
incvfmtasc() | Converts a string to an interval by using a specific format |
intoasc() | Formats an interval in ISO format |
intofmtasc() | Formats an interval in a specified format |
invdivdbl() | Divides an interval by using a double |
invdivinv() | Divides an interval by using another interval |
invextend() | Extends an interval |
invmuldbl() | Multiplies an interval by a double |
To add two decimal values
mint decadd(dec_t *n1, struct decimal *n2, struct decimal *n3);
Code | Description |
0 | The operation was successful. |
-1200 | The operation resulted in overflow. |
-1201 | The operation resulted in underflow. |
To subtract two decimal values
mint decsub(dec_t *n1, struct decimal *n2, struct decimal *n3);
Code | Description |
0 | The operation was successful. |
-1200 | The operation resulted in overflow. |
-1201 | The operation resulted in underflow. |
To multiply two decimal values
int decmul(dec_t *n1, struct decimal *n2, struct decimal *n3);
Code | Description |
0 | The operation was successful. |
-1200 | The operation resulted in overflow. |
-1201 | The operation resulted in underflow. |
To divide one decimal value by another(n1 divided by n2)
mint decdiv(dec_t *n1, struct decimal *n2, struct decimal *n3);
Code | Description |
0 | The operation was successful. |
-1200 | The operation resulted in overflow. |
-1201 | The operation resulted in underflow. |
-1202 | The operation attempted to divide by zero. |
To compare two decimal values
mint deccmp(dec_t *n1, struct decimal *n2);
Code | Description |
0 | The two values are identical. |
1 | The first value is greater than the second value. |
-1 | The first value is less than the second value. |
-2 | Either value is null. |
To copy one decimal value to another
void deccopy(dec_t *n1, struct decimal *n2);
To convert a string value to a decimal
mint deccvasc(char *cp, mint len, dec_t *np);
Code | Description |
0 | The conversion was successful. |
-1200 | The number is too large to fit into a decimal type structure. |
To convert a double value to a decimal
mint deccvdbl(double dbl, dec_t *np);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert a 4-byte integer value to a decimal
mint deccvint(mint in, dec_t *np);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert a 4-byte integer value to a decimal
mint deccvlong(int4 lng, dec_t *np);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
Warning: Even if the function name is "deccvlong", it takes a 4-byte int as argument.
To convert a decimal value to a string value, specifying the length of the string (the total number of digits)
char *dececvt(dec_t *np, mint ndigit, mint *decpt, mint *sign);
This function returns a pointer to the result string. This string is temporary and has to be copied into your own string buffer.
To convert a decimal value to a string value, specifying the number of digits to the right of the decimal point
char *decfcvt(dec_t *np, mint ndigit, mint *decpt, mint *sign);
This function returns a pointer to the result string. This string is temporary and has to be copied into your own string buffer.
To round a decimal value, specifying the number of digits to the right of the decimal point
void decround(dec_t *np, mint dec_round);
To convert a decimal value to an ASCII string, specifying the length of the string and the number of digits to the right of the decimal point
mint dectoasc(dec_t *np, char *cp, mint len, mint right);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert a decimal value to a double value
mint dectodbl(dec_t *np, double *dblp);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert a decimal value to a SMALLINT equivalent (2-byte integer)
mint dectoint2(dec_t *np, mint *ip);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1200 | The magnitude of the decimal type number is greater than 32767. |
Warning: This functions takes a machine-dependent int pointer as argument (usually 4 bytes), but converts the decimal to a SMALLINT equivalent, with possible overflow errors.
To convert a decimal value to a long integer
mint dectolong(dec_t *np, int4 *lngp);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1200 | The magnitude of the decimal type number is greater than 2,147,483,647. |
Warning: Even if the function name is "dectolong", it takes a 4-byte int pointer as argument, and converts the decimal to an INTEGER equivalent.
To truncate a decimal value, specifying the number of digits to the right of the decimal point
void dectrunc(dec_t *np, mint trunc);
To convert a float to a decimal value
mint deccvflt(float source, dec_t *destination);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
mint dectoflt(dec_t *source, float *destination);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert a decimal value to a string having a specified format
int rfmtdec(dec_t *dec, char *format, char *outbuf);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1211 | The program ran out of memory (memory-allocation error). |
-1217 | The format string is too large. |
To compare two groups of contiguous bytes, for a specified length, byte-by-byte.
mint bycmpr(char *st1, char *st2, mint count);
Code | Description |
0 | The two groups of bytes are identical. |
1 | The st1 group of bytes is less than the st2 group. |
-1 | The st1 group of bytes is greater than the st2group. |
To copy a specified number of bytes to another location in memory
void bycopy(char *s1, char *s2, mint n);
Warning: Do not overwrite the memory areas adjacent to the destination area.
To fill a specified number of bytes with a specified character
void byfill(char *s1, mint n, char c);
Warning: Do not overwrite the memory areas adjacent to the destination area.
To check whether a variable is null
int risnull(int vtype, char *pcvar);
Code | Description |
1 | The variable does contain a null value. |
0 | The variable does not contain a null value. |
To set a variable to NULL
mint rsetnull(mint vtype, char *pcvar);
Code | Description |
0 | The operation was successful. |
<0 | The operation failed. |
Returns the error message for a specified error number, restricted to two-byte integers.
mint rgetmsg(int msgnum, char *s, mint maxsize);
Code | Description |
0 | The operation was successful. |
-1227 | Message file not found. |
-1228 | Message number not found in message file. |
-1231 | Cannot seek within message file. |
-1232 | Message buffer is too small. |
Warning: This function returns Informix specific messages; it will not work properly if the Informix client software is not installed.
Returns the error message for a specified error number, which can be a 4-byte integer.
int4 rgetlmsg(int msgnum, char *s, mint maxsize, mint *msg_length);
Code | Description |
0 | The operation was successful. |
-1227 | Message file not found. |
-1228 | Message number not found in message file. |
-1231 | Cannot seek within message file. |
-1232 | Message buffer is too small. |
Warning: This function returns Informix specific messages; it will not work properly if the Informix client software is not installed.
Returns the position to align a variable at the proper boundary for its data type
mlong rtypalign(mlong pos, mint datatype)
Code | Description |
>0 | The return value is the offset of the next proper boundary for a variable of type data type. |
Returns the size in bytes required for a specified data type
mint rtypmsize(mint datatype, mint length)
Code | Description |
0 | The datatype is not a valid SQL type. |
>0 | The return value is the number of bytes that the data type requires. |
Returns a pointer to a null-terminated string containing the name of the data type
char *rtypname(mint datatype)
The rtypname function returns a pointer to a string that contains the name of the data type specified datatype.
If datatype is an invalid value, rtypname() returns a null string (" ").
Returns the minimum number of characters required to convert a specified data type to a character data type
mint rtypwidth(mint datatype, mint length)
Code | Description |
0 | The sqltype is not a valid SQL data type. |
>0 | Minimum number of characters that the sqltype data type requires. |
To convert a date that is in the native database date format to a string
mint rdatestr(int4 jdate, char *str);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1210 | The internal date could not be converted to the character string format. |
-1212 | Data conversion format must contain a month, day, or year component. |
The DBDATE environment variable specifies the data conversion format.
Returns the day of the week of a date that is in the native database format
mint rdayofweek(int4 jdate);
Code | Description |
<0 | Invalid date value |
0 | Sunday |
1 | Monday |
2 | Tuesday |
3 | Wednesday |
4 | Thursday |
5 | Friday |
6 | Saturday |
To convert a string in a specified format to the native database date format
mint rdefmtdate(int4 *pdate, char *fmt, char *input);
Code | Description |
0 | The operation was successful. |
-1204 | The input parameter specifies an invalid year. |
-1205 | The input parameter specifies an invalid month. |
-1206 | The input parameter specifies an invalid day. |
-1209 | Because input does not contain delimiters between the year,month,and day, the length of input must be exactly six or eight bytes. |
-1212 | fmt does not specify a year, a month, and a day. |
To convert a date that is in the native database date format to a string having a specified format
mint rfmtdate(int4 jdate, char *fmt, char *result);
Code | Description |
0 | The operation was successful. |
-1210 | The internal date cannot be converted to month-day-year format. |
-1211 | The program ran out of memory (memory-allocation error). |
-1212 | Format string is NULL or invalid. |
To create an array of short integer values representing year, month, and day from a date that is in the native database date format
mint rjulmdy(int4 jdate, int2 mdy[3]);
Code | Description |
1 | The year is a leap year. |
0 | The operation was successful. |
<0 | The operation failed. |
-1210 | The internal date could not be converted to the character string format. |
To determine whether the value passed as a parameter is a leap year; returns 1 when TRUE.
mint rleapyear(mint year);
Code | Description |
1 | The year is a leap year. |
0 | The year is not a leap year. |
To create a value in the native database date format from an array of short integer values representing month, day, and year
mint rmdyjul(int2 mdy[3], int4 *jdate);
Code | Description |
0 | The operation was successful. |
-1204 | The mdy[2] variable contains an invalid year. |
-1205 | The mdy[0] variable contains an invalid month. |
-1206 | The mdy[1] variable contains an invalid day. |
To convert a character string to the native database date format.
mint rstrdate(char *str, int4 *jdate);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1204 | The str parameter specifies an invalid year. |
-1205 | The str parameter specifies an invalid month. |
-1206 | The str parameter specifies an invalid day. |
-1212 | Data conversion format must contain a month, day, or year component. DBDATE specifies the data conversion format. |
-1218 | The date specified by the str argument does not properly represent a date. |
The DBDATE environment variable specifies the data conversion format.
Returns the system date in the internal database date format
void rtoday(int4 *today);
To convert a string in a specified format to the native database date format; allows you to specify the century setting for two-digit dates.
mint ifx_defmtdate(int4 *pdate, char *fmt, char *input, char
c);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1204 | The str parameter specifies an invalid year. |
-1205 | The str parameter specifies an invalid month. |
-1206 | The str parameter specifies an invalid day. |
-1212 | Data conversion format must contain a month, day, or year component. DBDATE specifies the data conversion format. |
-1209 | Because *input does not contain delimiters between the year, month, and day, the length of *input must be exactly six or eight bytes. |
To convert a character string to the native database date format; allows you to specify the century setting for two-digit dates.
mint ifx_strdate(char *str, int4 *jdate, char c);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1204 | The str parameter specifies an invalid year. |
-1205 | The str parameter specifies an invalid month. |
-1206 | The str parameter specifies an invalid day. |
-1212 | Data conversion format must contain a month, day, or year component. DBDATE specifies the data conversion format. |
-1218 | The date specified by the str argument does not properly represent a date. |
The DBDATE environment variable specifies the data conversion format.
Returns the number bytes as significant characters in the specified string; omitting trailing blanks
mint byleng(char *s1, mint count);
Number of bytes.
To copy a fixed-length string into a null-terminated string without trailing blanks
void ldchar(char *from, mint count, char *to);
To convert all the characters in a null-terminated string to lowercase.
void rdownshift(char *s);
To convert all the characters in a null-terminated string to uppercase.
void rupshift(char *s);
To concatenate one null-terminated string to another (src is added to the end of dst).
void stcat(char *src, char *dst);
To copy a string to another location
void stcopy(char *src, char *dst);
Returns the number of bytes of significant characters, including trailing blanks
mint stleng(char *src);
Number of bytes.
To compare two strings
mint stcmpr(char *s1, char *s2);
Code | Description |
0 | The two strings are identical. |
<0 | The first string is less than the second string. |
>0 | The first string is greater than the second string. |
To copy a null-terminated string into a fixed-length string
void stchar(char *from, char *to, mint count);
To convert a string to a double.
mint rstod(char *str, double *val);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert a string to a 2-byte integer.
mint rstoi(char *str, mint *val);
Warning: The function takes a machine-dependent int pointer (usually 4 bytes), but the function converts to a 2 byte integer (overflow error may occur if string does not represent a valid 2-byte integer).
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert a string to a 4-byte integer (machine dependent)
mint rstol(char *str, mlong *val);
Warning: The function takes a machine-dependent long pointer (4 bytes on 32b and 8 bytes on 64b architectures), but the function converts to a 4-byte integer (overflow error may occur if string does not represent a valid 2 byte integer).
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert a double value to a character string having a specified format.
mint rfmtdouble(double dvalue, char *format, char *outbuf);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1211 | The program ran out of memory (memory-allocation error). |
-1217 | The format string is too large. |
To convert a 4-byte integer to a character string having a specified format
mint rfmtint4(int4 lvalue, char *format, char *outbuf);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1211 | The program ran out of memory (memory-allocation error). |
-1217 | The format string is too large. |
To add an interval value to a datetime value
mint dtaddinv(dtime_t *d, intrvl_t *i, dtime_t *r);
Code | Description |
0 | The addition was successful. |
<0 | The addition failed. |
Returns the current date and time
void dtcurrent(dtime_t *d);
To convert an ASCII-standard character string to a datetime value
mint dtcvasc(char *str, dtime_t *d);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1260 | It is not possible to convert between the specified types. |
-1261 | Too many digits in the first field of datetime or interval. |
-1262 | Non-numeric character in datetime or interval. |
-1263 | A field in a datetime or interval value is out of range or incorrect. |
-1264 | Extra characters exist at the end of a datetime or interval. |
-1265 | Overflow occurred on a datetime or interval operation. |
-1266 | A datetime or interval value is incompatible with the operation. |
-1267 | The result of a datetime computation is out of range. |
-1268 | A parameter contains an invalid datetime qualifier. |
To convert a character string to a datetime value; allows you to specify the century setting for 2-digit years
mint ifx_dtcvasc(char *str, dtime_t *d, char c);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1260 | It is not possible to convert between the specified types. |
-1261 | Too many digits in the first field of datetime or interval. |
-1262 | Non-numeric character in datetime or interval. |
-1263 | A field in a datetime or interval value is out of range or incorrect. |
-1264 | Extra characters exist at the end of a datetime or interval. |
-1265 | Overflow occurred on a datetime or interval operation. |
-1266 | A datetime or interval value is incompatible with the operation. |
-1267 | The result of a datetime computation is out of range. |
-1268 | A parameter contains an invalid datetime qualifier. |
To convert a character string to a datetime value, specifying the format of the string
mint dtcvfmtasc(char *input, char *fmt, dtime_t *d);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert a character string to a datetime value, specifying the format of the string
mint ifx_dtcvfmtasc(char *input, char *fmt, dtime_t *d, char c);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To copy a datetime value id to the datetime value od, adding or dropping fields based on the qualifier of od
mint dtextend(dtime_t *id, dtime_t *od);
Code | Description |
0 | The operation was successful. |
<0 | The operation failed. |
-1268 | A parameter contains an invalid datetime qualifier |
To subtract one datetime value from another
mint dtsub(dtime_t *d1, dtime_t *d2, intrvl_t *i);
Code | Description |
0 | The subtraction was successful. |
<0 | The subtraction failed. |
To subtract an interval value from a datetime value
mint dtsubinv(dtime_t *d, intrvl_t *i, dtime_t *r);
Code | Description |
0 | The subtraction was successful. |
<0 | The subtraction failed. |
To convert a datetime value to an ANSI-standard character string
mint dttoasc(dtime_t *d, char *str);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
Field | Field Size |
year | four digits |
fraction of datetime | as specified by precision |
all other fields | two digits |
For example, datetime year to fraction(5):
YYYY-MM-DD HH:MM:SS.FFFFF
To convert a datetime value to a character string, specifying the format
mint dttofmtasc(dtime_t *d, char *output, mint len, char *fmt);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert a datetime value to a character string, specifying the format
mint ifx_dttofmtasc(dtime_t *d, char *output, mint len, char *fmt, char c);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert an ANSI-standard character string to an interval value
mint incvasc(char *str, intrvl_t *i);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1260 | It is not possible to convert between the specified types. |
-1261 | Too many digits in the first field of datetime or interval. |
To convert a character string having the specified format to an interval value
mint incvfmtasc(char *input, char *fmt, intrvl_t *intvl);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert an interval value to an ANSI-standard character string
mint intoasc(intrvl_t *i, char *str);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To convert an interval value to a character string, specifying the format
mint intofmtasc(intrvl_t *i, char *output, mint len, char *fmt);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
To divide an interval value by a numeric value
mint invdivdbl(intrvl_t *iv, double dbl, intrvl_t *ov);
Code | Description |
0 | The division was successful. |
<0 | The division failed. |
-1200 | A numeric value is too large (in magnitude). |
-1201 | A numeric value is too small (in magnitude). |
-1202 | The dbl parameter is zero (0). |
To divide one interval value by another
mint invdivinv(intrvl_t *i1, intrvl_t *i2, double *res);
Code | Description |
0 | The division was successful. |
<0 | The division failed. |
-1200 | A numeric value is too large (in magnitude). |
-1201 | A numeric value is too small (in magnitude). |
-1266 | An interval value is incompatible with the operation. |
-1268 | A parameter contains an invalid interval qualifier. |
To copy an interval value i to the interval value o, adding or dropping fields based on the qualifier of o
mint invextend(intrvl_t *i, intrvl_t *o);
Code | Description |
0 | The conversion was successful. |
<0 | The conversion failed. |
-1266 | An interval value is incompatible with the operation. |
-1268 | A parameter contains an invalid interval qualifier. |
To multiply an interval value by a numeric value
mint invmuldbl(intrvl_t *iv, double dbl, intrvl_t *ov);
Code | Description |
0 | The multiplication was successful. |
<0 | The multiplication failed. |
-1200 | A numeric value is too large (in magnitude). |
-1201 | A numeric value is too small (in magnitude). |
-1266 | An interval value is incompatible with the operation. |
-1268 | A parameter contains an invalid interval qualifier. |
A numeric-formatting mask specifies a format to apply to some numeric value. This mask is a combination of the following formatting directives:
Character | Description |
* | This character fills with asterisks any positions in the display field that would otherwise be blank. |
& | This character fills with zeros any positions in the display field that would otherwise be blank. |
# | This character changes leading zeros to blanks. Use this character to specify the maximum leftward extent of a field. |
< | This character left-justifies the numbers in the display field. It changes leading zeros to a null string. |
, |
This character indicates the symbol that separates groups of three digits (counting leftward from the units position) in the whole-number part of the value. By default, this symbol is a comma. You can set the symbol with the DBMONEY environment variable. In a formatted number, this symbol appears only if the whole-number part of the value has four or more digits. |
. |
This character indicates the symbol that separates the whole-number part of a money value from the fractional part. By default, this symbol is a period. You can set the symbol with the DBMONEY environment variable. You can have only one period in a format string. |
- |
This character is a literal. It appears as a minus sign when the expression is less than zero. When you group several minus signs in a row, a single minus sign floats to the rightmost position that it can occupy; it does not interfere with the number and its currency symbol. |
+ |
This character is a literal. It appears as a plus sign when the expression is greater than or equal to zero and as a minus sign when expr1 is less than zero. When you group several plus signs in a row, a single plus or minus sign floats to the rightmost position that it can occupy; it does not interfere with the number and its currency symbol. |
( |
This character is a literal. It appears as a left parenthesis to the left of a negative number. It is one of the pair of accounting parentheses that replace a minus sign for a negative number. When you group several in a row, a single left parenthesis floats to the rightmost position that it can occupy; it does not interfere with the number and its currency symbol. |
) | This is one of the pair of accounting parentheses that replace a minus sign for a negative value. |
$ |
This character displays the currency symbol that appears at the front of the numeric value. By default, the currency symbol is the dollar sign ($). You can set the currency symbol with the DBMONEY environment variable. When you group several dollar signs in a row, a single currency symbol floats to the rightmost position that it can occupy; it does not interfere with the number. |
Any other characters in the formatting mask are reproduced literally in the result.
Mask | Numeric value | Formatted String |
-##,###.## |
-12345.67 12345.67 113.11 |
-12,234.67 b12,345.67 bbbb113.11 |
##,###.## |
-12345.67 12345.67 |
12,345.67 12,345.67 |
--,---.&& | -445.67 | bb-445.67 |
$$,$$$.&& |
2345.67 445.67 |
$2,345.67 bb$445.67 |
A date-formatting mask specifies a format to apply to some date value. This mask is a combination of the following formatting directives:
Character | Description |
dd | Day of the month as a two-digit number (01 through 31) |
ddd | Day of the week as a three-letter abbreviation (Sun through Sat) |
mm | Month as a two-digit number (01 through 12) |
mmm | Month as a three-letter abbreviation (Jan through Dec) |
yy | Year as a two-digit number (00 through 99) |
yyyy | Year as a four-digit number (0001 through 9999) |
ww | Day of the week as a two-digit number (00 for Sunday, 01 for Monday, 02 for Tuesday … 06 for Saturday) |
Any other characters in the formatting mask are reproduced literally in the result.
A datetime-formatting mask specifies a format to apply to some datetime value. This mask is a combination of the following formatting directives:
Directive | Description |
Date related directives | |
%a | Identifies abbreviated weekday name as defined in locale. |
%A | Identifies full weekday name as defined in locale. |
%b | Identifies abbreviated month name as defined in locale. |
%B | Identifies full month name as defined in locale. |
%C | Identifies century number (year divided by 100 and truncated to an integer) |
%d | Identifies the day of the month (01 to 31). Single digit is preceded by zero. |
%D | Identifies commonly used date format (%m/%d/%y). |
%e | Identifies the day of the month as a number (1 to 31). Single digit is preceded by space. |
%h | Same as %b. |
%iy | Identifies the year as a 2-digit number (00 to 99). |
%iY | Identifies the year as a 4-digit number (0000 to 9999). |
%m | Identifies the month as a number (01 to 12). Single digit is preceded by zero. |
%w | Identifies the weekday as a number (0 to 6), where 0 is the locale equivalent of Sunday. |
%x | Identifies a special date representation that the locale defines. |
%y | Identifies the year as a 2-digit number (00 to 99). |
%Y | Identifies the year as a 4-digit number (0000 to 9999). |
Time related directives | |
%c | Identifies special date/time representation that locale defines. |
%Fn | Identifies value of the fraction of a second, with precision specified by integer n. Range of n
is 0 to 5. Note that the %Fn directive includes the dot character: For example, if you want to specify a format a time value as 23:35:17.9123, you must use %H:%M:%S%F4 |
%H | Identifies the hour as 24-hour clock integer (00-23). |
%I | Identifies the hour as 12-hour clock integer (00-12). |
%M | Identifies the minute as an integer (00-59). |
%p | Identifies AM or PM equivalent as defined in locale. |
%r | Identifies commonly used time representation for a 12-hour clock. |
%R | Identifies commonly used time representation for a 24-hour clock (%H:%M). |
%S | Identifies the second as an integer (00-61). Second can be up to 61 instead of 59 to allow for the occasional leap second and double leap second. |
%T | Identifies commonly used time format (%H:%M:%S). |
%X | Identifies commonly used time representation as defined in the locale. |
Specials | |
%% | Identifies the % character. |
%n | Identifies a new-line character. |
%t | Identifies a TAB character. |
Any other characters in the formatting mask are reproduced literally in the result.
An interval-formatting mask specifies a format to apply to some interval value. This mask must be combination of Class 1 interval or Class 2 interval formatting directives:
Character | Description |
Class 1 formatting directives ( YEAR to MONTH ) | |
%C | Identifies century number (year divided by 100 and truncated to an integer) |
%iy | Identifies the year as a 2-digit number (00 to 99). |
%iY | Identifies the year as a 4-digit number (0000 to 9999). |
%m | Identifies the month as a number (01 to 12). Single digit is preceded by zero. |
%y | Identifies the year as a 2-digit number (00 to 99). |
%Y | Identifies the year as a 4-digit number (0000 to 9999). |
Class 2 formatting directives ( DAY to FRACTION ) | |
%a | Identifies abbreviated weekday name as defined in locale. |
%A | Identifies full weekday name as defined in locale. |
%d | Identifies the day of the month (01 to 31). Single digit is preceded by zero. |
%e | Identifies the day of the month as a number (1 to 31). Single digit is preceded by space. |
%Fn | Identifies value of the fraction of a second, with precision specified by integer n. Range of n is 0 to 5. |
%H | Identifies the hour as 24-hour clock integer (00-23). |
%I | Identifies the hour as 12-hour clock integer (00-12). |
%M | Identifies the minute as an integer (00-59). |
%S | Identifies the second as an integer (00-61). Second can be up to 61 instead of 59 to allow for the occasional leap second and double leap second. |
%w | Identifies the weekday as a number (0 to 6), where 0 is the locale equivalent of Sunday. |
Specials | |
%% | Identifies the % character. |
%n | Identifies a new-line character. |
%t | Identifies a TAB character. |