diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml index 523ab363af6..241c524bbd8 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -1,4 +1,4 @@ - + <application>ECPG</application> - Embedded <acronym>SQL</acronym> in C @@ -384,7 +384,11 @@ EXEC SQL SET CONNECTION connection-name; 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. @@ -408,9 +412,7 @@ EXEC SQL INSERT INTO sometable VALUES (:v1, 'foo', :v2); 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. @@ -437,8 +439,16 @@ EXEC SQL END DECLARE SECTION; 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. @@ -455,20 +465,104 @@ char foo[16], bar[16]; 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. + + + + @@ -648,6 +742,2925 @@ 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 + PostgreSQL server. + + + 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 <function>PGTYPESdate_from_asc</function>. + <tgroup cols="2"> + <thead> + <row> + <entry>Input</entry> + <entry>Result</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>January 8, 1999</literal></entry> + <entry><literal>January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>1999-01-08</literal></entry> + <entry><literal>January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>1/8/1999</literal></entry> + <entry><literal>January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>1/18/1999</literal></entry> + <entry><literal>January 18, 1999</literal></entry> + </row> + <row> + <entry><literal>01/02/03</literal></entry> + <entry><literal>February 1, 2003</literal></entry> + </row> + <row> + <entry><literal>1999-Jan-08</literal></entry> + <entry><literal>January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>Jan-08-1999</literal></entry> + <entry><literal>January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>08-Jan-1999</literal></entry> + <entry><literal>January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>99-Jan-08</literal></entry> + <entry><literal>January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>08-Jan-99</literal></entry> + <entry><literal>January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>08-Jan-06</literal></entry> + <entry><literal>January 8, 2006</literal></entry> + </row> + <row> + <entry><literal>Jan-08-99</literal></entry> + <entry><literal>January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>19990108</literal></entry> + <entry><literal>ISO 8601; January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>990108</literal></entry> + <entry><literal>ISO 8601; January 8, 1999</literal></entry> + </row> + <row> + <entry><literal>1999.008</literal></entry> + <entry><literal>year and day of year</literal></entry> + </row> + <row> + <entry><literal>J2451187</literal></entry> + <entry><literal>Julian day</literal></entry> + </row> + <row> + <entry><literal>January 8, 99 BC</literal></entry> + <entry><literal>year 99 before the Common Era</literal></entry> + </row> + </tbody> + </tgroup> + </table> + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPESdatetoasc"> + <term><function>PGTYPESdate_to_asc</function></term> + <listitem> + <para> + Return the textual representation of a date variable. +<synopsis> +char *PGTYPESdate_to_asc(date dDate); +</synopsis> + The function receives the date <literal>dDate</> as its only parameter. + It will output the date in the form <literal>1999-01-18</>, i.e. in the + <literal>YYYY-MM-DD</> format. + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPESdatejulmdy"> + <term><function>PGTYPESdate_julmdy</function></term> + <listitem> + <para> + Extract the values for the day, the month and the year from a variable + of type date. +<synopsis> +void PGTYPESdate_julmdy(date d, int *mdy); +</synopsis> + <!-- almost same description as for rjulmdy() --> + The function receives the date <literal>d</> and a pointer to an array + of 3 integer values <literal>mdy</>. The variable name indicates + the sequential order: <literal>mdy[0]</> will be set to contain the + number of the month, <literal>mdy[1]</> will be set to the value of the + day and <literal>mdy[2]</> will contain the year. + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPESdatemdyjul"> + <term><function>PGTYPESdate_mdyjul</function></term> + <listitem> + <para> + Create a date value from an array of 3 integers that specify the + day, the month and the year of the date. +<synopsis> +void PGTYPESdate_mdyjul(int *mdy, date *jdate); +</synopsis> + The function receives the array of the 3 integers (<literal>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. + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPESdatedayofweek"> + <term><function>PGTYPESdate_dayofweek</function></term> + <listitem> + <para> + Return a number representing the day of the week for a date value. +<synopsis> +int PGTYPESdate_dayofweek(date d); +</synopsis> + The function receives the date variable <literal>d</> as its only + argument and returns an integer that indicates the day of the week for + this date. + <itemizedlist> + <listitem> + <para> + 0 - Sunday + </para> + </listitem> + <listitem> + <para> + 1 - Monday + </para> + </listitem> + <listitem> + <para> + 2 - Tuesday + </para> + </listitem> + <listitem> + <para> + 3 - Wednesday + </para> + </listitem> + <listitem> + <para> + 4 - Thursday + </para> + </listitem> + <listitem> + <para> + 5 - Friday + </para> + </listitem> + <listitem> + <para> + 6 - Saturday + </para> + </listitem> + </itemizedlist> + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPESdatetoday"> + <term><function>PGTYPESdate_today</function></term> + <listitem> + <para> + Get the current date. +<synopsis> +void PGTYPESdate_today(date *d); +</synopsis> + The function receives a pointer to a date variable (<literal>d</>) + that it sets to the current date. + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPESdatefmtasc"> + <term><function>PGTYPESdate_fmt_asc</function></term> + <listitem> + <para> + Convert a variable of type date to its textual representation using a + format mask. +<synopsis> +int PGTYPESdate_fmt_asc(date dDate, char *fmtstring, char *outbuf); +</synopsis> + The function receives the date to convert (<literal>dDate</>), the + format mask (<literal>fmtstring</>) and the string that will hold the + textual representation of the date (<literal>outbuf</>). + </para> + <para> + On success, 0 is returned and a negative value if an error occurred. + </para> + <para> + The following literals are the field specifiers you can use: + <itemizedlist> + <listitem> + <para> + <literal>dd</literal> - The number of the day of the month. + </para> + </listitem> + <listitem> + <para> + <literal>mm</literal> - The number of the month of the year. + </para> + </listitem> + <listitem> + <para> + <literal>yy</literal> - The number of the year as a two digit number. + </para> + </listitem> + <listitem> + <para> + <literal>yyyy</literal> - The number of the year as a four digit number. + </para> + </listitem> + <listitem> + <para> + <literal>ddd</literal> - The name of the day (abbreviated). + </para> + </listitem> + <listitem> + <para> + <literal>mmm</literal> - The name of the month (abbreviated). + </para> + </listitem> + </itemizedlist> + All other characters are copied 1:1 to the output string. + </para> + <para> + 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. + <table> + <title>Valid input formats for <function>PGTYPESdate_fmt_asc</function>. + <tgroup cols="2"> + <thead> + <row> + <entry>fmt</entry> + <entry>result</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>mmddyy</literal></entry> + <entry><literal>112359</literal></entry> + </row> + <row> + <entry><literal>ddmmyy</literal></entry> + <entry><literal>231159</literal></entry> + </row> + <row> + <entry><literal>yymmdd</literal></entry> + <entry><literal>591123</literal></entry> + </row> + <row> + <entry><literal>yy/mm/dd</literal></entry> + <entry><literal>59/11/23</literal></entry> + </row> + <row> + <entry><literal>yy mm dd</literal></entry> + <entry><literal>59 11 23</literal></entry> + </row> + <row> + <entry><literal>yy.mm.dd</literal></entry> + <entry><literal>59.11.23</literal></entry> + </row> + <row> + <entry><literal>.mm.yyyy.dd.</literal></entry> + <entry><literal>.11.1959.23.</literal></entry> + </row> + <row> + <entry><literal>mmm. dd, yyyy</literal></entry> + <entry><literal>Nov. 23, 1959</literal></entry> + </row> + <row> + <entry><literal>mmm dd yyyy</literal></entry> + <entry><literal>Nov 23 1959</literal></entry> + </row> + <row> + <entry><literal>yyyy dd mm</literal></entry> + <entry><literal>1959 23 11</literal></entry> + </row> + <row> + <entry><literal>ddd, mmm. dd, yyyy</literal></entry> + <entry><literal>Mon, Nov. 23, 1959</literal></entry> + </row> + <row> + <entry><literal>(ddd) mmm. dd, yyyy</literal></entry> + <entry><literal>(Mon) Nov. 23, 1959</literal></entry> + </row> + </tbody> + </tgroup> + </table> + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPESdatedefmtasc"> + <term><function>PGTYPESdate_defmt_asc</function></term> + <listitem> + <para> + Use a format mask to convert a C char* string to a value of type + date. +<synopsis> +int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str); +</synopsis> + <!-- same description as rdefmtdate --> + The function receives a pointer to the date value that should hold the + result of the operation (<literal>d</>), the format mask to use for + parsing the date (<literal>fmt</>) and the C char* string containing + the textual representation of the date (<literal>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 + <literal>yy</literal> or <literal>yyyy</literal> that indicate the + position of the year, <literal>mm</literal> to indicate the position of + the month and <literal>dd</literal> to indicate the position of the + day. + </para> + <para> + The following table indicates a few possible formats. This will give + you an idea of how to use this function. + <table> + <title>Valid input formats for <function>rdefmtdate</function>. + <tgroup cols="2"> + <thead> + <row> + <entry>fmt</entry> + <entry>str</entry> + <entry>result</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>ddmmyy</literal></entry> + <entry><literal>21-2-54</literal></entry> + <entry><literal>1954-02-21</literal></entry> + </row> + <row> + <entry><literal>ddmmyy</literal></entry> + <entry><literal>2-12-54</literal></entry> + <entry><literal>1954-12-02</literal></entry> + </row> + <row> + <entry><literal>ddmmyy</literal></entry> + <entry><literal>20111954</literal></entry> + <entry><literal>1954-11-20</literal></entry> + </row> + <row> + <entry><literal>ddmmyy</literal></entry> + <entry><literal>130464</literal></entry> + <entry><literal>1964-04-13</literal></entry> + </row> + <row> + <entry><literal>mmm.dd.yyyy</literal></entry> + <entry><literal>MAR-12-1967</literal></entry> + <entry><literal>1967-03-12</literal></entry> + </row> + <row> + <entry><literal>yy/mm/dd</literal></entry> + <entry><literal>1954, February 3rd</literal></entry> + <entry><literal>1954-02-03</literal></entry> + </row> + <row> + <entry><literal>mmm.dd.yyyy</literal></entry> + <entry><literal>041269</literal></entry> + <entry><literal>1969-04-12</literal></entry> + </row> + <row> + <entry><literal>yy/mm/dd</literal></entry> + <entry><literal>In the year 2525, in the month of July, mankind will be alive on the 28th day</literal></entry> + <entry><literal>2525-07-28</literal></entry> + </row> + <row> + <entry><literal>dd-mm-yy</literal></entry> + <entry><literal>I said on the 28th of July in the year 2525</literal></entry> + <entry><literal>2525-07-28</literal></entry> + </row> + <row> + <entry><literal>mmm.dd.yyyy</literal></entry> + <entry><literal>9/14/58</literal></entry> + <entry><literal>1958-09-14</literal></entry> + </row> + <row> + <entry><literal>yy/mm/dd</literal></entry> + <entry><literal>47/03/29</literal></entry> + <entry><literal>1947-03-29</literal></entry> + </row> + <row> + <entry><literal>mmm.dd.yyyy</literal></entry> + <entry><literal>oct 28 1975</literal></entry> + <entry><literal>1975-10-28</literal></entry> + </row> + <row> + <entry><literal>mmddyy</literal></entry> + <entry><literal>Nov 14th, 1985</literal></entry> + <entry><literal>1985-11-14</literal></entry> + </row> + </tbody> + </tgroup> + </table> + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </sect2> + + <sect2> + <title>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 <function>PGTYPEStimestamp_from_asc</function>. + <tgroup cols="2"> + <thead> + <row> + <entry>Input</entry> + <entry>Result</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>1999-01-08 04:05:06</literal></entry> + <entry><literal>1999-01-08 04:05:06</literal></entry> + </row> + <row> + <entry><literal>January 8 04:05:06 1999 PST</literal></entry> + <entry><literal>1999-01-08 04:05:06</literal></entry> + </row> + <row> + <entry><literal>1999-Jan-08 04:05:06.789-8</literal></entry> + <entry><literal>1999-01-08 04:05:06.789 (time zone specifier ignored)</literal></entry> + </row> + <row> + <entry><literal>J2451187 04:05-08:00</literal></entry> + <entry><literal>1999-01-08 04:05:00 (time zone specifier ignored)</literal></entry> + </row> + </tbody> + </tgroup> + </table> + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPEStimestamptoasc"> + <term><function>PGTYPEStimestamp_to_asc</function></term> + <listitem> + <para> + Converts a date to a C char* string. +<synopsis> +char *PGTYPEStimestamp_to_asc(timestamp tstamp); +</synopsis> + The function receives the timestamp <literal>tstamp</> as + its only argument and returns an allocated string that contains the + textual representation of the timestamp. + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPEStimestampcurrent"> + <term><function>PGTYPEStimestamp_current</function></term> + <listitem> + <para> + Retrieve the current timestamp. +<synopsis> +void PGTYPEStimestamp_current(timestamp *ts); +</synopsis> + The function retrieves the current timestamp and saves it into the + timestamp variable that <literal>ts</> points to. + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPEStimestampfmtasc"> + <term><function>PGTYPEStimestamp_fmt_asc</function></term> + <listitem> + <para> + Convert a timestamp variable to a C char* using a format mask. +<synopsis> +int PGTYPEStimestamp_fmt_asc(timestamp *ts, char *output, int str_len, char *fmtstr); +</synopsis> + The function receives a pointer to the timestamp to convert as its + first argument (<literal>ts</>), a pointer to the output buffer + (<literal>output</>), the maximal length that has been allocated for + the output buffer (<literal>str_len</literal>) and the format mask to + use for the conversion (<literal>fmtstr</literal>). + </para> + <para> + Upon success, the function returns 0 and a negative value if an + error occurred. + </para> + <para> + You can use the following format specifiers for the format mask. The + format specifiers are the same ones that are used in the + <function>strftime</> function in <productname>libc</productname>. Any + non-format specifier will be copied into the output buffer. + <!-- This is from the FreeBSD man page: + http://www.freebsd.org/cgi/man.cgi?query=strftime&apropos=0&sektion=3&manpath=FreeBSD+7.0-current&format=html + --> + <itemizedlist> + <listitem> + <para> + <literal>%A</literal> - is replaced by national representation of + the full weekday name. + </para> + </listitem> + <listitem> + <para> + <literal>%a</literal> - is replaced by national representation of + the abbreviated weekday name. + </para> + </listitem> + <listitem> + <para> + <literal>%B</literal> - is replaced by national representation of + the full month name. + </para> + </listitem> + <listitem> + <para> + <literal>%b</literal> - is replaced by national representation of + the abbreviated month name. + </para> + </listitem> + <listitem> + <para> + <literal>%C</literal> - is replaced by (year / 100) as decimal + number; single digits are preceded by a zero. + </para> + </listitem> + <listitem> + <para> + <literal>%c</literal> - is replaced by national representation of + time and date. + </para> + </listitem> + <listitem> + <para> + <literal>%D</literal> - is equivalent to + <literal>%m/%d/%y</literal>. + </para> + </listitem> + <listitem> + <para> + <literal>%d</literal> - is replaced by the day of the month as a + decimal number (01-31). + </para> + </listitem> + <listitem> + <para> + <literal>%E*</literal> <literal>%O*</literal> - POSIX locale + extensions. The sequences + <literal>%Ec</literal> + <literal>%EC</literal> + <literal>%Ex</literal> + <literal>%EX</literal> + <literal>%Ey</literal> + <literal>%EY</literal> + <literal>%Od</literal> + <literal>%Oe</literal> + <literal>%OH</literal> + <literal>%OI</literal> + <literal>%Om</literal> + <literal>%OM</literal> + <literal>%OS</literal> + <literal>%Ou</literal> + <literal>%OU</literal> + <literal>%OV</literal> + <literal>%Ow</literal> + <literal>%OW</literal> + <literal>%Oy</literal> + are supposed to provide alternate representations. + </para> + <para> + Additionally <literal>%OB</literal> implemented to represent + alternative months names (used standalone, without day mentioned). + </para> + </listitem> + <listitem> + <para> + <literal>%e</literal> - is replaced by the day of month as a decimal + number (1-31); single digits are preceded by a blank. + </para> + </listitem> + <listitem> + <para> + <literal>%F</literal> - is equivalent to <literal>%Y-%m-%d</literal>. + </para> + </listitem> + <listitem> + <para> + <literal>%G</literal> - 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). + </para> + </listitem> + <listitem> + <para> + <literal>%g</literal> - is replaced by the same year as in + <literal>%G</literal>, but as a decimal number without century + (00-99). + </para> + </listitem> + <listitem> + <para> + <literal>%H</literal> - is replaced by the hour (24-hour clock) as a + decimal number (00-23). + </para> + </listitem> + <listitem> + <para> + <literal>%h</literal> - the same as <literal>%b</literal>. + </para> + </listitem> + <listitem> + <para> + <literal>%I</literal> - is replaced by the hour (12-hour clock) as a + decimal number (01-12). + </para> + </listitem> + <listitem> + <para> + <literal>%j</literal> - is replaced by the day of the year as a + decimal number (001-366). + </para> + </listitem> + <listitem> + <para> + <literal>%k</literal> - is replaced by the hour (24-hour clock) as a + decimal number (0-23); single digits are preceded by a blank. + </para> + </listitem> + <listitem> + <para> + <literal>%l</literal> - is replaced by the hour (12-hour clock) as a + decimal number (1-12); single digits are preceded by a blank. + </para> + </listitem> + <listitem> + <para> + <literal>%M</literal> - is replaced by the minute as a decimal + number (00-59). + </para> + </listitem> + <listitem> + <para> + <literal>%m</literal> - is replaced by the month as a decimal number + (01-12). + </para> + </listitem> + <listitem> + <para> + <literal>%n</literal> - is replaced by a newline. + </para> + </listitem> + <listitem> + <para> + <literal>%O*</literal> - the same as <literal>%E*</literal>. + </para> + </listitem> + <listitem> + <para> + <literal>%p</literal> - is replaced by national representation of + either "ante meridiem" or "post meridiem" as appropriate. + </para> + </listitem> + <listitem> + <para> + <literal>%R</literal> - is equivalent to <literal>%H:%M</literal>. + </para> + </listitem> + <listitem> + <para> + <literal>%r</literal> - is equivalent to <literal>%I:%M:%S + %p</literal>. + </para> + </listitem> + <listitem> + <para> + <literal>%S</literal> - is replaced by the second as a decimal + number (00-60). + </para> + </listitem> + <listitem> + <para> + <literal>%s</literal> - is replaced by the number of seconds since + the Epoch, UTC. + </para> + </listitem> + <listitem> + <para> + <literal>%T</literal> - is equivalent to <literal>%H:%M:%S</literal> + </para> + </listitem> + <listitem> + <para> + <literal>%t</literal> - is replaced by a tab. + </para> + </listitem> + <listitem> + <para> + <literal>%U</literal> - is replaced by the week number of the year + (Sunday as the first day of the week) as a decimal number (00-53). + </para> + </listitem> + <listitem> + <para> + <literal>%u</literal> - is replaced by the weekday (Monday as the + first day of the week) as a decimal number (1-7). + </para> + </listitem> + <listitem> + <para> + <literal>%V</literal> - 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. + </para> + </listitem> + <listitem> + <para> + <literal>%v</literal> - is equivalent to + <literal>%e-%b-%Y</literal>. + </para> + </listitem> + <listitem> + <para> + <literal>%W</literal> - is replaced by the week number of the year + (Monday as the first day of the week) as a decimal number (00-53). + </para> + </listitem> + <listitem> + <para> + <literal>%w</literal> - is replaced by the weekday (Sunday as the + first day of the week) as a decimal number (0-6). + </para> + </listitem> + <listitem> + <para> + <literal>%X</literal> - is replaced by national representation of + the time. + </para> + </listitem> + <listitem> + <para> + <literal>%x</literal> - is replaced by national representation of + the date. + </para> + </listitem> + <listitem> + <para> + <literal>%Y</literal> - is replaced by the year with century as a + decimal number. + </para> + </listitem> + <listitem> + <para> + <literal>%y</literal> - is replaced by the year without century as a + decimal number (00-99). + </para> + </listitem> + <listitem> + <para> + <literal>%Z</literal> - is replaced by the time zone name. + </para> + </listitem> + <listitem> + <para> + <literal>%z</literal> - 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). + </para> + </listitem> + <listitem> + <para> + <literal>%+</literal> - is replaced by national representation of + the date and time. + </para> + </listitem> + <listitem> + <para> + <literal>%-*</literal> - GNU libc extension. Do not do any padding + when performing numerical outputs. + </para> + </listitem> + <listitem> + <para> + $_* - GNU libc extension. Explicitly specify space for padding. + </para> + </listitem> + <listitem> + <para> + <literal>%0*</literal> - GNU libc extension. Explicitly specify zero + for padding. + </para> + </listitem> + <listitem> + <para> + <literal>%%</literal> - is replaced by <literal>%</literal>. + </para> + </listitem> + </itemizedlist> + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPEStimestampsub"> + <term><function>PGTYPEStimestamp_sub</function></term> + <listitem> + <para> + Subtract one timestamp from another one and save the result in a + variable of type interval. +<synopsis> +int PGTYPEStimestamp_sub(timestamp *ts1, timestamp *ts2, interval *iv); +</synopsis> + The function will subtract the timestamp variable that <literal>ts2</> + points to from the timestamp variable that <literal>ts1</> points to + and will store the result in the interval variable that <literal>iv</> + points to. + </para> + <para> + Upon success, the function returns 0 and a negative value if an + error occurred. + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPEStimestampdefmtasc"> + <term><function>PGTYPEStimestamp_defmt_asc</function></term> + <listitem> + <para> + Parse a timestamp value from its textual representation using a + formatting mask. +<synopsis> +int PGTYPEStimestamp_defmt_asc(char *str, char *fmt, timestamp *d); +</synopsis> + The function receives the textual representation of a timestamp in the + variable <literal>str</> as well as the formatting mask to use in the + variable <literal>fmt</>. The result will be stored in the variable + that <literal>d</> points to. + </para> + <para> + If the formatting mask <literal>fmt</> is NULL, the function will fall + back to the default formatting mask which is <literal>%Y-%m-%d + %H:%M:%S</literal>. + </para> + <para> + This is the reverse function to <xref + linkend="PGTYPEStimestampfmtasc">. See the documentation there in + order to find out about the possible formatting mask entries. + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPEStimestampaddinterval"> + <term><function>PGTYPEStimestamp_add_interval</function></term> + <listitem> + <para> + Add an interval variable to a timestamp variable. +<synopsis> +int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout); +</synopsis> + The function receives a pointer to a timestamp variable <literal>tin</> + and a pointer to an interval variable <literal>span</>. It adds the + interval to the timestamp and saves the resulting timestamp in the + variable that <literal>tout</> points to. + </para> + <para> + Upon success, the function returns 0 and a negative value if an + error occurred. + </para> + </listitem> + </varlistentry> + + <varlistentry id="PGTYPEStimestampsubinterval"> + <term><function>PGTYPEStimestamp_sub_interval</function></term> + <listitem> + <para> + Subtract an interval variable from a timestamp variable. +<synopsis> +int PGTYPEStimestamp_sub_interval(timestamp *tin, interval *span, timestamp *tout); +</synopsis> + The function subtracts the interval variable that <literal>span</> + points to from the timestamp variable that <literal>tin</> points to + and saves the result into the variable that <literal>tout</> points + to. + </para> + <para> + Upon success, the function returns 0 and a negative value if an + error occurred. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </sect2> + + <sect2> + <title>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 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 . + + + + + + 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 . + + + + + + 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 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 . 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 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 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 + + 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). + + + + + + 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). + + + + + + 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). + + + + + + 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). + + + + + + 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). + + + + + + 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). + + + + + + ECPG_INFORMIX_DATE_CONVERT + + + Functions return this value if Internally it is defined to -1210 (the + Informix definition). + + + + + + ECPG_INFORMIX_OUT_OF_MEMORY + + + Functions return this value if Internally it is defined to -1211 (the + Informix definition). + + + + + + 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). + + + + + + 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). + + + + + + 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). + + + + + + + + Using SQL Descriptor Areas @@ -955,7 +3968,7 @@ EXEC SQL WHENEVER condition action - BREAK + DO BREAK Execute the C statement break. This should @@ -1467,41 +4480,163 @@ struct - - Including Files + + 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. - - - - - The include file name is case-sensitive, even though the rest of - the EXEC SQL INCLUDE command follows the normal - SQL case-sensitivity rules. + 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; + + + + + 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