|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
#include <ecpg_informix.h>
|
|
|
|
#include <pgtypes_error.h>
|
|
|
|
#include <pgtypes_date.h>
|
|
|
|
|
|
|
|
/* we start with the numeric functions */
|
|
|
|
int
|
|
|
|
decadd(Numeric *arg1, Numeric *arg2, Numeric *sum)
|
|
|
|
{
|
|
|
|
Numeric *temp_sum = malloc(sizeof(Numeric)) ;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (temp_sum == NULL)
|
|
|
|
return -1211;
|
|
|
|
|
|
|
|
i = PGTYPESnumeric_add(arg1, arg2, temp_sum);
|
|
|
|
|
|
|
|
if (i == 0) /* No error */
|
|
|
|
{
|
|
|
|
|
|
|
|
if (PGTYPESnumeric_copy(temp_sum, sum) !=0)
|
|
|
|
return -1211;
|
|
|
|
|
|
|
|
free(temp_sum);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
free(temp_sum);
|
|
|
|
|
|
|
|
if (errno == PGTYPES_NUM_OVERFLOW)
|
|
|
|
return -1200;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1201;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
deccmp(Numeric *arg1, Numeric *arg2)
|
|
|
|
{
|
|
|
|
int i = PGTYPESnumeric_cmp(arg1, arg2);
|
|
|
|
|
|
|
|
return (i);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
deccopy(Numeric *src, Numeric *target)
|
|
|
|
{
|
|
|
|
PGTYPESnumeric_copy(src, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
strndup(char *str, int len)
|
|
|
|
{
|
|
|
|
int real_len = strlen(str);
|
|
|
|
int use_len = (real_len > len) ? len : real_len;
|
|
|
|
|
|
|
|
char *new = malloc(use_len + 1);
|
|
|
|
|
|
|
|
if (new)
|
|
|
|
{
|
|
|
|
memcpy(new, str, use_len);
|
|
|
|
new[use_len] = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
errno = ENOMEM;
|
|
|
|
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
deccvasc(char *cp, int len, Numeric *np)
|
|
|
|
{
|
|
|
|
char *str = strndup(cp, len); /* Numeric_in always converts the complete string */
|
|
|
|
int ret = 0;
|
|
|
|
Numeric *result;
|
|
|
|
|
|
|
|
if (!str)
|
|
|
|
ret = -1201;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = PGTYPESnumeric_from_asc(str, NULL);
|
|
|
|
if (!result)
|
|
|
|
{
|
|
|
|
switch (errno)
|
|
|
|
{
|
|
|
|
case PGTYPES_NUM_OVERFLOW: ret = -1200;
|
|
|
|
break;
|
|
|
|
case PGTYPES_NUM_BAD_NUMERIC: ret = -1213;
|
|
|
|
break;
|
|
|
|
default: ret = -1216;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (PGTYPESnumeric_copy(result, np) !=0)
|
|
|
|
ret = -1211;
|
|
|
|
|
|
|
|
free(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
deccvdbl(double dbl, Numeric *np)
|
|
|
|
{
|
|
|
|
return(PGTYPESnumeric_from_double(dbl, np));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
deccvint(int in, Numeric *np)
|
|
|
|
{
|
|
|
|
return(PGTYPESnumeric_from_int(in, np));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
deccvlong(long lng, Numeric *np)
|
|
|
|
{
|
|
|
|
return(PGTYPESnumeric_from_long(lng, np));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
decdiv(Numeric *n1, Numeric *n2, Numeric *n3)
|
|
|
|
{
|
|
|
|
Numeric *temp = malloc(sizeof(Numeric));
|
|
|
|
int i, ret = 0;
|
|
|
|
|
|
|
|
if (temp == NULL)
|
|
|
|
return -1211;
|
|
|
|
|
|
|
|
i = PGTYPESnumeric_div(n1, n2, temp);
|
|
|
|
|
|
|
|
if (i != 0)
|
|
|
|
switch (errno)
|
|
|
|
{
|
|
|
|
case PGTYPES_NUM_DIVIDE_ZERO: ret = -1202;
|
|
|
|
break;
|
|
|
|
case PGTYPES_NUM_OVERFLOW: ret = -1200;
|
|
|
|
break;
|
|
|
|
default: ret = -1201;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (PGTYPESnumeric_copy(temp, n3) !=0)
|
|
|
|
ret = -1211;
|
|
|
|
|
|
|
|
free(temp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
decmul(Numeric *n1, Numeric *n2, Numeric *n3)
|
|
|
|
{
|
|
|
|
Numeric *temp = malloc(sizeof(Numeric));
|
|
|
|
int i, ret = 0;
|
|
|
|
|
|
|
|
if (temp == NULL)
|
|
|
|
return -1211;
|
|
|
|
|
|
|
|
i = PGTYPESnumeric_mul(n1, n2, temp);
|
|
|
|
|
|
|
|
if (i != 0)
|
|
|
|
switch (errno)
|
|
|
|
{
|
|
|
|
case PGTYPES_NUM_OVERFLOW: ret = -1200;
|
|
|
|
break;
|
|
|
|
default: ret = -1201;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (PGTYPESnumeric_copy(temp, n3) !=0)
|
|
|
|
ret = -1211;
|
|
|
|
|
|
|
|
free(temp);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
decsub(Numeric *n1, Numeric *n2, Numeric *n3)
|
|
|
|
{
|
|
|
|
Numeric *temp = malloc(sizeof(Numeric));
|
|
|
|
int i, ret = 0;
|
|
|
|
|
|
|
|
if (temp == NULL)
|
|
|
|
return -1211;
|
|
|
|
|
|
|
|
i = PGTYPESnumeric_sub(n1, n2, temp);
|
|
|
|
|
|
|
|
if (i != 0)
|
|
|
|
switch (errno)
|
|
|
|
{
|
|
|
|
case PGTYPES_NUM_OVERFLOW: ret = -1200;
|
|
|
|
break;
|
|
|
|
default: ret = -1201;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (PGTYPESnumeric_copy(temp, n3) !=0)
|
|
|
|
ret = -1211;
|
|
|
|
|
|
|
|
free(temp);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dectoasc(Numeric *np, char *cp, int len, int right)
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
if (right >= 0)
|
|
|
|
str = PGTYPESnumeric_to_asc(np, right);
|
|
|
|
else
|
|
|
|
str = PGTYPESnumeric_to_asc(np, 0);
|
|
|
|
|
|
|
|
if (!str)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* TODO: have to take care of len here and create exponatial notion if necessary */
|
|
|
|
strncpy(cp, str, len);
|
|
|
|
free (str);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dectodbl(Numeric *np, double *dblp)
|
|
|
|
{
|
|
|
|
return(PGTYPESnumeric_to_double(np, dblp));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dectoint(Numeric *np, int *ip)
|
|
|
|
{
|
|
|
|
int ret = PGTYPESnumeric_to_int(np, ip);
|
|
|
|
|
|
|
|
if (ret == PGTYPES_NUM_OVERFLOW)
|
|
|
|
ret = -1200;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dectolong(Numeric *np, long *lngp)
|
|
|
|
{
|
|
|
|
int ret = PGTYPESnumeric_to_long(np, lngp);
|
|
|
|
|
|
|
|
if (ret == PGTYPES_NUM_OVERFLOW)
|
|
|
|
ret = -1200;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now the date functions */
|
|
|
|
int
|
|
|
|
rdatestr (Date d, char *str)
|
|
|
|
{
|
|
|
|
char *tmp = PGTYPESdate_to_asc(d);
|
|
|
|
|
|
|
|
if (!tmp)
|
|
|
|
return -1210;
|
|
|
|
|
|
|
|
/* move to user allocated buffer */
|
|
|
|
strcpy(tmp, str);
|
|
|
|
free(str);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rstrdate (char *str, Date *d)
|
|
|
|
{
|
|
|
|
Date dat = PGTYPESdate_from_asc(str, NULL);
|
|
|
|
|
|
|
|
if (errno != PGTYPES_DATE_BAD_DATE && dat == 0)
|
|
|
|
return -1218;
|
|
|
|
|
|
|
|
*d=dat;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rtoday (Date *d)
|
|
|
|
{
|
|
|
|
PGTYPESdate_today(d);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rjulmdy (Date d, short mdy[3])
|
|
|
|
{
|
|
|
|
PGTYPESdate_julmdy(d, (int *)mdy);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rdefmtdate (Date *d, char *fmt, char *str)
|
|
|
|
{
|
|
|
|
/* TODO: take care of DBCENTURY environment variable */
|
|
|
|
/* PGSQL functions allow all centuries */
|
|
|
|
|
|
|
|
if (PGTYPESdate_defmt_asc(d, fmt, str) == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (errno)
|
|
|
|
{
|
|
|
|
case PGTYPES_DATE_ERR_ENOSHORTDATE: return -1209;
|
|
|
|
case PGTYPES_DATE_ERR_EARGS:
|
|
|
|
case PGTYPES_DATE_ERR_ENOTDMY: return -1212;
|
|
|
|
case PGTYPES_DATE_BAD_DAY: return -1204;
|
|
|
|
case PGTYPES_DATE_BAD_MONTH: return -1205;
|
|
|
|
default: return -1206;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rfmtdate (Date d, char *fmt, char *str)
|
|
|
|
{
|
|
|
|
if (PGTYPESdate_fmt_asc(d, fmt, str) == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (errno == ENOMEM)
|
|
|
|
return -1211;
|
|
|
|
|
|
|
|
return -1210;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rmdyjul (short mdy[3], Date *d)
|
|
|
|
{
|
|
|
|
PGTYPESdate_mdyjul((int *)mdy, d);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* And the datetime stuff */
|
|
|
|
|
|
|
|
void
|
|
|
|
dtcurrent (Timestamp *ts)
|
|
|
|
{
|
|
|
|
PGTYPEStimestamp_current (ts);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dtcvasc (char *str, Timestamp *ts)
|
|
|
|
{
|
|
|
|
Timestamp ts_tmp;
|
|
|
|
int i;
|
|
|
|
char **endptr = &str;
|
|
|
|
|
|
|
|
ts_tmp = PGTYPEStimestamp_from_asc(str, endptr);
|
|
|
|
i = errno;
|
|
|
|
if (i) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
if (**endptr) {
|
|
|
|
/* extra characters exist at the end */
|
|
|
|
return -1264;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* everything went fine */
|
|
|
|
*ts = ts_tmp;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dtsub (Timestamp *ts1, Timestamp *ts2, Interval *iv)
|
|
|
|
{
|
|
|
|
return PGTYPEStimestamp_sub(ts1, ts2, iv);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dttoasc (Timestamp *ts, char *output)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dttofmtasc (Timestamp *ts, char *output, int str_len, char *fmtstr)
|
|
|
|
{
|
|
|
|
return PGTYPEStimestamp_fmt_asc(ts, output, str_len, fmtstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
intoasc(Interval *i, char *str)
|
|
|
|
{
|
|
|
|
str = PGTYPESinterval_to_asc(i);
|
|
|
|
|
|
|
|
if (!str)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* And finally some misc functions */
|
|
|
|
int
|
|
|
|
rfmtlong(long lvalue, char *format, char *outbuf)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rgetmsg(int msgnum, char *s, int maxsize)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
risnull(int vtype, char *pcvar)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rsetnull(int vtype, char *pcvar)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rtypalign(int offset, int type)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rtypmsize(int type, int len)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rupshift(char *str)
|
|
|
|
{
|
|
|
|
for (; *str != '\0'; str++)
|
|
|
|
if (islower(*str)) *str = toupper(*str);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|