-
+
not really useful in real applications. This section explains in
detail how you can pass data between your C program and the
embedded SQL statements using a simple mechanism called
- host variables.
+ host variables. In an embedded SQL program we
+ consider the SQL statements to be guests in the C
+ program code which is the host language. Therefore
+ the variables of the C program are called host
+ variables.
This style of inserting C variables in SQL statements works
- anywhere a value expression is expected in an SQL statement. In
- the SQL environment we call the references to C variables
- host variables.
+ anywhere a value expression is expected in an SQL statement.
Between those lines, there must be normal C variable declarations,
such as
-int x;
+int x = 4;
char foo[16], bar[16];
+
+ As you can see, you can optionally assign an initial value to the variable.
+ The variable's scope is determined by the location of its declaring
+ section within the program.
+ You can also declare variables with the following syntax which implicitly
+ creates a declare section:
+EXEC SQL int i = 4;
You can have as many declare sections in a program as you like.
a DECLARE> section. Otherwise the preprocessor cannot
handle these types since it does not know the definition.
+
+
+
+
Different types of host variables
+ As a host variable you can also use arrays, typedefs, structs and
+ pointers. Moreover there are special types of host variables that exist
+ only in ecpg.
+
- The special type VARCHAR
- is converted into a named struct> for every variable. A
- declaration like
+ A few examples on host variables:
+
+
+ Arrays
+
+ One of the most common uses of an array declaration is probably the
+ allocation of a char array as in
+EXEC SQL BEGIN DECLARE SECTION;
+ char str[50];
+EXEC SQL END DECLARE SECTION;
+
+ Note that you have to take care of the length for yourself. If you use
+ this host variable as the target variable of a query which returns a
+ string with more than 49 characters, a buffer overflow occurs.
+
+
+
+
+
+ Typedefs
+
+ Use the typedef keyword to map new types to already
+ existing types.
+EXEC SQL BEGIN DECLARE SECTION;
+ typedef char mychartype[40];
+ typedef long serial_t;
+EXEC SQL END DECLARE SECTION;
+
+ Note that you could also use
+EXEC SQL TYPE serial_t IS long;
+
+ This declaration does not need to be part of a declare section.
+
+
+
+
+
+ Pointers
+
+ You can declare pointers to the most common types. Note however that
+ you can not use pointers as target variables of queries without
+ auto-allocation. See for more
+ information on auto-allocation.
+
+EXEC SQL BEGIN DECLARE SECTION;
+ int *intp;
+ char **charp;
+EXEC SQL END DECLARE SECTION;
+
+
+
+
+
+ Special types of variables
+
+ ecpg contains some special types that help you to interact easily with
+ data from the SQL server. For example it has implemented support for
+ the varchar, numeric, date, timestamp and interval types.
+ contains basic functions to deal with
+ those types, such that you do not need to send a query to the SQL
+ server just for adding an interval to a timestamp for example.
+
+ The special type VARCHAR
+ is converted into a named struct> for every variable. A
+ declaration like
VARCHAR var[180];
- is converted into
+ is converted into
struct varchar_var { int len; char arr[180]; } var;
- This structure is suitable for interfacing with SQL datums of type
- varchar.
+ This structure is suitable for interfacing with SQL datums of type
+ varchar.
+
+
+
+
-
Indicators
-
+
Indicators
+
+ The examples above do not handle null values. In fact, the
+ retrieval examples will raise an error if they fetch a null value
+ from the database. To be able to pass null values to the database
+ or retrieve null values from the database, you need to append a
+ second host variable specification to each host variable that
+ contains data. This second host variable is called the
+ indicator and contains a flag that tells
+ whether the datum is null, in which case the value of the real
+ host variable is ignored. Here is an example that handles the
+ retrieval of null values correctly:
+EXEC SQL BEGIN DECLARE SECTION;
+VARCHAR val;
+int val_ind;
+EXEC SQL END DECLARE SECTION:
+
+ ...
+
+EXEC SQL SELECT b INTO :val :val_ind FROM test1;
+
+ The indicator variable val_ind will be zero if
+ the value was not null, and it will be negative if the value was
+ null.
+
+
+ The indicator has another function: if the indicator value is
+ positive, it means that the value is not null, but it was
+ truncated when it was stored in the host variable.
+
+
+
+
+
+
Dynamic SQL
+
+ In many cases, the particular SQL statements that an application
+ has to execute are known at the time the application is written.
+ In some cases, however, the SQL statements are composed at run time
+ or provided by an external source. In these cases you cannot embed
+ the SQL statements directly into the C source code, but there is a
+ facility that allows you to call arbitrary SQL statements that you
+ provide in a string variable.
+
+
+ The simplest way to execute an arbitrary SQL statement is to use
+ the command EXECUTE IMMEDIATE. For example:
+EXEC SQL BEGIN DECLARE SECTION;
+const char *stmt = "CREATE TABLE test1 (...);";
+EXEC SQL END DECLARE SECTION;
+
+EXEC SQL EXECUTE IMMEDIATE :stmt;
+
+ You may not execute statements that retrieve data (e.g.,
+ SELECT) this way.
+
+
+ A more powerful way to execute arbitrary SQL statements is to
+ prepare them once and execute the prepared statement as often as
+ you like. It is also possible to prepare a generalized version of
+ a statement and then execute specific versions of it by
+ substituting parameters. When preparing the statement, write
+ question marks where you want to substitute parameters later. For
+ example:
+EXEC SQL BEGIN DECLARE SECTION;
+const char *stmt = "INSERT INTO test1 VALUES(?, ?);";
+EXEC SQL END DECLARE SECTION;
+
+EXEC SQL PREPARE mystmt FROM :stmt;
+ ...
+EXEC SQL EXECUTE mystmt USING 42, 'foobar';
+
+ If the statement you are executing returns values, then add an
+ INTO clause:
+EXEC SQL BEGIN DECLARE SECTION;
+const char *stmt = "SELECT a, b, c FROM test1 WHERE a > ?";
+int v1, v2;
+VARCHAR v3;
+EXEC SQL END DECLARE SECTION;
+
+EXEC SQL PREPARE mystmt FROM :stmt;
+ ...
+EXEC SQL EXECUTE mystmt INTO v1, v2, v3 USING 37;
+
+ An EXECUTE command may have an
+ INTO clause, a USING clause,
+ both, or neither.
+
+
+ When you don't need the prepared statement anymore, you should
+ deallocate it:
+EXEC SQL DEALLOCATE PREPARE name;
+
+
+
+
+
+
+
pgtypes library
+
+ The pgtypes library maps
PostgreSQL database
+ types to C equivalents that can be used in C programs. It also offers
+ functions to do basic calculations with those types within C, i.e. without
+ the help of the
PostgreSQL server. See the
+ following example:
+EXEC SQL BEGIN DECLARE SECTION;
+ date date1;
+ timestamp ts1, tsout;
+ interval iv1;
+ char *out;
+EXEC SQL END DECLARE SECTION;
+
+PGTYPESdate_today(&date1);
+EXEC SQL SELECT started, duration INTO :ts1, :iv1 FROM datetbl WHERE d=:date1;
+PGTYPEStimestamp_add_interval(&ts1, &iv1, &tsout);
+out = PGTYPEStimestamp_to_asc(&tsout);
+printf("Started + duration: %s\n", out);
+free(out);
+
+
+
+
+
The numeric type
+ The numeric type offers to do calculations with arbitrary precision. See
+ for the equivalent type in the
+
PostgreSQL> server. Because of the arbitrary precision this
+ variable needs to be able to expand and shrink dynamically. That's why you
+ can only create variables on the heap by means of the
+ PGTYPESnumeric_new> and PGTYPESnumeric_free>
+ functions. The decimal type, which is similar but limited in the precision,
+ can be created on the stack as well as on the heap.
+
+ The following functions can be used to work with the numeric type:
+
+
+ PGTYPESnumeric_new
+
+ Request a pointer to a newly allocated numeric variable.
+
+numeric *PGTYPESnumeric_new(void);
+
+
+
+
+
+
+ PGTYPESnumeric_free
+
+ Free a numeric type, release all of its memory.
+
+void PGTYPESnumeric_free(numeric *var);
+
+
+
+
+
+
+ PGTYPESnumeric_from_asc
+
+ Parse a numeric type from its string notation.
+
+numeric *PGTYPESnumeric_from_asc(char *str, char **endptr);
+
+ Valid formats are for example:
+ -2,
+ .794,
+ +3.44,
+ 592.49E07 or
+ -32.84e-4.
+ If the value could be parsed successfully, a valid pointer is returned,
+ else the NULL pointer. At the moment ecpg always parses the complete
+ string and so it currently does not support to store the address of the
+ first invalid character in *endptr. You can safely
+ set endptr to NULL.
+
+
+
+
+
+ PGTYPESnumeric_to_asc
+
+ Returns a pointer to a malloced string that contains the string
+ representation of the numeric type num.
+
+char *PGTYPESnumeric_to_asc(numeric *num, int dscale);
+
+ The numeric value will be printed with dscale decimal
+ digits, with rounding applied if necessary.
+
+
+
+
+
+ PGTYPESnumeric_add
+
+ Add two numeric variables into a third one.
+
+int PGTYPESnumeric_add(numeric *var1, numeric *var2, numeric *result);
+
+ The function adds the variables var1 and
+ var2 into the result variable
+ result.
+ The function returns 0 on success and -1 in case of error.
+
+
+
+
+
+ PGTYPESnumeric_sub
+
+ Subtract two numeric variables and return the result in a third one.
+
+int PGTYPESnumeric_sub(numeric *var1, numeric *var2, numeric *result);
+
+ The function subtracts the variable var2 from
+ the variable var1. The result of the operation is
+ stored in the variable result.
+ The function returns 0 on success and -1 in case of error.
+
+
+
+
+
+ PGTYPESnumeric_mul
+
+ Multiply two numeric variables and return the result in a third one.
+
+int PGTYPESnumeric_mul(numeric *var1, numeric *var2, numeric *result);
+
+ The function multiplies the variables var1 and
+ var2. The result of the operation is stored in the
+ variable result.
+ The function returns 0 on success and -1 in case of error.
+
+
+
+
+
+ PGTYPESnumeric_div
+
+ Divide two numeric variables and return the result in a third one.
+
+int PGTYPESnumeric_div(numeric *var1, numeric *var2, numeric *result);
+
+ The function divides the variables var1 by
+ var2. The result of the operation is stored in the
+ variable result.
+ The function returns 0 on success and -1 in case of error.
+
+
+
+
+
+ PGTYPESnumeric_cmp
+
+ Compare two numeric variables.
+
+int PGTYPESnumeric_cmp(numeric *var1, numeric *var2)
+
+ This function compares two numeric variables. In case of error,
+ INT_MAX is returned. On success, the function
+ returns one of three possible results:
+
+
+ 1, if var1> is bigger than var2>
+
+
+
+ -1, if var1> is smaller than var2>
+
+
+
+ 0, if var1> and var2> are equal
+
+
+
+
+
+
+
+
+ PGTYPESnumeric_from_int
+
+ Convert an int variable to a numeric variable.
+
+int PGTYPESnumeric_from_int(signed int int_val, numeric *var);
+
+ This function accepts a variable of type signed int and stores it
+ in the numeric variable var>. Upon success, 0 is returned and
+ -1 in case of a failure.
+
+
+
+
+
+ PGTYPESnumeric_from_long
+
+ Convert a long int variable to a numeric variable.
+
+int PGTYPESnumeric_from_long(signed long int long_val, numeric *var);
+
+ This function accepts a variable of type signed long int and stores it
+ in the numeric variable var>. Upon success, 0 is returned and
+ -1 in case of a failure.
+
+
+
+
+
+ PGTYPESnumeric_copy
+
+ Copy over one numeric variable into another one.
+
+int PGTYPESnumeric_copy(numeric *src, numeric *dst);
+
+ This function copies over the value of the variable that
+ src points to into the variable that dst>
+ points to. It returns 0 on success and -1 if an error occurs.
+
+
+
+
+
+ PGTYPESnumeric_from_double
+
+ Convert a variable of type double to a numeric.
+
+int PGTYPESnumeric_from_double(double d, numeric *dst);
+
+ This function accepts a variable of type double and stores the result
+ in the variable that dst> points to. It returns 0 on success
+ and -1 if an error occurs.
+
+
+
+
+
+ PGTYPESnumeric_to_double
+
+ Convert a variable of type numeric to double.
+
+int PGTYPESnumeric_to_double(numeric *nv, double *dp)
+
+ The function converts the numeric value from the variable that
+ nv> points to into the double variable that dp> points
+ to. It retuns 0 on success and -1 if an error occurs, including
+ overflow. On overflow, the global variable errno> will be set
+ to PGTYPES_NUM_OVERFLOW> additionally.
+
+
+
+
+
+ PGTYPESnumeric_to_int
+
+ Convert a variable of type numeric to int.
+
+int PGTYPESnumeric_to_int(numeric *nv, int *ip);
+
+ The function converts the numeric value from the variable that
+ nv> points to into the integer variable that ip>
+ points to. It retuns 0 on success and -1 if an error occurs, including
+ overflow. On overflow, the global variable errno> will be set
+ to PGTYPES_NUM_OVERFLOW> additionally.
+
+
+
+
+
+ PGTYPESnumeric_to_long
+
+ Convert a variable of type numeric to long.
+
+int PGTYPESnumeric_to_long(numeric *nv, long *lp);
+
+ The function converts the numeric value from the variable that
+ nv> points to into the long integer variable that
+ lp> points to. It retuns 0 on success and -1 if an error
+ occurs, including overflow. On overflow, the global variable
+ errno> will be set to PGTYPES_NUM_OVERFLOW>
+ additionally.
+
+
+
+
+
+ PGTYPESnumeric_to_decimal
+
+ Convert a variable of type numeric to decimal.
+
+int PGTYPESnumeric_to_decimal(numeric *src, decimal *dst);
+
+ The function converts the numeric value from the variable that
+ src> points to into the decimal variable that
+ dst> points to. It retuns 0 on success and -1 if an error
+ occurs, including overflow. On overflow, the global variable
+ errno> will be set to PGTYPES_NUM_OVERFLOW>
+ additionally.
+
+
+
+
+
+ PGTYPESnumeric_from_decimal
+
+ Convert a variable of type decimal to numeric.
+
+int PGTYPESnumeric_from_decimal(decimal *src, numeric *dst);
+
+ The function converts the decimal value from the variable that
+ src> points to into the numeric variable that
+ dst> points to. It retuns 0 on success and -1 if an error
+ occurs. Since the decimal type is implemented as a limited version of
+ the numeric type, overflow can not occur with this conversion.
+
+
+
+
+
+
+
+
+
The date type
+ The date type in C enables your programs to deal with data of the SQL type
+ date. See for the equivalent type in the
+
+ The following functions can be used to work with the date type:
+
+
+ PGTYPESdate_from_timestamp
+
+ Extract the date part from a timestamp.
+
+date PGTYPESdate_from_timestamp(timestamp dt);
+
+ The function receives a timestamp as its only argument and returns the
+ extracted date part from this timestamp.
+
+
+
+
+
+ PGTYPESdate_from_asc
+
+ Parse a date from its textual representation.
+
+date PGTYPESdate_from_asc(char *str, char **endptr);
+
+ The function receives a C char* string str> and a pointer to
+ a C char* string endptr>. At the moment ecpg always parses
+ the complete string and so it currently does not support to store the
+ address of the first invalid character in *endptr.
+ You can safely set endptr to NULL.
+
+ Note that the function always assumes MDY-formatted dates and there is
+ currently no variable to change that within ecpg.
+
+ The following input formats are allowed:
+
+
Valid input formats for PGTYPESdate_from_asc.
+
+
+ |
+ January 8, 1999
+ January 8, 1999
+
+ |
+ 1999-01-08
+ January 8, 1999
+
+ |
+ 1/8/1999
+ January 8, 1999
+
+ |
+ 1/18/1999
+ January 18, 1999
+
+ |
+ 01/02/03
+ February 1, 2003
+
+ |
+ 1999-Jan-08
+ January 8, 1999
+
+ |
+ Jan-08-1999
+ January 8, 1999
+
+ |
+ 08-Jan-1999
+ January 8, 1999
+
+ |
+ 99-Jan-08
+ January 8, 1999
+
+ |
+ 08-Jan-99
+ January 8, 1999
+
+ |
+ 08-Jan-06
+ January 8, 2006
+
+ |
+ Jan-08-99
+ January 8, 1999
+
+ |
+ 19990108
+ ISO 8601; January 8, 1999
+
+ |
+ 990108
+ ISO 8601; January 8, 1999
+
+ |
+ 1999.008
+ year and day of year
+
+ |
+ J2451187
+ Julian day
+
+ |
+ January 8, 99 BC
+ year 99 before the Common Era
+
+
+
+
+
+
+
+
+
+ PGTYPESdate_to_asc
+
+ Return the textual representation of a date variable.
+
+char *PGTYPESdate_to_asc(date dDate);
+
+ The function receives the date dDate> as its only parameter.
+ It will output the date in the form 1999-01-18>, i.e. in the
+ YYYY-MM-DD> format.
+
+
+
+
+
+ PGTYPESdate_julmdy
+
+ Extract the values for the day, the month and the year from a variable
+ of type date.
+
+void PGTYPESdate_julmdy(date d, int *mdy);
+
+
+ The function receives the date d> and a pointer to an array
+ of 3 integer values mdy>. The variable name indicates
+ the sequential order: mdy[0]> will be set to contain the
+ number of the month, mdy[1]> will be set to the value of the
+ day and mdy[2]> will contain the year.
+
+
+
+
+
+ PGTYPESdate_mdyjul
+
+ Create a date value from an array of 3 integers that specify the
+ day, the month and the year of the date.
+
+void PGTYPESdate_mdyjul(int *mdy, date *jdate);
+
+ The function receives the array of the 3 integers (mdy>) as
+ its first argument and as its second argument a pointer to a variable
+ of type date that should hold the result of the operation.
+
+
+
+
+
+ PGTYPESdate_dayofweek
+
+ Return a number representing the day of the week for a date value.
+
+int PGTYPESdate_dayofweek(date d);
+
+ The function receives the date variable d> as its only
+ argument and returns an integer that indicates the day of the week for
+ this date.
+
+
+ 0 - Sunday
+
+
+
+ 1 - Monday
+
+
+
+ 2 - Tuesday
+
+
+
+ 3 - Wednesday
+
+
+
+ 4 - Thursday
+
+
+
+ 5 - Friday
+
+
+
+ 6 - Saturday
+
+
+
+
+
+
+
+
+ PGTYPESdate_today
+
+ Get the current date.
+
+void PGTYPESdate_today(date *d);
+
+ The function receives a pointer to a date variable (d>)
+ that it sets to the current date.
+
+
+
+
+
+ PGTYPESdate_fmt_asc
+
+ Convert a variable of type date to its textual representation using a
+ format mask.
+
+int PGTYPESdate_fmt_asc(date dDate, char *fmtstring, char *outbuf);
+
+ The function receives the date to convert (dDate>), the
+ format mask (fmtstring>) and the string that will hold the
+ textual representation of the date (outbuf>).
+
+ On success, 0 is returned and a negative value if an error occurred.
+
+ The following literals are the field specifiers you can use:
+
+
+ dd - The number of the day of the month.
+
+
+
+ mm - The number of the month of the year.
+
+
+
+ yy - The number of the year as a two digit number.
+
+
+
+ yyyy - The number of the year as a four digit number.
+
+
+
+ ddd - The name of the day (abbreviated).
+
+
+
+ mmm - The name of the month (abbreviated).
+
+
+
+ All other characters are copied 1:1 to the output string.
+
+ The following table indicates a few possible formats. This will give
+ you an idea of how to use this function. All output lines are based on
+ the same date: November, 23rd, 1959.
+
+
Valid input formats for PGTYPESdate_fmt_asc.
+
+
+ |
+ mmddyy
+ 112359
+
+ |
+ ddmmyy
+ 231159
+
+ |
+ yymmdd
+ 591123
+
+ |
+ yy/mm/dd
+ 59/11/23
+
+ |
+ yy mm dd
+ 59 11 23
+
+ |
+ yy.mm.dd
+ 59.11.23
+
+ |
+ .mm.yyyy.dd.
+ .11.1959.23.
+
+ |
+ mmm. dd, yyyy
+ Nov. 23, 1959
+
+ |
+ mmm dd yyyy
+ Nov 23 1959
+
+ |
+ yyyy dd mm
+ 1959 23 11
+
+ |
+ ddd, mmm. dd, yyyy
+ Mon, Nov. 23, 1959
+
+ |
+ (ddd) mmm. dd, yyyy
+ (Mon) Nov. 23, 1959
+
+
+
+
+
+
+
+
+
+ PGTYPESdate_defmt_asc
+
+ Use a format mask to convert a C char* string to a value of type
+ date.
+
+int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str);
+
+
+ The function receives a pointer to the date value that should hold the
+ result of the operation (d>), the format mask to use for
+ parsing the date (fmt>) and the C char* string containing
+ the textual representation of the date (str>). The textual
+ representation is expected to match the format mask. However you do not
+ need to have a 1:1 mapping of the string to the format mask. The
+ function only analyzes the sequential order and looks for the literals
+ yy or yyyy that indicate the
+ position of the year, mm to indicate the position of
+ the month and dd to indicate the position of the
+ day.
+
+ The following table indicates a few possible formats. This will give
+ you an idea of how to use this function.
+
+
Valid input formats for rdefmtdate.
+
+
+ |
+ fmt
+ str
+ result
+
+
+
+ |
+ ddmmyy
+ 21-2-54
+ 1954-02-21
+
+ |
+ ddmmyy
+ 2-12-54
+ 1954-12-02
+
+ |
+ ddmmyy
+ 20111954
+ 1954-11-20
+
+ |
+ ddmmyy
+ 130464
+ 1964-04-13
+
+ |
+ mmm.dd.yyyy
+ MAR-12-1967
+ 1967-03-12
+
+ |
+ yy/mm/dd
+ 1954, February 3rd
+ 1954-02-03
+
+ |
+ mmm.dd.yyyy
+ 041269
+ 1969-04-12
+
+ |
+ yy/mm/dd
+ In the year 2525, in the month of July, mankind will be alive on the 28th day
+ 2525-07-28
+
+ |
+ dd-mm-yy
+ I said on the 28th of July in the year 2525
+ 2525-07-28
+
+ |
+ mmm.dd.yyyy
+ 9/14/58
+ 1958-09-14
+
+ |
+ yy/mm/dd
+ 47/03/29
+ 1947-03-29
+
+ |
+ mmm.dd.yyyy
+ oct 28 1975
+ 1975-10-28
+
+ |
+ mmddyy
+ Nov 14th, 1985
+ 1985-11-14
+
+
+
+
+
+
+
+
+
+
+
+
+
The timestamp type
+ The timestamp type in C enables your programs to deal with data of the SQL
+ type timestamp. See for the equivalent
+ type in the
PostgreSQL> server.
+
+ The following functions can be used to work with the timestamp type:
+
+
+ PGTYPEStimestamp_from_asc
+
+ Parse a timestamp from its textual representation into a timestamp
+ variable.
+
+timestamp PGTYPEStimestamp_from_asc(char *str, char **endptr);
+
+ The function receives the string to parse (str>) and a
+ pointer to a C char* (endptr>).
+ At the moment ecpg always parses
+ the complete string and so it currently does not support to store the
+ address of the first invalid character in *endptr.
+ You can safely set endptr to NULL.
+
+ The function returns the parsed timestamp on success. On error,
+ PGTYPESInvalidTimestamp is returned and errno is
+ set to PGTYPES_TS_BAD_TIMESTAMP>. See for important notes on this value.
+
+
+ In general, the input string can contain any combination of an allowed
+ date specification, a whitespace character and an allowed time
+ specification. Note that timezones are not supported by ecpg. It can
+ parse them but does not apply any calculation as the
+
PostgreSQL> server does for example. Timezone
+ specificiers are silently discarded.
+
+ The following table contains a few examples for input strings:
+
+
Valid input formats for PGTYPEStimestamp_from_asc.
+
+
+ |
+ 1999-01-08 04:05:06
+ 1999-01-08 04:05:06
+
+ |
+ January 8 04:05:06 1999 PST
+ 1999-01-08 04:05:06
+
+ |
+ 1999-Jan-08 04:05:06.789-8
+ 1999-01-08 04:05:06.789 (time zone specifier ignored)
+
+ |
+ J2451187 04:05-08:00
+ 1999-01-08 04:05:00 (time zone specifier ignored)
+
+
+
+
+
+
+
+
+
+ PGTYPEStimestamp_to_asc
+
+ Converts a date to a C char* string.
+
+char *PGTYPEStimestamp_to_asc(timestamp tstamp);
+
+ The function receives the timestamp tstamp> as
+ its only argument and returns an allocated string that contains the
+ textual representation of the timestamp.
+
+
+
+
+
+ PGTYPEStimestamp_current
+
+ Retrieve the current timestamp.
+
+void PGTYPEStimestamp_current(timestamp *ts);
+
+ The function retrieves the current timestamp and saves it into the
+ timestamp variable that ts> points to.
+
+
+
+
+
+ PGTYPEStimestamp_fmt_asc
+
+ Convert a timestamp variable to a C char* using a format mask.
+
+int PGTYPEStimestamp_fmt_asc(timestamp *ts, char *output, int str_len, char *fmtstr);
+
+ The function receives a pointer to the timestamp to convert as its
+ first argument (ts>), a pointer to the output buffer
+ (output>), the maximal length that has been allocated for
+ the output buffer (str_len) and the format mask to
+ use for the conversion (fmtstr).
+
+ Upon success, the function returns 0 and a negative value if an
+ error occurred.
+
+ You can use the following format specifiers for the format mask. The
+ format specifiers are the same ones that are used in the
+
strftime> function in libc. Any
+ non-format specifier will be copied into the output buffer.
+
+
+
+ %A - is replaced by national representation of
+ the full weekday name.
+
+
+
+ %a - is replaced by national representation of
+ the abbreviated weekday name.
+
+
+
+ %B - is replaced by national representation of
+ the full month name.
+
+
+
+ %b - is replaced by national representation of
+ the abbreviated month name.
+
+
+
+ %C - is replaced by (year / 100) as decimal
+ number; single digits are preceded by a zero.
+
+
+
+ %c - is replaced by national representation of
+ time and date.
+
+
+
+ %D - is equivalent to
+ %m/%d/%y.
+
+
+
+ %d - is replaced by the day of the month as a
+ decimal number (01-31).
+
+
+
+ %E* %O* - POSIX locale
+ extensions. The sequences
+ %Ec
+ %EC
+ %Ex
+ %EX
+ %Ey
+ %EY
+ %Od
+ %Oe
+ %OH
+ %OI
+ %Om
+ %OM
+ %OS
+ %Ou
+ %OU
+ %OV
+ %Ow
+ %OW
+ %Oy
+ are supposed to provide alternate representations.
+
+ Additionally %OB implemented to represent
+ alternative months names (used standalone, without day mentioned).
+
+
+
+ %e - is replaced by the day of month as a decimal
+ number (1-31); single digits are preceded by a blank.
+
+
+
+ %F - is equivalent to %Y-%m-%d.
+
+
+
+ %G - is replaced by a year as a decimal number
+ with century. This year is the one that contains the greater part of
+ the week (Monday as the first day of the week).
+
+
+
+ %g - is replaced by the same year as in
+ %G, but as a decimal number without century
+ (00-99).
+
+
+
+ %H - is replaced by the hour (24-hour clock) as a
+ decimal number (00-23).
+
+
+
+ %h - the same as %b.
+
+
+
+ %I - is replaced by the hour (12-hour clock) as a
+ decimal number (01-12).
+
+
+
+ %j - is replaced by the day of the year as a
+ decimal number (001-366).
+
+
+
+ %k - is replaced by the hour (24-hour clock) as a
+ decimal number (0-23); single digits are preceded by a blank.
+
+
+
+ %l - is replaced by the hour (12-hour clock) as a
+ decimal number (1-12); single digits are preceded by a blank.
+
+
+
+ %M - is replaced by the minute as a decimal
+ number (00-59).
+
+
+
+ %m - is replaced by the month as a decimal number
+ (01-12).
+
+
+
+ %n - is replaced by a newline.
+
+
+
+ %O* - the same as %E*.
+
+
+
+ %p - is replaced by national representation of
+ either "ante meridiem" or "post meridiem" as appropriate.
+
+
+
+ %R - is equivalent to %H:%M.
+
+
+
+ %r - is equivalent to %I:%M:%S
+ %p.
+
+
+
+ %S - is replaced by the second as a decimal
+ number (00-60).
+
+
+
+ %s - is replaced by the number of seconds since
+ the Epoch, UTC.
+
+
+
+ %T - is equivalent to %H:%M:%S
+
+
+
+ %t - is replaced by a tab.
+
+
+
+ %U - is replaced by the week number of the year
+ (Sunday as the first day of the week) as a decimal number (00-53).
+
+
+
+ %u - is replaced by the weekday (Monday as the
+ first day of the week) as a decimal number (1-7).
+
+
+
+ %V - is replaced by the week number of the year
+ (Monday as the first day of the week) as a decimal number (01-53).
+ If the week containing January 1 has four or more days in the new
+ year, then it is week 1; otherwise it is the last week of the
+ previous year, and the next week is week 1.
+
+
+
+ %v - is equivalent to
+ %e-%b-%Y.
+
+
+
+ %W - is replaced by the week number of the year
+ (Monday as the first day of the week) as a decimal number (00-53).
+
+
+
+ %w - is replaced by the weekday (Sunday as the
+ first day of the week) as a decimal number (0-6).
+
+
+
+ %X - is replaced by national representation of
+ the time.
+
+
+
+ %x - is replaced by national representation of
+ the date.
+
+
+
+ %Y - is replaced by the year with century as a
+ decimal number.
+
+
+
+ %y - is replaced by the year without century as a
+ decimal number (00-99).
+
+
+
+ %Z - is replaced by the time zone name.
+
+
+
+ %z - is replaced by the time zone offset from
+ UTC; a leading plus sign stands for east of UTC, a minus sign for
+ west of UTC, hours and minutes follow with two digits each and no
+ delimiter between them (common form for RFC 822 date headers).
+
+
+
+ %+ - is replaced by national representation of
+ the date and time.
+
+
+
+ %-* - GNU libc extension. Do not do any padding
+ when performing numerical outputs.
+
+
+
+ $_* - GNU libc extension. Explicitly specify space for padding.
+
+
+
+ %0* - GNU libc extension. Explicitly specify zero
+ for padding.
+
+
+
+ %% - is replaced by %.
+
+
+
+
+
+
+
+
+ PGTYPEStimestamp_sub
+
+ Subtract one timestamp from another one and save the result in a
+ variable of type interval.
+
+int PGTYPEStimestamp_sub(timestamp *ts1, timestamp *ts2, interval *iv);
+
+ The function will subtract the timestamp variable that ts2>
+ points to from the timestamp variable that ts1> points to
+ and will store the result in the interval variable that iv>
+ points to.
+
+ Upon success, the function returns 0 and a negative value if an
+ error occurred.
+
+
+
+
+
+ PGTYPEStimestamp_defmt_asc
+
+ Parse a timestamp value from its textual representation using a
+ formatting mask.
+
+int PGTYPEStimestamp_defmt_asc(char *str, char *fmt, timestamp *d);
+
+ The function receives the textual representation of a timestamp in the
+ variable str> as well as the formatting mask to use in the
+ variable fmt>. The result will be stored in the variable
+ that d> points to.
+
+ If the formatting mask fmt> is NULL, the function will fall
+ back to the default formatting mask which is %Y-%m-%d
+ %H:%M:%S.
+
+ This is the reverse function to
+ linkend="PGTYPEStimestampfmtasc">. See the documentation there in
+ order to find out about the possible formatting mask entries.
+
+
+
+
+
+ PGTYPEStimestamp_add_interval
+
+ Add an interval variable to a timestamp variable.
+
+int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout);
+
+ The function receives a pointer to a timestamp variable tin>
+ and a pointer to an interval variable span>. It adds the
+ interval to the timestamp and saves the resulting timestamp in the
+ variable that tout> points to.
+
+ Upon success, the function returns 0 and a negative value if an
+ error occurred.
+
+
+
+
+
+ PGTYPEStimestamp_sub_interval
+
+ Subtract an interval variable from a timestamp variable.
+
+int PGTYPEStimestamp_sub_interval(timestamp *tin, interval *span, timestamp *tout);
+
+ The function subtracts the interval variable that span>
+ points to from the timestamp variable that tin> points to
+ and saves the result into the variable that tout> points
+ to.
+
+ Upon success, the function returns 0 and a negative value if an
+ error occurred.
+
+
+
+
+
+
+
+
+
The interval type
+ The interval type in C enables your programs to deal with data of the SQL
+ type interval. See for the equivalent
+ type in the
PostgreSQL> server.
+
+ The following functions can be used to work with the interval type:
+
+
+
+ PGTYPESinterval_new
+
+ Return a pointer to a newly allocated interval variable.
+
+interval *PGTYPESinterval_new(void);
+
+
+
+
+
+
+ PGTYPESinterval_free
+
+ Release the memory of a previously allocated interval variable.
+
+void PGTYPESinterval_new(interval *intvl);
+
+
+
+
+
+
+ PGTYPESinterval_from_asc
+
+ Parse an interval from its textual representation.
+
+interval *PGTYPESinterval_from_asc(char *str, char **endptr);
+
+ The function parses the input string str> and returns a
+ pointer to an allocated interval variable.
+ At the moment ecpg always parses
+ the complete string and so it currently does not support to store the
+ address of the first invalid character in *endptr.
+ You can safely set endptr to NULL.
+
+
+
+
+
+ PGTYPESinterval_to_asc
+
+ Convert a variable of type interval to its textual representation.
+
+char *PGTYPESinterval_to_asc(interval *span);
+
+ The function converts the interval variable that span>
+ points to into a C char*. The output looks like this example:
+ @ 1 day 12 hours 59 mins 10 secs.
+
+
+
+
+
+ PGTYPESinterval_copy
+
+ Copy a variable of type interval.
+
+int PGTYPESinterval_copy(interval *intvlsrc, interval *intvldest);
+
+ The function copies the interval variable that intvlsrc>
+ points to into the variable that intvldest> points to. Note
+ that you need to allocate the memory for the destination variable
+ before.
+
+
+
+
+
+
+
+
+
The decimal type
+ The decimal type is similar to the numeric type. However it is limited to
+ a maximal precision of 30 significant digits. In contrast to the numeric
+ type which can be created on the heap only, the decimal type can be
+ created either on the stack or on the heap (by means of the functions
+ PGTYPESdecimal_new() and PGTYPESdecimal_free(). There are a lot of other
+ functions that deal with the decimal type in the Informix compatibility
+ mode described in .
+
+ The following functions can be used to work with the decimal type and are
+ not only contained in the libcompat> library.
+
+
+ PGTYPESdecimal_new
+
+ Request a pointer to a newly allocated decimal variable.
+
+decimal *PGTYPESdecimal_new(void);
+
+
+
+
+
+
+ PGTYPESdecimal_free
+
+ Free a decimal type, release all of its memory.
+
+void PGTYPESdecimal_free(decimal *var);
+
+
+
+
+
+
+
+
+
+
errno values of pgtypeslib
+
+
+ PGTYPES_NUM_BAD_NUMERIC
+
+ An argument should contain a numeric variable (or point to a numeric
+ variable) but in fact its in-memory representation was invalid.
+
+
+
+
+
+ PGTYPES_NUM_OVERFLOW
+
+ An overflow occurred. Since the numeric type can deal with almost
+ arbitrary precision, converting a numeric variable into other types
+ might cause overflow.
+
+
+
+
+
+ PGTYPES_NUM_OVERFLOW
+
+ An underflow occurred. Since the numeric type can deal with almost
+ arbitrary precision, converting a numeric variable into other types
+ might cause underflow.
+
+
+
+
+
+ PGTYPES_NUM_DIVIDE_ZERO
+
+ A division by zero has been attempted.
+
+
+
+
+
+
+ PGTYPES_DATE_BAD_DATE
+
+
+
+
+
+
+
+
+ PGTYPES_DATE_ERR_EARGS
+
+
+
+
+
+
+
+
+ PGTYPES_DATE_ERR_ENOSHORTDATE
+
+
+
+
+
+
+
+
+ PGTYPES_INTVL_BAD_INTERVAL
+
+
+
+
+
+
+
+
+ PGTYPES_DATE_ERR_ENOTDMY
+
+
+
+
+
+
+
+
+ PGTYPES_DATE_BAD_DAY
+
+
+
+
+
+
+
+
+ PGTYPES_DATE_BAD_MONTH
+
+
+
+
+
+
+
+
+ PGTYPES_TS_BAD_TIMESTAMP
+
+
+
+
+
+
+
+
+
+
+
Special constants of pgtypeslib
+
+
+ PGTYPESInvalidTimestamp
+
+ A value of type timestamp representing an invalid time stamp. This is
+ returned by the function PGTYPEStimestamp_from_asc> on
+ parse error.
+ Note that due to the internal representation of the timestamp datatype,
+ PGTYPESInvalidTimestamp is also a valid timestamp at
+ the same time. It is set to 1899-12-31 23:59:59>. In order
+ to detect errors, make sure that your application does not only test
+ for PGTYPESInvalidTimestamp but also for
+ errno != 0> after each call to
+ PGTYPEStimestamp_from_asc>.
+
+
+
+
+
+
+
+
+
+
Informix compatibility mode
+ ecpg can be run in a so-called Informix compatibility mode>. If
+ this mode is active, it tries to behave as if it were the Informix
+ precompiler for Informix E/SQL. Generally spoken this will allow you to use
+ the dollar sign instead of the EXEC SQL> primitive to introduce
+ embedded SQL commands.
+ $int j = 3;
+ $CONNECT TO :dbname;
+ $CREATE TABLE test(i INT PRIMARY KEY, j INT);
+ $INSERT INTO test(i, j) VALUES (7, :j);
+ $COMMIT;
+
+
+ There are two compatiblity modes: INFORMIX, INFORMIX_SE
+
+ When linking programs that use this compatibility mode, remember to link
+ against libcompat> that is shipped with ecpg.
+
+ Besides the previously explained syntactic sugar, the Informix compatibility
+ mode ports some functions for input, output and transformation of data as
+ well as embedded SQL statements known from E/SQL to ecpg.
+
+ Informix compatibility mode is closely connected to the pgtypeslib library
+ of ecpg. pgtypeslib maps SQL data types to data types within the C host
+ program and most of the additional functions of the Informix compatibility
+ mode allow you to operate on those C host program types. Note however that
+ the extend of the compatibility is limited. It does not try to copy Informix
+ behaviour but it allows you to do more or less the same operations and gives
+ you functions that have the same name and the same basic behavior but it is
+ no drop-in replacement if you are using Informix at the moment. Moreover,
+ some of the data types are different. For example,
+
PostgreSQL's datetime and interval types do not
+ know about ranges like for example YEAR TO MINUTE> so you won't
+ find support in ecpg for that either.
+
+
+
+
Additional embedded SQL statements
+
+
+ CLOSE DATABASE>
+
+ This statement closes the current connection. In fact, this is a
+ synonym for ecpg's DISCONNECT CURRENT>.
+ $CLOSE DATABASE; /* close the current connection */
+ EXEC SQL ClOSE DATABASE;
+
+
+
+
+
+
+
+
+
Additional functions
+
+
+ decadd>
+
+ Add two decimal type values.
+
+int decadd(decimal *arg1, decimal *arg2, decimal *sum);
+
+ The function receives a pointer to the first operand of type decimal
+ (arg1>), a pointer to the second operand of type decimal
+ (arg2>) and a pointer to a value of type decimal that will
+ contain the sum (sum>). On success, the function returns 0.
+ ECPG_INFORMIX_NUM_OVERFLOW is returned in case of overflow and
+ ECPG_INFORMIX_NUM_UNDERFLOW in case of underflow. -1 is returned for
+ other failures and errno is set to the respective errno number of the
+ pgtypeslib.
+
+
+
+
+
+ deccmp>
+
+ Compare two variables of type decimal.
+
+int deccmp(decimal *arg1, decimal *arg2);
+
+ The function receives a pointer to the first decimal value
+ (arg1>), a pointer to the second decimal value
+ (arg2>) and returns an integer value that indicates which is
+ the bigger value.
+
+
+ 1, if the value that arg1> points to is bigger than the
+ value that var2> points to
+
+
+
+ -1, if the value that arg1> points to is smaller than the
+ value that arg2> points to
+
+
+ 0, if the value that arg1> points to and the value that
+ arg2> points to are equal
+
+
+
+
+
+
+
+
+ deccopy>
+
+ Copy a decimal value.
+
+void deccopy(decimal *src, decimal *target);
+
+ The function receives a pointer to the decimal value that should be
+ copied as the first argument (src>) and a pointer to the
+ target structure of type decimal (target>) as the second
+ argument.
+
+
+
+
+
+ deccvasc>
+
+ Convert a value from its ASCII representation into a decimal type.
+
+int deccvasc(char *cp, int len, decimal *np);
+
+ The function receives a pointer to string that contains the string
+ representation of the number to be converted (cp>) as well
+ as its length len>. np> is a pointer to the
+ decimal value that saves the result of the operation.
+
+ Valid formats are for example:
+ -2,
+ .794,
+ +3.44,
+ 592.49E07 or
+ -32.84e-4.
+
+ The function returns 0 on success. If overflow or underflow occurred,
+ ECPG_INFORMIX_NUM_OVERFLOW> or
+ ECPG_INFORMIX_NUM_UNDERFLOW> is returned. If the ASCII
+ representation could not be parsed,
+ ECPG_INFORMIX_BAD_NUMERIC> is returned or
+ ECPG_INFORMIX_BAD_EXPONENT> if this problem ocurred while
+ parsing the exponent.
+
+
+
+
+
+ deccvdbl>
+
+ Convert a value of type double to a value of type decimal.
+
+int deccvdbl(double dbl, decimal *np);
+
+ The function receives the variable of type double that should be
+ converted as its first argument (dbl>). As the second
+ argument (np>), the function receives a pointer to the
+ decimal variable that should hold the result of the operation.
+
+ The function returns 0 on success and a negative value if the
+ conversion failed.
+
+
+
+
+
+ deccvint>
+
+ Convert a value of type int to a value of type decimal.
+
+int deccvint(int in, decimal *np);
+
+ The function receives the variable of type int that should be
+ converted as its first argument (in>). As the second
+ argument (np>), the function receives a pointer to the
+ decimal variable that should hold the result of the operation.
+
+ The function returns 0 on success and a negative value if the
+ conversion failed.
+
+
+
+
+
+ deccvlong>
+
+ Convert a value of type long to a value of type decimal.
+
+int deccvlong(long lng, decimal *np);
+
+ The function receives the variable of type long that should be
+ converted as its first argument (lng>). As the second
+ argument (np>), the function receives a pointer to the
+ decimal variable that should hold the result of the operation.
+
+ The function returns 0 on success and a negative value if the
+ conversion failed.
+
+
+
+
+
+ decdiv>
+
+ Divide two variables of type decimal.
+
+int decdiv(decimal *n1, decimal *n2, decimal *result);
+
+ The function receives pointers to the variables that are the first
+ (n1>) and the second (n2>) operands and
+ calculates n1>/n2>. result> is a
+ pointer to the variable that should hold the result of the operation.
+
+ On success, 0 is returned and a negative value if the division fails.
+ If overflow or underflow occurred, the function returns
+ ECPG_INFORMIX_NUM_OVERFLOW> or
+ ECPG_INFORMIX_NUM_UNDERFLOW> respectively. If an attempt to
+ divide by zero is observed, the function returns
+ ECPG_INFORMIX_DIVIDE_ZERO.
+
+
+
+
+
+ decmul>
+
+ Multiply two decimal values.
+
+int decmul(decimal *n1, decimal *n2, decimal *result);
+
+ The function receives pointers to the variables that are the first
+ (n1>) and the second (n2>) operands and
+ calculates n1>*n2>. result> is a
+ pointer to the variable that should hold the result of the operation.
+
+ On success, 0 is returned and a negative value if the multiplication
+ fails. If overflow or underflow occurred, the function returns
+ ECPG_INFORMIX_NUM_OVERFLOW> or
+ ECPG_INFORMIX_NUM_UNDERFLOW> respectively.
+
+
+
+
+
+ decsub>
+
+ Subtract one decimal value from another.
+
+int decsub(decimal *n1, decimal *n2, decimal *result);
+
+ The function receives pointers to the variables that are the first
+ (n1>) and the second (n2>) operands and
+ calculates n1>-n2>. result> is a
+ pointer to the variable that should hold the result of the operation.
+
+ On success, 0 is returned and a negative value if the subtraction
+ fails. If overflow or underflow occurred, the function returns
+ ECPG_INFORMIX_NUM_OVERFLOW> or
+ ECPG_INFORMIX_NUM_UNDERFLOW> respectively.
+
+
+
+
+
+ dectoasc>
+
+ Convert a variable of type decimal to its ASCII representation in a C
+ char* string.
+
+int dectoasc(decimal *np, char *cp, int len, int right)
+
+ The function receives a pointer to a variable of type decimal
+ (np>) that it converts to its textual representation.
+ cp> is the buffer that should hold the result of the
+ operation. The parameter right> specifies, how many digits
+ right of the decimal point should be included in the output. The result
+ will be rounded to this number of decimal digits. Setting
+ right> to -1 indicates that all available decimal digits
+ should be included in the output. If the length of the output buffer,
+ which is indicated by len> is not sufficient to hold the
+ textual representation including the trailing NUL character, only a
+ single *> character is stored in the result and -1 is
+ returned.
+
+ The function returns either -1 if the buffer cp> was too
+ small or ECPG_INFORMIX_OUT_OF_MEMORY> if memory was
+ exhausted.
+
+
+
+
+
+ dectodbl>
+
+ Convert a variable of type decimal to a double.
+
+int dectodbl(decimal *np, double *dblp);
+
+ The function receives a pointer to the decimal value to convert
+ (np>) and a pointer to the double variable that
+ should hold the result of the operation (dblp>).
+
+ On success, 0 is returned and a negative value if the conversion
+ failed.
+
+
+
+
+
+ dectoint>
+
+ Convert a variable to type decimal to an integer.
+
+int dectoint(decimal *np, int *ip);
+
+ The function receives a pointer to the decimal value to convert
+ (np>) and a pointer to the integer variable that
+ should hold the result of the operation (ip>).
+
+ On success, 0 is returned and a negative value if the conversion
+ failed. If an overflow occurred, ECPG_INFORMIX_NUM_OVERFLOW>
+ is returned.
+
+ Note that the ecpg implementation differs from the Informix
+ implementation. Informix limits an integer to the range from -32767 to
+ 32767, while the limits in the ecpg implementation depend on the
+ architecture (-INT_MAX .. INT_MAX>).
+
+
+
+
+
+ dectolong>
+
+ Convert a variable to type decimal to a long integer.
+
+int dectolong(decimal *np, long *lngp);
+
+ The function receives a pointer to the decimal value to convert
+ (np>) and a pointer to the long variable that
+ should hold the result of the operation (lngp>).
+
+ On success, 0 is returned and a negative value if the conversion
+ failed. If an overflow occurred, ECPG_INFORMIX_NUM_OVERFLOW>
+ is returned.
+
+ Note that the ecpg implementation differs from the Informix
+ implementation. Informix limits a long integer to the range from
+ -2,147,483,647 to 2,147,483,647, while the limits in the ecpg
+ implementation depend on the architecture (-LONG_MAX ..
+ LONG_MAX>).
+
+
+
+
+
+ rdatestr>
+
+ Converts a date to a C char* string.
+
+int rdatestr(date d, char *str);
+
+ The function receives two arguments, the first one is the date to
+ convert (d> and the second one is a pointer to the target
+ string. The output format is always yyyy-mm-dd>, so you need
+ to allocate at least 11 bytes (including the NUL-terminator) for the
+ string.
+
+ The function returns 0 on success and a negative value in case of
+ error.
+
+ Note that ecpg's implementation differs from the Informix
+ implementation. In Informix the format can be influenced by setting
+ environment variables. In ecpg however, you cannot change the output
+ format.
+
+
+
+
+
+ rstrdate>
+
+ Parse the textual representation of a date.
+
+int rstrdate(char *str, date *d);
+
+ The function receives the textual representation of the date to convert
+ (str>) and a pointer to a variable of type date
+ (d>). This function does not allow you to specify a format
+ mask. It uses the default format mask of Informix which is
+ mm/dd/yyyy>. Internally, this function is implemented by
+ means of rdefmtdate>. Therefore, rstrdate> is
+ not faster and if you have the choice you should opt for
+ rdefmtdate> which allows you to specify the format mask
+ explicitly.
+
+ The function returns the same values as rdefmtdate>.
+
+
+
+
+
+ rtoday>
+
+ Get the current date.
+
+void rtoday(date *d);
+
+ The function receives a pointer to a date variable (d>)
+ that it sets to the current date.
+
+ Internally this function uses the
+ function.
+
+
+
+
+
+ rjulmdy>
+
+ Extract the values for the day, the month and the year from a variable
+ of type date.
+
+int rjulmdy(date d, short mdy[3]);
+
+ The function receives the date d> and a pointer to an array
+ of 3 short integer values mdy>. The variable name indicates
+ the sequential order: mdy[0]> will be set to contain the
+ number of the month, mdy[1]> will be set to the value of the
+ day and mdy[2]> will contain the year.
+
+ The function always returns 0 at the moment.
+
+ Internally the function uses the
+ function.
+
+
+
+
+
+ rdefmtdate>
+
+ Use a format mask to convert a character string to a value of type
+ date.
+
+int rdefmtdate(date *d, char *fmt, char *str);
+
+ The function receives a pointer to the date value that should hold the
+ result of the operation (d>), the format mask to use for
+ parsing the date (fmt>) and the C char* string containing
+ the textual representation of the date (str>). The textual
+ representation is expected to match the format mask. However you do not
+ need to have a 1:1 mapping of the string to the format mask. The
+ function only analyzes the sequential order and looks for the literals
+ yy or yyyy that indicate the
+ position of the year, mm to indicate the position of
+ the month and dd to indicate the position of the
+ day.
+
+ The function returns the following values:
+
+
+ 0 - The function terminated successfully.
+
+
+
+ ECPG_INFORMIX_ENOSHORTDATE> - The date does not contain
+ delimiters between day, month and year. In this case the input
+ string must be exactly 6 or 8 bytes long but isn't.
+
+
+
+ ECPG_INFORMIX_ENOTDMY> - The format string did not
+ correctly indicate the sequential order of year, month and day.
+
+
+
+ ECPG_INFORMIX_BAD_DAY> - The input string does not
+ contain a valid day.
+
+
+
+ ECPG_INFORMIX_BAD_MONTH> - The input string does not
+ contain a valid month.
+
+
+
+ ECPG_INFORMIX_BAD_YEAR> - The input string does not
+ contain a valid year.
+
+
+
+
+ Internally this function is implemented to use the
+ linkend="PGTYPESdatedefmtasc"> function. See the reference there for a
+ table of example input.
+
+
+
+
+
+ rfmtdate>
+
+ Convert a variable of type date to its textual representation using a
+ format mask.
+
+int rfmtdate(date d, char *fmt, char *str);
+
+ The function receives the date to convert (d>), the format
+ mask (fmt>) and the string that will hold the textual
+ representation of the date (str>).
+
+ On success, 0 is returned and a negative value if an error occurred.
+
+ Internally this function uses the
+ function, see the reference there for examples.
+
+
+
+
+
+ rmdyjul>
+
+ Create a date value from an array of 3 short integers that specify the
+ day, the month and the year of the date.
+
+int rmdyjul(short mdy[3], date *d);
+
+ The function receives the array of the 3 short integers
+ (mdy>) and a pointer to a variable of type date that should
+ hold the result of the operation.
+
+ Currently the function returns always 0.
+
+ Internally the function is implemented to use the function
+ linkend="PGTYPESdatemdyjul">.
+
+
+
+
+
+ rdayofweek>
+
+ Return a number representing the day of the week for a date value.
+
+int rdayofweek(date d);
+
+ The function receives the date variable d> as its only
+ argument and returns an integer that indicates the day of the week for
+ this date.
+
+
+ 0 - Sunday
+
+
+
+ 1 - Monday
+
+
+
+ 2 - Tuesday
+
+
+
+ 3 - Wednesday
+
+
+
+ 4 - Thursday
+
+
+
+ 5 - Friday
+
+
+
+ 6 - Saturday
+
+
+
+
+ Internally the function is implemented to use the function
+ linkend="PGTYPESdatedayofweek">.
+
+
+
+
+
+ dtcurrent>
+
+ Retrieve the current timestamp.
+
+void dtcurrent(timestamp *ts);
+
+ The function retrieves the current timestamp and saves it into the
+ timestamp variable that ts> points to.
+
+
+
+
+
+ dtcvasc>
+
+ Parses a timestamp from its textual representation in ANSI standard
+ into a timestamp variable.
+
+int dtcvasc(char *str, timestamp *ts);
+
+ The function receives the string to parse (str>) and a
+ pointer to the timestamp variable that should hold the result of the
+ operation (ts>).
+
+ The function returns 0 on success and a negative value in case of
+ error.
+
+ Internally this function uses the
+ linkend="PGTYPEStimestampfromasc"> function. See the reference there
+ for a table with example inputs.
+
+
+
+
+
+ dtcvfmtasc>
+
+ Parses a timestamp from its textual representation in ANSI standard
+ using a format mask into a timestamp variable.
+
+dtcvfmtasc(char *inbuf, char *fmtstr, timestamp *dtvalue)
+
+ The function receives the string to parse (inbuf>), the
+ format mask to use (fmtstr>) and a pointer to the timestamp
+ variable that should hold the result of the operation (ts>).
+
+ This functions is implemented by means of the
+ linkend="PGTYPEStimestampdefmtasc">. See the documentation
+ there for a list of format specifiers that can be used.
+
+ The function returns 0 on success and a negative value in case of
+ error.
+
+
+
+
+
+ dtsub>
+
+ Subtract one timestamp from another and return a variable of type
+ interval.
+
+int dtsub(timestamp *ts1, timestamp *ts2, interval *iv);
+
+ The function will subtract the timestamp variable that ts2>
+ points to from the timestamp variable that ts1> points to
+ and will store the result in the interval variable that iv>
+ points to.
+
+ Upon success, the function returns 0 and a negative value if an
+ error occurred.
+
+
+
+
+
+ dttoasc>
+
+ Convert a timestamp variable to a C char* string.
+
+int dttoasc(timestamp *ts, char *output);
+
+ The function receives a pointer to the timestamp variable to convert
+ (ts>) and the string that should hold the result of the
+ operation output>). It converts ts> to its
+ textual representation in the ANSI SQL standard which is defined to
+ be YYYY-MM-DD HH:MM:SS.
+
+ Upon success, the function returns 0 and a negative value if an
+ error occurred.
+
+
+
+
+
+ dttofmtasc>
+
+ Convert a timestamp variable to a C char* using a format mask.
+
+int dttofmtasc(timestamp *ts, char *output, int str_len, char *fmtstr);
+
+ The function receives a pointer to the timestamp to convert as its
+ first argument (ts>), a pointer to the output buffer
+ (output>), the maximal length that has been allocated for
+ the output buffer (str_len) and the format mask to
+ use for the conversion (fmtstr).
+
+ Upon success, the function returns 0 and a negative value if an
+ error occurred.
+
+ Internally this function uses the
+ linkend="PGTYPEStimestampfmtasc"> function. See the reference there for
+ informations on what format mask specifiers can be used.
+
+
+
+
+
+ intoasc>
+
+ Convert an interval variable to a C char* string.
+
+int intoasc(interval *i, char *str);
+
+ The function receives a pointer to the interval variable to convert
+ (i>) and the string that should hold the result of the
+ operation str>). It converts i> to its
+ textual representation in the ANSI SQL standard which is defined to
+ be YYYY-MM-DD HH:MM:SS.
+
+ Upon success, the function returns 0 and a negative value if an
+ error occurred.
+
+
+
+
+
+ rfmtlong>
+
+ Convert a long integer value to its textual representation using a
+ format mask.
+
+int rfmtlong(long lng_val, char *fmt, char *outbuf);
+
+ The function receives the long value lng_val>, the format
+ mask fmt> and a pointer to the output buffer
+ outbuf>. It converts the long value according to the format
+ mask to its textual representation.
+
+ The format mask can be composed of the following format specifying
+ characters:
+
+
+ * (asterisk) - if this position would be blank
+ otherwise, fill it with an asterisk.
+
+
+
+ & (ampersand) - if this position would be
+ blank otherwise, fill it with a zero.
+
+
+
+ # - turn leading zeroes into blanks.
+
+
+
+ < - left-justify the number in the string.
+
+
+
+ , (comma) - group numbers of four or more digits
+ into groups of three digits separated by a comma.
+
+
+
+ . (period) - this character separates the
+ whole-number part of the number from the fractional part.
+
+
+
+ - (minus) - the minus sign appears if the number
+ is a negative value.
+
+
+
+ + (plus) - the plus sign appears if the number is
+ a positive value.
+
+
+
+ ( - this replaces the minus sign in front of the
+ negative number. The minus sign will not appear.
+
+
+
+ ) - this character replaces the minus and is
+ printed behind the negative value.
+
+
+
+ $ - the currency symbol.
+
+
+
+
+
+
+
+
+ rupshift>
+
+ Convert a string to upper case.
+
+void rupshift(char *str);
+
+ The function receives a pointer to the string and transforms every
+ lower case character to upper case.
+
+
+
+
+
+ byleng>
+
+ Return the number of characters in a string without counting trailing
+ blanks.
+
+int byleng(char *str, int len);
+
+ The function expects a fixed-length string as its first argument
+ (str>) and its length as its second argument
+ (len>). It returns the number of significant characters,
+ that is the length of the string without trailing blanks.
+
+
+
+
+
+ ldchar>
+
+ Copy a fixed-length string into a null-terminated string.
+
+void ldchar(char *src, int len, char *dest);
+
+ The function receives the fixed-length string to copy
+ (src>), its length (len>) and a pointer to the
+ destination memory (dest>). Note that you need to reserve at
+ least len+1> bytes for the string that dest>
+ points to. The function copies at most len> bytes to the new
+ location (less if the source string has trailing blanks) and adds the
+ null-terminator.
+
+
+
+
+
+ rgetmsg>
+
+
+int rgetmsg(int msgnum, char *s, int maxsize);
+
+ This function exists but is not implemented at the moment!
+
+
+
+
+
+ rtypalign>
+
+
+int rtypalign(int offset, int type);
+
+ This function exists but is not implemented at the moment!
+
+
+
+
+
+ rtypmsize>
+
+
+int rtypmsize(int type, int len);
+
+ This function exists but is not implemented at the moment!
+
+
+
+
+
+ rtypwidth>
+
+
+int rtypwidth(int sqltype, int sqllen);
+
+ This function exists but is not implemented at the moment!
+
+
+
+
+
+ rsetnull>
+
+ Set a variable to NULL.
+
+int rsetnull(int t, char *ptr);
+
+ The function receives an integer that indicates the type of the
+ variable and a pointer to the variable itself that is casted to a C
+ char* pointer.
+
+ The following types exist:
+
+
+ CCHARTYPE - For a variable of type char or char*
+
+
+
+ CSHORTTYPE - For a variable of type short int
+
+
+
+ CINTTYPE - For a variable of type int
+
+
+
+ CBOOLTYPE - For a variable of type boolean
+
+
+
+ CFLOATTYPE - For a variable of type float
+
+
+
+ CLONGTYPE - For a variable of type long
+
+
+
+ CDOUBLETYPE - For a variable of type double
+
+
+
+ CDECIMALTYPE - For a variable of type decimal
+
+
+
+ CDATETYPE - For a variable of type date
+
+
+
+ CDTIMETYPE - For a variable of type timestamp
+
+
+
+ Here is an example of a call to this function:
+$char c[] = "abc ";
+$short s = 17;
+$int i = -74874;
+
+rsetnull(CCHARTYPE, (char *) c);
+rsetnull(CSHORTTYPE, (char *) &s);
+rsetnull(CINTTYPE, (char *) &i);
+
+
+
+
+
+
+ risnull>
+
+ Test if a variable is NULL.
+
+int risnull(int t, char *ptr);
+
+ The function receives the type of the variable to test (t>)
+ as well a pointer to this variable (ptr>). Note that the
+ latter needs to be casted to a char*. See the function
+ linkend="rsetnull"> for a list of possible variable types.
+
+ Here is an example of how to use this function:
+$char c[] = "abc ";
+$short s = 17;
+$int i = -74874;
+
+risnull(CCHARTYPE, (char *) c);
+risnull(CSHORTTYPE, (char *) &s);
+risnull(CINTTYPE, (char *) &i);
+
+
+
+
+
+
+
+
+
+
Additional constants
- The examples above do not handle null values. In fact, the
- retrieval examples will raise an error if they fetch a null value
- from the database. To be able to pass null values to the database
- or retrieve null values from the database, you need to append a
- second host variable specification to each host variable that
- contains data. This second host variable is called the
- indicator and contains a flag that tells
- whether the datum is null, in which case the value of the real
- host variable is ignored. Here is an example that handles the
- retrieval of null values correctly:
-EXEC SQL BEGIN DECLARE SECTION;
-VARCHAR val;
-int val_ind;
-EXEC SQL END DECLARE SECTION:
+ Note that all constants here describe errors and all of them are defined
+ to represent negative values. In the descriptions of the different
+ constants you can also find the value that the constants represent in the
+ current implementation. However you should not rely on this number. You can
+ however rely on the fact all of them are defined to represent negative
+ values.
+
+
+ ECPG_INFORMIX_NUM_OVERFLOW>
+
+ Functions return this value if an overflow occurred in a
+ calculation. Internally it is defined to -1200 (the Informix
+ definition).
+
+
+
- ...
+
+ ECPG_INFORMIX_NUM_UNDERFLOW>
+
+ Functions return this value if an underflow occurred in a calculation.
+ Internally it is defined to -1201 (the Informix definition).
+
+
+
-EXEC SQL SELECT b INTO :val :val_ind FROM test1;
-
- The indicator variable val_ind will be zero if
- the value was not null, and it will be negative if the value was
- null.
-
+
+ ECPG_INFORMIX_DIVIDE_ZERO>
+
+ Functions return this value if an attempt to divide by zero is
+ observed. Internally it is defined to -1202 (the Informix definition).
+
+
+
- The indicator has another function: if the indicator value is
- positive, it means that the value is not null, but it was
- truncated when it was stored in the host variable.
-
-
-
+
+ ECPG_INFORMIX_BAD_YEAR>
+
+ Functions return this value if a bad value for a year was found while
+ parsing a date. Internally it is defined to -1204 (the Informix
+ definition).
+
+
+
-
-
Dynamic SQL
+
+ ECPG_INFORMIX_BAD_MONTH>
+
+ Functions return this value if a bad value for a month was found while
+ parsing a date. Internally it is defined to -1205 (the Informix
+ definition).
+
+
+
- In many cases, the particular SQL statements that an application
- has to execute are known at the time the application is written.
- In some cases, however, the SQL statements are composed at run time
- or provided by an external source. In these cases you cannot embed
- the SQL statements directly into the C source code, but there is a
- facility that allows you to call arbitrary SQL statements that you
- provide in a string variable.
-
+
+ ECPG_INFORMIX_BAD_DAY>
+
+ Functions return this value if a bad value for a day was found while
+ parsing a date. Internally it is defined to -1206 (the Informix
+ definition).
+
+
+
- The simplest way to execute an arbitrary SQL statement is to use
- the command EXECUTE IMMEDIATE. For example:
-EXEC SQL BEGIN DECLARE SECTION;
-const char *stmt = "CREATE TABLE test1 (...);";
-EXEC SQL END DECLARE SECTION;
+
+ ECPG_INFORMIX_ENOSHORTDATE>
+
+ Functions return this value if a parsing routine needs a short date
+ representation but did not get the date string in the right length.
+ Internally it is defined to -1209 (the Informix definition).
+
+
+
-EXEC SQL EXECUTE IMMEDIATE :stmt;
-
- You may not execute statements that retrieve data (e.g.,
- SELECT) this way.
-
+
+ ECPG_INFORMIX_DATE_CONVERT>
+
+ Functions return this value if Internally it is defined to -1210 (the
+ Informix definition).
+
+
+
- A more powerful way to execute arbitrary SQL statements is to
- prepare them once and execute the prepared statement as often as
- you like. It is also possible to prepare a generalized version of
- a statement and then execute specific versions of it by
- substituting parameters. When preparing the statement, write
- question marks where you want to substitute parameters later. For
- example:
-EXEC SQL BEGIN DECLARE SECTION;
-const char *stmt = "INSERT INTO test1 VALUES(?, ?);";
-EXEC SQL END DECLARE SECTION;
+
+ ECPG_INFORMIX_OUT_OF_MEMORY>
+
+ Functions return this value if Internally it is defined to -1211 (the
+ Informix definition).
+
+
+
-EXEC SQL PREPARE mystmt FROM :stmt;
- ...
-EXEC SQL EXECUTE mystmt USING 42, 'foobar';
-
- If the statement you are executing returns values, then add an
- INTO clause:
-EXEC SQL BEGIN DECLARE SECTION;
-const char *stmt = "SELECT a, b, c FROM test1 WHERE a > ?";
-int v1, v2;
-VARCHAR v3;
-EXEC SQL END DECLARE SECTION;
+
+ ECPG_INFORMIX_ENOTDMY>
+
+ Functions return this value if a parsing routine was supposed to get a
+ format mask (like mmddyy>) but not all fields were listed
+ correctly. Internally it is defined to -1212 (the Informix definition).
+
+
+
-EXEC SQL PREPARE mystmt FROM :stmt;
- ...
-EXEC SQL EXECUTE mystmt INTO v1, v2, v3 USING 37;
-
- An EXECUTE command may have an
- INTO clause, a USING clause,
- both, or neither.
-
+
+ ECPG_INFORMIX_BAD_NUMERIC>
+
+ Functions return this value either if a parsing routine cannot parse
+ the textual representation for a numeric value because it contains
+ errors or if a routine cannot complete a calculation involving numeric
+ variables because at least one of the numeric variables is invalid.
+ Internally it is defined to -1213 (the Informix definition).
+
+
+
- When you don't need the prepared statement anymore, you should
- deallocate it:
-EXEC SQL DEALLOCATE PREPARE name;
-
-
+
+ ECPG_INFORMIX_BAD_EXPONENT>
+
+ Functions return this value if Internally it is defined to -1216 (the
+ Informix definition).
+
+
+
+
+
+ ECPG_INFORMIX_BAD_DATE>
+
+ Functions return this value if Internally it is defined to -1218 (the
+ Informix definition).
+
+
+
+
+
+ ECPG_INFORMIX_EXTRA_CHARS>
+
+ Functions return this value if Internally it is defined to -1264 (the
+ Informix definition).
+
+
+
+
+
+
- BREAK
+ DO BREAK
Execute the C statement break. This should
- include">
-
Including Files
+ preproc">
+
Preprocessor directives
- To include an external file into your embedded SQL program, use:
+
+
Including files
+
+ To include an external file into your embedded SQL program, use:
EXEC SQL INCLUDE filename;
- The embedded SQL preprocessor will look for a file named
- filename.h,
- preprocess it, and include it in the resulting C output. Thus,
- embedded SQL statements in the included file are handled correctly.
-
+ The embedded SQL preprocessor will look for a file named
+ filename.h,
+ preprocess it, and include it in the resulting C output. Thus,
+ embedded SQL statements in the included file are handled correctly.
+
- Note that this is not the same as
+ Note that this is not the same as
#include <filename.h>
- because this file would not be subject to SQL command preprocessing.
- Naturally, you can continue to use the C
- #include directive to include other header
- files.
-
+ because this file would not be subject to SQL command preprocessing.
+ Naturally, you can continue to use the C
+ #include directive to include other header
+ files.
+
+
+
+ The include file name is case-sensitive, even though the rest of
+ the EXEC SQL INCLUDE command follows the normal
+ SQL case-sensitivity rules.
+
+
+
+
+
+
The #define and #undef directives
+ Similar to the directive #define that is known from C,
+ embedded SQL has a similar concept:
+EXEC SQL DEFINE name>;
+EXEC SQL DEFINE name> value>;
+
+ So you can define a name:
+EXEC SQL DEFINE HAVE_FEATURE;
+
+ And you can also define constants:
+EXEC SQL DEFINE MYNUMBER 12;
+EXEC SQL DEFINE MYSTRING 'abc';
+
+ Use undef> to remove a previous definition:
+EXEC SQL UNDEF MYNUMBER;
+
+
-
- The include file name is case-sensitive, even though the rest of
- the EXEC SQL INCLUDE command follows the normal
- SQL case-sensitivity rules.
+ Of course you can continue to use the C versions #define
+ and #undef in your embedded SQL program. The difference
+ is where your defined values get evaluated. If you use EXEC SQL
+ DEFINE> then the ecpg preprocessor evaluates the defines and substitutes
+ the values. For example if you write:
+EXEC SQL DEFINE MYNUMBER 12;
+...
+EXEC SQL UPDATE Tbl SET col = MYNUMBER;
+
+ then ecpg will already do the substitution and your C compiler will never
+ see any name or identifier MYNUMBER>. Note that you can not use
+ #define for a constant that you are going to use in an
+ embedded SQL query because in this case the embedded SQL precompiler is not
+ able to see this declaration.
-
-
+
+
+
+
ifdef, ifndef, else, elif and endif directives
+ You can use the following directives to compile code sections conditionally:
+
+
+
+ EXEC SQL ifdef name>;
+
+ Checks a name> and processes subsequent lines if
+ name> has been created with EXEC SQL define
+ name>.
+
+
+
+
+
+ EXEC SQL ifndef name>;
+
+ Checks a name> and processes subsequent lines if
+ name> has not been created with
+ EXEC SQL define name>.
+
+
+
+
+
+ EXEC SQL else;
+
+ Starts processing an alternative section to a section introduced by
+ either EXEC SQL ifdef name> or
+ EXEC SQL ifndef name>.
+
+
+
+
+
+ EXEC SQL elif name>;
+
+ Checks name> and starts an alternative section if
+ name> has been created with EXEC SQL define
+ name>.
+
+
+
+
+
+ EXEC SQL endif;
+
+ Ends an alternative section.
+
+
+
+
-
+ Example:
+ exec sql ifndef TZVAR;
+ exec sql SET TIMEZONE TO 'GMT';
+ exec sql elif TZNAME;
+ exec sql SET TIMEZONE TO TZNAME;
+ exec sql else;
+ exec sql SET TIMEZONE TO TZVAR;
+ exec sql endif;
+
+
+
+
+
+
+
Processing Embedded SQL Programs